/* Maille à Maille : la MATIÈRE des thèmes.
 *
 * La feuille des composants (style.css) dessine la page avec des jetons ;
 * celle-ci ajoute ce qui fait qu'un thème se reconnaît : feutrine et
 * coutures, bouloche, contours au fil, animations de laine. Tout y passe par
 * les jetons du thème actif (assets/themes.css) et par des classes
 * génériques (.bt--primaire, .segmente, [aria-selected], .zone .zo...) : un
 * composant nouveau qui reprend ces classes prend le thème sans retouche.
 *
 * Trois règles tiennent pour tous les thèmes :
 *  1. Le patron ne bouloche jamais : vue Patron, Suivi, Matériel et mode
 *     « Je tricote » ont un fond plein, sans grain ni motif, et des
 *     chiffres tabulaires (section « Lisibilité » plus bas).
 *  2. La bouloche est fixe : textures générées une fois (données SVG des
 *     jetons), filtres SVG jamais animés.
 *  3. Mouvement réduit (système) ou animations coupées à la main
 *     (`data-calme`) : rien ne bouge, tout est posé dans son état final.
 *
 * Le thème Classique (l'ancienne charte Fjord) n'a aucune matière : ses
 * jetons de texture valent `none`, ses ombres aussi. */

/* --- Typographie ------------------------------------------------------- */

.serif, .patron h2, .entete h1, .panneau-tete h2, .carte-v, .marque-mot, .nom-projet,
.patron h3, .materiel h3, .suivi h3, .partage-tete h2, .tech-nom, .parcours h2, .parcours-question {
  font-weight: var(--w-titre);
  font-stretch: var(--etire);
  font-variation-settings: var(--var-titre);
}
.marque-mot span { font-weight: 400; }
:root:not([data-theme="classique"]) .marque-mot { letter-spacing: 0; font-size: 1.12rem; }
/* Herbier : les intertitres du rail s'écrivent à la main, comme dans un carnet. */
:root[data-theme="herbier"] .rail-titre {
  font-family: var(--main); font-size: 1.05rem; font-weight: 700;
  text-transform: none; letter-spacing: 0; color: var(--accent);
}

/* --- Fonds : grain sur le rail, motif dans la scène -------------------- */

.rail { background-image: var(--grain); }
.barre-haut { background-image: var(--peluches); }
.scene-wrap { background-image: var(--motif); }
.parcours-scene { background-image: var(--motif); }

/* --- Formes : pastilles et boutons arrondis selon le thème ------------- */

.bt, .bt-secondaire, .segmente button, .presets button, .puces button,
.tailles-rapides button, .scene-outils .vues-scene, .toast, .bt-correction, .toast-action {
  border-radius: var(--r-pill);
}
.scene-outils .vues-scene button { border-radius: var(--r-pill); }
.nuancier-fil button { border-radius: var(--r-pill); }
.familles button, .projets li, .sec-tete { border-radius: var(--r-sm); }
.mini { border-radius: var(--r-md); }
.porte, .apercu-vue { border-radius: var(--r-md); }

/* --- Feutrine : cartes et boutons en pièces de laine cousues ----------- *
 * Le fond reste une couleur pleine ; peluches et grain se posent dessus en
 * images de fond (générées une fois). La couture court à 4 px du bord
 * (`--couture`), le bord peluche grâce au filtre fixe `--fuzz` posé sur un
 * liseré de la couleur du fond (le contenu, lui, reste net). */

.bt--primaire, .bt--doux, .bt-secondaire, .familles button[aria-selected="true"],
.tailles-rapides button[aria-pressed="true"], .segmente button.actif, .puces button.actif,
.presets button.actif, .scene-outils .vues-scene, .mini, .toast, .onglets-bas .ob-p,
.calcul, .theme-choix:has(input:checked) {
  background-image: var(--peluches), var(--grain);
}
:root:not([data-theme="classique"]) :is(.bt--primaire, .bt--doux, .bt-secondaire, .mini, .toast, .scene-outils .vues-scene,
  .familles button[aria-selected="true"], .tailles-rapides button[aria-pressed="true"]) {
  box-shadow: var(--ombre-1);
}
.bt--primaire, .bt--doux, .bt-secondaire, .familles button[aria-selected="true"], .mini, .toast,
.tailles-rapides button[aria-pressed="true"] {
  position: relative; isolation: isolate;
}
.mini { position: sticky; }
.toast { position: fixed; }

