/* ══════════ Folio ══════════
   Papier, encre, toile de reliure. Le fond n'est pas blanc mais crème,
   l'encre n'est pas noire mais brun très sombre : c'est ce qui fait la
   différence entre un écran et une page. Les titres sont en romain à
   empattements, le reste de l'interface en linéale — comme un livre dont
   la couverture et les notes de bas de page ne parlent pas de la même
   voix. */
:root{
  color-scheme:light;
  --bg:#FAF6EC; --bg2:#F1E9DA;
  --ink:#221C15; --ink2:#4C4238; --soft:#8C8072;
  --card:#FFFDF8; --hair:rgba(34,28,21,.08);
  --surf:rgba(34,28,21,.05); --surf2:rgba(34,28,21,.09);
  --ok:#3F7D55; --ko:#B34A3C; --leather:#7A4B34;
  --serif:ui-serif,"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",
    Georgia,"Times New Roman",serif;
  --s1:0 1px 2px rgba(74,52,32,.06), 0 4px 12px rgba(74,52,32,.06);
  --s2:0 2px 6px rgba(74,52,32,.07), 0 14px 32px rgba(74,52,32,.10);
  --s3:0 6px 16px rgba(74,52,32,.09), 0 28px 60px rgba(74,52,32,.16);
  --e:cubic-bezier(.22,1,.36,1);
  --sp:cubic-bezier(.34,1.32,.5,1);
  --pad:20px;
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html{height:100%;background:var(--bg)}
/* Une feuille ouverte gèle le document derrière elle. Sans ça, un doigt
   posé sur le voile ou sur une feuille trop courte pour défiler elle-même
   faisait défiler la page en dessous — invisible, mais bien réelle. */
html.sheet-open,html.sheet-open body{overflow:hidden}
body{
  margin:0;min-height:100%;background:var(--bg);color:var(--ink);
  font:500 17px/1.42 -apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Inter,system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
  overscroll-behavior-y:none;text-rendering:optimizeLegibility;
}
button{font:inherit;color:inherit;border:0;background:none;padding:0;cursor:pointer}
input,textarea{font:inherit;color:inherit;border:0;outline:none;background:none;border-radius:0}
svg{fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
#app{min-height:100svh;display:flex;flex-direction:column;
  padding:max(10px,env(safe-area-inset-top)) var(--pad) calc(12px + env(safe-area-inset-bottom))}
.fade > *{animation:rise .5s var(--e) both}
.fade > *:nth-child(2){animation-delay:.03s}
.fade > *:nth-child(3){animation-delay:.06s}
.fade > *:nth-child(4){animation-delay:.09s}
@keyframes rise{from{opacity:0;transform:translateY(12px)}}
@keyframes pop{from{opacity:0;transform:translateY(14px) scale(.97)}}
@keyframes fadein{from{opacity:0}}

/* ---------- barres ---------- */
.bar{display:flex;align-items:center;gap:8px;min-height:46px;flex:none}
.bar h1{flex:1;margin:0;font-weight:700;font-size:18px;line-height:1.25;letter-spacing:-.35px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bar .num{font-size:14px;font-weight:700;color:var(--soft);
  font-variant-numeric:tabular-nums;letter-spacing:0;padding-right:2px}
.hero{font-family:var(--serif);margin:12px 1px 20px;font-weight:700;font-size:38px;
  line-height:1.02;letter-spacing:-.9px}
/* pages balayables */
.page{flex:1;min-height:0;display:flex;flex-direction:column;will-change:transform;
  transition:transform .4s var(--e)}
#page{padding-bottom:150px}
.page.in-right{animation:inR .42s var(--e) both}
.page.in-left{animation:inL .42s var(--e) both}
@keyframes inR{from{opacity:0;transform:translateX(48px)}}
@keyframes inL{from{opacity:0;transform:translateX(-48px)}}
#page{touch-action:pan-y}

.top{display:flex;align-items:flex-end;gap:10px;margin:14px 1px 20px}
/* le titre cède la place aux boutons plutôt que de les pousser dehors ;
   il rétrécit, il ne se coupe jamais au milieu d'un mot */
.top .hero{flex:1;min-width:0;margin:0;font-size:clamp(27px,8vw,38px)}
.top .ic{margin-bottom:3px}
.ic{width:40px;height:40px;border-radius:13px;display:grid;place-items:center;flex:none;
  background:var(--surf);color:var(--ink2);
  transition:transform .32s var(--sp),background .25s var(--e),color .25s}
.ic:active{transform:scale(.86);background:var(--surf2)}
.ic.solid{background:var(--ink);color:var(--bg)}
.ic svg{width:19px;height:19px}

/* ---------- pastilles de matière ---------- */
.pills{display:flex;gap:7px;overflow-x:auto;scrollbar-width:none;
  margin:0 calc(var(--pad) * -1) 16px;padding:2px var(--pad) 6px;scroll-padding:var(--pad)}
.pills::-webkit-scrollbar{display:none}
.p{flex:none;display:flex;align-items:center;gap:8px;height:36px;padding:0 15px;
  border-radius:12px;background:var(--surf);font-size:14.5px;font-weight:650;letter-spacing:-.15px;
  white-space:nowrap;color:var(--ink2);
  transition:background .28s var(--e),color .28s var(--e),transform .3s var(--sp)}
.p:active{transform:scale(.93)}
.p.on{background:var(--ink);color:var(--bg)}
.p i{width:9px;height:9px;border-radius:50%;background:var(--d);flex:none;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.08)}

/* ---------- grille de paquets ---------- */
.grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;align-content:start}
/* Une couverture reliée : dos carré à gauche, tranche arrondie à droite,
   toile teintée de son rayon, titre en romain. Le signet qui dépasse en
   haut porte le nombre de fiches à lire aujourd'hui. */
.tile{position:relative;border-radius:5px 22px 22px 5px;padding:17px 15px 14px 24px;
  min-height:142px;
  display:flex;flex-direction:column;justify-content:space-between;text-align:left;
  background:var(--c);color:var(--ci);box-shadow:var(--s1);overflow:hidden;
  transition:transform .34s var(--sp),box-shadow .34s var(--e),opacity .3s}
/* le dos du livre, avec ses deux nerfs */
.tile .spine{position:absolute;left:0;top:0;bottom:0;width:14px;z-index:2;pointer-events:none;
  background:linear-gradient(90deg,rgba(0,0,0,.17),rgba(0,0,0,.05) 55%,rgba(255,255,255,.14));
  box-shadow:inset -1px 0 0 rgba(0,0,0,.06)}
.tile .spine::before,.tile .spine::after{content:'';position:absolute;left:0;right:0;height:1px;
  background:rgba(0,0,0,.12)}
.tile .spine::before{top:24%} .tile .spine::after{bottom:24%}
.fade .tile{animation:pop .55s var(--e) both;animation-delay:calc(var(--i) * 40ms)}
.tile::before{content:'';position:absolute;inset:0;border-radius:5px 22px 22px 5px;
  pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.34),inset 0 1px 0 rgba(255,255,255,.5)}
/* le grain du papier teinté, très en dessous du seuil de perception */
.tile::after{content:'';position:absolute;inset:0;border-radius:5px 22px 22px 5px;
  pointer-events:none;opacity:.5;
  background:linear-gradient(152deg,rgba(255,255,255,.42),rgba(255,255,255,0) 62%),
    repeating-linear-gradient(90deg,rgba(0,0,0,.022) 0 1px,transparent 1px 3px)}
.tile:active{transform:scale(.955);box-shadow:var(--s2)}
/* épingle et barre de maturité posées sur la tuile, sans rien pousser */
.tile .pind{position:absolute;top:13px;left:24px;z-index:2;opacity:.55;display:grid;place-items:center}
.tile .pind svg{width:13px;height:13px;stroke-width:2.4}
.tile .tbar{position:absolute;left:24px;right:15px;bottom:9px;height:3px;border-radius:3px;
  background:rgba(255,255,255,.45);overflow:hidden;z-index:1}
.tile .tbar b{display:block;height:100%;border-radius:3px;background:var(--ci);opacity:.5}

/* barre de contrôles de l'accueil : tri à gauche, affichage à droite */
.hbar{display:flex;align-items:center;gap:8px;margin:0 1px 10px}
.hbar .lnk{margin:0;padding:6px 11px;background:var(--card);box-shadow:var(--s1);color:var(--ink2)}
.hbar .lnk.on{background:var(--ink);color:var(--bg);box-shadow:none}