/* La couture en points avant */
.bt--primaire::after, .bt--doux::after, .bt-secondaire::after, .familles button[aria-selected="true"]::after,
.mini::after, .toast::after {
  content: ""; position: absolute; inset: 4px; border-radius: inherit;
  border: var(--couture); pointer-events: none; z-index: -1;
}
.bt--primaire::after, .familles button[aria-selected="true"]::after, .toast::after {
  border-color: color-mix(in srgb, var(--sur-accent) 55%, transparent);
}
:root[data-theme="classique"] .bt--doux::after, :root[data-theme="classique"] .bt-secondaire::after { content: none; }
/* Une pastille trop petite pour une couture : pas de couture. */
.bt--petit::after, .bt--icone::after { content: none !important; }

/* Le bord qui peluche : un liseré de la couleur du fond, passé au filtre. */
:root[data-filtres] :is(.bt--primaire, .bt--doux, .familles button[aria-selected="true"], .tailles-rapides button[aria-pressed="true"])::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; pointer-events: none; z-index: -1;
  border: 3px solid var(--fond-feutre, var(--surface)); filter: var(--fuzz);
}
:root[data-theme="classique"] :is(.bt--primaire, .bt--doux, .familles button, .tailles-rapides button)::before { content: none !important; }
.bt--primaire { --fond-feutre: var(--accent); }
.bt--primaire:hover { --fond-feutre: var(--accent-2); }
.familles button[aria-selected="true"], .tailles-rapides button[aria-pressed="true"] { --fond-feutre: var(--accent); }

/* L'action principale : la couleur d'accent du thème (Classique garde l'encre). */
:root:not([data-theme="classique"]) .bt--primaire,
:root:not([data-theme="classique"]) .onglets-bas .ob-p {
  background-color: var(--accent); border-color: var(--accent); color: var(--sur-accent);
}
:root:not([data-theme="classique"]) .bt--primaire:hover { background-color: var(--accent-2); border-color: var(--accent-2); }
:root:not([data-theme="classique"]) :is(.familles button[aria-selected="true"], .tailles-rapides button[aria-pressed="true"],
  .segmente button.actif, .puces button.actif, .presets button.actif) {
  background-color: var(--accent); border-color: var(--accent); color: var(--sur-accent);
}
:root:not([data-theme="classique"]) .toast { background-color: var(--encre); }
/* Granny : contours chocolat francs partout où il y a une pièce. */
:root[data-theme="granny"] :is(.bt--primaire, .bt--doux, .bt-secondaire, .familles button[aria-selected="true"],
  .tailles-rapides button, .mini, .scene-outils .vues-scene) {
  border: 2px solid var(--encre);
}

/* Le bouton cousu, sur l'action principale de Pays de laine : un disque de
 * laine claire percé de quatre trous, posé avant le mot. */
:root[data-theme="laine"] .bt--primaire:not(.bt--petit, .tricote .bt--primaire) {
  padding-left: calc(.8rem + 18px);
}
:root[data-theme="laine"] .bt--primaire:not(.bt--petit, .tricote .bt--primaire) {
  background-image:
    radial-gradient(circle at 5.4px 5.4px, var(--accent) 1.1px, transparent 1.4px),
    radial-gradient(circle at 10.6px 5.4px, var(--accent) 1.1px, transparent 1.4px),
    radial-gradient(circle at 5.4px 10.6px, var(--accent) 1.1px, transparent 1.4px),
    radial-gradient(circle at 10.6px 10.6px, var(--accent) 1.1px, transparent 1.4px),
    radial-gradient(circle at 8px 8px, var(--laine-clair) 6.4px, var(--laine-fonce) 6.6px, var(--laine-fonce) 7.4px, transparent 7.7px),
    var(--peluches), var(--grain);
  background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, repeat, repeat;
  background-size: 16px 16px, 16px 16px, 16px 16px, 16px 16px, 16px 16px, auto, auto;
  background-position: .7rem 50%, .7rem 50%, .7rem 50%, .7rem 50%, .7rem 50%, 0 0, 0 0;
}
:root[data-theme="laine"] .bt--primaire:not(.bt--petit, .tricote .bt--primaire):hover { background-color: var(--accent-2); }