/* progression de la sélection, une ligne fine sous les pastilles */
.sbar{display:flex;gap:2px;height:4px;margin:0 2px 12px;border-radius:3px;overflow:hidden}
.sbar i{border-radius:3px;background:var(--surf2)}
.sbar i.mature{background:var(--ok)}
.sbar i.young{background:#7FB08F}
.sbar i.learn{background:#C9A526}
.sbar i.new{background:var(--surf2)}

/* vue liste des paquets */
.rows.lst{padding-bottom:34px}
.lrow{display:flex;align-items:center;gap:10px;background:var(--card);box-shadow:var(--s1);
  border-radius:4px 16px 16px 4px;border-left:5px solid var(--d);padding:11px 14px;margin-bottom:8px;
  transition:box-shadow .3s,transform .3s var(--sp)}
.fade .lrow{animation:pop .5s var(--e) both;animation-delay:calc(var(--i) * 14ms)}
.lrow.mute{opacity:.5}
.lrow .ldot{width:10px;height:10px;border-radius:50%;flex:none;background:var(--d)}
.lrow .lmain{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;text-align:left}
.lrow .n{display:flex;align-items:center;gap:6px;font-weight:700;font-size:15.5px;
  letter-spacing:-.25px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lrow .n svg{width:12px;height:12px;flex:none;color:var(--soft)}
.lrow .s{font-size:12.5px;font-weight:600;color:var(--soft)}
.lrow .ldue{flex:none;min-width:24px;height:24px;padding:0 7px;border-radius:9px;
  background:var(--ink);color:var(--bg);display:grid;place-items:center;font-style:normal;
  font-size:12px;font-weight:800;font-variant-numeric:tabular-nums}
.lrow.drag{position:relative;z-index:3;box-shadow:var(--s3)}
.rows.dragging .lrow:not(.drag){transition:transform .2s var(--e)}
.tile .n{position:relative;z-index:1;font-family:var(--serif);font-weight:700;font-size:18px;
  line-height:1.22;letter-spacing:-.2px;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
/* le filet sous le titre, comme sur une couverture de collection */
.tile .n::after{content:'';display:block;width:26px;height:1.5px;margin-top:9px;
  background:currentColor;opacity:.3}
.tile .m{position:relative;z-index:1;display:flex;align-items:center;gap:6px;margin-top:12px;
  font-size:12.5px;font-weight:700;opacity:.55;font-variant-numeric:tabular-nums}
.tile .m svg{width:13px;height:13px;stroke-width:2.2}
.tile.mute{opacity:.4}
.tile.all{background:var(--ink);color:var(--bg)}
.tile.all::before{box-shadow:inset 0 0 0 1px rgba(255,255,255,.09)}
.tile.all::after{background:linear-gradient(155deg,rgba(255,255,255,.09),rgba(255,255,255,0) 58%)}

/* Un écran vide dit ce qui manque, en une ligne, et rien de plus. Le
   pavé d'explications qu'il portait avant se lisait comme une notice et
   décalait l'icône hors du centre. */
.empty{flex:1;min-height:46vh;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:18px;color:var(--soft);text-align:center;padding:0 24px 12vh}
.empty svg{width:56px;height:56px;stroke-width:1.3;opacity:.3}
.empty p{margin:0;font-size:15.5px;font-weight:650;letter-spacing:-.2px;
  max-width:19em;line-height:1.45;opacity:.85}
.empty p b{display:block;font-size:18px;font-weight:750;letter-spacing:-.4px;
  color:var(--ink2);margin-bottom:5px;opacity:.9}

.tabs{position:fixed;left:50%;bottom:calc(13px + env(safe-area-inset-bottom));
  transform:translateX(-50%);display:flex;padding:5px;border-radius:20px;z-index:25;
  background:rgba(255,255,255,.72);backdrop-filter:blur(24px) saturate(1.9);
  -webkit-backdrop-filter:blur(24px) saturate(1.9);
  box-shadow:var(--s2),inset 0 0 0 1px rgba(255,255,255,.7)}
.tabs button{position:relative;z-index:1;width:74px;height:44px;border-radius:15px;
  display:grid;place-items:center;color:var(--soft);transition:color .35s var(--e)}
.tabs button.on{color:var(--bg)}
.tabs svg{width:20px;height:20px;stroke-width:2}
.tabs .sl{position:absolute;top:5px;left:5px;width:74px;height:44px;border-radius:15px;
  background:var(--ink);transition:transform .46s var(--sp)}
.tabs .icb{position:absolute;top:4px;right:14px;min-width:16px;height:16px;padding:0 4px;
  border-radius:8px;background:var(--ko);color:#fff;font-size:10.5px;font-weight:800;
  line-height:16px;text-align:center;font-style:normal}

/* ---------- bouton flottant ---------- */
.fab{position:fixed;right:var(--pad);bottom:calc(84px + env(safe-area-inset-bottom));
  width:56px;height:56px;border-radius:20px;background:var(--ink);color:var(--bg);
  display:grid;place-items:center;box-shadow:var(--s3);z-index:20;
  transition:transform .38s var(--sp)}
.fade .fab{animation:pop .55s var(--e) .12s both}
.fab:active{transform:scale(.85)}
.fab svg{width:23px;height:23px;stroke-width:2.3}
/* le rond vert qui valide le rangement : même place que le bouton
   d'ajout qu'il remplace, rond plutôt que pilule puisqu'il ne porte
   qu'une icône, et vert pour se distinguer de tout le reste, éteint */
.fab.fabok{border-radius:50%;background:var(--ok);animation:fabin .3s var(--sp) both}
@keyframes fabin{from{opacity:0;transform:scale(.5) rotate(-30deg)}}

/* ---------- fiche paquet ---------- */
.head{position:relative;border-radius:28px;padding:22px 20px 18px;margin-bottom:14px;
  background:var(--c);color:var(--ci);box-shadow:var(--s1);overflow:hidden}
.fade .head{animation:pop .5s var(--e) both}
.head::after{content:'';position:absolute;inset:0;border-radius:28px;pointer-events:none;
  background:linear-gradient(150deg,rgba(255,255,255,.52),rgba(255,255,255,0) 62%)}
.head .t{position:relative;z-index:1;font-family:var(--serif);font-weight:700;font-size:28px;
  line-height:1.14;letter-spacing:-.4px;
  min-height:31px;outline:none}
.head .t:focus{opacity:.5}
.head .s{position:relative;z-index:1;display:flex;align-items:center;gap:8px;margin-top:11px;
  font-size:13.5px;font-weight:700;opacity:.62;font-variant-numeric:tabular-nums}
.head .s span{display:flex;align-items:center;gap:5px}
.head .s svg{width:14px;height:14px;stroke-width:2.2}
.head .s b{width:3px;height:3px;border-radius:50%;background:currentColor;opacity:.5}
.duo{display:flex;gap:10px;margin-bottom:18px}
.duo button{flex:1;height:54px;border-radius:19px;display:flex;align-items:center;
  justify-content:center;gap:9px;font-weight:700;font-size:15.5px;letter-spacing:-.2px;
  background:var(--card);box-shadow:var(--s1);transition:transform .3s var(--sp),box-shadow .3s}
.duo button:active{transform:scale(.96);box-shadow:var(--s2)}
.duo svg{width:19px;height:19px;stroke-width:2.1}
.duo .prim{background:var(--ink);color:var(--bg)}

.lbl{display:flex;align-items:center;gap:8px;
  margin:22px 3px 9px;font-size:12.5px;font-weight:750;letter-spacing:.5px;
  text-transform:uppercase;color:var(--soft)}
.lbl > span:first-child{margin-right:auto}
.page > .lbl:first-of-type,.top + .lbl{margin-top:0}
.rows{padding-bottom:34px}
#app[data-view="home"] .page,#app[data-view="commu"] .page{padding-bottom:74px}
.row{display:flex;align-items:center;gap:6px;background:var(--card);box-shadow:var(--s1);
  border-radius:18px;padding:11px 8px 11px 15px;margin-bottom:8px;
  transition:box-shadow .3s,transform .3s var(--sp)}
.fade .row{animation:pop .5s var(--e) both;animation-delay:calc(var(--i) * 14ms)}
.row:focus-within{box-shadow:var(--s2)}
.row .fl{flex:1;min-width:0;position:relative}
.row input{width:100%;padding:2px 0;font-weight:650;letter-spacing:-.2px}
.row input.b{color:var(--soft);font-size:15px;font-weight:500}
.row .x{width:32px;height:32px;flex:none;display:grid;place-items:center;color:var(--soft);
  border-radius:11px;transition:transform .3s var(--sp),color .25s,background .25s}
.row .x:active{transform:scale(.82);color:var(--ko);background:rgba(196,86,107,.1)}
.row .x svg{width:16px;height:16px;stroke-width:2.4}
.duo.ghost button{background:var(--surf);box-shadow:none;height:50px;color:var(--ink2)}

/* ---------- glisser pour réordonner ---------- */
.grip{width:22px;height:34px;flex:none;display:grid;place-items:center;margin-left:-7px;
  color:var(--soft);opacity:.38;cursor:grab;touch-action:none;
  transition:opacity .22s,transform .22s var(--sp)}
.grip svg{width:18px;height:18px}
.grip:active{cursor:grabbing;opacity:.85;transform:scale(1.12)}
.row.drag{position:relative;z-index:3;box-shadow:var(--s3);transform-origin:center;
  transition:box-shadow .2s}
.rows.dragging .row:not(.drag){transition:transform .2s var(--e)}
.rows.dragging input{pointer-events:none}

/* ---------- sélection multiple ----------
   En mode sélection la ligne entière devient une cible : les champs de
   saisie ne prennent plus le doigt, sinon taper sur un mot ouvrirait le
   clavier au lieu de cocher. */
/* « Sélectionner » posé dans le bandeau CARTES : il doit se lire comme un
   bouton, pas comme un intitulé. Gris sur gris, à la même graisse que le
   mot CARTES, personne n'avait l'idée d'appuyer dessus. */
/* Le premier bouton d'une ligne se pousse vers la droite (marge gauche
   automatique) ; s'il y en a un second — la loupe puis Sélectionner —
   celui-là suit juste après, au « gap » de la ligne, sans réclamer sa
   propre marge automatique : sinon les deux se partageaient l'espace
   libre et s'écartaient l'un de l'autre au lieu de rester groupés. */
.pick{margin-right:10px;display:flex;align-items:center;gap:6px;
  padding:6px 12px 6px 10px;border-radius:12px;background:var(--card);box-shadow:var(--s1);
  color:var(--ink);font-size:12.5px;font-weight:750;letter-spacing:-.1px;text-transform:none;
  transition:background .2s,color .2s,transform .2s var(--sp)}
.lbl > .pick:first-of-type{margin-left:auto}
.pick svg{width:15px;height:15px;stroke-width:2.1}
/* sans texte, le remplissage prévu pour « icône + mot » décalait la loupe
   vers la gauche : un carré, et elle tombe au milieu */
/* la ligne « Pages » qui la porte a déjà 8px de « gap » entre ses
   enfants : cette marge s'ajoutait par-dessus et doublait l'écart avec
   le bouton Sélectionner juste à côté */
.pick.ico{width:32px;height:32px;padding:0;gap:0;justify-content:center;margin-right:0}
.pick:active{transform:scale(.94)}
.pick.on{background:var(--ink);color:var(--bg);box-shadow:none}
.rows.picking input{pointer-events:none;user-select:none}
.rows.picking .row{cursor:pointer;padding-left:8px}
.row .ck{width:26px;height:26px;flex:none;display:grid;place-items:center;border-radius:9px;
  background:var(--surf);color:transparent;transition:background .2s,color .2s,transform .2s var(--sp)}
.row .ck svg{width:15px;height:15px;stroke-width:3}
.row.pk .ck{background:var(--ink);color:var(--bg)}
.row.pk{box-shadow:var(--s2)}
.row .ck:active{transform:scale(.85)}
.selb{position:fixed;left:10px;right:10px;bottom:calc(10px + env(safe-area-inset-bottom));
  z-index:39;display:flex;align-items:center;gap:10px;padding:9px 10px 9px 8px;
  background:var(--card);border-radius:20px;box-shadow:var(--s3);animation:up .42s var(--e)}
.sbl{padding:8px 12px;border-radius:13px;background:var(--surf);color:var(--ink);
  font-weight:730;font-size:13.5px;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}
.sbl svg{width:14px;height:14px;stroke-width:2.6}
.sbn{flex:1;min-width:0;font-size:14px;font-weight:730;color:var(--soft);
  letter-spacing:-.2px;font-variant-numeric:tabular-nums}
.sba{display:flex;gap:2px}
.sba .x{width:38px;height:38px;flex:none;display:grid;place-items:center;border-radius:13px;
  color:var(--ink);transition:transform .3s var(--sp),background .25s,opacity .25s}
.sba .x svg{width:18px;height:18px;stroke-width:2.2}
.sba .x.warn{color:var(--ko)}
.sba .x:active{transform:scale(.86);background:var(--surf)}
.sba .x[disabled]{opacity:.25;pointer-events:none}
@media (min-width:900px){.selb{left:auto;right:40px;width:420px}}
.duo.ghost button:active{background:var(--surf2)}

/* ---------- révision ---------- */
.study{flex:1;display:flex;flex-direction:column;min-height:0}
.prog{height:4px;border-radius:4px;background:var(--surf2);overflow:hidden;margin:4px 1px 2px;flex:none}
.prog i{display:block;height:100%;border-radius:4px;background:var(--ink);
  transition:width .6s var(--e)}
/* La fiche : un rectangle qu'on pousse à gauche ou à droite et qu'on
   retourne sur son axe. Rien d'autre — la reliure, la gouttière et la
   page qui se soulève rendaient le geste lourd et illisible. */
.stage{flex:1;display:flex;align-items:center;justify-content:center;
  padding:16px 0;perspective:1700px;min-height:0}
.stack{position:relative;width:100%;height:min(58svh,460px)}
.card{position:absolute;inset:0;border-radius:30px;will-change:transform;
  touch-action:none;-webkit-user-select:none;user-select:none;
  transition:transform .52s var(--sp),opacity .34s var(--e)}
.card.in{transform:translateY(14px) scale(.94);opacity:0}
.flipper{position:absolute;inset:0;transform-style:preserve-3d;will-change:transform;
  transition:transform .42s cubic-bezier(.2,.65,.8,.35)}
.card.flip .flipper{transform:rotateY(180deg)}
.face{position:absolute;inset:0;border-radius:30px;display:grid;place-items:center;
  padding:34px;text-align:center;gap:10px;backface-visibility:hidden;-webkit-backface-visibility:hidden;
  background:var(--c);color:var(--ci);box-shadow:var(--s3);overflow:hidden;
  /* l'échange des deux faces se fait quand la fiche est sur la tranche :
     plus tôt on voit le verso à l'envers, plus tard le recto revient */
  opacity:1;transform:translateZ(0);transition:opacity 0s linear .2s}
.face::before{content:'';position:absolute;inset:0;border-radius:30px;pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.34),inset 0 1.5px 0 rgba(255,255,255,.5)}
.face::after{content:'';position:absolute;inset:0;border-radius:30px;pointer-events:none;
  background:linear-gradient(158deg,rgba(255,255,255,.42),rgba(255,255,255,0) 60%)}
/* .tx porte le texte : une vraie boîte de bloc (le retournement se fait sur
   .face, pas sur un <span> en ligne) qui peut se limiter en hauteur et,
   passé cette limite, défiler plutôt que déborder du cadre. La taille se
   règle selon la longueur du texte (.l/.xl/.xxl, posées par faceSize() en
   JS) pour qu'une longue définition rétrécisse au lieu de couper. */
/* --fs est le réglage de confort ; il multiplie les quatre paliers sans
   toucher à la façon dont ils sont choisis (c'est la longueur du texte
   qui décide du palier, la préférence ne fait que l'échelle). */
.face .tx{position:relative;z-index:1;max-width:100%;max-height:100%;min-height:0;overflow:auto;
  font-family:var(--serif);font-weight:700;font-size:calc(clamp(27px,8vw,46px) * var(--fs,1));
  line-height:1.18;letter-spacing:-.5px}
.face.l .tx{font-size:calc(clamp(21px,6.6vw,34px) * var(--fs,1));line-height:1.26;letter-spacing:-.3px}
.face.xl .tx{font-size:calc(clamp(17px,5.2vw,26px) * var(--fs,1));line-height:1.3;letter-spacing:-.4px;font-weight:750}
.face.xxl .tx{font-size:calc(clamp(15px,4.2vw,20px) * var(--fs,1));line-height:1.36;letter-spacing:-.2px;font-weight:700}
.face.bk{transform:rotateY(180deg) translateZ(0);background:var(--ci);color:var(--c);opacity:0}
.card.flip .face{opacity:0}
.card.flip .face.bk{opacity:1}
.face.bk::before{box-shadow:inset 0 0 0 1px rgba(255,255,255,.1)}
.face.bk::after{background:linear-gradient(158deg,rgba(255,255,255,.1),rgba(255,255,255,0) 60%)}
.face.bk .tx{font-weight:650;font-size:clamp(22px,6vw,36px);letter-spacing:-.6px}
.face.bk.l .tx{font-size:clamp(18px,5.2vw,27px);line-height:1.26;letter-spacing:-.4px}
.face.bk.xl .tx{font-size:clamp(15.5px,4.4vw,21px);line-height:1.32;letter-spacing:-.2px;font-weight:600}
.face.bk.xxl .tx{font-size:clamp(14px,3.6vw,17px);line-height:1.38;letter-spacing:-.1px;font-weight:600}
.ov{position:absolute;top:24px;width:54px;height:54px;border-radius:18px;display:grid;
  place-items:center;opacity:0;transform:scale(.55);pointer-events:none;color:#fff;z-index:3;
  transition:opacity .18s,transform .3s var(--sp);box-shadow:var(--s2)}
.ov.y{right:22px;background:var(--ok)} .ov.n{left:22px;background:var(--ko)}
.ov svg{width:26px;height:26px;stroke-width:2.8}
.gone{transition:transform .36s cubic-bezier(.4,0,.55,1),opacity .32s !important}
.acts{display:flex;gap:11px;padding:2px 0 2px;flex:none}
.act{flex:1;height:60px;border-radius:21px;display:grid;place-items:center;
  background:var(--card);box-shadow:var(--s1);transition:transform .3s var(--sp),box-shadow .3s}
.fade .act{animation:pop .4s var(--e) both}
.act:active{transform:scale(.94);box-shadow:var(--s2)}
.act svg{width:25px;height:25px;stroke-width:2.5}
.act.no{color:var(--ko)} .act.yes{color:var(--ok)}
.hint{height:60px;display:grid;place-items:center;color:var(--soft);flex:none}
.hint svg{width:72px;height:22px;stroke-width:1.9;animation:sway 2.8s var(--e) infinite}
@keyframes sway{0%,100%{opacity:.25;transform:translateX(0)}
  30%{opacity:.6;transform:translateX(-5px)}70%{opacity:.6;transform:translateX(5px)}}

/* ---------- écran de fin ---------- */
.done{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:30px}
.ring{position:relative;width:172px;height:172px;animation:pop .6s var(--sp) both}
.ring svg{position:absolute;inset:0;width:172px;height:172px;transform:rotate(-90deg)}
.ring circle{fill:none;stroke-width:9;stroke-linecap:round}
.ring .bgc{stroke:var(--surf2)}
.ring .fgc{stroke:var(--rc,var(--ok));stroke-dasharray:471;stroke-dashoffset:471;
  transition:stroke-dashoffset 1.1s var(--e) .18s}
.ring .in{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:2px}
.ring .v{font-weight:800;font-size:44px;letter-spacing:-2px;line-height:1;
  font-variant-numeric:tabular-nums}
.ring .u{font-size:13.5px;font-weight:700;color:var(--soft);font-variant-numeric:tabular-nums}
.done .b{display:flex;gap:11px;animation:rise .5s var(--e) .24s both}
.done .b button{height:56px;padding:0 24px;border-radius:19px;display:flex;align-items:center;
  gap:9px;font-weight:700;font-size:15.5px;background:var(--card);box-shadow:var(--s1);
  transition:transform .3s var(--sp)}
.done .b button:active{transform:scale(.94)}
.done .b .prim{background:var(--ink);color:var(--bg)}
.done .b svg{width:19px;height:19px;stroke-width:2.1}

/* ---------- bilan de fin de session ---------- */
.rev{flex:1;min-height:0;overflow:auto;scrollbar-width:none;
  display:flex;flex-direction:column;align-items:center;gap:18px;
  padding:10px 0 24px}
.rev::-webkit-scrollbar{display:none}
.rev .ring{flex:none}
.rev .b{display:flex;gap:9px;width:100%;animation:rise .5s var(--e) .2s both}
.rev .b button{flex:1;height:52px;border-radius:18px;display:flex;align-items:center;
  justify-content:center;gap:8px;font-weight:700;font-size:14.5px;letter-spacing:-.2px;
  background:var(--card);box-shadow:var(--s1);transition:transform .3s var(--sp)}
.rev .b button:active{transform:scale(.95)}
.rev .b .prim{background:var(--ink);color:var(--bg)}
.rev .b svg{width:17px;height:17px;stroke-width:2.2}
.rev .lbl{width:100%;margin:0 2px -8px}

.tiles{display:flex;gap:8px;width:100%;animation:rise .5s var(--e) .1s both}
.st{flex:1;min-width:0;background:var(--card);box-shadow:var(--s1);border-radius:17px;
  padding:12px 6px 10px;display:flex;flex-direction:column;align-items:center;gap:2px}
.st b{font-weight:800;font-size:21px;letter-spacing:-.7px;font-variant-numeric:tabular-nums}
.st span{font-size:10.5px;font-weight:750;letter-spacing:.4px;text-transform:uppercase;
  color:var(--soft);white-space:nowrap}

/* ══════════ statistiques ══════════ */
.tiles.st4{flex-wrap:wrap;animation:none}
.tiles.st4 .st{flex:1 1 calc(50% - 4px);min-width:calc(50% - 4px)}
.card2{background:var(--card);box-shadow:var(--s1);border-radius:20px;padding:14px 16px}
/* sur cet écran les sections s'enchaînent : chaque intitulé a besoin
   d'air au-dessus, sinon il colle au bloc précédent */
#app[data-view="stats"] .lbl{margin-top:24px}
#app[data-view="stats"] .slist{gap:8px}

/* calendrier d'assiduité : une colonne par semaine, une case par jour */
.heat{display:flex;gap:3px;overflow-x:auto;scrollbar-width:none;padding-bottom:2px}
.heat::-webkit-scrollbar{display:none}
.hc{display:flex;flex-direction:column;gap:3px;flex:none}
.hc i{width:13px;height:13px;border-radius:4px;background:var(--surf)}
.hc i.l1{background:color-mix(in srgb,var(--ok) 26%,var(--surf))}
.hc i.l2{background:color-mix(in srgb,var(--ok) 48%,var(--surf))}
.hc i.l3{background:color-mix(in srgb,var(--ok) 72%,var(--surf))}
.hc i.l4{background:var(--ok)}
.heatk{display:flex;justify-content:space-between;margin-top:8px;font-size:11.5px;
  font-weight:650;color:var(--soft)}

/* barres comparées : rétention, progression, temps par matière */
.brow{display:flex;align-items:center;gap:10px;padding:5px 0}
.brow .bl{flex:0 0 46%;min-width:0;font-size:13px;font-weight:650;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.brow .bt{flex:1;min-width:0;height:8px;border-radius:5px;background:var(--surf);overflow:hidden}
.brow .bt i{display:block;height:100%;border-radius:5px;background:var(--ink);
  transition:width .5s var(--e)}
.brow .bv{flex:none;min-width:44px;text-align:right;font-size:12.5px;font-weight:750;
  color:var(--soft);font-variant-numeric:tabular-nums}

/* cartes les plus ratées : le nombre d'échecs porte l'information */
.wrow .wn{flex:none;min-width:26px;height:26px;padding:0 6px;border-radius:9px;
  background:rgba(196,86,107,.13);color:var(--ko);display:grid;place-items:center;
  font-style:normal;font-size:12.5px;font-weight:800;font-variant-numeric:tabular-nums}

.strip{display:flex;gap:3px;width:100%;height:9px;animation:rise .5s var(--e) .14s both}
.strip i{flex:1;min-width:3px;border-radius:3px;background:var(--ok);opacity:.85}
.strip i.n{background:var(--ko)}

.hist{display:flex;align-items:flex-end;gap:6px;width:100%;height:62px;
  padding-bottom:1px;border-bottom:1px solid var(--hair);
  animation:rise .5s var(--e) .18s both}
.hb{flex:1;max-width:46px;height:100%;display:flex;align-items:flex-end}
.hb i{width:100%;min-height:5px;border-radius:8px 8px 3px 3px;background:var(--surf2);
  transition:height .7s var(--e)}
.hb.now i{background:var(--ink)}

.miss{display:flex;flex-direction:column;gap:8px;width:100%}
.mr{background:var(--card);box-shadow:var(--s1);border-radius:17px;padding:12px 15px;
  display:flex;flex-direction:column;gap:5px;animation:pop .45s var(--e) both}
.mr .q{font-weight:750;letter-spacing:-.25px;font-size:15.5px}
.mr .w,.mr .g{display:flex;align-items:flex-start;gap:7px;font-size:14.5px;font-weight:600;line-height:1.42}
.mr .w{color:var(--soft);text-decoration:line-through;text-decoration-color:rgba(196,86,107,.5)}
.mr .g{color:var(--ok);font-weight:700}
.mr svg{width:14px;height:14px;stroke-width:2.6;flex:none;margin-top:4px}
.mr .w svg{color:var(--ko)}

/* ---------- quiz ---------- */
.qz{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:22px;padding:14px 0 18px;min-height:0}
.ask{font-weight:800;font-size:clamp(28px,8.2vw,48px);line-height:1.14;letter-spacing:-1.3px;
  text-align:center;transition:color .34s var(--e),transform .45s var(--sp)}
.fade .ask{animation:rise .42s var(--e) both}
.ask.good{color:var(--ok);transform:scale(1.05)}
.ask.bad{color:var(--ko)}
.sol{display:flex;align-items:center;gap:10px;padding:12px 20px;border-radius:18px;
  background:rgba(62,143,98,.11);color:var(--ok);font-weight:750;
  font-size:clamp(19px,5.2vw,27px);letter-spacing:-.5px;text-align:center}
.fade .sol{animation:pop .5s var(--sp) both}
.sol svg{width:20px;height:20px;stroke-width:2.6;flex:none}
.ans{width:100%;border-radius:20px;background:var(--card);box-shadow:var(--s1);
  padding:19px 22px;font-size:19px;font-weight:700;text-align:center;letter-spacing:-.3px;
  transition:background .32s var(--e),color .32s,box-shadow .3s}
.ans::placeholder{color:var(--soft);opacity:.45;font-weight:600}
.ans:focus{box-shadow:var(--s2)}
.ans.good{background:rgba(62,143,98,.14);color:var(--ok);box-shadow:none}
.ans.bad{background:rgba(196,86,107,.13);color:var(--ko);box-shadow:none;animation:shake .45s}
@keyframes shake{12%,88%{transform:translateX(-3px)}25%,75%{transform:translateX(6px)}
  38%,62%{transform:translateX(-9px)}50%{transform:translateX(9px)}}
.cta{height:56px;border-radius:19px;background:var(--ink);color:var(--bg);width:100%;
  display:flex;align-items:center;justify-content:center;gap:9px;font-weight:700;font-size:16px;
  box-shadow:var(--s2);transition:transform .3s var(--sp),opacity .25s;flex:none}
.cta:active{transform:scale(.965)}
.cta[disabled]{opacity:.25;box-shadow:none}
.cta svg{width:20px;height:20px;stroke-width:2.3}

/* ---------- création / import ---------- */
.sheet{flex:1;display:flex;flex-direction:column;gap:12px;min-height:0;padding-bottom:10px}
.field{background:var(--card);box-shadow:var(--s1);border-radius:20px;padding:15px 18px}
.field input{width:100%;font-weight:750;font-size:19px;letter-spacing:-.4px}
.field input::placeholder{color:var(--soft);opacity:.45;font-weight:600}
.ta{flex:none;background:var(--card);box-shadow:var(--s1);border-radius:20px;
  padding:16px 18px;display:flex;flex-direction:column}
.ta textarea{resize:none;line-height:1.6;font-weight:520;min-height:104px;overflow:auto;
  scrollbar-width:none}
.ta textarea::-webkit-scrollbar{display:none}
.ta textarea::placeholder{color:var(--soft);opacity:.42}
.prev{flex:1;min-height:0;display:flex;flex-direction:column;gap:6px;overflow:auto;
  scrollbar-width:none;margin-top:2px;padding-bottom:2px}
.prev::-webkit-scrollbar{display:none}
.pr{display:flex;align-items:center;gap:10px;background:var(--card);box-shadow:var(--s1);
  border-radius:14px;padding:9px 14px;font-size:14.5px}
.pr .a{font-weight:700;letter-spacing:-.2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pr svg{width:14px;height:14px;stroke-width:2.2;color:var(--soft);flex:none}
.pr .b{color:var(--soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1}
/* doublons repérés à l'import : grisés tant qu'on ne demande pas à les garder */
.pr.dup{opacity:.42}
.pr.dup .a{text-decoration:line-through;text-decoration-thickness:1.5px}
.pr .dpi{flex:none;display:grid;place-items:center;color:var(--soft);opacity:.75}
.pr .dpi svg{width:13px;height:13px}
.dupb{display:flex;align-items:center;gap:10px;padding:9px 12px 9px 14px;border-radius:14px;
  background:var(--surf);font-size:13px;font-weight:650;color:var(--ink2);letter-spacing:-.1px}
.dupb > span{flex:1;min-width:0}
.dupt{flex:none;padding:6px 11px;border-radius:10px;background:var(--card);box-shadow:var(--s1);
  font-size:12.5px;font-weight:750;color:var(--soft);letter-spacing:-.1px;transition:color .2s,background .2s}
.dupt.on{background:var(--ink);color:var(--bg);box-shadow:none}
.count{display:flex;align-items:center;gap:7px;align-self:center;padding:8px 15px;
  border-radius:12px;background:var(--surf);font-size:13.5px;font-weight:750;color:var(--soft);
  font-variant-numeric:tabular-nums;transition:background .3s var(--e),color .3s}
.count.on{background:var(--ink);color:var(--bg)}
.count svg{width:14px;height:14px;stroke-width:2.3}

/* ---------- composeur de cartes ---------- */
.comp{position:relative;border-radius:24px;padding:18px 20px 18px;background:var(--c);color:var(--ci);
  box-shadow:var(--s1);overflow:hidden;animation:pop .5s var(--e) both}
.comp::before{content:'';position:absolute;inset:0;border-radius:24px;pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.4),inset 0 1px 0 rgba(255,255,255,.6)}
.comp::after{content:'';position:absolute;inset:0;border-radius:24px;pointer-events:none;
  background:linear-gradient(155deg,rgba(255,255,255,.5),rgba(255,255,255,0) 58%)}
.comp input{position:relative;z-index:1;width:100%;padding:5px 58px 5px 0;color:inherit}
.comp .cf{font-weight:800;font-size:20px;letter-spacing:-.5px}
.comp .cb{font-weight:600;font-size:17px;letter-spacing:-.2px;opacity:.85}
.comp input::placeholder{color:currentColor;opacity:.4;font-weight:600}
.csep{position:relative;z-index:1;height:1px;background:currentColor;opacity:.16;margin:11px 0}
.cadd{position:absolute;z-index:2;right:14px;top:50%;transform:translateY(-50%);
  width:46px;height:46px;border-radius:16px;display:grid;place-items:center;
  background:var(--ink);color:var(--bg);box-shadow:var(--s1);
  transition:transform .3s var(--sp)}
.cadd:active{transform:translateY(-50%) scale(.86)}
.cadd svg{width:21px;height:21px;stroke-width:2.4}

.dlist{flex:1;min-height:0;overflow:auto;scrollbar-width:none;
  display:flex;flex-direction:column;gap:7px;padding-bottom:2px}
.dlist::-webkit-scrollbar{display:none}
.dc{display:flex;align-items:center;gap:8px;background:var(--card);box-shadow:var(--s1);
  border-radius:16px;padding:10px 8px 10px 15px;
  transition:box-shadow .25s,transform .25s var(--sp)}
.dc:active{transform:scale(.985)}
.dc.on{box-shadow:var(--s2),inset 0 0 0 2px var(--ink)}
.dc .tx{flex:1;min-width:0;display:flex;flex-direction:column}
.dc b{font-weight:750;font-size:15.5px;letter-spacing:-.25px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dc span{color:var(--soft);font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.dc .x{width:30px;height:30px;flex:none;display:grid;place-items:center;color:var(--soft);
  border-radius:10px;transition:transform .3s var(--sp),color .2s,background .2s}
.dc .x:active{transform:scale(.82);color:var(--ko);background:rgba(196,86,107,.1)}
.dc .x svg{width:15px;height:15px;stroke-width:2.4}

/* ---------- menu ---------- */
.scrim{position:fixed;inset:0;background:rgba(27,24,29,.3);z-index:40;
  backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px);animation:fadein .32s var(--e)}
/* La feuille elle-même ne défile plus jamais : elle a une hauteur
   plafonnée et c'est .mbody, en dessous de la poignée, qui prend le
   débordement. overscroll-behavior:contain empêche un swipe qui
   atteint le haut ou le bas de .mbody de continuer sur l'écran
   derrière — c'était exactement le défaut signalé. */
.menu{position:fixed;left:10px;right:10px;bottom:calc(10px + env(safe-area-inset-bottom));
  z-index:41;background:var(--card);border-radius:26px;box-shadow:var(--s3);
  max-height:min(78vh,calc(100svh - 96px));display:flex;flex-direction:column;
  overflow:hidden;animation:up .5s var(--e)}
@keyframes up{from{opacity:0;transform:translateY(60px)}}
.mtop{flex:none;position:relative;display:flex;align-items:center;justify-content:center;padding:11px 7px 5px}
.mgrip{width:34px;height:4px;border-radius:3px;background:var(--hair)}
.mx{position:absolute;right:8px;top:8px;width:30px;height:30px;border-radius:11px;
  display:grid;place-items:center;color:var(--soft);background:var(--surf);
  transition:background .2s,transform .2s var(--sp)}
.mx svg{width:15px;height:15px;stroke-width:2.4}
.mx:active{transform:scale(.88);background:var(--surf2)}
.mbody{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;padding:2px 7px 7px}
.mi{display:flex;align-items:center;gap:14px;width:100%;height:54px;padding:0 16px;
  border-radius:19px;font-weight:650;font-size:16px;letter-spacing:-.25px;
  transition:background .22s}
.mi:active{background:var(--surf)}
.mi svg{width:20px;height:20px;stroke-width:2;color:var(--soft)}
.mi.warn{color:var(--ko)} .mi.warn svg{color:var(--ko)}
.mi .tail{margin-left:auto;font-size:14px;font-weight:700;color:var(--soft)}
.msep{height:1px;background:var(--hair);margin:5px 16px}
/* liste de paquets dans une feuille : au-delà de six elle défile toute seule */
.mscroll{max-height:46vh;overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
.mscroll .tri{margin-right:-2px}
.tok{width:calc(100% - 14px);margin:2px 7px 4px;padding:15px 16px;border-radius:17px;
  background:var(--surf);font-size:15px;font-weight:600;letter-spacing:.2px}
.tok::placeholder{color:var(--soft);opacity:.5}
.mgrid{display:grid;grid-template-columns:1fr 1fr;gap:7px;padding:7px 7px 3px}
.ms{display:flex;align-items:center;gap:9px;min-width:0;height:46px;padding:0 14px;
  border-radius:16px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  background:var(--surf);font-size:14.5px;font-weight:700;transition:background .22s,color .22s}
.ms.on{background:var(--ink);color:var(--bg)}
.ms i{width:9px;height:9px;border-radius:50%;background:var(--d);flex:none}
/* un nom de matière trop long se coupe proprement au lieu de pousser la
   feuille entière vers la droite */
.ms span{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ---------- connexion ---------- */
.login{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:0;padding:0 6px 40px;animation:rise .55s var(--e) both}
.login .logo{width:78px;height:78px;border-radius:22px;box-shadow:var(--s2);
  animation:pop .7s var(--sp) both}
.login .lt{margin:16px 0 30px;font-weight:800;font-size:27px;letter-spacing:-.9px;
  animation:rise .55s var(--e) .08s both}
.lf{width:100%;display:flex;flex-direction:column;gap:10px;
  animation:rise .55s var(--e) .14s both}
.lrow{display:flex;align-items:center;gap:12px;background:var(--card);box-shadow:var(--s1);
  border-radius:19px;padding:0 8px 0 17px;height:58px;transition:box-shadow .3s}
.lrow:focus-within{box-shadow:var(--s2)}
.lrow > svg{width:19px;height:19px;color:var(--soft);flex:none}
.lrow input{flex:1;min-width:0;height:100%;font-size:16.5px;font-weight:600;letter-spacing:-.2px}
.lrow input::placeholder{color:var(--soft);opacity:.55;font-weight:500}
.peek{width:42px;height:42px;flex:none;border-radius:14px;display:grid;place-items:center;
  color:var(--soft);transition:transform .3s var(--sp),background .2s}
.peek:active{transform:scale(.86);background:var(--surf)}
.peek svg{width:19px;height:19px}
.lerr{min-height:19px;text-align:center;font-size:13.5px;font-weight:650;color:var(--ko);
  padding:0 4px}
.lf .cta{margin-top:2px}

/* ---------- réglages ---------- */
.slist{display:flex;flex-direction:column;gap:8px;margin-bottom:22px}
.sr{display:flex;align-items:center;gap:12px;background:var(--card);box-shadow:var(--s1);
  border-radius:18px;padding:15px 15px;text-align:left;
  transition:transform .3s var(--sp),box-shadow .3s}
.fade .sr{animation:pop .45s var(--e) both}
.sr:active{transform:scale(.98)}
.sr > i{width:16px;height:16px;border-radius:50%;flex:none;background:var(--d);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.08)}
.sr .n{flex:1;min-width:0;font-weight:700;font-size:16px;letter-spacing:-.25px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sr .c{font-size:13.5px;font-weight:750;color:var(--soft);font-variant-numeric:tabular-nums;
  white-space:nowrap;flex:none}
.sr > svg{width:17px;height:17px;color:var(--soft);opacity:.5;flex:none}
.sr.add{color:var(--soft)}
.sr.add > svg:first-child{width:19px;height:19px;opacity:1;color:var(--ink)}
.sr.flat{box-shadow:var(--s1)}
.sr.flat > svg:first-child{width:19px;height:19px;color:var(--soft);opacity:1}
.sr.warn .n{color:var(--ko)}
.sr.warn > svg:first-child{color:var(--ko)}
.foot{text-align:center;font-size:12.5px;font-weight:700;color:var(--soft);opacity:.7;
  padding:4px 0 100px;letter-spacing:.2px}
.off-dot{width:8px;height:8px;border-radius:50%;background:var(--ko);flex:none;
  align-self:center;margin-right:2px}

/* champ de recherche : dans la barre du haut, ou sous l'intitulé Cartes */
.fld{flex:1;min-width:0;display:flex;align-items:center;background:var(--surf);
  border-radius:14px;padding:0 14px;height:40px}
.fld input{flex:1;min-width:0;height:100%;background:none;font-size:15px;font-weight:600;
  letter-spacing:-.15px;color:var(--ink)}
.fld input::placeholder{color:var(--soft);opacity:.7}
.fld input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none}
.deckfld{margin:0 1px 10px}
mark{background:rgba(201,165,38,.28);color:inherit;border-radius:4px;padding:0 2px}

/* aperçu du réglage de taille, juste sous le curseur */
.fprev{padding:2px 2px 0;font-weight:750;letter-spacing:-.3px;color:var(--soft)}

/* ---------- mode sans distraction ----------
   Tout ce qui n'est pas la carte s'efface : il reste le geste et le mot.
   Rien n'est démonté, seulement rendu invisible et inatteignable — on en
   sort par le même bouton, qui lui reste. */
.study.zen .prog,.study.zen #foot{opacity:0;pointer-events:none;transition:opacity .3s}
.study.zen{gap:0}
#app[data-view="study"] .study.zen ~ *{opacity:0}
.study.zen .stage{flex:1}

/* ---------- boîte de réception ----------
   Le badge est un simple élément de flux par défaut (il se pose à la fin
   d'une ligne du rail, poussé par margin-left:auto) ; seul .icmail, la
   petite icône ronde de l'accueil, le sort du flux pour le poser dessus. */
.icb{min-width:16px;height:16px;padding:0 4px;border-radius:8px;background:var(--ko);
  color:#fff;display:grid;place-items:center;font-size:10px;font-weight:800;
  line-height:1;font-variant-numeric:tabular-nums;flex:none}
.icmail{position:relative}
.icmail .icb{position:absolute;top:-2px;right:-2px;box-shadow:0 0 0 2px var(--bg)}
#rail nav button .icb{margin-left:auto;box-shadow:0 0 0 2px var(--card)}
#rail nav button.on .icb{box-shadow:0 0 0 2px var(--ink)}

.mlrow{align-items:center}
.ml2{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.ml2 .n{font-size:15px}
.mlrow.unread .n{font-weight:800}
/* la deuxième ligne porte le mot de l'expéditeur : c'est ce qu'on venait
   lire, il ne peut pas rester invisible dans la liste */
.sub{font-size:12.5px;font-weight:600;color:var(--soft);letter-spacing:-.1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mlrow.unread .sub{color:var(--ink2)}
.mlrow .mdot{width:9px;height:9px;border-radius:50%;background:var(--ko);flex:none}
.mlrow:not(.unread) > svg:first-child{opacity:.45}

/* en-tête d'un message ouvert : le paquet est le sujet, l'expéditeur, le
   nombre de cartes et la date passent derrière, sur une seule ligne */
.mhd{display:flex;align-items:flex-start;gap:13px;padding:8px 16px 11px}
.mhd > svg{width:20px;height:20px;color:var(--soft);flex:none;margin-top:3px}
.mhx{display:flex;flex-direction:column;gap:3px;min-width:0}
.mhx b{font-weight:780;font-size:17px;letter-spacing:-.3px;overflow-wrap:anywhere}
.mhx i{font-style:normal;font-size:12.5px;font-weight:640;color:var(--soft);
  letter-spacing:-.05px;overflow-wrap:anywhere}

/* le mot de l'expéditeur : le seul endroit où quelqu'un s'adresse à vous.
   Sur fond plein et en encre pleine, il ne se confond plus avec les
   informations grises du paquet juste au-dessus. */
.mmsg{display:flex;gap:11px;margin:0 7px 9px;padding:13px 15px;border-radius:16px;
  background:var(--surf);color:var(--ink)}
.mmsg > svg{width:16px;height:16px;flex:none;margin-top:2px;opacity:.45}
.mmsg p{margin:0;min-width:0;font-size:14.5px;line-height:1.5;font-weight:620;
  letter-spacing:-.1px;overflow-wrap:anywhere}

/* destinataire choisi : une coche grise seule ne se remarquait pas */
.mi.on{background:var(--surf)}
.mi.on > svg:last-child{color:var(--ink);opacity:1}

/* le champ du mot à joindre : sur fond plein, cerné, il se lit comme
   quelque chose où l'on écrit — pas comme un bloc d'aide de plus */
.msgin{min-height:88px;line-height:1.5;font-weight:600;background:var(--card);
  box-shadow:inset 0 0 0 1.5px var(--surf2)}
.msgin::placeholder{color:var(--soft);opacity:.72}

.swatch{display:grid;grid-template-columns:repeat(8,1fr);gap:7px;padding:4px 7px 8px}
.sw2{aspect-ratio:1;border-radius:13px;position:relative;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);transition:transform .3s var(--sp)}
.sw2:active{transform:scale(.86)}
.sw2.on{box-shadow:inset 0 0 0 2px var(--ink),0 0 0 3px var(--bg),0 0 0 5px var(--ink)}
.sw2::after{content:'';position:absolute;left:50%;top:50%;width:7px;height:7px;margin:-3.5px;
  border-radius:50%;background:var(--dd)}

/* ---------- toast ---------- */
.toast{position:fixed;left:50%;bottom:calc(22px + env(safe-area-inset-bottom));
  width:max-content;max-width:min(86vw,420px);
  transform:translateX(-50%);background:var(--ink);color:var(--bg);
  display:flex;align-items:center;gap:9px;padding:12px 18px;border-radius:16px;
  font-weight:700;font-size:15px;z-index:60;box-shadow:var(--s3);
  font-variant-numeric:tabular-nums;animation:tin .45s var(--sp)}
.toast svg{width:17px;height:17px;stroke-width:2.4}
/* « Annuler » posé dans le toast : la dernière action reste rattrapable
   quelques secondes sans quitter l'écran où on l'a faite */
.tun{display:flex;align-items:center;gap:6px;margin-left:4px;padding:5px 11px 5px 8px;
  border-radius:11px;background:rgba(255,255,255,.14);color:var(--bg);
  font-weight:780;font-size:14px;letter-spacing:-.2px}
.tun:active{background:rgba(255,255,255,.26)}
.tun svg{width:15px;height:15px}
@keyframes tin{from{opacity:0;transform:translate(-50%,16px) scale(.88)}}
@media (prefers-reduced-motion:reduce){*{animation-duration:.01ms !important;transition-duration:.1s !important}}

/* ══════════════════════════════════════════════════════════════
   Desktop — rail latéral, contenu cadré, mises en page à deux colonnes
   ══════════════════════════════════════════════════════════════ */
#rail{display:none}
.fab > span,.hint .keys{display:none}

@media (min-width:900px){
  :root{--rail:248px;--gut:44px;--wide:1180px}

  /* les feuilles restent lisibles au lieu de s'étirer sur toute la largeur */
  .menu{left:var(--rail);right:0;max-width:620px;margin:0 auto}
  .menu.pv{max-height:min(72vh,760px)}

  /* ---------- rail ---------- */
  .tabs{display:none}
  #rail{
    position:fixed;left:0;top:0;bottom:0;width:var(--rail);z-index:30;
    display:flex;flex-direction:column;gap:4px;padding:22px 14px 16px;
    background:var(--bg2);border-right:1px solid var(--hair);
    animation:rise .5s var(--e) both}
  #rail .brand{display:flex;align-items:center;gap:11px;padding:0 10px 20px}
  #rail .brand img{width:32px;height:32px;border-radius:10px;box-shadow:var(--s1)}
  #rail .brand span{font-weight:800;font-size:17px;letter-spacing:-.4px}
  #rail nav{display:flex;flex-direction:column;gap:3px}
  #rail nav button{display:flex;align-items:center;gap:12px;width:100%;height:44px;
    padding:0 12px;border-radius:13px;font-weight:650;font-size:15px;letter-spacing:-.2px;
    color:var(--ink2);transition:background .2s var(--e),color .2s var(--e)}
  #rail nav button svg{width:19px;height:19px;flex:none;color:var(--soft);transition:color .2s}
  #rail nav button:hover{background:var(--surf)}
  #rail nav button.on{background:var(--ink);color:var(--bg)}
  #rail nav button.on svg{color:var(--bg)}
  #rail .sp{flex:1}
  #rail .who{display:flex;align-items:center;gap:10px;padding:12px 12px 4px;margin-top:6px;
    border-top:1px solid var(--hair);font-size:12.5px;font-weight:650;color:var(--soft)}
  #rail .who svg{width:16px;height:16px;flex:none}
  #rail .who span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

  /* ---------- cadre général ---------- */
  #app{padding:26px var(--gut) 56px calc(var(--rail) + var(--gut));min-height:100vh}
  #app > *{width:100%;max-width:var(--wide);margin-inline:auto}
  #app > .fab,#app > .tabs{width:auto;max-width:none;margin:0}
  .top [data-act="settings"],.top [data-act="mail"]{display:none}   /* le rail porte déjà Réglages et la Boîte */
  .hero{font-size:44px;letter-spacing:-2px;margin:6px 1px 24px}
  .top{margin:6px 1px 24px}
  .bar{min-height:52px;margin-bottom:6px}
  .bar h1{font-size:21px}

  /* ---------- accueil ---------- */
  #page{padding-bottom:40px}   /* pas de barre d'onglets fixe à dégager ici */
  .grid{grid-template-columns:repeat(auto-fill,minmax(216px,1fr));gap:16px}
  .tile{min-height:150px;border-radius:26px;padding:19px 18px 16px}
  .tile .n{font-size:17.5px}
  .fab{right:var(--gut);bottom:34px;width:auto;height:54px;border-radius:18px;
    padding:0 22px 0 18px;display:flex;align-items:center;gap:10px}
  .fab > span{display:inline;font-weight:700;font-size:15px;letter-spacing:-.2px}
  .fab:active{transform:scale(.96)}
  .pills{margin:0 0 22px;padding:2px 0 6px}

  /* ---------- fiche paquet : panneau figé + liste ---------- */
  #app[data-view="deck"]{display:grid;justify-content:center;column-gap:26px;
    grid-template-columns:minmax(0,352px) minmax(0,760px);
    grid-template-rows:auto auto auto 1fr;align-content:start;max-width:none}
  #app[data-view="deck"] > *{max-width:none;margin:0}
  #app[data-view="deck"] .bar{grid-column:1/-1}
  #app[data-view="deck"] .head{grid-column:1;grid-row:2;margin-bottom:12px}
  #app[data-view="deck"] .head .t{font-size:30px}
  #app[data-view="deck"] .duo{grid-column:1;grid-row:3;position:sticky;top:26px}
  #app[data-view="deck"] .lbl{grid-column:2;grid-row:2;margin-top:10px}
  #app[data-view="deck"] .rows{grid-column:2;grid-row:3/-1}
  .row{padding:13px 10px 13px 17px;border-radius:19px}

  /* ---------- révision ---------- */
  #app > .study{max-width:720px;margin-inline:auto}
  .stack{height:min(62vh,500px)}
  .face{border-radius:34px}
  .acts{gap:14px}
  .act{height:66px}
  .hint .keys{display:flex;align-items:center;gap:7px;color:var(--soft)}
  .hint svg:first-child{display:none}
  .hint .keys svg{width:16px;height:16px;stroke-width:2.6;margin-right:8px}
  .hint .keys svg:nth-of-type(1){color:var(--ok)}
  .hint .keys svg:nth-of-type(2){color:var(--ko)}
  .hint .keys svg:nth-of-type(3){color:var(--soft);opacity:.7}
  .hint .keys kbd{font:inherit;font-size:11.5px;font-weight:750;letter-spacing:.3px;
    padding:5px 9px;border-radius:8px;background:var(--surf);
    box-shadow:inset 0 0 0 1px var(--hair);color:var(--ink2)}

  /* ---------- quiz ---------- */
  .qz{max-width:720px;margin-inline:auto}
  /* question, champ et bouton forment un bloc, au lieu de s'écarter en hauteur */
  #app[data-view="run"] .qz{flex:none;margin-top:clamp(28px,11vh,110px);padding:0 0 24px}
  #app[data-view="run"] .study > .ans,
  #app[data-view="run"] .study > .cta,
  #app[data-view="run"] .study > .duo{max-width:720px;margin-inline:auto;width:100%}

  /* ---------- bilan : chiffres à gauche, ratés à droite ---------- */
  .rev{display:grid;justify-content:center;column-gap:34px;align-content:start;
    grid-template-columns:minmax(0,380px) minmax(0,600px);
    grid-template-rows:auto auto auto auto auto 1fr;gap:16px 34px;max-width:none}
  .rev > *{grid-column:1}
  .rev .ring{grid-row:1;justify-self:center}
  .rev .lbl.lm{grid-column:2;grid-row:1;align-self:start;margin:4px 2px 0}
  .rev .miss{grid-column:2;grid-row:2/-1;align-self:start}
  .rev .b{margin-top:4px}

  /* ---------- création : composeur figé + liste ---------- */
  .sheet.sh-comp{display:grid;column-gap:28px;justify-content:center;align-content:start;
    grid-template-columns:minmax(0,440px) minmax(0,640px);
    grid-template-rows:auto auto auto auto 1fr;gap:12px 28px}
  .sheet.sh-comp > *{grid-column:1}
  .sheet.sh-comp .lbl{grid-column:2;grid-row:1;margin-top:10px}
  .sheet.sh-comp .dlist{grid-column:2;grid-row:2/-1;max-height:none}
  .sheet.sh-bulk{max-width:760px;margin-inline:auto}
  .comp{border-radius:26px;padding:22px 24px}
  .comp .cf{font-size:22px}
  .dc{padding:12px 10px 12px 17px}

  /* ---------- réglages ---------- */
  #app[data-view="settings"] .page,
  #app[data-view="settings"] .bar{max-width:720px;margin-inline:auto}

  /* ---------- connexion ---------- */
  .login{max-width:380px;margin-inline:auto}
  .login .logo{width:86px;height:86px;border-radius:24px}
  .login .lt{font-size:30px;margin:18px 0 34px}

  /* ---------- survol ---------- */
  @media (hover:hover){
    .tile:hover{transform:translateY(-3px);box-shadow:var(--s2)}
    .tile:active{transform:translateY(-1px) scale(.99)}
    .row:hover,.dc:hover,.sr:hover{box-shadow:var(--s2)}
    .sr:hover{transform:translateY(-1px)}
    .p:hover:not(.on),.ic:hover{background:var(--surf2)}
    .duo button:hover,.act:hover,.rev .b button:hover{transform:translateY(-2px);box-shadow:var(--s2)}
    .cta:hover:not([disabled]),.fab:hover{transform:translateY(-2px);box-shadow:var(--s3)}
    .mi:hover,.ms:hover:not(.on){background:var(--surf)}
    .x:hover,.peek:hover{background:var(--surf2)}
    .sw2:hover{transform:scale(1.08)}
  }
  :focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:8px}
}

@media (min-width:1500px){
  :root{--wide:1280px}
  .grid{grid-template-columns:repeat(auto-fill,minmax(228px,1fr))}
}

/* ══════════ moteur d'apprentissage ══════════ */
/* état d'une carte : nouvelle · apprentissage · jeune · mûre · suspendue */
.cst{width:7px;height:7px;border-radius:50%;flex:none;align-self:center;margin-right:-2px}
.cst.new{background:#4A7FBE} .cst.learn{background:#D4842E}
.cst.young{background:#4C9862} .cst.mature{background:#2A2730;opacity:.5}
.cst.susp{background:var(--soft);opacity:.4}
.row.off{opacity:.45}
.x.sus{color:var(--soft)}
.x.sus.on{color:var(--ink)}

.mixwrap{margin:0 2px 16px;display:flex;flex-direction:column;gap:8px}
.mix{display:flex;gap:2px;height:7px;border-radius:4px;overflow:hidden}
.mix i{display:block}
.mix i.new{background:#4A7FBE} .mix i.learn{background:#D4842E}
.mix i.young{background:#4C9862} .mix i.mature{background:var(--ink)}
.mix i.susp{background:var(--surf2)}
.mixk{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;font-weight:650;color:var(--soft)}
.mixk span{display:flex;align-items:center;gap:6px}
.mixk i{width:7px;height:7px;border-radius:50%}
.mixk i.new{background:#4A7FBE} .mixk i.learn{background:#D4842E}
.mixk i.young{background:#4C9862} .mixk i.mature{background:var(--ink)}
.mixk .lee{color:var(--ko)}
.mixk .lee svg{width:12px;height:12px;stroke-width:2.4}

/* quatre boutons de notation */
.grades{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;padding:2px 0;flex:none}
.gr{height:62px;border-radius:18px;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:3px;background:var(--card);box-shadow:var(--s1);
  transition:transform .24s var(--sp),box-shadow .24s}
.gr:active{transform:scale(.94)}
.gr span{font-weight:750;font-size:13.5px;letter-spacing:-.2px}
.gr i{font-style:normal;font-size:11px;font-weight:700;color:var(--soft);
  font-variant-numeric:tabular-nums}
.gr.g0{color:var(--ko)} .gr.g1{color:#C9803A}
.gr.g2{color:var(--ok)} .gr.g3{color:#3E8FA8}

/* échéance sur une tuile, anneau d'objectif, reprise, marathon */
/* Le signet : il dépasse du haut de la couverture et porte le nombre de
   fiches à lire aujourd'hui. Sa pointe est découpée en V, comme un vrai. */
.tile .due{position:absolute;top:-1px;right:16px;width:26px;padding:7px 0 11px;
  background:var(--ci);color:var(--c);display:grid;place-items:center;
  clip-path:polygon(0 0,100% 0,100% 100%,50% 74%,0 100%);
  font-size:12px;font-weight:800;font-variant-numeric:tabular-nums;font-style:normal;z-index:3;
  box-shadow:-1px 0 0 rgba(0,0,0,.08)}
.goal{position:relative;width:44px;height:44px;flex:none;margin-bottom:2px}
.goal svg{position:absolute;inset:0;width:44px;height:44px;transform:rotate(-90deg)}
.goal circle{fill:none;stroke-width:4;stroke-linecap:round}
.goal .b{stroke:var(--surf2)} .goal .f{stroke:var(--ok);transition:stroke-dashoffset .8s var(--e)}
.goal b{position:absolute;inset:0;display:grid;place-items:center;font-size:13px;font-weight:800;
  font-variant-numeric:tabular-nums}
.resume,.marathon{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;
  border-radius:19px;background:var(--card);box-shadow:var(--s1);margin-bottom:14px;text-align:left;
  transition:transform .26s var(--sp),box-shadow .26s}
.fade .resume,.fade .marathon{animation:pop .5s var(--e) both}
/* Il se retrouvait souvent juste au-dessus du bouton rond, du même noir :
   deux taches identiques qu'on confond. Reliure fauve, encre claire. */
.marathon{margin:6px 0 20px;background:var(--leather);color:#FDF6EC;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.1),var(--s1)}
.resume:active,.marathon:active{transform:scale(.98)}
.resume svg,.marathon svg{width:19px;height:19px;flex:none}
.resume span,.marathon span{font-weight:750;font-size:15px;letter-spacing:-.25px}
.resume i,.marathon i{font-style:normal;font-size:13px;color:var(--soft);margin-left:auto;
  font-variant-numeric:tabular-nums}
.marathon i{color:#FDF6EC;opacity:.62}

/* ══════════ réglages ══════════ */
.sr.col{flex-direction:column;align-items:stretch;gap:11px;cursor:default}
.srh{display:flex;align-items:center;gap:12px}
.srh svg{width:19px;height:19px;color:var(--soft);flex:none}
.srh .n{flex:1;font-weight:700;font-size:15.5px;letter-spacing:-.25px}
.srh .c{font-size:13px;font-weight:750;color:var(--soft);font-variant-numeric:tabular-nums}
.rng{-webkit-appearance:none;appearance:none;width:100%;height:5px;border-radius:5px;
  background:var(--surf2);outline:none}
.rng::-webkit-slider-thumb{-webkit-appearance:none;width:22px;height:22px;border-radius:50%;
  background:var(--ink);box-shadow:var(--s1);cursor:pointer}
.rng::-moz-range-thumb{width:22px;height:22px;border:0;border-radius:50%;background:var(--ink)}
.seg{display:flex;gap:5px;flex-wrap:wrap}
.seg button{flex:1;min-width:88px;height:38px;border-radius:13px;background:var(--surf);
  font-size:13px;font-weight:700;color:var(--ink2);transition:background .2s,color .2s}
.seg button.on{background:var(--ink);color:var(--bg)}
.tgl{width:42px;height:25px;border-radius:13px;background:var(--surf2);flex:none;position:relative;
  transition:background .26s var(--e)}
.tgl::after{content:'';position:absolute;top:3px;left:3px;width:19px;height:19px;border-radius:50%;
  background:var(--card);box-shadow:var(--s1);transition:transform .3s var(--sp)}
.tgl.on{background:var(--ok)}
.tgl.on::after{transform:translateX(17px)}
.mrr{min-height:17px;text-align:center;font-size:13px;font-weight:650;color:var(--ko);padding:0 16px}

/* ══════════ connexion ══════════ */
.lseg{width:100%;margin-bottom:16px}
.lseg button{height:40px}
.lnk{display:inline-flex;align-items:center;justify-content:center;gap:7px;
  margin-top:12px;align-self:center;font-size:13.5px;font-weight:650;color:var(--soft);
  padding:8px 12px;border-radius:10px;transition:background .2s,color .2s}
.lnk:hover{background:var(--surf);color:var(--ink)}
.lnk svg{width:15px;height:15px;flex:none}

@media (min-width:900px){
  .grades{gap:10px}
  .gr{height:68px}
  #app > .study .grades{max-width:720px;margin-inline:auto;width:100%}
}

/* ---------- feuille de prévention (mode simple) ---------- */
.menu.pv{max-height:min(78vh,720px);display:flex;flex-direction:column}
.menu.pv > .mi:last-child{border-top:1px solid var(--hair);border-radius:0 0 19px 19px;
  flex:none;margin-top:4px}
.pvb{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:2px 18px 10px;
  -webkit-overflow-scrolling:touch}
.pvb::-webkit-scrollbar{display:none}
.pvh{margin:14px 0 7px;font-size:12px;font-weight:800;letter-spacing:.9px;
  text-transform:uppercase;color:var(--soft)}
.pvh:first-child{margin-top:4px}
.pvl{display:flex;flex-direction:column;gap:9px;list-style:none}
.pvl li{position:relative;padding-left:15px;font-size:13.5px;line-height:1.5;
  font-weight:520;color:var(--ink);opacity:.9}
.pvl li::before{content:"";position:absolute;left:0;top:8px;width:5px;height:5px;
  border-radius:50%;background:var(--soft);opacity:.55}
.pvl b{font-weight:800}
.note{padding:2px 4px 4px;font-size:13px;line-height:1.5;font-weight:520;
  color:var(--soft);letter-spacing:-.05px}

/* ---------- corbeille ---------- */
.trr{gap:12px}
.tri{width:9px;height:9px;flex:none;border-radius:50%;background:var(--c)}
.trf{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.trd{flex:1;min-width:96px;font-size:12.5px;font-weight:650;color:var(--soft)}
.trd.soon{color:var(--ko)}
.trb{display:flex;align-items:center;gap:6px;padding:8px 13px;border-radius:12px;
  background:var(--surf);color:var(--ink);font-weight:730;font-size:13.5px;
  letter-spacing:-.2px;transition:transform .16s,background .16s}
.trb svg{width:15px;height:15px;stroke-width:2.2}
.trb:active{transform:scale(.95)}
.trb.warn{color:var(--ko)}
.trb.warn.on{background:rgba(196,86,107,.14)}

/* ---------- génération de cartes ---------- */
.airow{display:flex;gap:7px;align-items:stretch}
.airow .cta{width:auto;flex:1;min-width:0}
.ai{width:52px;height:56px;flex:none;border-radius:19px;background:var(--card);
  box-shadow:var(--s1);display:grid;place-items:center;transition:transform .2s,opacity .2s}
.ai svg{width:22px;height:22px;stroke-width:2;color:var(--ink)}
.ai:active{transform:scale(.94)}
.ai[disabled]{opacity:.3;box-shadow:none}
.ai.busy svg{animation:spin 1.1s linear infinite;color:var(--soft)}
@keyframes spin{to{transform:rotate(360deg)}}

/* ══════════ contenu enrichi ══════════ */
.face{align-content:center;gap:14px}
.fim{position:relative;z-index:1;max-width:100%;max-height:48%;border-radius:16px;
  object-fit:contain;box-shadow:0 5px 20px rgba(0,0,0,.16)}
.face .tx b{font-weight:900}
.face .tx u{text-underline-offset:3px}
.face .tx ul{text-align:left;margin:0;padding-left:1.05em;font-size:.66em;line-height:1.45}
.face .tx li{list-style:disc}
.face .tx br + br{display:none}

/* formules : on garde la police de l'app, on ne construit que les structures */
.mth{white-space:nowrap}
.mth sup,.mth sub{font-size:.6em;line-height:0}
.fr{display:inline-flex;flex-direction:column;vertical-align:middle;text-align:center;margin:0 .16em}
.fr i{font-style:normal;padding:0 .26em;font-size:.84em;line-height:1.16}
.fr i:first-child{border-bottom:.055em solid currentColor}
.rt{display:inline-flex;align-items:flex-start;margin:0 .08em}
.rt i{font-style:normal}
.rt .rb{border-top:.055em solid currentColor;padding:.06em .12em 0}
.rt .ri{font-size:.55em;margin:-.05em -.32em 0 0}
.mth .tx{font-weight:inherit}

/* ══════════ son sur la carte ══════════ */
/* Les commandes de son vivent dans le flux de la face, sous le texte et
   l'image : tout se centre alors d'un bloc, qu'il y ait les trois, deux,
   ou seulement le son. Collées dans un coin, elles laissaient une fiche
   sans texte ni image paraître vide. */
.fbody{position:relative;z-index:1;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:13px;
  width:100%;max-width:100%;max-height:100%;min-height:0}
.snds{display:flex;gap:10px;flex:none}
.snd{width:44px;height:44px;flex:none;
  border-radius:15px;display:grid;place-items:center;color:inherit;
  background:rgba(255,255,255,.22);box-shadow:inset 0 0 0 1px rgba(255,255,255,.32);
  transition:transform .2s var(--sp)}
/* Quand le son est tout ce que porte la fiche, il en est le sujet : il
   prend la place qui va avec, au lieu d'un bouton perdu au milieu du vide. */
.snds.seul .snd{width:84px;height:84px;border-radius:29px}
.snds.seul .snd svg{width:36px;height:36px;stroke-width:1.9}
.snd:active{transform:scale(.9)}
.snd svg{width:20px;height:20px;stroke-width:2}
.face.bk .snd{background:rgba(255,255,255,.12);box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
.snd.sm{position:static;display:inline-grid;width:34px;height:34px;border-radius:12px;
  margin-left:9px;background:var(--surf);box-shadow:none;vertical-align:middle;color:var(--soft)}
.snd.sm svg{width:17px;height:17px}

/* ══════════ étiquettes de carte ══════════ */
.ctags{position:absolute;left:16px;top:16px;z-index:2;display:flex;gap:5px;
  flex-wrap:wrap;max-width:62%;pointer-events:none}
.ctags i{font-style:normal;font-size:11px;font-weight:750;letter-spacing:.3px;
  padding:4px 9px;border-radius:9px;color:var(--ci);
  background:rgba(255,255,255,.28);box-shadow:inset 0 0 0 1px rgba(255,255,255,.3)}

/* ══════════ repère de matière (marathon) ══════════
   En marathon les cartes viennent de partout : un petit rectangle en bas
   à gauche dit d'où vient celle qu'on a sous les yeux. Il se pose sur la
   carte, hors du retourneur, donc il ne bascule pas avec elle et reste
   lisible des deux côtés. Volontairement discret : la couleur de la
   matière est déjà portée par la carte entière. */
.sbj{position:absolute;left:16px;bottom:16px;z-index:2;pointer-events:none;
  display:flex;align-items:center;gap:6px;padding:5px 10px 5px 8px;border-radius:9px;
  font-size:11.5px;font-weight:750;letter-spacing:.2px;color:var(--ci);
  background:rgba(255,255,255,.22);box-shadow:inset 0 0 0 1px rgba(255,255,255,.28)}
.sbj i{width:7px;height:7px;border-radius:2.5px;background:var(--ci);opacity:.75}

/* ══════════ vrai / faux ══════════ */
.card.tf .face .tx{font-size:clamp(20px,5.2vw,31px);font-weight:750;letter-spacing:-.5px}
.tfb{display:flex;gap:10px;margin-top:4px}
.tv{flex:1;height:62px;border-radius:20px;display:flex;align-items:center;justify-content:center;
  gap:9px;font-weight:800;font-size:17px;letter-spacing:-.3px;
  background:var(--card);box-shadow:var(--s1);transition:transform .2s var(--sp)}
.tv:active{transform:scale(.96)}
.tv svg{width:20px;height:20px;stroke-width:2.4}
.tv.y{color:var(--ok)}
.tv.n{color:var(--ko)}
.tfv{height:62px;display:flex;align-items:center;justify-content:center;gap:12px}
.tfv > svg{width:34px;height:34px;stroke-width:2.6;flex:none}
.tfv .cta{flex:1;height:62px;margin:0;color:var(--bg)}
.tfv.y{color:var(--ok)}
.tfv.n{color:var(--ko)}

/* ══════════ QCM ══════════ */
.qcard{position:relative;margin:10px 0 14px;padding:26px 22px;min-height:132px;
  border-radius:26px;background:var(--c);color:var(--ci);box-shadow:var(--s2);
  display:grid;place-items:center;align-content:center;gap:12px;text-align:center}
.fade .qcard{animation:pop .45s var(--e) both}
.qcard span{font-family:var(--serif);font-weight:700;font-size:clamp(20px,5.4vw,30px);
  line-height:1.24;letter-spacing:-.2px}
.qcard .snds{position:absolute;right:11px;bottom:11px;gap:7px}
.qcard .snd{width:36px;height:36px;border-radius:12px}
.qcard .snd svg{width:17px;height:17px}
.study.mcq > .prog{margin-bottom:auto}
.study.mcq > div:last-child{margin-bottom:auto}
.opts{display:flex;flex-direction:column;gap:9px}
.qopts{margin-top:11px}
.op{min-height:56px;padding:14px 16px;border-radius:18px;background:var(--card);
  box-shadow:var(--s1);font-weight:700;font-size:15.5px;letter-spacing:-.2px;text-align:left;
  transition:transform .2s var(--sp),background .25s,color .25s,opacity .25s}
.op:active{transform:scale(.98)}
.op.ok{background:var(--ok);color:#fff;box-shadow:none}
.op.ko{background:var(--ko);color:#fff;box-shadow:none}
.op.dim{opacity:.38;box-shadow:none}

/* ══════════ association ══════════ */
.mwrap{flex:1;min-height:0;overflow:auto;scrollbar-width:none;padding:8px 0 18px}
.mwrap::-webkit-scrollbar{display:none}
/* une seule grille : les douze étiquettes d'un lot sont mélangées entre
   elles, il n'y a plus de colonne « recto » et de colonne « verso ». */
.match{display:grid;grid-template-columns:1fr 1fr;gap:9px;align-items:stretch}
.mc{min-height:64px;padding:12px 13px;border-radius:17px;background:var(--card);
  box-shadow:var(--s1);font-weight:700;font-size:14.5px;line-height:1.25;letter-spacing:-.2px;
  transition:transform .2s var(--sp),background .25s,color .25s,opacity .3s}
.mc:active{transform:scale(.97)}
.mc.on{background:var(--d);color:#fff;box-shadow:var(--s2)}
.mc.done{background:var(--c);color:var(--ci);opacity:.4;box-shadow:none;pointer-events:none}
.shk{animation:shk .38s}
@keyframes shk{25%{transform:translateX(-7px)}55%{transform:translateX(6px)}80%{transform:translateX(-3px)}}

/* ══════════ feuilles : lignes de réglage ══════════ */
.mrow{display:flex;align-items:center;gap:9px;padding:7px 12px}
.mrow.col{flex-direction:column;align-items:stretch;gap:9px}
/* chercher et remplacer : le « Aa » se glisse dans le champ de recherche */
.frow{display:flex;align-items:center;gap:7px}
.frow .tok{flex:1;min-width:0}
.cs{width:44px;height:44px;flex:none;border-radius:14px;background:var(--surf);
  color:var(--soft);font-weight:800;font-size:14px;letter-spacing:-.3px;
  transition:background .22s,color .22s}
.cs.on{background:var(--ink);color:var(--bg)}
.mi[disabled]{opacity:.3;pointer-events:none}
.menu .note{padding:0 18px 10px}
.menu .note b{font-weight:800;color:var(--ink)}
.ml .tail{margin-left:auto;font-weight:800;color:var(--ink);font-variant-numeric:tabular-nums}
.ml{display:flex;align-items:center;gap:9px;flex:1;font-size:14px;font-weight:700;color:var(--soft)}
.ml svg{width:17px;height:17px;flex:none}
.mb{width:52px;height:52px;flex:none;border-radius:17px;background:var(--surf);
  display:grid;place-items:center;position:relative;overflow:hidden;transition:transform .2s var(--sp)}
.mb:active{transform:scale(.93)}
.mb svg{width:20px;height:20px;color:var(--soft)}
.mb.on{box-shadow:inset 0 0 0 2px var(--ink)}
.mb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.rmv{position:absolute;right:3px;top:3px;width:18px;height:18px;border-radius:50%;
  background:var(--ink);display:grid;place-items:center}
.rmv svg{width:11px;height:11px;color:var(--bg);stroke-width:3}
.mseg{margin:2px 12px 6px}
.mseg.wrap button{min-width:78px;flex:0 1 auto}

/* ══════════ quiz : chrono, indice, dictée, série ══════════ */
.tbar{height:3px;border-radius:3px;overflow:hidden;margin:5px 1px 0;flex:none}
.tbar i{display:block;height:100%;border-radius:3px;background:var(--soft);opacity:.5;
  transition:width .1s linear,background .3s,opacity .3s}
.tbar i.low{background:var(--ko);opacity:1}
.hmask{font-weight:800;font-size:19px;letter-spacing:1.5px;color:var(--soft);opacity:.75;
  font-variant-numeric:tabular-nums;
  max-width:min(560px,100%);margin:0 auto;padding:0 14px;text-align:center;
  white-space:normal;overflow-wrap:break-word;line-height:1.5}
.fade .hmask{animation:rise .3s var(--e) both}
.arow{display:flex;gap:8px;align-items:stretch}
.arow .ans{flex:1;min-width:0;width:auto}
.ai.mic{width:56px;height:auto}
.qrow{display:flex;gap:8px;margin-top:11px}
.qrow .cta{flex:1;width:auto;min-width:0;margin-top:0}
.qb{width:56px;height:56px;flex:none;border-radius:19px;background:var(--card);
  box-shadow:var(--s1);display:grid;place-items:center;transition:transform .2s var(--sp)}
.qb:active{transform:scale(.94)}
.qb svg{width:21px;height:21px;color:var(--ink2);stroke-width:2}
.qb.on{background:var(--ink);box-shadow:none}
.qb.on svg{color:var(--bg)}
.strk{display:inline-flex;align-items:center;gap:3px;font-size:13px;font-weight:800;
  color:var(--ko);font-variant-numeric:tabular-nums}
.strk svg{width:15px;height:15px;stroke-width:2.2}
.df{font-style:normal;border-radius:4px;background:rgba(196,86,107,.18);
  box-shadow:inset 0 -2px 0 var(--ko)}
.df.gap{display:inline-block;width:5px;background:none}

@media (min-width:900px){
  .match{grid-template-columns:repeat(3,1fr);gap:12px;max-width:820px;margin:0 auto}
  .mc{min-height:70px;font-size:15.5px}
  .opts{max-width:760px;margin-left:auto;margin-right:auto}
  .qcard{max-width:760px;margin-left:auto;margin-right:auto}
  .mc:hover,.op:hover{transform:translateY(-2px);box-shadow:var(--s2)}
  .mc.done:hover{transform:none;box-shadow:none}
}

/* ══════════ accessibilité ══════════
   Le contour de focus n'existait que sur la mise en page de bureau : un
   clavier branché sur un iPad ne montrait plus où l'on se trouvait. Les
   cibles tactiles atteignent partout la hauteur du doigt, et le mode
   contraste renforcé du système assombrit les gris secondaires. */
:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:8px}
.ic,.tabs button,.mx,.trb,.sba .x,.pick,.lnk{min-height:40px}
.mi,.sr{min-height:48px}
@media (prefers-contrast:more){
  :root{--soft:#6A6472; --ink2:#2A262F; --hair:rgba(27,24,29,.16)}
  .note,.sub,.mhx i{color:var(--ink2)}
}
/* seule la carte du dessus est interactive : les suivantes ne doivent
   être ni cliquables ni annoncées */
.stack .card:not(#top){pointer-events:none}

/* ══════════ le groupe : bibliothèque, défis, classement ══════════ */
.seg#gTabs,.seg#bRange{margin:2px 0 14px}
.dsc{font-variant-numeric:tabular-nums;font-weight:800;color:var(--ink)}
.dnew{font-size:12px;font-weight:750;color:var(--bg);background:var(--ink);
  padding:3px 8px;border-radius:9px}
/* une ligne de classement : rang, nom, détail, et une barre de fond
   proportionnelle au volume — lisible d'un coup d'œil, sans graphique */
.bdr{display:flex;align-items:center;gap:11px;background:var(--card);box-shadow:var(--s1);
  border-radius:17px;padding:11px 14px;margin-bottom:8px}
.bdr.me{box-shadow:inset 0 0 0 2px var(--ink),var(--s1)}
.bdp{flex:none;width:26px;text-align:center;font-size:17px;font-weight:800;
  color:var(--soft);font-variant-numeric:tabular-nums}
.bdn{flex:1;min-width:0;display:block;position:relative}
.bdn b{display:block;font-size:15px;font-weight:750;letter-spacing:-.2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bdn i{display:block;font-style:normal;font-size:12.5px;color:var(--soft);margin-top:1px}
.bdn em{display:block;height:4px;border-radius:4px;background:var(--ink);opacity:.16;margin-top:6px}
.bdr.me .bdn em{opacity:.4}
/* progression du défi : la même barre fine que le chrono du quiz */
.dbar{height:4px;border-radius:4px;background:var(--surf);overflow:hidden;margin:2px 1px 14px;flex:none}
.dbar i{display:block;height:100%;border-radius:4px;background:var(--ink);
  transition:width .35s var(--e)}
.cta.ghost{background:var(--card);color:var(--ink);box-shadow:var(--s1);margin:0 0 14px}
.cta.ghost svg{color:var(--ink)}

/* ══════════ file d'attente et conflits ══════════ */
.qchip{display:inline-flex;align-items:center;gap:5px;height:30px;padding:0 11px;
  border-radius:11px;background:var(--surf);color:var(--ink2);font-size:13px;font-weight:750;
  font-variant-numeric:tabular-nums;flex:none}
.qchip svg{width:14px;height:14px;stroke-width:2.2}
.qchip.off{background:rgba(196,86,107,.14);color:var(--ko)}
.qchip:active{transform:scale(.94)}
/* les deux versions côte à côte : on compare avant de trancher */
.csides{display:flex;gap:8px;margin:2px 12px 8px}
.cside{flex:1;min-width:0;background:var(--surf);border-radius:15px;padding:11px 12px}
.cside b{display:block;font-size:12px;font-weight:800;text-transform:uppercase;
  letter-spacing:.6px;color:var(--soft)}
.cside i{display:block;font-style:normal;font-size:13.5px;font-weight:750;margin-top:5px}
.cside span{display:block;font-size:12.5px;color:var(--soft);margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ══════════ historique, limites, liste par pages ══════════ */
.more{text-align:center;font-size:13px;font-weight:700;color:var(--soft);
  padding:16px 0 6px;letter-spacing:-.1px}
.fl .lim{position:absolute;right:8px;bottom:5px;font-style:normal;font-size:11px;
  font-weight:800;color:var(--soft);font-variant-numeric:tabular-nums;
  background:var(--card);padding:0 3px;border-radius:5px;pointer-events:none}
.fl .lim.ko{color:var(--ko)}
.row input.over{box-shadow:inset 0 -2px 0 var(--ko)}
.dupb.warn{background:rgba(196,86,107,.12)}
.dupb.warn .dupt{opacity:.75}

/* Un message qui arrive pendant qu'une feuille est ouverte se posait
   pile sur son bouton principal : « Envoi impossible » recouvrait
   « Enregistrer », au point qu'on croyait lire le bouton. Feuille
   ouverte, le message passe en haut. */
.toast.up{animation:tdown .45s var(--sp)}
@keyframes tdown{from{opacity:0;transform:translate(-50%,-14px) scale(.97)}}

/* Le contenu défilait derrière l'heure et la batterie : sur iPhone la
   barre d'état est transparente et rien ne la doublait. Un bandeau de la
   couleur du fond la garnit, et le contenu disparaît proprement dessous. */
.statusmask{position:fixed;left:0;right:0;top:0;height:env(safe-area-inset-top);
  background:var(--bg);z-index:50;pointer-events:none}

/* La pastille d'explication : posée contre le nom du réglage, elle ne
   prend pas de ligne à elle et ne se lit que si on la touche. */
.hq{flex:none;width:19px;height:19px;min-height:0;border-radius:50%;
  background:var(--surf2);color:var(--soft);font-size:12px;font-weight:800;
  line-height:19px;text-align:center;letter-spacing:0;text-transform:none}
.hq:active{transform:scale(.86)}
.lbl .hq{margin-left:-2px}
.sr .hq,.srh .hq{margin-left:-4px}
.htxt{padding:0 14px 14px;line-height:1.55}
/* Une ligne à interrupteur est un bouton : on ne peut pas en imbriquer un
   second dedans (le navigateur referme le premier et la ligne se casse en
   deux). La pastille se pose donc par-dessus, à gauche de l'interrupteur. */
.srw{position:relative;display:block}
.srw > .sr{width:100%}
.srw > .hq{position:absolute;top:50%;right:66px;transform:translateY(-50%);z-index:2}
.srw > .sr .n{padding-right:26px}

/* ══════════ visite guidée ══════════
   Un seul halo se déplace d'une zone à l'autre ; c'est son ombre portée,
   démesurée, qui assombrit tout le reste. Une seule chose à animer, donc
   le mouvement reste net même sur un vieux téléphone. */
.tour{position:fixed;inset:0;z-index:70;pointer-events:none}
.tspot{position:absolute;border-radius:20px;pointer-events:none;
  box-shadow:0 0 0 9999px rgba(22,19,24,.66);
  transition:left .5s var(--e),top .5s var(--e),width .5s var(--e),
             height .5s var(--e),opacity .3s}
.tring{position:absolute;border-radius:20px;pointer-events:none;
  box-shadow:0 0 0 2px rgba(255,255,255,.92),0 0 26px 4px rgba(255,255,255,.28);
  transition:left .5s var(--e),top .5s var(--e),width .5s var(--e),
             height .5s var(--e),opacity .3s;
  animation:tpulse 2.2s ease-in-out infinite}
@keyframes tpulse{50%{box-shadow:0 0 0 4px rgba(255,255,255,.5),0 0 34px 8px rgba(255,255,255,.16)}}
/* volets de blocage : tout est inerte sauf, si l'étape attend un geste,
   la zone montrée */
.tblk{position:absolute;pointer-events:auto}
.tbub{position:absolute;left:14px;right:14px;pointer-events:auto;
  background:var(--card);border-radius:24px;padding:16px 18px 14px;
  box-shadow:var(--s3);animation:tbin .45s var(--sp) both;
  transition:top .5s var(--e)}
@keyframes tbin{from{opacity:0;transform:translateY(14px) scale(.97)}}
.tprog{display:block;height:3px;border-radius:3px;background:var(--surf);overflow:hidden;
  margin:0 0 12px}
.tprog b{display:block;height:100%;border-radius:3px;background:var(--ink);
  transition:width .5s var(--e)}
.tchap{display:block;font-style:normal;font-size:11.5px;font-weight:800;
  letter-spacing:.5px;text-transform:uppercase;color:var(--soft)}
.tbub > b{display:block;font-size:19px;font-weight:800;letter-spacing:-.5px;
  margin:5px 0 6px}
.tbub p{margin:0;font-size:15px;font-weight:550;line-height:1.5;color:var(--ink2)}
.tswipe{display:block;margin:12px auto 0;width:96px;color:var(--soft);opacity:.7}
.tswipe svg{width:96px;height:32px;animation:tsw 1.8s var(--e) infinite}
@keyframes tsw{0%,100%{transform:translateX(-8px)}50%{transform:translateX(8px)}}
.tnav{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-top:14px}
/* le geste attendu passe sur sa propre ligne, au-dessus des boutons :
   sur un écran étroit il se coupait en deux au milieu du mot */
.ttap{flex:1 0 100%;order:-1;display:flex;align-items:center;gap:6px;font-style:normal;
  font-size:13.5px;font-weight:750;color:var(--ok);margin-bottom:-2px}
.ttap svg{width:15px;height:15px;flex:none}
.tnav > i:empty{flex:1;order:0}
.tskip{flex:none;height:42px;padding:0 14px;border-radius:14px;color:var(--soft);
  font-weight:700;font-size:14.5px}
.tnext{flex:none;display:flex;align-items:center;gap:7px;height:42px;padding:0 16px;
  border-radius:15px;background:var(--ink);color:var(--bg);font-weight:750;font-size:15px;
  transition:transform .25s var(--sp)}
.tnext:active{transform:scale(.94)}
.tnext svg{width:16px;height:16px;stroke-width:2.4}
/* pendant la visite, rien d'autre ne doit attirer l'œil ni le doigt */
/* le bouton rond fait partie de la visite : c'est le message passager,
   lui, qui n'a rien à y faire */
body.touring .toast{display:none}
@media (min-width:900px){
  .tbub{left:auto;right:34px;width:360px}
}

/* ══════════ communauté ══════════ */
.mecard{display:flex;align-items:center;gap:13px;width:100%;background:var(--card);
  box-shadow:var(--s1);border-radius:22px;padding:14px 16px;margin-bottom:14px;text-align:left;
  transition:transform .3s var(--sp)}
.mecard:active{transform:scale(.985)}
/* dans une ligne .sr, tout « i » direct est une pastille de matière :
   il faut être plus précis pour que l'initiale garde sa place */
.sr > i.av,.mhd > i.av{border-radius:16px;background:var(--ink)}
.av{flex:none;width:46px;height:46px;border-radius:16px;background:var(--ink);color:var(--bg);
  display:grid;place-items:center;font-style:normal;font-size:19px;font-weight:800}
.av.sm,.sr > i.av.sm{width:34px;height:34px;border-radius:12px;font-size:15px}
.mex{flex:1;min-width:0}
.mex b{display:block;font-size:17px;font-weight:800;letter-spacing:-.4px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mex i{display:block;font-style:normal;font-size:13px;color:var(--soft);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mecard > svg{width:17px;height:17px;color:var(--soft);opacity:.5;flex:none}
/* quatre portes, pas une liste : on voit d'un coup ce qui existe */
.ctiles{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-bottom:22px}
.ctile{position:relative;display:flex;flex-direction:column;align-items:flex-start;gap:7px;
  background:var(--card);box-shadow:var(--s1);border-radius:22px;padding:15px 15px 13px;
  text-align:left;transition:transform .3s var(--sp),box-shadow .3s}
.ctile:active{transform:scale(.96)}
.ci{position:relative;display:grid;place-items:center;width:38px;height:38px;border-radius:13px;
  background:var(--surf);font-style:normal}
.ci svg{width:19px;height:19px;color:var(--ink2)}
/* Renommée : « .cb » était aussi le champ Verso du composeur, qui se
   retrouvait peint en pastille rouge centrée. */
.cbdg{position:absolute;top:-5px;right:-5px;min-width:18px;height:18px;padding:0 5px;
  border-radius:9px;background:var(--ko);color:#fff;font-size:11px;font-weight:800;
  line-height:18px;text-align:center}
.cn{font-size:15.5px;font-weight:750;letter-spacing:-.25px}
.cv{font-size:12.5px;font-weight:650;color:var(--soft)}
/* .fld a flex:1 pour vivre dans une barre ; posé seul dans une colonne il
   s'étirait sur toute la hauteur de l'écran */
.addf{flex:none;display:flex;align-items:center;gap:8px;margin-bottom:16px;height:46px}
.addf input{flex:1;min-width:0}
.addf .lnk{flex:none}
.addf .at{font-weight:800;color:var(--soft);padding-left:2px}
.fyes,.fno{flex:none;width:38px;height:38px;border-radius:13px;display:grid;place-items:center}
.fyes{background:var(--ok);color:#fff}
.fno{background:var(--surf);color:var(--soft)}
.fyes svg,.fno svg{width:17px;height:17px;stroke-width:2.6}
.mhd .av{width:40px;height:40px;border-radius:14px;font-size:17px}
/* la feuille suit le doigt quand on la tire vers le bas */
.menu{transition:transform .32s var(--e)}
.scrim{transition:opacity .32s var(--e)}
/* le rappel discret qu'on est chez Léa, à toutes les étapes */
.tdemo{display:inline-block;margin-left:7px;padding:1px 7px;border-radius:8px;
  background:var(--surf2);color:var(--ink2);font-size:10.5px;font-weight:800;
  letter-spacing:.3px;text-transform:none;vertical-align:1px}
/* la signature sous le titre, à l'ouverture */
.lsub{font-family:var(--serif);font-size:15px;font-style:italic;color:var(--soft);
  margin:-10px 0 22px;text-align:center}
.lt{font-family:var(--serif);letter-spacing:-.5px}
.brand span{font-family:var(--serif);font-weight:700;letter-spacing:-.2px}

/* ══════════ le livre ouvert ══════════ */
.cta.read{margin:0 0 8px}
.cta.read b{font-variant-numeric:tabular-nums;background:rgba(255,255,255,.18);
  border-radius:9px;padding:1px 8px;margin-left:2px}
/* les autres façons de travailler le livre, sur une ligne */
.acts{display:grid;grid-template-columns:repeat(4,1fr);gap:7px;margin:0 0 16px}
.acts button{display:flex;flex-direction:column;align-items:center;gap:5px;
  background:var(--card);box-shadow:var(--s1);border-radius:16px;padding:11px 4px 9px;
  font-size:11px;font-weight:700;color:var(--ink2);letter-spacing:-.1px;
  transition:transform .28s var(--sp)}
.acts button:active{transform:scale(.94)}
.acts svg{width:18px;height:18px;color:var(--ink)}
.acts span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}

/* ══════════ appui long sur un livre ══════════ */
/* l'appui long s'annonce : le livre s'enfonce et se détache du fond */
.tile.hold,.lrow.hold{animation:holdin .5s var(--e) forwards}
@keyframes holdin{to{transform:scale(.955);box-shadow:var(--s2)}}
/* ranger sa bibliothèque : le livre pris sous le doigt, et les autres
   qui s'écartent pour lui faire place. Le déplacement se fait sur
   « translate » (et « scale » pour la couverture tenue), jamais sur
   « transform » : c'est cette dernière que le tremblement ci-dessous
   utilise pour tourner, et les deux propriétés ne se gênent pas. */
/* #page autorise le défilement vertical natif (touch-action:pan-y) pour
   que la page défile normalement — sauf ici : pendant le rangement, un
   doigt qui glisse sur un livre ne doit jamais faire défiler la page en
   dessous, seulement déplacer le livre. Sans ce blocage, le geste
   partait au hasard entre « faire glisser le livre » et « scroller » ;
   posé au repos AVANT même le premier mouvement, il tranche d'emblée. */
.grid.reord,.rows.lst.reord{touch-action:none}
.grid.reord .tile,.rows.lst.reord .lrow{cursor:grab}
.reord .tile.drag,.reord .lrow.drag{position:relative;z-index:5;animation:none;
  box-shadow:var(--s3);opacity:.95;transition:none}
/* le livre tenu ne doit pas aussi se tasser au doigt : ce rétrécissement
   (hérité de l'état pressé) annulerait le grossissement qu'on lui donne
   en le soulevant */
.reord .tile.drag:active{transform:none}
.reord.dragging .tile:not(.drag),.reord.dragging .lrow:not(.drag){transition:translate .22s var(--e)}
.reord .grip{opacity:.55}
/* le tremblement, comme sur un écran d'accueil de téléphone : chaque
   livre penche à son propre rythme, décalé par --i pour ne pas trembler
   à l'unisson. Celui qu'on tient s'arrête d'osciller et flotte, net. */
@keyframes wiggle{0%,100%{rotate:-1.4deg}50%{rotate:1.4deg}}
.reord .tile:not(.drag),.reord .lrow:not(.drag){
  animation:wiggle .24s ease-in-out infinite;animation-delay:calc(var(--i,0) * -47ms)}
@media (prefers-reduced-motion:reduce){
  .reord .tile:not(.drag),.reord .lrow:not(.drag){animation:none}
}
/* Le rangement fige tout le reste : plus de recherche, de filtres, de
   balayage ni d'ouverture d'un livre — seuls les livres eux-mêmes
   répondent, jusqu'à ce qu'on valide avec le rond vert. */
.page.frozen > *:not(.grid):not(.rows){
  pointer-events:none;opacity:.4;filter:saturate(.7);transition:opacity .25s var(--e)}
#app.reordering .tabs{pointer-events:none;opacity:.4;transition:opacity .25s var(--e)}
.mpick{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:2px 12px 10px}
.mg{display:flex;flex-direction:column;align-items:center;gap:7px;background:var(--surf);
  border-radius:17px;padding:14px 6px 11px;font-size:11.5px;font-weight:700;color:var(--ink2);
  transition:transform .28s var(--sp)}
.mg:active{transform:scale(.93)}
.mg svg{width:19px;height:19px;color:var(--ink)}
.mg span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.mg.off{opacity:.35;pointer-events:none}
/* la suppression restait seule dans un coin de la dernière rangée :
   elle prend la ligne entière, comme un vrai bouton */
.mg.warn{grid-column:1/-1;flex-direction:row;justify-content:center;gap:9px;
  padding:13px 10px;font-size:14px}

/* ══════════ réglages d'affichage signalés ══════════ */
/* L'appui long sélectionnait le fond de la page en bleu, comme si on
   copiait du texte, et iOS proposait Copier/Traduire par-dessus la
   feuille. Rien n'est sélectionnable, sauf ce qu'on écrit. */
body{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
input,textarea,[contenteditable]{-webkit-user-select:text;user-select:text;
  -webkit-touch-callout:default}
/* la période, au-dessus des chiffres, avait l'air posée dessus */
#app[data-view="stats"] .seg{margin-bottom:14px}
/* le champ d'ajout d'un lecteur touchait la flèche de retour */
#app[data-view="friends"] .addf{margin-top:10px}
/* la feuille défile verticalement et rien d'autre : pas de pincement,
   pas de déplacement latéral. « overflow-y » seul rend l'axe horizontal
   défilable lui aussi : c'est ce qui laissait pousser la feuille de côté
   dès qu'un nom de matière dépassait. */
.menu{touch-action:pan-y;overflow:hidden}
.mgrid,.mpick,.mtop{touch-action:none}

/* ══════════ ouverture ══════════
   Le voile de démarrage : l'icône se pose, le nom arrive, puis tout
   s'efface sur la première vue. Sans lui, l'app s'ouvrait sur du noir le
   temps que le script se charge. */
/* Les mêmes règles que dans l'en-tête de la page, en plus fini. Elles y
   sont écrites deux fois volontairement : celles de la page peignent la
   première image, celles-ci prennent le relais avec les vraies couleurs
   du thème. */
#boot{position:fixed;inset:0;z-index:80;background:var(--bg);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:15px;
  transition:opacity .5s var(--e),transform .5s var(--e)}
#boot img{width:84px;height:84px;border-radius:26px;box-shadow:var(--s2);
  animation:bookin .85s cubic-bezier(.2,1.1,.3,1) both}
#boot b{font-family:var(--serif);font-size:30px;font-weight:700;letter-spacing:-.5px;
  color:var(--ink);animation:bootname .7s var(--e) .3s both}
/* le trait se remplit pendant que le compte et les livres arrivent :
   trois secondes qui se regardent, au lieu d'une attente muette */
#boot i{position:relative;display:block;width:104px;height:2px;border-radius:2px;
  overflow:hidden;background:var(--surf2);animation:bootname .5s var(--e) .62s both}
#boot i::after{content:'';position:absolute;inset:0;border-radius:2px;background:var(--ink);
  transform-origin:left center;animation:bootbar 2.3s cubic-bezier(.35,.5,.2,1) .66s both}
@keyframes bookin{from{opacity:0;transform:translateY(22px) scale(.84) rotate(-6deg)}}
@keyframes bootname{from{opacity:0;transform:translateY(10px)}}
@keyframes bootbar{from{transform:scaleX(0)}to{transform:scaleX(1)}}
#boot.off{opacity:0;transform:scale(1.04);pointer-events:none}
/* le bouton d'ajout, aligné sur le champ plutôt que flottant au-dessus */
.addgo{flex:none;align-self:stretch;display:flex;align-items:center;padding:0 14px;
  margin:-1px -12px -1px 0;border-radius:0 14px 14px 0;background:var(--ink);color:var(--bg);
  font-weight:750;font-size:14.5px;letter-spacing:-.2px}
.addgo:active{opacity:.85}
.mg.warn{color:var(--ko)}
.mg.warn svg{color:var(--ko)}

/* ══════════ journal : sept jours, et l'état de chaque livre ══════════ */
/* Trois lignes empilées : le chiffre, la piste, le jour. La barre se
   mesure dans la piste — avant, elle partageait sa hauteur avec le
   chiffre et le jour, et le calcul de proportion se faisait écraser par
   le reste : deux journées très différentes finissaient de même taille. */
.week{display:flex;align-items:stretch;gap:7px;height:132px}
.wd{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:5px;height:100%}
.wd b{flex:none;min-height:14px;font-size:12px;font-weight:800;color:var(--ink2);
  font-variant-numeric:tabular-nums}
.wd u{flex:1;min-height:0;position:relative;width:100%;text-decoration:none}
.wd i{position:absolute;left:0;right:0;bottom:0;border-radius:7px 7px 3px 3px;
  background:var(--ok);animation:grow .55s var(--e) both}
.wd i.nil{height:3px !important;background:var(--surf2)}
@keyframes grow{from{height:3px;opacity:.4}}
.wd span{flex:none;font-size:11px;font-weight:750;color:var(--soft)}
/* légende des couleurs, sous l'état des livres */
.bkkey{display:flex;flex-wrap:wrap;gap:6px 14px;padding-top:10px;margin-top:4px;
  border-top:1px solid var(--hair);font-size:12px;font-weight:650;color:var(--soft)}
.bkkey span{display:flex;align-items:center;gap:6px}
.bkkey i{width:8px;height:8px;border-radius:50%;flex:none}
.bkkey i.new{background:#4A7FBE} .bkkey i.learn{background:#D4842E}
.bkkey i.young{background:#4C9862} .bkkey i.mature{background:var(--ink)}
.bkline{display:flex;align-items:center;gap:12px;padding:7px 0}
.bkn{flex:1;min-width:0;font-size:14.5px;font-weight:700;letter-spacing:-.2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bkn i{display:block;font-style:normal;font-size:12px;font-weight:650;color:var(--soft);
  margin-top:2px}
.mix.sm{flex:none;width:104px;height:7px}

/* ---------- l'écran d'accueil ----------
   Trois pas numérotés, et le vrai glyphe de partage d'iOS posé dans la
   phrase plutôt que décrit avec des mots : c'est une icône qu'on
   reconnaît, pas un nom qu'on cherche. */
.msub{font-size:13.5px;line-height:1.45;font-weight:500;color:var(--soft);letter-spacing:-.1px}
.insteps{display:grid;gap:2px;padding:2px 7px 6px}
.instep{display:flex;align-items:flex-start;gap:13px;padding:11px 12px;
  border-radius:15px;background:var(--surf)}
.instep i{flex:none;width:22px;height:22px;border-radius:8px;background:var(--card);
  display:grid;place-items:center;font-style:normal;font-size:12px;font-weight:800;
  color:var(--ink);box-shadow:var(--s1)}
.instep span{font-size:14.5px;line-height:1.45;font-weight:520;color:var(--ink2);letter-spacing:-.15px}
.instep b{font-weight:750;color:var(--ink)}
.inshare{display:inline-flex;align-items:center;justify-content:center;
  width:23px;height:23px;border-radius:7px;background:var(--card);
  vertical-align:-6px;margin:0 1px;box-shadow:var(--s1)}
.shg{width:13px;height:13px;stroke-width:2.1;fill:none;stroke:currentColor;
  stroke-linecap:round;stroke-linejoin:round;color:#2B7BE4}

/* ---------- le cadre légal ----------
   Un texte de loi se lit en colonne étroite, avec de l'air entre les
   paragraphes : c'est un document, pas une interface. */
.legal{max-width:62ch;padding:0 0 28px;font-size:15px;line-height:1.62;color:var(--ink2)}
.legal p{margin:0 0 15px}
.legal b{font-weight:750;color:var(--ink)}
.legal i{font-style:italic}
.legal ul{margin:0 0 15px;padding-left:1.1em;display:grid;gap:8px}
.legal li{margin:0}
.legal p:last-child{color:var(--soft);font-size:13px;margin-top:22px}

/* la case d'âge : une vraie case, assez grande pour le pouce */
.lage{display:flex;align-items:flex-start;gap:11px;padding:2px 2px 4px;
  font-size:13.5px;line-height:1.45;color:var(--ink2);text-align:left}
.lage input{flex:none;width:21px;height:21px;margin:0;accent-color:var(--ink)}

/* les trois liens sous le formulaire de connexion */
.lleg{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;
  gap:8px;margin-top:22px;font-size:12.5px;color:var(--soft)}
.lleg button{font-size:12.5px;color:var(--soft);text-decoration:underline;
  text-underline-offset:2px;padding:4px 2px}
.lleg i{font-style:normal;opacity:.5}

/* ---------- signaler ----------
   Les motifs sont des choix, pas des liens : celui qui est retenu doit se
   voir d'un coup d'œil, sinon on ne sait plus ce qu'on s'apprête à envoyer. */
.rlist{display:grid;gap:1px}
.rlist .mi{height:48px;font-size:15px;font-weight:600}
.rlist .mi.on{background:var(--surf2)}
.rlist .mi.on svg{color:var(--ok)}
.mi[disabled]{opacity:.35}

/* ---------- console de modération ----------
   Chaque signalement est une fiche de dossier : le motif, ce qu'on a
   écrit, la copie du contenu telle qu'elle a été prise, et deux réponses. */
.rep{background:var(--card);border-radius:20px;box-shadow:var(--s1);
  padding:15px 16px;margin-bottom:12px;display:grid;gap:11px}
.rh{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.rh b{font-weight:780;font-size:15.5px;letter-spacing:-.2px}
.rh i{font-style:normal;font-size:12px;font-weight:700;letter-spacing:.2px;
  padding:3px 9px;border-radius:9px;background:var(--surf);color:var(--ko)}
.rh span{margin-left:auto;font-size:12.5px;color:var(--soft);font-variant-numeric:tabular-nums}
.rn{display:flex;gap:9px;padding:10px 12px;border-radius:14px;background:var(--surf)}
.rn svg{width:15px;height:15px;color:var(--soft);flex:none;margin-top:3px}
.rn p{margin:0;font-size:14px;line-height:1.45;color:var(--ink2)}
.rs{display:grid;gap:7px}
.sl{display:flex;gap:10px;font-size:13.5px;line-height:1.45}
.sl i{font-style:normal;color:var(--soft);min-width:62px;flex:none;text-transform:capitalize}
.sl span{color:var(--ink2);overflow-wrap:anywhere}
.scards{display:grid;gap:4px;max-height:190px;overflow-y:auto;
  -webkit-overflow-scrolling:touch;padding:2px 0}
.rb{display:flex;gap:8px}
.rb button{flex:1;display:flex;align-items:center;justify-content:center;gap:7px;
  height:46px;border-radius:15px;background:var(--surf);font-size:14.5px;font-weight:680;
  color:var(--ink);transition:transform .2s var(--sp)}
.rb button:active{transform:scale(.96)}
.rb button.warn{background:var(--ko);color:#fff}
.rb button svg{width:17px;height:17px}
.rb button.warn svg{color:#fff}

/* ---------- classes ----------
   Le code de la classe est la seule chose que le professeur doit pouvoir
   lire de loin, projeté au tableau : il est donc gros et détaché. */
.ccode{display:flex;align-items:center;gap:12px;padding:16px 18px;margin-bottom:16px;
  background:var(--card);border-radius:20px;box-shadow:var(--s1)}
.ccode svg{width:19px;height:19px;color:var(--soft);flex:none}
.ccode span{font-size:14px;font-weight:600;color:var(--ink2)}
.ccode b{margin-left:auto;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:24px;font-weight:800;letter-spacing:3px;color:var(--ink)}
.av{flex:none;width:34px;height:34px;border-radius:12px;background:var(--surf);
  display:grid;place-items:center;font-style:normal;font-size:14px;font-weight:800;color:var(--ink2)}

/* ---------- le contour qui répond au doigt ----------
   La pastille arrivait trop tard : elle ne commençait qu'à vingt pixels et
   n'était pleine qu'à quatre-vingt-dix, soit à peu près au moment du
   lâcher. Le contour, lui, s'allume dès six pixels et sature à
   soixante-six — on sait donc où l'on va pendant qu'on peut encore
   changer d'avis. */
.card{--sw:0;--swc:transparent}
.swr{position:absolute;inset:0;border-radius:30px;pointer-events:none;z-index:2;
  opacity:var(--sw);
  box-shadow:inset 0 0 0 calc(3px + var(--sw) * 4px) var(--swc),
             0 0 calc(var(--sw) * 28px) -6px var(--swc);
  transition:opacity .09s linear}
.card.gone .swr{transition:opacity .3s linear}
@media (prefers-reduced-motion:reduce){.swr{transition:none}}


/* ══════════ l'écran ne rebondit plus ══════════
   C'était le document lui-même qui glissait : sur iPhone une page tirée
   vers le bas rebondit même quand il n'y a rien de plus à voir, et pendant
   qu'on déplaçait une fiche c'est tout l'écran qui partait avec elle.

   La racine ne défile plus du tout — elle n'a donc plus rien contre quoi
   rebondir — et le défilement passe au corps de page, qui garde la main
   jusqu'au bout au lieu de la repasser au document.

   On ne touche pas à #app : en faire un conteneur de hauteur fixe aurait
   comprimé les enfants des écrans qui n'ont pas de .page — le détail d'un
   livre, par exemple, dont la liste de fiches se serait tassée au lieu de
   déborder. Il garde sa hauteur libre, et c'est le corps qui défile.

   La fiche qu'on déplace, elle, est déjà protégée par son touch-action :
   un doigt qui part d'elle ne fait rien défiler. */
html{height:100%;overflow:hidden;overscroll-behavior:none}
body{height:100%;overflow-y:auto;overflow-x:hidden;
  overscroll-behavior-y:contain;-webkit-overflow-scrolling:touch}