/* Rebonds : réservés aux boutons et pastilles, jamais au patron. */
:root:not([data-theme="classique"]) :is(.bt, .bt-secondaire, .segmente button, .puces button, .presets button,
  .tailles-rapides button, .familles button, .nuancier-fil button, .onglets-bas button) {
  transition: transform calc(380ms * var(--lent)) var(--rebond), background var(--mvt-vif), border-color var(--mvt-vif), color var(--mvt-vif);
}
:root:not([data-theme="classique"]) :is(.bt, .bt-secondaire, .segmente button, .puces button, .presets button,
  .tailles-rapides button, .familles button, .nuancier-fil button, .onglets-bas button):active {
  transform: scale(.94);
}
:root[data-anims~="rebond"] :is(.tailles-rapides button, .puces button, .segmente button, .nuancier-fil button):active {
  transform: scale(1.12, .86);
}

/* La bascule Tricot / Crochet : une pastille de feutrine, le choix en accent. */
#technique { border-radius: var(--r-pill); }
#technique button { border-radius: var(--r-pill); }
:root:not([data-theme="classique"]) #technique { box-shadow: var(--ombre-1); background-image: var(--grain); }
:root:not([data-theme="classique"]) #technique button[aria-checked="true"] {
  background-color: var(--accent); color: var(--sur-accent); background-image: var(--peluches), var(--grain);
}
:root[data-theme="granny"] #technique { border: 2px solid var(--encre); }
/* Les diagrammes au crochet suivent l'encre (currentColor) : clairs en
 * sombre, noirs à l'impression ; jamais de texture sous un symbole. */
.diagramme-crochet { color: var(--encre); background: none; }

/* --- Filets et soulignés : le fil qui se trace ------------------------- */

/* L'onglet actif et le titre de la section ouverte : un fil ondulé, tracé à
 * l'apparition (révélé de gauche à droite), de la couleur d'accent. */
:root:not([data-theme="classique"]) .vues button[aria-current] { border-bottom-color: transparent; position: relative; }
:root:not([data-theme="classique"]) .onglets button[aria-selected="true"] { border-bottom-color: transparent; position: relative; }
:root:not([data-theme="classique"]) :is(.vues button[aria-current], .onglets button[aria-selected="true"], .sec.ouvert .sec-titre)::after {
  content: ""; position: absolute; left: .4rem; right: .4rem; bottom: 2px; height: 7px;
  background: var(--accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 8' preserveAspectRatio='none'%3E%3Cpath d='M1 5c12-3 22 2 34-1s20-2 30 0 22 1 34-2' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 8' preserveAspectRatio='none'%3E%3Cpath d='M1 5c12-3 22 2 34-1s20-2 30 0 22 1 34-2' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") 0 0 / 100% 100% no-repeat;
  pointer-events: none;
}
:root:not([data-theme="classique"]) .onglets button[aria-selected="true"]::after { left: 0; right: 0; bottom: 0; }
:root:not([data-theme="classique"]) .sec.ouvert .sec-titre { position: relative; }
:root:not([data-theme="classique"]) .sec.ouvert .sec-titre::after { left: 0; right: 0; bottom: -5px; height: 6px; }
:root[data-anims~="trace"] :is(.vues button[aria-current], .onglets button[aria-selected="true"], .sec.ouvert .sec-titre)::after {
  animation: fil-trace calc(700ms * var(--lent)) var(--rebond-doux) both;
}
@keyframes fil-trace { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

/* --- Le croquis : contour au fil torsadé ------------------------------- */

/* Un contour épais, en pixels d'écran (`--ppu` : pixels par unité du dessin). */
:root:not([data-theme="classique"]) .zone .zo {
  stroke: var(--contour);
  stroke-width: calc(var(--contour-w) * .55px / var(--ppu, 4));
}
:root:not([data-theme="classique"]) .zone.est-active .zo { stroke: var(--accent); stroke-width: calc(var(--contour-w) * .7px / var(--ppu, 4)); }
:root:not([data-theme="classique"]) .zone:hover .zo { stroke-width: calc(var(--contour-w) * .7px / var(--ppu, 4)); }
/* Pays de laine : le contour est un fil torsadé (motif de brins en biais). */
:root[data-theme="laine"][data-filtres] .zone:not(.est-active) .zo {
  stroke: url(#torsade);
  stroke-width: calc(var(--contour-w) * 1px / var(--ppu, 4));
}
:root[data-theme="laine"][data-filtres] .mini-scene .zone .zo { stroke-width: .9; }
/* Herbier : un trait de crayon, légèrement tremblé (filtre fixe). */
:root[data-theme="herbier"][data-filtres] .scene .zone .zo { filter: var(--trace); }
:root:not([data-theme="classique"]) .zone .zb { fill: var(--laine); }

/* Le croquis se renoue après un changement de vêtement : le contour, à moitié
 * défait, se resserre (Pays de laine) ou se trace (Herbier, Feu de bois,
 * Carré granny). L'attribut `pathLength="1"` est posé le temps du geste
 * (src/animations.js). */
.renoue .zone .zo[pathLength] { stroke-dasharray: 1; }
:root[data-anims~="defait"] .renoue .zone .zo[pathLength] {
  animation: fil-renoue calc(1.1s * var(--lent)) var(--rebond-doux) both;
}
:root:not([data-anims~="defait"])[data-anims~="trace"] .renoue .zone .zo[pathLength] {
  animation: fil-dessine calc(1.1s * var(--lent)) var(--rebond-doux) both;
}
@keyframes fil-renoue { 0% { stroke-dashoffset: .82; } 100% { stroke-dashoffset: 0; } }
@keyframes fil-dessine { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

/* --- La pelote qui roule pendant un calcul ----------------------------- */

.pelote .pelote-corps { fill: var(--laine); stroke: var(--laine-fonce); stroke-width: 1.8; }
.pelote .pelote-brins { fill: none; stroke: var(--laine-fonce); stroke-width: 1.6; stroke-linecap: round; opacity: .55; }
.pelote .pelote-reflet { fill: none; stroke: var(--laine-clair); stroke-width: 1.6; stroke-linecap: round; opacity: .8; }
.pelote .pelote-visage { display: var(--visage); fill: var(--encre); }
.pelote .pelote-visage path { fill: none; stroke: var(--encre); stroke-width: 1.4; stroke-linecap: round; }

.calcul {
  display: none; align-items: center; gap: .45rem;
  padding: .2rem .65rem .2rem .3rem; border-radius: var(--r-pill);
  background-color: var(--surface); border: var(--bord);
  font-family: var(--mono); font-size: .72rem; color: var(--encre-2); white-space: nowrap;
  opacity: 0; transition: opacity calc(240ms * var(--lent)) ease-out;
  pointer-events: none;
}
:root[data-anims~="pelote"] .calcul { display: inline-flex; }
.calcul.roule { opacity: 1; }
.calcul-piste { position: relative; width: 52px; height: 18px; flex: none; }
.calcul-pelote { position: absolute; left: 0; bottom: 0; width: 18px; height: 18px; }
.calcul-pelote svg { display: block; width: 100%; height: 100%; }
.calcul-fil {
  position: absolute; left: 4px; right: 0; bottom: 1px; height: 2px; border-radius: 2px;
  background: var(--laine-fonce); transform-origin: left; transform: scaleX(.92);
}
.calcul.roule .calcul-pelote { animation: pelote-roule calc(1.6s * var(--lent)) var(--rebond-doux) infinite; }
.calcul.roule .calcul-pelote svg { animation: pelote-tourne calc(1.6s * var(--lent)) linear infinite; }
.calcul.roule .calcul-fil { animation: pelote-devide calc(1.6s * var(--lent)) var(--rebond-doux) infinite; }
@keyframes pelote-roule { 0% { transform: translateX(0); } 70%, 100% { transform: translateX(34px); } }
@keyframes pelote-tourne { to { transform: rotate(540deg); } }
@keyframes pelote-devide { 0% { transform: scaleX(0); opacity: 1; } 70% { transform: scaleX(.92); opacity: 1; } 100% { transform: scaleX(.92); opacity: 0; } }
@media (max-width: 34rem) { .calcul-mot { display: none; } .calcul { padding-right: .3rem; } }
/* Le chargement de l'aperçu porté : la même pelote, en boucle. */
.apercu-charge { display: flex; align-items: center; gap: .6rem; }
.apercu-charge .calcul { display: inline-flex; opacity: 1; padding: .2rem; }

/* --- Le fil qui se tend sur les curseurs ------------------------------- */

.regle { position: relative; }
.regle .fil-tendu {
  position: absolute; left: 0; top: 0; width: 100%; height: 26px;
  overflow: visible; pointer-events: none;
}
.fil-tendu .fil-tire { fill: none; stroke: var(--accent); stroke-width: 3; stroke-linecap: round; }
.fil-tendu .fil-lache { fill: none; stroke: var(--trait-fort); stroke-width: 2; stroke-linecap: round; }
.champ .regle.a-fil input[type="range"] { position: relative; }
.champ .regle.a-fil input[type="range"]::-webkit-slider-runnable-track { background: transparent; }
.champ .regle.a-fil input[type="range"]::-moz-range-track { background: transparent; }
/* Le pouce devient une petite pelote d'accent. */
:root:not([data-theme="classique"]) .champ .regle input[type="range"]::-webkit-slider-thumb {
  height: var(--pouce); border-radius: 50%; background: var(--accent); border-color: var(--accent);
  margin-top: -6px; box-shadow: 0 0 0 2px var(--surface);
}
:root:not([data-theme="classique"]) .champ .regle input[type="range"]::-moz-range-thumb {
  height: var(--pouce); border-radius: 50%; background: var(--accent); border-color: var(--accent);
}

/* --- La maille qui se forme sur « Je tricote » ------------------------- */

.maille-forme { position: fixed; z-index: 90; width: 34px; height: 40px; pointer-events: none; overflow: visible; }
.maille-forme path {
  fill: none; stroke: var(--laine-fonce); stroke-width: 5; stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: 0;
}
.maille-forme { animation: maille-monte calc(1.1s * var(--lent)) var(--rebond) both; }
.maille-forme path { animation: fil-dessine calc(.55s * var(--lent)) ease-out both; }
.maille-forme path + path { animation-delay: calc(.18s * var(--lent)); }
.joue { animation: bouton-pousse calc(.5s * var(--lent)) var(--rebond); }
@keyframes maille-monte { 0% { opacity: 1; transform: translateY(14px) scale(.6); } 60% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(-10px); } }
@keyframes bouton-pousse { 0% { transform: scale(1); } 30% { transform: scale(.9, 1.06); } 100% { transform: scale(1); } }

/* --- La couture du témoin d'enregistrement ----------------------------- */

:root[data-anims~="couture"] .temoin { position: relative; }
:root[data-anims~="couture"] .temoin.frais::after {
  content: ""; position: absolute; left: .3rem; right: .3rem; bottom: -3px; height: 2px;
  background: repeating-linear-gradient(90deg, var(--ok) 0 4px, transparent 4px 8px);
  animation: couture-avance calc(.9s * var(--lent)) linear 3;
}
@keyframes couture-avance { from { background-position: 16px 0; } to { background-position: 0 0; } }

/* --- Brins qui flottent ------------------------------------------------- */

.brins { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 1; }
.brins svg {
  position: absolute; width: 16px; height: 16px; opacity: 0;
  fill: none; stroke: var(--laine-fonce); stroke-width: 1.6; stroke-linecap: round;
  animation: brin-flotte calc(3.2s * var(--lent)) ease-out both;
}
@keyframes brin-flotte { 0% { opacity: 0; transform: translateY(20px) rotate(0); } 18% { opacity: .75; } 100% { opacity: 0; transform: translateY(-40px) translateX(4px) rotate(140deg); } }

/* --- Fenêtres, aperçu porté ------------------------------------------- */

:root:not([data-theme="classique"]) :is(.partage, .demo-technique, .import-patron, .apparence) {
  box-shadow: var(--ombre-1);
}
/* un fond plein derrière la 3D : le motif de la scène, décalé, s'y lisait comme un cadre */
.porte .apercu-vue { background: var(--surface); }

/* --- La fenêtre « Apparence » ----------------------------------------- */

.apparence {
  width: min(30rem, calc(100vw - 1.2rem));
  max-height: calc(100dvh - 1.2rem); overflow-y: auto;
  padding: 1.1rem 1.2rem 1.2rem;
  border: var(--filet); border-radius: var(--r-lg);
  background: var(--surface); color: var(--encre);
}
.apparence::backdrop { background: var(--voile); }
.apparence-groupe { border: 0; margin: .9rem 0 0; padding: 0; min-width: 0; }
.apparence-groupe legend {
  padding: 0; margin-bottom: .45rem;
  font-family: var(--mono); font-size: .72rem; font-weight: 500;
  text-transform: uppercase; letter-spacing: .06em; color: var(--encre-2);
}
.themes-liste { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .4rem; }
.theme-choix {
  position: relative; display: grid; gap: .35rem; min-width: 0;
  padding: .5rem .55rem .55rem; cursor: pointer;
  border: var(--filet); border-radius: var(--r-md); background-color: var(--surface);
}
.theme-choix:hover { border-color: var(--encre-2); }
.theme-choix:has(input:checked) { border: 2px solid var(--encre); padding: calc(.5rem - 1px) calc(.55rem - 1px) calc(.55rem - 1px); }
.theme-choix:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-choix input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.theme-pastille { display: flex; height: 18px; border-radius: 5px; overflow: hidden; box-shadow: inset 0 0 0 1px var(--trait); }
.theme-pastille i { flex: 1; }
.theme-nom { display: grid; gap: 1px; font-size: .86rem; font-weight: 600; line-height: 1.25; min-width: 0; }
.theme-nom small { font-weight: 400; font-size: .74rem; color: var(--encre-2); }
.apparence-seg { display: flex; gap: .3rem; }
.apparence-seg label { flex: 1 1 0; position: relative; min-width: 0; }
.apparence-seg input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.apparence-seg span {
  display: block; padding: .45rem .4rem; text-align: center; cursor: pointer;
  border: var(--filet); border-radius: var(--r-pill); background: var(--surface);
  font-size: .84rem; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.apparence-seg input:checked + span { background: var(--encre); color: var(--surface); border-color: var(--encre); font-weight: 600; }
.apparence-seg input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.apparence-reduit { margin: .45rem 0 0; }
@media (pointer: coarse) { .apparence-seg span { padding: .7rem .4rem; } }
.rail-pied #bt-theme .ic { opacity: .75; }

/* ======================================================================== */
/*  Lisibilité : le patron ne bouloche jamais                               */
/* ======================================================================== */
/* Vue Patron (et Matériel, Suivi, Techniques), mode « Je tricote », livret
 * imprimé : fond plein, aucune texture, filets simples, chiffres
 * tabulaires. La sobriété de Feu de bois, quel que soit le thème. Les jetons
 * sont neutralisés à la racine de ces zones : tout ce qui s'y trouve (et ce
 * qu'on y ajoutera) en hérite. */
.sorties, .tricote, .impression, .tricote-liste {
  --grain: none; --peluches: none; --motif: none; --couture: none; --fuzz: none; --trace: none;
  --filet: 1px solid var(--trait);
  background-color: var(--surface); background-image: none;
}
.sorties .mini { box-shadow: none; }
.sorties .mini::after { content: none; }
.patron, .suivi, .materiel, .tricote {
  font-variant-numeric: tabular-nums lining-nums;
}
.panneau-sortie .patron { font-size: 1rem; line-height: 1.5; }
.panneau-sortie .patron li, .suivi .etapes li { font-size: 1rem; line-height: 1.5; }
.tricote .tricote-texte, .tricote-etape { font-variant-numeric: tabular-nums lining-nums; }

/* ======================================================================== */
/*  Mouvement réduit ou animations coupées : tout est posé, rien ne bouge   */
/* ======================================================================== */
@media (prefers-reduced-motion: reduce) {
  .calcul, .brins, .maille-forme { display: none !important; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
:root[data-calme] .calcul:not(.apercu-charge .calcul), :root[data-calme] .brins, :root[data-calme] .maille-forme { display: none !important; }
:root[data-calme] *, :root[data-calme] *::before, :root[data-calme] *::after { animation: none !important; transition: none !important; }
:root[data-calme] ::view-transition-old(contenu), :root[data-calme] ::view-transition-new(contenu) { animation: none !important; }

@media print {
  .calcul, .brins, .maille-forme, .fil-tendu { display: none !important; }
  .bt::after, .bt::before { content: none !important; }
}
