/* ===================================================================
   FormaSkills Design System — base, layout et composants (§105-184)
   Propriétés logiques uniquement (RTL structurel).
   =================================================================== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;scroll-padding-block-start:calc(var(--fs-sticky-top) + var(--fs-space-sm));scroll-padding-block-end:calc(var(--fs-sticky-bottom) + var(--fs-sticky-bar, 0px) + var(--fs-cookie-h, 0px) + var(--fs-space-sm))}
/* WCAG 2.2 SC 2.4.11 (focus non masqué) — la barre supérieure et la navigation basse restent collées au
   défilement. Sans marge de défilement, un élément atteint à la tabulation arrière est ramené juste
   sous le bord de la fenêtre, donc SOUS la barre : l'anneau de focus existe mais personne ne le voit.
   Les jetons --fs-sticky-top / --fs-sticky-bottom sont ajustés par chaque gabarit (en-tête public,
   barre de quiz, barre d'enregistrement, bandeau cookies). */
body{margin:0;font-family:var(--fs-font);font-size:var(--fs-text-base);line-height:var(--fs-leading);color:var(--fs-text);background:var(--fs-bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;min-height:100vh}
img,svg,video,canvas{display:block;max-width:100%}
img{height:auto}
a{color:var(--fs-link);text-decoration:none;transition:color var(--fs-fast) var(--fs-ease)}
a:hover{color:var(--fs-link-hover)}
h1,h2,h3,h4,h5,h6{margin:0 0 .4em;font-weight:750;line-height:var(--fs-leading-tight);color:var(--fs-text);letter-spacing:-.018em}
h1,h2{font-weight:800;letter-spacing:-.03em}
h1{font-size:var(--fs-text-3xl)}h2{font-size:var(--fs-text-2xl)}h3{font-size:var(--fs-text-xl)}h4{font-size:var(--fs-text-lg)}h5{font-size:var(--fs-text-md)}
p{margin:0 0 1em}
small,.text-xs{font-size:var(--fs-text-xs)}
code,kbd,pre{font-family:var(--fs-font-mono);font-size:.92em}
kbd{display:inline-block;padding:1px 6px;border:1px solid var(--fs-border);border-bottom-width:2px;border-radius:var(--fs-radius-xs);background:var(--fs-surface-sunken);font-size:var(--fs-text-xs);color:var(--fs-text-muted)}
hr{border:0;border-top:1px solid var(--fs-divider);margin:var(--fs-space-lg) 0}
button,input,select,textarea{font:inherit;color:inherit}
button{cursor:pointer;background:none;border:0;padding:0}
:focus-visible{outline:var(--fs-focus-outline);outline-offset:var(--fs-focus-offset);box-shadow:var(--fs-focus-ring);border-radius:var(--fs-radius-sm)}
a:focus-visible,button:focus-visible,summary:focus-visible,[tabindex]:focus-visible,[role="button"]:focus-visible,[role="tab"]:focus-visible{outline:var(--fs-focus-outline);outline-offset:var(--fs-focus-offset)}
.skip-link{position:absolute;inset-block-start:-100px;inset-inline-start:var(--fs-space-md);z-index:calc(var(--fs-z-toast) + 10);padding:10px 18px;border-radius:var(--fs-radius-md);background:var(--fs-primary-solid);color:var(--fs-on-solid);font-weight:600;font-size:var(--fs-text-sm);box-shadow:var(--fs-shadow-lg);transition:inset-block-start var(--fs-fast) var(--fs-ease)}
.skip-link:focus{inset-block-start:var(--fs-space-md);color:var(--fs-on-solid)}
.sr-only-focusable:not(:focus):not(:focus-within){position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
@media (forced-colors:active){:focus-visible{outline:2px solid Highlight;outline-offset:2px}}
::selection{background:var(--fs-primary-soft-2);color:var(--fs-text)}
[hidden]{display:none!important}
.ic{width:var(--fs-icon);height:var(--fs-icon);flex:none;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vertical-align:middle}
.ic-sm{width:var(--fs-icon-sm);height:var(--fs-icon-sm)}.ic-lg{width:var(--fs-icon-lg);height:var(--fs-icon-lg)}.ic-xl{width:var(--fs-icon-xl);height:var(--fs-icon-xl)}
[dir="rtl"] .ic-flip{transform:scaleX(-1)}
/* §121 — toute icone directionnelle est inversee en RTL, sans que l'appelant ait a poser .ic-flip :
   le selecteur porte sur le symbole reference, il couvre donc aussi les icones injectees en JS.
   (Navigateur sans :has() : comportement inchange, .ic-flip reste la pose explicite.) */
[dir="rtl"] .ic:has(> use[href$="#arrow-right"]),
[dir="rtl"] .ic:has(> use[href$="#arrow-left"]),
[dir="rtl"] .ic:has(> use[href$="#arrow-up-right"]),
[dir="rtl"] .ic:has(> use[href$="#chevron-right"]),
[dir="rtl"] .ic:has(> use[href$="#chevron-left"]),
[dir="rtl"] .ic:has(> use[href$="#chevrons-left"]),
[dir="rtl"] .ic:has(> use[href$="#skip-forward"]),
[dir="rtl"] .ic:has(> use[href$="#skip-back"]),
[dir="rtl"] .ic:has(> use[href$="#log-in"]),
[dir="rtl"] .ic:has(> use[href$="#log-out"]),
[dir="rtl"] .ic:has(> use[href$="#send"]),
[dir="rtl"] .ic:has(> use[href$="#share"]),
[dir="rtl"] .ic:has(> use[href$="#external-link"]){transform:scaleX(-1)}
.sr-only{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}

/* ---------- Utilitaires ---------- */
.container{width:100%;max-width:var(--fs-content-max);margin-inline:auto;padding-inline:var(--fs-space-lg)}
.flex{display:flex}.inline-flex{display:inline-flex}.items-center{align-items:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.flex-1{flex:1 1 0%;min-width:0}.grow{flex-grow:1}
.gap-1{gap:4px}.gap-2{gap:8px}.gap-3{gap:12px}.gap-4{gap:16px}.gap-5{gap:20px}.gap-6{gap:24px}.gap-8{gap:32px}
.grid{display:grid}.grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-4{grid-template-columns:repeat(4,minmax(0,1fr))}.grid-auto{grid-template-columns:repeat(auto-fill,minmax(260px,1fr))}
.col-span-2{grid-column:span 2}.col-span-3{grid-column:span 3}
.mt-0{margin-top:0}.mt-1{margin-top:4px}.mt-2{margin-top:8px}.mt-3{margin-top:12px}.mt-4{margin-top:16px}.mt-6{margin-top:24px}.mt-8{margin-top:32px}.mb-0{margin-bottom:0}.mb-1{margin-bottom:4px}.mb-2{margin-bottom:8px}.mb-3{margin-bottom:12px}.mb-4{margin-bottom:16px}.mb-6{margin-bottom:24px}.mb-8{margin-bottom:32px}
.ms-auto{margin-inline-start:auto}.me-auto{margin-inline-end:auto}.mx-auto{margin-inline:auto}
.p-0{padding:0}.p-2{padding:8px}.p-3{padding:12px}.p-4{padding:16px}.p-6{padding:24px}.px-4{padding-inline:16px}.py-2{padding-block:8px}
.w-full{width:100%}.h-full{height:100%}.min-w-0{min-width:0}.text-center{text-align:center}.text-start{text-align:start}.text-end{text-align:end}
.text-sm{font-size:var(--fs-text-sm)}.text-md{font-size:var(--fs-text-md)}.text-lg{font-size:var(--fs-text-lg)}.text-xl{font-size:var(--fs-text-xl)}.text-2xl{font-size:var(--fs-text-2xl)}.text-3xl{font-size:var(--fs-text-3xl)}
.font-medium{font-weight:500}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-extrabold{font-weight:800}
.muted{color:var(--fs-text-muted)}.faint{color:var(--fs-text-faint)}.text-secondary{color:var(--fs-text-secondary)}
.text-primary{color:var(--fs-primary-text)}.text-mod-alert{color:var(--fs-mod-alert-text)}.text-mod-progress{color:var(--fs-mod-progress-text)}.text-success{color:var(--fs-success-text)}.text-danger{color:var(--fs-danger-text)}.text-warning{color:var(--fs-warning-text)}.text-info{color:var(--fs-info-text)}.text-accent{color:var(--fs-accent-text)}
.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.clamp-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.relative{position:relative}.hidden{display:none}.block{display:block}.inline-block{display:inline-block}.overflow-auto{overflow:auto}.rounded{border-radius:var(--fs-radius-md)}.rounded-full{border-radius:var(--fs-radius-full)}.shadow{box-shadow:var(--fs-shadow-md)}
.nowrap{white-space:nowrap}.tabular{font-variant-numeric:tabular-nums}.ltr{direction:ltr;unicode-bidi:isolate}.cursor-pointer{cursor:pointer}.pointer{cursor:pointer}
.gradient-text{background:var(--fs-grad-primary);-webkit-background-clip:text;background-clip:text;color:transparent}
.gradient-text-ai{background:var(--fs-grad-ai);-webkit-background-clip:text;background-clip:text;color:transparent}
.divider{border-top:1px solid var(--fs-divider);margin-block:var(--fs-space-md)}
@media (max-width:1100px){.grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:720px){.grid-2,.grid-3,.grid-4{grid-template-columns:minmax(0,1fr)}.col-span-2,.col-span-3{grid-column:auto}.container{padding-inline:var(--fs-space-md)}.hide-mobile{display:none!important}}
@media (min-width:721px){.show-mobile{display:none!important}}

/* ---------- Boutons (§116-117 ; proposition 01, ds6 §34.1) ----------
   Gabarit de la maquette (.button) : hauteur 48 / 43 / 57 px, rayon 13 / 12 / 15 px, graisse 800, survol soulevé
   de 2 px. Le principal porte le dégradé 118deg cyan → bleu → violet → magenta, son ombre colorée et un reflet
   interne d'un pixel ; le texte garde une légère ombre portée pour rester lisible sur l'extrémité cyan. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-block-size:3rem;padding:0 22px;border-radius:var(--fs-radius-btn);font-family:var(--fs-font);font-weight:800;font-size:var(--fs-text-base);line-height:1.15;letter-spacing:-.005em;border:1px solid transparent;white-space:nowrap;transition:transform .2s var(--fs-ease),box-shadow .2s var(--fs-ease),background .2s var(--fs-ease),color var(--fs-fast),border-color var(--fs-fast);user-select:none;position:relative;text-decoration:none}
.btn:hover{transform:translateY(-2px)}.btn:active{transform:translateY(0) scale(.99)}
.btn:disabled,.btn.disabled{opacity:.55;pointer-events:none;box-shadow:none}
.btn .ic{width:var(--fs-icon-md);height:var(--fs-icon-md)}
.btn-sm{min-block-size:2.6875rem;padding:0 18px;gap:8px;font-size:var(--fs-text-sm);border-radius:var(--fs-radius-btn-sm)}.btn-sm .ic{width:var(--fs-icon-sm);height:var(--fs-icon-sm)}
.btn-lg{min-block-size:3.5625rem;padding:0 27px;font-size:var(--fs-text-md);border-radius:var(--fs-radius-btn-lg)}
/* WCAG 2.2 SC 2.5.8 : même le plus petit bouton offre une cible de 24 × 24 px — sa hauteur ne dépend
   plus de la bordure transparente héritée de .btn ni de la police choisie. */
.btn-xs{min-block-size:var(--fs-target-min);min-inline-size:var(--fs-target-min);padding:4px 10px;font-size:var(--fs-text-xs);font-weight:750;border-radius:var(--fs-radius-sm);gap:5px}.btn-xs .ic{width:var(--fs-icon-xs);height:var(--fs-icon-xs)}
.btn-primary{background:var(--fs-grad-primary);color:var(--fs-on-solid);box-shadow:var(--fs-shadow-btn);text-shadow:0 1px 1px rgba(4,9,26,.22)}
.btn-primary:hover{color:var(--fs-on-solid);box-shadow:var(--fs-shadow-btn-hover)}
.btn-primary:active{box-shadow:var(--fs-shadow-btn)}
.btn-secondary{background:var(--fs-primary-soft);color:var(--fs-primary-text);border-color:var(--fs-primary-border)}
.btn-secondary:hover{background:var(--fs-primary-soft-2);color:var(--fs-primary-text);border-color:var(--fs-primary)}
/* Secondaire « contour » : pastille blanche de la maquette (.filter-button), survol violet. */
.btn-outline{background:var(--fs-surface);color:var(--fs-text-secondary);border-color:var(--fs-filter-border)}
.btn-outline:hover{border-color:var(--fs-filter-hover-border);color:var(--fs-filter-hover);background:var(--fs-surface)}
.btn-ghost{background:transparent;color:var(--fs-text-secondary)}
.btn-ghost:hover{background:var(--fs-surface-sunken);color:var(--fs-text)}
.btn-danger{background:var(--fs-danger-solid);color:var(--fs-on-solid);box-shadow:0 10px 24px rgba(222,42,75,.28),inset 0 1px rgba(255,255,255,.25)}.btn-danger:hover{background:var(--fs-danger-solid-hover);color:var(--fs-on-solid)}.btn-danger:active{background:var(--fs-danger-active)}
.btn-danger-soft{background:var(--fs-danger-soft);color:var(--fs-danger-text);border-color:var(--fs-danger-border)}.btn-danger-soft:hover{background:var(--fs-danger-soft-2);color:var(--fs-danger-text)}
.btn-success{background:var(--fs-grad-success-solid);color:var(--fs-on-solid);box-shadow:0 10px 24px rgba(13,128,85,.26),inset 0 1px rgba(255,255,255,.25)}.btn-success:hover{color:var(--fs-on-solid);filter:brightness(1.06)}
.btn-accent{background:var(--fs-grad-warm-solid);color:var(--fs-on-solid);box-shadow:0 10px 24px rgba(181,22,166,.24),inset 0 1px rgba(255,255,255,.25)}.btn-accent:hover{color:var(--fs-on-solid);filter:brightness(1.06)}
/* Bouton blanc de la maquette (.button--white) : encre violet profond, ombre portée sur fond coloré. */
.btn-white{background:var(--fs-on-solid);color:var(--fs-btn-white-text);box-shadow:var(--fs-shadow-btn-white)}.btn-white:hover{background:var(--fs-on-solid);color:var(--fs-btn-white-text)}
/* Fantôme sur fond sombre ou coloré (.button--ghost) : voile blanc translucide, filet clair. */
.card-gradient .btn-ghost,.card-gradient .btn-outline,.on-dark-surface .btn-ghost{color:var(--fs-on-navy);border-color:rgba(255,255,255,.18);background:rgba(255,255,255,.055)}
.card-gradient .btn-ghost:hover,.card-gradient .btn-outline:hover,.on-dark-surface .btn-ghost:hover{color:var(--fs-on-solid);background:rgba(255,255,255,.1)}
.btn-ai{background:var(--fs-grad-ai-solid);color:var(--fs-on-solid);box-shadow:var(--fs-shadow-ai),inset 0 1px rgba(255,255,255,.25);position:relative;overflow:hidden}
.btn-ai::after{content:"";position:absolute;inset:0;background:linear-gradient(120deg,transparent 30%,rgba(255,255,255,.28) 50%,transparent 70%);transform:translateX(-120%);transition:transform .6s var(--fs-ease)}
.btn-ai:hover::after{transform:translateX(120%)}
.btn-ai:hover{color:var(--fs-on-solid);box-shadow:0 0 0 1px rgba(124,58,237,.3),0 14px 34px -8px rgba(59,130,246,.55)}
.btn-ai-soft{background:var(--fs-mod-ai-soft);color:var(--fs-primary-text);border-color:var(--fs-primary-border)}
/* Bouton icône : carré de 44 px (cible confortable), rayon de la maquette ; petit 36 px, très petit 28 px. */
.btn-icon{padding:0;border-radius:var(--fs-radius-md);width:44px;height:44px;min-block-size:0}.btn-icon.btn-sm{width:36px;height:36px;padding:0;border-radius:var(--fs-radius-btn-sm)}.btn-icon.btn-xs{width:28px;height:28px;padding:0;border-radius:var(--fs-radius-sm)}
/* Dans une cellule de tableau, le petit bouton reste compact : la ligne ne prend pas 43 px pour une action. */
.table .btn-sm:not(.btn-icon),.table-toolbar .btn-sm:not(.btn-icon),.menu .btn-sm:not(.btn-icon){min-block-size:2.25rem;padding-inline:14px}
.btn-block{width:100%}
/* Ajout au panier sans rechargement (§118) : le bouton confirme sur place (fond succès + coche qui apparaît),
   le compteur du panier « rebondit » une fois. 220 ms, neutralisé par prefers-reduced-motion (tokens.css). */
.btn.is-added,.btn.is-added:hover{background:var(--fs-success-soft);color:var(--fs-success-text);border-color:var(--fs-success-border);box-shadow:none;filter:none}
.btn.is-added .ic{animation:pop var(--fs-normal) var(--fs-ease)}
.dot-badge.bump{animation:cartBump var(--fs-normal) var(--fs-ease)}
@keyframes cartBump{0%{transform:scale(1)}45%{transform:scale(1.35)}100%{transform:scale(1)}}
.btn.loading{color:transparent!important;pointer-events:none}
.btn.loading::before{content:"";position:absolute;width:18px;height:18px;border:2px solid rgba(255,255,255,.4);border-top-color:var(--fs-on-solid);border-radius:50%;animation:spin .7s linear infinite}
.btn-outline.loading::before,.btn-ghost.loading::before{border-color:var(--fs-border-strong);border-top-color:var(--fs-primary)}
@keyframes spin{to{transform:rotate(360deg)}}
.btn-group{display:inline-flex}.btn-group .btn{border-radius:0}.btn-group .btn:hover{transform:none}.btn-group .btn:first-child{border-start-start-radius:var(--fs-radius-btn);border-end-start-radius:var(--fs-radius-btn)}.btn-group .btn:last-child{border-start-end-radius:var(--fs-radius-btn);border-end-end-radius:var(--fs-radius-btn)}

/* ---------- Badges (§136) ---------- */
/* Proposition 01 (ds6) : pastille pleine arrondie, filet d'un ton plus soutenu que le fond, graisse 750 —
   les « niveaux » et étiquettes de la maquette (.course-pill, .live-badge). */
.badge{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:var(--fs-radius-full);border:1px solid var(--fs-border);font-size:var(--fs-text-xs);font-weight:750;letter-spacing:.01em;line-height:1.5;white-space:nowrap;background:var(--fs-surface-sunken);color:var(--fs-text-secondary)}
[dir="rtl"] .badge{letter-spacing:0}
.badge .dot{width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
/* §136 — le statut ne repose jamais sur la seule couleur : chaque famille a sa FORME de pastille
   (actif : disque · en attente : losange · en cours : anneau · suspendu : carré · expiré : trait). */
.badge-warning .dot{border-radius:0;transform:rotate(45deg)}
.badge-info .dot{background:transparent;box-shadow:inset 0 0 0 1.5px currentColor}
.badge-danger .dot{border-radius:0}
.badge-neutral .dot{height:2px;width:8px;border-radius:var(--fs-radius-full)}
.badge-success{background:var(--fs-success-soft);color:var(--fs-success-text);border-color:var(--fs-success-border)}.badge-warning{background:var(--fs-warning-soft);color:var(--fs-warning-text);border-color:var(--fs-warning-border)}.badge-danger{background:var(--fs-danger-soft);color:var(--fs-danger-text);border-color:var(--fs-danger-border)}.badge-info{background:var(--fs-info-soft);color:var(--fs-info-text);border-color:var(--fs-info-border)}.badge-primary{background:var(--fs-primary-soft);color:var(--fs-primary-text);border-color:var(--fs-primary-border)}.badge-accent{background:var(--fs-accent-soft);color:var(--fs-accent-text);border-color:var(--fs-accent-border)}.badge-neutral{background:var(--fs-surface-sunken);color:var(--fs-text-muted)}.badge-orange{background:var(--fs-mod-course-soft);color:var(--fs-course-text)}.badge-cyan{background:var(--fs-mod-cert-soft);color:var(--fs-info-text)}.badge-progress{background:var(--fs-mod-progress-soft);color:var(--fs-mod-progress-text)}.badge-notif{background:var(--fs-mod-notif-soft);color:var(--fs-mod-notif-text)}.badge-alert{background:var(--fs-mod-alert-soft);color:var(--fs-mod-alert-text)}
.badge-live{background:var(--fs-accent-soft);color:var(--fs-accent-text)}.badge-live .dot{animation:pulse 1.4s infinite}
.badge-ai{background:var(--fs-grad-ai-solid);color:var(--fs-on-solid);border-color:transparent}.badge-gradient{background:var(--fs-grad-filter);color:var(--fs-on-solid);border-color:transparent}
.badge-live{border-color:var(--fs-accent-border)}
.badge-lg{padding:6px 14px;font-size:var(--fs-text-sm)}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.4;transform:scale(.8)}}
.chip{display:inline-flex;align-items:center;gap:6px;min-block-size:2.5rem;padding:0 16px;border-radius:var(--fs-radius-full);border:1px solid var(--fs-filter-border);background:var(--fs-surface);font-size:var(--fs-text-sm);font-weight:750;color:var(--fs-filter-text);cursor:pointer;transition:all .2s var(--fs-ease)}
.chip:hover{border-color:var(--fs-filter-hover-border);color:var(--fs-filter-hover);background:var(--fs-surface)}
/* État actif de la maquette (.filter-button.active) : dégradé bleu → violet → magenta et ombre colorée. */
.chip.active,.chip[aria-pressed="true"],.chip[aria-selected="true"]{background:var(--fs-grad-filter);color:var(--fs-on-solid);border-color:transparent;box-shadow:var(--fs-shadow-filter)}

/* ---------- Cartes (§112) ---------- */
.card{background:var(--fs-surface);border:1px solid var(--fs-border);border-radius:var(--fs-radius-xl);box-shadow:var(--fs-shadow-card);transition:box-shadow .24s var(--fs-ease),transform .24s var(--fs-ease),border-color var(--fs-fast)}
.card-hover:hover{box-shadow:var(--fs-shadow-card-hover);transform:translateY(-4px);border-color:var(--fs-border)}
.card-body{padding:var(--fs-space-lg)}.card-body-sm{padding:var(--fs-space-md)}
.card-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px var(--fs-space-lg) 0}
.card-header h3,.card-header h2{margin:0;font-size:var(--fs-text-lg);font-weight:800;letter-spacing:-.02em}
.card-header + .card-body{padding-top:14px}
.card-footer{padding:14px var(--fs-space-lg);border-top:1px solid var(--fs-divider);display:flex;align-items:center;gap:12px}
.card-accent{position:relative;overflow:hidden}
.card-accent::before{content:"";position:absolute;inset-block:0;inset-inline-start:0;width:4px;background:var(--accent,var(--fs-grad-primary));border-start-start-radius:var(--fs-radius-xl);border-end-start-radius:var(--fs-radius-xl)}
/* Panneau coloré (bandeau « reprendre », mise en avant) : fond du panneau formateur de la maquette, texte blanc lisible. */
.card-gradient{background:var(--fs-grad-panel);color:var(--fs-on-solid);border:0;box-shadow:0 28px 70px rgba(32,31,105,.25)}.card-gradient h1,.card-gradient h2,.card-gradient h3,.card-gradient .muted{color:var(--fs-on-solid)}.card-gradient .muted{opacity:.85}
.card-ai{background:linear-gradient(135deg,rgba(124,58,237,.06),rgba(6,182,212,.06));border:1px solid rgba(124,58,237,.18);box-shadow:var(--fs-shadow-ai)}
.card-glass{background:var(--fs-surface-glass);backdrop-filter:var(--fs-blur-glass);-webkit-backdrop-filter:var(--fs-blur-glass);border:1px solid rgba(255,255,255,.4)}
.card-flat{box-shadow:none}
.card-sunken{background:var(--fs-surface-sunken);border:0;box-shadow:none}

/* KPI (§133) */
.kpi{display:flex;flex-direction:column;gap:6px;padding:20px 22px;position:relative;overflow:hidden}
.kpi-head{display:flex;align-items:center;justify-content:space-between;gap:10px}
.kpi-title{font-size:var(--fs-text-xs);font-weight:750;letter-spacing:.05em;text-transform:uppercase;color:var(--fs-text-muted)}
[dir="rtl"] .kpi-title{letter-spacing:0}
.kpi-icon{width:44px;height:44px;border-radius:var(--fs-radius-lg);display:grid;place-items:center;background:var(--kpi-soft,var(--fs-primary-soft));color:var(--kpi-color,var(--fs-primary));box-shadow:inset 0 0 0 1px rgba(56,134,220,.08)}
.kpi-icon .ic{width:var(--fs-icon);height:var(--fs-icon)}
.kpi-value{font-size:30px;font-weight:800;letter-spacing:-.035em;line-height:1.1;font-variant-numeric:tabular-nums;color:var(--fs-text)}
.kpi-delta{display:inline-flex;align-items:center;gap:4px;font-size:var(--fs-text-xs);font-weight:600;padding:2px 8px;border-radius:var(--fs-radius-full)}
.kpi-delta.up{background:var(--fs-success-soft);color:var(--fs-success-text)}.kpi-delta.down{background:var(--fs-danger-soft);color:var(--fs-danger-text)}.kpi-delta.flat{background:var(--fs-surface-sunken);color:var(--fs-text-muted)}
.kpi-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 8px;font-size:var(--fs-text-xs);color:var(--fs-text-muted)}
/* Une hausse n'est pas toujours une bonne nouvelle (impayes, litiges) : .bad inverse la lecture. */
.kpi-delta.up.bad{background:var(--fs-danger-soft);color:var(--fs-danger-text)}
.kpi-delta.down.bad{background:var(--fs-success-soft);color:var(--fs-success-text)}
.kpi-period{min-width:0;overflow-wrap:anywhere}
.kpi-hint{display:block;margin-block-start:6px;color:var(--fs-text-faint);font-size:var(--fs-text-xs)}
.kpi-spark{height:34px;width:100%}
.kpi-spark svg{width:100%;height:100%;overflow:visible}
.kpi.kpi-primary{--kpi-color:var(--fs-primary);--kpi-soft:var(--fs-primary-soft)}.kpi.kpi-success{--kpi-color:var(--fs-success);--kpi-soft:var(--fs-success-soft)}.kpi.kpi-accent{--kpi-color:var(--fs-accent);--kpi-soft:var(--fs-accent-soft)}.kpi.kpi-info{--kpi-color:var(--fs-info);--kpi-soft:var(--fs-info-soft)}.kpi.kpi-warning{--kpi-color:var(--fs-warning);--kpi-soft:var(--fs-warning-soft)}.kpi.kpi-orange{--kpi-color:var(--fs-mod-course);--kpi-soft:var(--fs-mod-course-soft)}.kpi.kpi-secondary{--kpi-color:var(--fs-secondary);--kpi-soft:var(--fs-secondary-soft)}
/* Modules « progression », « notifications », « alertes / échéances » (§109) : accent d’icône, jamais de fond agressif. */
.kpi.kpi-progress{--kpi-color:var(--fs-mod-progress);--kpi-soft:var(--fs-mod-progress-soft)}.kpi.kpi-notif{--kpi-color:var(--fs-mod-notif-text);--kpi-soft:var(--fs-mod-notif-soft)}.kpi.kpi-alert{--kpi-color:var(--fs-mod-alert);--kpi-soft:var(--fs-mod-alert-soft)}

/* Smart cards (§134) */
.smart{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:var(--fs-radius-lg);background:var(--sc-bg,var(--fs-warning-soft));border:1px solid var(--sc-border,transparent)}
.smart .ic{width:var(--fs-icon-lead);height:var(--fs-icon-lead);color:var(--sc-color,var(--fs-warning))}
.smart strong{display:block;font-size:var(--fs-text-md)}
.smart-warning{--sc-bg:var(--fs-warning-soft);--sc-color:var(--fs-warning-text);--sc-border:var(--fs-warning-border)}.smart-primary{--sc-bg:var(--fs-primary-soft);--sc-color:var(--fs-primary-text);--sc-border:var(--fs-primary-border)}.smart-info{--sc-bg:var(--fs-info-soft);--sc-color:var(--fs-info-text);--sc-border:var(--fs-info-border)}.smart-danger{--sc-bg:var(--fs-danger-soft);--sc-color:var(--fs-danger-text);--sc-border:var(--fs-danger-border)}.smart-success{--sc-bg:var(--fs-success-soft);--sc-color:var(--fs-success-text);--sc-border:var(--fs-success-border)}

/* ---------- Formulaires (§137) ---------- */
.form-group{display:flex;flex-direction:column;gap:6px;margin-bottom:var(--fs-space-md)}
.form-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--fs-space-md)}
.form-row-3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media (max-width:720px){.form-row,.form-row-3{grid-template-columns:minmax(0,1fr)}}
label,.label{font-size:var(--fs-text-sm);font-weight:700;color:var(--fs-text-secondary)}
label .req{color:var(--fs-danger-text)}
.hint{font-size:var(--fs-text-xs);color:var(--fs-text-muted);min-width:0;overflow-wrap:break-word}
.input,.select,.textarea,input[type=text].input,input[type=email].input{display:block;width:100%;padding:11px 14px;border:1px solid var(--fs-border-input);border-radius:var(--fs-radius-md);background:var(--fs-surface);color:var(--fs-text);font-size:var(--fs-text-base);transition:border-color var(--fs-fast),box-shadow var(--fs-fast);min-height:44px}
.input:hover,.select:hover,.textarea:hover{border-color:var(--fs-border-input-hover)}
/* Focus de la maquette : filet violet + anneau cyan (thème clair), filet cyan + anneau violet (sombre). */
.input:focus,.select:focus,.textarea:focus{outline:none;border-color:var(--fs-focus-color);box-shadow:var(--fs-focus-ring)}
.input::placeholder,.textarea::placeholder{color:var(--fs-text-faint)}
.input.is-invalid,.textarea.is-invalid,.select.is-invalid{border-color:var(--fs-danger);box-shadow:0 0 0 3px var(--fs-danger-soft)}
.input.is-valid{border-color:var(--fs-success)}
/* Même hauteur que .btn-sm (43 px) : champs, listes et boutons d'une barre de filtres s'alignent (18/09). */
.input-sm{padding:7px 11px;min-height:2.6875rem;font-size:var(--fs-text-sm);border-radius:var(--fs-radius-sm)}
.input-lg{padding:14px 18px;min-height:52px;font-size:var(--fs-text-md);border-radius:var(--fs-radius-lg)}
.textarea{min-height:110px;resize:vertical;line-height:1.55}
.select{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748B' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center;padding-inline-end:38px}
[dir="rtl"] .select{background-position:left 12px center}
.input-group{position:relative;display:flex;align-items:center}
.input-group .input{padding-inline-start:42px}
/* Le champ qui suit l'icône de tête garde sa place même quand il est typé : input[type=email].input,
   plus précis que .input-group .input, ramenait le retrait à 14px et l'adresse passait sous l'enveloppe. */
.input-group>.ic~.input{padding-inline-start:42px}
/* Seule l'icône DE TÊTE est positionnée : l'œil d'un bouton de fin de champ s'étirait sinon hors du bouton. */
.input-group>.ic{position:absolute;inset-inline-start:14px;color:var(--fs-text-faint);pointer-events:none;width:var(--fs-icon-md);height:var(--fs-icon-md)}
.input-group .input-addon{position:absolute;inset-inline-end:12px;color:var(--fs-text-muted);font-size:var(--fs-text-sm)}
.input-group .input.has-addon{padding-inline-end:56px}
/* Afficher / masquer le mot de passe : commande ajoutée à chaque champ mot de passe (FS.pwToggle). */
.pw-wrap{position:relative;display:block;flex:1 1 auto;min-width:0}
.pw-wrap>.input.has-addon{padding-inline-end:48px}
.input-group .pw-toggle,.pw-wrap>.pw-toggle{position:absolute;inset-inline-end:4px;top:50%;transform:translateY(-50%);display:inline-grid;place-items:center;width:36px;height:36px;padding:0;border:0;border-radius:var(--fs-radius-sm);background:transparent;color:var(--fs-text-muted);cursor:pointer;transition:color var(--fs-fast),background var(--fs-fast)}
.pw-toggle:hover{color:var(--fs-text);background:var(--fs-surface-sunken)}
.pw-toggle:focus-visible{outline:var(--fs-focus-outline);outline-offset:-2px}
.pw-toggle[aria-pressed="true"]{color:var(--fs-primary-text)}
.pw-toggle .ic{width:var(--fs-icon-md);height:var(--fs-icon-md)}
.field-error{font-size:var(--fs-text-xs);color:var(--fs-danger-text);display:flex;align-items:center;gap:4px}
.check{display:flex;align-items:flex-start;gap:10px;cursor:pointer;font-weight:500;color:var(--fs-text-secondary);font-size:var(--fs-text-base)}
.check input{appearance:none;width:20px;height:20px;flex:none;border:1.5px solid var(--fs-border-input);border-radius:var(--fs-radius-xs);background:var(--fs-surface);display:grid;place-items:center;transition:all var(--fs-fast);margin-top:1px;cursor:pointer}
.check input[type=radio]{border-radius:50%}
.check input:checked{background:var(--fs-grad-filter);border-color:transparent}
.check input[type=checkbox]:checked::after{content:"";width:6px;height:10px;border:solid var(--fs-on-solid);border-width:0 2px 2px 0;transform:rotate(45deg) translate(-1px,-1px)}
.check input[type=radio]:checked::after{content:"";width:8px;height:8px;border-radius:50%;background:var(--fs-on-solid)}
.check input:focus-visible{box-shadow:var(--fs-focus-ring)}
.toggle{position:relative;display:inline-flex;align-items:center;gap:10px;cursor:pointer;font-weight:500}
.toggle input{position:absolute;opacity:0;width:0;height:0}
.toggle .track{width:44px;height:26px;border-radius:var(--fs-radius-full);background:var(--fs-border-input);position:relative;transition:background var(--fs-normal) var(--fs-ease);flex:none}
.toggle .track::after{content:"";position:absolute;top:3px;inset-inline-start:3px;width:20px;height:20px;border-radius:50%;background:var(--fs-on-solid);box-shadow:0 1px 3px rgba(0,0,0,.25);transition:transform var(--fs-normal) var(--fs-ease)}
.toggle input:checked+.track{background:var(--fs-grad-filter)}
.toggle input:checked+.track::after{transform:translateX(18px)}
[dir="rtl"] .toggle input:checked+.track::after{transform:translateX(-18px)}
.toggle input:focus-visible+.track{box-shadow:var(--fs-focus-ring)}
.radio-cards{display:grid;gap:10px}
.radio-card{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border:1.5px solid var(--fs-border-input);border-radius:var(--fs-radius-lg);cursor:pointer;transition:all var(--fs-fast);background:var(--fs-surface)}
.radio-card:hover{border-color:var(--fs-primary-border)}
.radio-card.active,.radio-card:has(input:checked){border-color:var(--fs-primary);background:var(--fs-primary-soft);box-shadow:0 0 0 1px var(--fs-primary)}
.radio-card input{margin-top:3px;accent-color:var(--fs-primary)}
.radio-card strong{display:block}
.radio-card .ic{width:var(--fs-icon-lead);height:var(--fs-icon-lead);color:var(--fs-primary-text);flex:none;margin-top:2px}
.upload-zone{display:block;border:2px dashed var(--fs-border-strong);border-radius:var(--fs-radius-xl);padding:32px 20px;text-align:center;color:var(--fs-text-muted);background:var(--fs-bg-subtle);transition:all var(--fs-fast);cursor:pointer}
.upload-zone:hover,.upload-zone.drag{border-color:var(--fs-primary);background:var(--fs-primary-soft);color:var(--fs-primary-text)}
.upload-zone.drag{transform:scale(1.01)}
.upload-zone:focus-visible,.upload-zone:has(input:focus-visible){outline:var(--fs-focus-outline);outline-offset:var(--fs-focus-offset)}
.upload-zone.busy{opacity:.75;pointer-events:none}
/* Format ou taille refusés : la bordure passe au rouge ET un message explicite suit la zone (§165, pas la couleur seule). */
.upload-zone.is-invalid{border-color:var(--fs-danger);background:var(--fs-danger-soft)}
.upload-error{margin-block-start:8px}
/* Fichiers déposés (§165) : aperçu, progression d'envoi, commande de retrait. */
.upload-files{list-style:none;margin:10px 0 0;padding:0;display:flex;flex-direction:column;gap:8px}
.upload-file{display:flex;align-items:center;gap:12px;padding:8px 10px;border:1px solid var(--fs-border);border-radius:var(--fs-radius-md);background:var(--fs-surface);animation:fadeIn var(--fs-normal) var(--fs-ease)}
.upload-file.is-done{border-color:var(--fs-success-border);background:var(--fs-success-soft)}
.upload-file.is-error{border-color:var(--fs-danger-border);background:var(--fs-danger-soft)}
.upload-file.out{opacity:0;transform:translateY(-4px);transition:opacity var(--fs-normal),transform var(--fs-normal)}
.upload-thumb{width:44px;height:44px;flex:none;border-radius:var(--fs-radius-sm);background:var(--fs-surface-sunken);display:grid;place-items:center;overflow:hidden;color:var(--fs-primary-text)}
.upload-thumb img{width:100%;height:100%;object-fit:cover}
.upload-thumb .ic{width:var(--fs-icon-md);height:var(--fs-icon-md)}
.upload-meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.upload-meta strong{font-size:var(--fs-text-sm);font-weight:600;color:var(--fs-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.upload-meta small{font-size:var(--fs-text-xs);color:var(--fs-text-muted);font-variant-numeric:tabular-nums}
.upload-file.is-done .upload-meta small{color:var(--fs-success-text)}.upload-file.is-error .upload-meta small{color:var(--fs-danger-text)}
.upload-meta .upload-progress{margin-top:4px;height:4px}
.upload-remove{flex:none}
.upload-zone .ic{width:var(--fs-icon-2xl);height:var(--fs-icon-2xl);margin:0 auto 10px;color:var(--fs-primary-text)}
.upload-zone strong{display:block;color:var(--fs-text);font-size:var(--fs-text-md)}
.upload-progress{height:6px;border-radius:var(--fs-radius-full);background:var(--fs-surface-sunken);overflow:hidden;margin-top:12px}
.upload-progress span{display:block;height:100%;background:var(--fs-grad-primary);width:0;transition:width .2s}
.upload-file.is-done .upload-progress span{background:var(--fs-grad-progress)}
.file-pill{display:inline-flex;align-items:center;gap:8px;padding-block:6px;padding-inline:8px 10px;border-radius:var(--fs-radius-md);background:var(--fs-surface-sunken);font-size:var(--fs-text-sm);max-width:100%}
.file-pill .ic{width:var(--fs-icon-sm);height:var(--fs-icon-sm);color:var(--fs-primary-text)}
.rich{min-height:220px}
.editor-toolbar{display:flex;flex-wrap:wrap;gap:2px;padding:6px;border:1px solid var(--fs-border);border-bottom:0;border-radius:var(--fs-radius-md) var(--fs-radius-md) 0 0;background:var(--fs-surface-sunken)}
.editor-toolbar button{padding:6px 8px;border-radius:var(--fs-radius-xs);color:var(--fs-text-secondary)}
.editor-toolbar button:hover,.editor-toolbar button.active{background:var(--fs-surface);color:var(--fs-primary-text)}
.editor-toolbar .sep{width:1px;background:var(--fs-border);margin:4px 4px}
.editor{min-height:200px;padding:14px;border:1px solid var(--fs-border);border-radius:0 0 var(--fs-radius-md) var(--fs-radius-md);background:var(--fs-surface);outline:none;line-height:1.6}
.editor:focus{border-color:var(--fs-primary);box-shadow:var(--fs-focus-ring)}
.editor img{max-width:100%;border-radius:var(--fs-radius-sm)}
.editor h2,.editor h3{margin-top:1em}
.prose{line-height:1.7;color:var(--fs-text-secondary);font-size:var(--fs-text-md)}
.prose h2,.prose h3,.prose h4{color:var(--fs-text);margin-top:1.4em}
.prose img{border-radius:var(--fs-radius-lg);margin:1em 0}
.prose ul,.prose ol{padding-inline-start:1.4em}
.prose blockquote{border-inline-start:4px solid var(--fs-primary-border);padding-inline-start:16px;margin:1em 0;color:var(--fs-text-muted);font-style:italic}
.prose pre{background:var(--fs-code-bg);color:var(--fs-code-text);padding:16px;border-radius:var(--fs-radius-md);overflow:auto;direction:ltr}
.prose code{background:var(--fs-surface-sunken);padding:2px 6px;border-radius:var(--fs-radius-2xs)}
.prose pre code{background:none;padding:0}
.prose table{width:100%;border-collapse:collapse}.prose td,.prose th{border:1px solid var(--fs-border);padding:8px 10px}

/* ---------- Date Picker & Calendar (§169) ----------
   Le sélecteur natif n'est ni stylable ni cohérent d'un navigateur à l'autre : le Design System
   fournit son propre calendrier, greffé sur un <input type="date"> qui reste la source de vérité
   (validation navigateur, saisie clavier, envoi du formulaire). Propriétés logiques → RTL natif. */
.fs-date{position:relative;display:block}
.fs-date>.input{padding-inline-end:40px}
.fs-date .fs-date-btn{position:absolute;inset-inline-end:6px;inset-block-start:50%;transform:translateY(-50%);width:32px;height:32px;display:grid;place-items:center;border-radius:var(--fs-radius-sm);color:var(--fs-text-muted);background:transparent}
.fs-date .fs-date-btn:hover{background:var(--fs-surface-sunken);color:var(--fs-primary-text)}
.fs-date .fs-date-btn .ic{width:var(--fs-icon-md);height:var(--fs-icon-md)}
/* Le calendrier natif ferait doublon avec le nôtre. */
.fs-date>.input::-webkit-calendar-picker-indicator{display:none}

.fs-cal{background:var(--fs-surface-raised);border:1px solid var(--fs-border);border-radius:var(--fs-radius-lg);box-shadow:var(--fs-shadow-lg);padding:12px;width:296px;max-width:100%}
.fs-date .fs-cal{position:absolute;inset-block-start:calc(100% + 6px);inset-inline-start:0;z-index:var(--fs-z-dropdown)}
.fs-cal-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:10px}
.fs-cal-head strong{font-size:var(--fs-text-md);font-weight:700;text-transform:capitalize}
.fs-cal-nav{display:flex;gap:4px}
.fs-cal-nav button{width:32px;height:32px;display:grid;place-items:center;border-radius:var(--fs-radius-sm);color:var(--fs-text-secondary)}
.fs-cal-nav button:hover{background:var(--fs-surface-sunken);color:var(--fs-primary-text)}
.fs-cal-nav .ic{width:var(--fs-icon-sm);height:var(--fs-icon-sm)}
.fs-cal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}
.fs-cal-dow{font-size:var(--fs-text-xs);font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--fs-text-muted);text-align:center;padding-block:4px}
.fs-cal-grid button{height:36px;border-radius:var(--fs-radius-sm);font-size:var(--fs-text-sm);font-variant-numeric:tabular-nums;color:var(--fs-text-secondary);background:transparent;transition:background var(--fs-fast) var(--fs-ease),color var(--fs-fast) var(--fs-ease)}
.fs-cal-grid button:hover:not(:disabled){background:var(--fs-primary-soft);color:var(--fs-primary-text)}
.fs-cal-grid button.out{color:var(--fs-text-faint)}
.fs-cal-grid button.today{box-shadow:inset 0 0 0 1px var(--fs-primary-border);font-weight:700}
.fs-cal-grid button[aria-selected="true"]{background:var(--fs-primary-solid);color:var(--fs-on-solid);font-weight:700}
.fs-cal-grid button:disabled{opacity:.4;cursor:not-allowed}
.fs-cal-foot{display:flex;justify-content:space-between;gap:8px;margin-top:10px;padding-top:10px;border-top:1px solid var(--fs-border-subtle)}
.fs-cal-foot button{font-size:var(--fs-text-sm);font-weight:600;color:var(--fs-primary-text);padding:6px 10px;border-radius:var(--fs-radius-sm)}
.fs-cal-foot button:hover{background:var(--fs-primary-soft)}

/* ---------- Alertes & toasts (§148) ---------- */
.alert{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-radius:var(--fs-radius-lg);border:1px solid transparent;font-size:var(--fs-text-base);margin-bottom:var(--fs-space-md)}
.alert .ic{width:var(--fs-icon);height:var(--fs-icon);flex:none;margin-top:1px}
.alert-success{background:var(--fs-success-soft);color:var(--fs-success-text);border-color:var(--fs-success-border)}.alert-error,.alert-danger{background:var(--fs-danger-soft);color:var(--fs-danger-text);border-color:var(--fs-danger-border)}.alert-warning{background:var(--fs-warning-soft);color:var(--fs-warning-text);border-color:var(--fs-warning-border)}.alert-info{background:var(--fs-info-soft);color:var(--fs-info-text);border-color:var(--fs-info-border)}.alert-primary{background:var(--fs-primary-soft);color:var(--fs-primary-text);border-color:var(--fs-primary-border)}
.alert-ai{background:linear-gradient(135deg,rgba(124,58,237,.08),rgba(6,182,212,.08));border-color:rgba(124,58,237,.25);color:var(--fs-text-secondary)}
.toasts{position:fixed;inset-block-end:24px;inset-inline-end:24px;display:flex;flex-direction:column;gap:10px;z-index:var(--fs-z-toast);max-width:380px;width:calc(100% - 48px)}
.toast{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-radius:var(--fs-radius-lg);background:var(--fs-surface-raised);box-shadow:var(--fs-shadow-lg);border:1px solid var(--fs-border-subtle);animation:toastIn .3s var(--fs-ease);position:relative;overflow:hidden}
.toast::before{content:"";position:absolute;inset-block:0;inset-inline-start:0;width:4px;background:var(--t,var(--fs-grad-primary))}
.toast-success{--t:var(--fs-success)}.toast-error{--t:var(--fs-danger)}.toast-warning{--t:var(--fs-warning)}.toast-info{--t:var(--fs-info)}
.toast .ic{width:var(--fs-icon);height:var(--fs-icon);color:var(--t,var(--fs-primary));flex:none;margin-top:2px}
.toast strong{display:block;font-size:var(--fs-text-base)}.toast p{margin:2px 0 0;font-size:var(--fs-text-sm);color:var(--fs-text-muted)}
.toast .toast-action{margin-block-start:10px}
.toast .close{margin-inline-start:auto;color:var(--fs-text-faint);display:inline-grid;place-items:center;flex:none;min-inline-size:var(--fs-target-min);min-block-size:var(--fs-target-min);border-radius:var(--fs-radius-xs)}
.toast.out{animation:toastOut .25s var(--fs-ease) forwards}
@keyframes toastIn{from{opacity:0;transform:translateY(12px) scale(.98)}to{opacity:1;transform:none}}
@keyframes toastOut{to{opacity:0;transform:translateY(8px)}}
@media (max-width:720px){.table-wrap{max-block-size:none}}
@media (max-width:720px){.toasts{inset-inline:12px;inset-block-end:76px;max-width:none;width:auto}}

/* ---------- Avatars ---------- */
/* Avatar : dégradé cyan → violet de la maquette (.window-avatar), nuances sombres pour l'initiale blanche (≥ 4,5:1). */
.avatar{width:40px;height:40px;border-radius:50%;object-fit:cover;flex:none;background:linear-gradient(135deg,var(--fs-info-solid),var(--fs-primary-active));display:inline-grid;place-items:center;font-weight:800;color:var(--fs-on-solid);overflow:hidden}
.avatar img{width:100%;height:100%;object-fit:cover}
.avatar-sm{width:32px;height:32px;font-size:12px}.avatar-xs{width:24px;height:24px;font-size:var(--fs-text-xs)}.avatar-lg{width:56px;height:56px;font-size:20px}.avatar-xl{width:88px;height:88px;font-size:30px}
.avatar-stack{display:flex}.avatar-stack .avatar{border:2px solid var(--fs-surface);margin-inline-start:-10px}.avatar-stack .avatar:first-child{margin-inline-start:0}
.status-dot{width:10px;height:10px;border-radius:50%;background:var(--fs-success);border:2px solid var(--fs-surface);position:absolute;inset-block-end:0;inset-inline-end:0}

/* ---------- Progression (§144) ---------- */
.progress{height:8px;border-radius:var(--fs-radius-full);background:var(--fs-surface-sunken);overflow:hidden;position:relative}
/* Barre de la maquette (.progress-line) : dégradé cyan → violet → magenta. */
.progress>span{display:block;height:100%;border-radius:var(--fs-radius-full);background:var(--fs-grad-bar);width:var(--p,0%);transition:width .6s var(--fs-ease)}
/* Module « progression » (§109) : jauge achevée. */
.progress-success>span,.progress.is-complete>span{background:var(--fs-grad-progress)}
.progress-primary>span{background:var(--fs-grad-primary)}.progress-accent>span{background:var(--fs-grad-warm)}.progress-info>span{background:var(--fs-grad-cyan)}
.progress-sm{height:5px}.progress-lg{height:12px}
.progress-label{display:flex;justify-content:space-between;font-size:var(--fs-text-xs);color:var(--fs-text-muted);margin-bottom:6px;font-weight:600}
.ring{--size:64px;--stroke:6;width:var(--size);height:var(--size);position:relative;display:inline-grid;place-items:center}
.ring svg{width:100%;height:100%;transform:rotate(-90deg)}
.ring circle{fill:none;stroke-width:var(--stroke);stroke-linecap:round}
.ring .bg{stroke:var(--fs-surface-sunken)}.ring .fg{stroke:url(#ringGrad);transition:stroke-dashoffset .8s var(--fs-ease)}
/* Anneau de progression (§109) : les arrêts du dégradé suivent le jeton de module plutôt qu’une couleur écrite dans la vue. */
.ring .stop-a{stop-color:var(--ring-a,var(--fs-mod-progress))}.ring .stop-b{stop-color:var(--ring-b,var(--fs-mod-cert))}
.ring .val{position:absolute;font-weight:700;font-size:calc(var(--size) * .24)}

/* ---------- Tableaux (§135, §154) ---------- */
/* §135 — en-tête figé : .table-wrap est un conteneur défilant (overflow-x) ; sans hauteur bornée il ne défilait jamais
   verticalement et le th sticky ne collait donc jamais. Borné à la fenêtre, un long tableau défile dans son cadre sous
   son en-tête ; un tableau court n'est pas affecté. En cartes (≤ 720 px), la page défile normalement. */
.table-wrap{overflow:auto;max-block-size:calc(100vh - var(--fs-topbar-h) - 120px);max-block-size:calc(100dvh - var(--fs-topbar-h) - 120px);scroll-padding-block-start:52px;border-radius:var(--fs-radius-xl);border:1px solid var(--fs-border);background:var(--fs-surface);box-shadow:var(--fs-shadow-card)}
.table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--fs-text-base)}
.table th{position:sticky;top:0;background:var(--fs-surface);z-index:1;text-align:start;font-size:var(--fs-text-xs);font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--fs-text-muted);padding:14px 16px;border-bottom:1px solid var(--fs-border);white-space:nowrap}
[dir="rtl"] .table th{letter-spacing:0}
.table th a{color:inherit;display:inline-flex;align-items:center;gap:4px}
.table td{padding:14px 16px;border-bottom:1px solid var(--fs-divider);vertical-align:middle}
.table tbody tr:last-child td{border-bottom:0}
.table tbody tr{transition:background var(--fs-fast)}
.table tbody tr:hover{background:var(--fs-bg)}
.table tr.selected{background:var(--fs-primary-soft)}
.table .num{text-align:end;font-variant-numeric:tabular-nums;white-space:nowrap}
.table .actions{text-align:end;white-space:nowrap}
.table .actions .btn{opacity:.75}.table tr:hover .actions .btn{opacity:1}
.table-compact td,.table-compact th{padding:8px 12px}
.table .cell-main{display:flex;align-items:center;gap:12px;min-width:0}
/* Le même bloc « avatar + intitulé » sert hors tableau (listes de la page Analytics) :
   sans min-width:0, l'élément flex ne descend pas sous sa largeur minimale et déborde. */
.cell-main{display:flex;align-items:center;gap:12px;min-width:0}
.cell-main strong{display:block;font-weight:600}
.cell-main small{display:block;color:var(--fs-text-muted)}
.table .cell-main .thumb{width:56px;height:38px;border-radius:var(--fs-radius-sm);object-fit:cover;flex:none;background:var(--fs-surface-sunken)}
.table .cell-main strong{display:block;font-weight:600}
.table .cell-main small{display:block;color:var(--fs-text-muted)}
.table-toolbar{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:var(--fs-space-md)}
.table-toolbar .input-group{max-width:320px;flex:1 1 220px}
/* Les champs heritent de width:100% : dans la barre d'outils (flex), un champ date ou select
   occuperait toute la ligne. On les ramene a une largeur intrinseque (§135, QA visuel §181). */
.table-toolbar>.input,.table-toolbar>.select,.table-toolbar>.dropdown>.input,.table-toolbar input[type=date]{width:auto;flex:0 0 auto;min-width:150px}
.table-toolbar>.select{min-width:170px}
@media (max-width:640px){.table-toolbar>.input,.table-toolbar>.select,.table-toolbar input[type=date]{flex:1 1 140px;min-width:0}}
.bulk-bar{display:none;align-items:center;gap:12px;padding:10px 16px;border-radius:var(--fs-radius-lg);background:var(--fs-grad-panel);color:var(--fs-on-solid);margin-bottom:12px;animation:toastIn .2s}
.bulk-bar.show{display:flex}.bulk-bar .btn{color:var(--fs-on-solid)}

/* Colonnes configurables : affichage, ordre, largeur (§135, CA-47).
   L'ordre se change a la souris (poignee) comme au clavier (fleches sur la poignee). */
.col-list{display:grid;gap:2px}
.col-row{display:flex;align-items:center;gap:6px;padding-inline-start:2px;border-radius:var(--fs-radius-sm)}
.col-row.dragging{opacity:.5}
.col-row .check{flex:1;min-width:0;padding:7px 8px;margin:0;border-radius:var(--fs-radius-sm)}
.col-row .check:hover{background:var(--fs-surface-sunken)}
.col-move{flex:none;width:26px;height:26px;display:grid;place-items:center;border-radius:var(--fs-radius-xs);color:var(--fs-text-faint);cursor:grab;background:transparent}
.col-move:hover{background:var(--fs-surface-sunken);color:var(--fs-text-muted)}
.col-move:active{cursor:grabbing}
.col-reset{margin-top:6px;justify-content:center;color:var(--fs-text-muted)}
/* Poignee de largeur : posee sur le bord de fin de l'en-tete, donc miroir en RTL. */
.table th[data-col]{position:relative}
.col-grip{position:absolute;inset-inline-end:0;inset-block:0;width:8px;cursor:col-resize;touch-action:none}
.col-grip::after{content:"";position:absolute;inset-block:8px;inset-inline-end:3px;width:2px;border-radius:var(--fs-radius-full);background:transparent;transition:background var(--fs-fast)}
.table th[data-col]:hover .col-grip::after{background:var(--fs-border-strong)}
body.col-resizing{cursor:col-resize;user-select:none}

/* Defilement controle (§154) : les tableaux qui ne basculent pas en cartes restent
   parcourables — region focalisable au clavier (WCAG 2.1.1) et ombres de bord. */
/* SC 2.4.11 : `.table-wrap` borne désormais sa hauteur (§135, en-tête figé) ; la marge de défilement
   `scroll-padding-block-start` réserve la hauteur de l'en-tête collant, qui ne masque donc jamais la
   cellule qui reçoit le focus. */
.table-wrap{position:relative}
.table-wrap:focus-visible{outline:var(--fs-focus-outline);outline-offset:var(--fs-focus-offset)}
.table-wrap.is-scrollable::before,.table-wrap.is-scrollable::after{content:"";position:absolute;inset-block:0;width:26px;pointer-events:none;z-index:2;opacity:0;transition:opacity var(--fs-fast) var(--fs-ease)}
.table-wrap.is-scrollable::before{inset-inline-start:0;background:linear-gradient(to right,var(--fs-shadow-edge),transparent)}
.table-wrap.is-scrollable::after{inset-inline-end:0;background:linear-gradient(to left,var(--fs-shadow-edge),transparent)}
[dir="rtl"] .table-wrap.is-scrollable::before{background:linear-gradient(to left,var(--fs-shadow-edge),transparent)}
[dir="rtl"] .table-wrap.is-scrollable::after{background:linear-gradient(to right,var(--fs-shadow-edge),transparent)}
.table-wrap.is-scrollable:not(.at-start)::before{opacity:1}
.table-wrap.is-scrollable:not(.at-end)::after{opacity:1}
.table-scroll-hint{display:none;align-items:center;gap:6px;font-size:var(--fs-text-xs);color:var(--fs-text-muted);margin-block-start:6px}
.table-wrap.is-scrollable+.table-scroll-hint{display:flex}
@media (max-width:720px){
  .table-cards thead{display:none}
  /* En mode cartes, la mise en page tabulaire ne sert plus à rien : conservée, elle impose
     au tableau une largeur minimale qui déborde de son conteneur (CDC §154, CA-43). */
  .table-cards,.table-cards tbody,.table-cards tfoot{display:block;width:100%}
  .table-cards tr{display:block;padding:12px 14px;border-bottom:1px solid var(--fs-divider)}
  /* flex-wrap + min-width:0 : sans eux, la somme « intitulé + valeur » impose une largeur
     minimale à la carte, qui déborde alors de son conteneur sur un écran de 375 px. */
  .table-cards td{display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;padding:5px 0;border:0;text-align:end;min-width:0}
  .table-cards td::before{content:attr(data-label);font-size:var(--fs-text-xs);text-transform:uppercase;letter-spacing:.05em;color:var(--fs-text-muted);font-weight:600;text-align:start}
  .table-cards td.actions,.table-cards td.cell-first{justify-content:flex-start;text-align:start}
  .table-cards td>.flex{flex-wrap:wrap}
  /* Un enfant de cellule est un élément flex : min-width:auto l'empêche de rétrécir
     sous la largeur de son contenu, et la carte déborde alors de son conteneur
     (constaté sur /admin/moderation/reviews : 576 px dans une cellule de 313 px). */
  .table-cards td>*{min-width:0;max-width:100%}
  /* Une pastille de statut est insécable par défaut : en carte, un libellé long
     (motif de modération, nom de plan) doit pouvoir passer à la ligne. */
  .table-cards td .badge{white-space:normal;text-align:start}
  /* Une jauge n'a pas de largeur propre : élément flex, elle disparaîtrait. */
  .table-cards td>.progress{flex:1 1 100%}
  /* En carte, la place manque en largeur mais pas en hauteur : un intitulé tronqué au
     bureau (max-width en style local) se replie plutôt que de s'abréger. */
  .table-cards td.truncate{max-width:100%!important;overflow:visible;white-space:normal}
  .table-cards td.truncate>*{white-space:normal;overflow-wrap:anywhere}
  .table-cards td.cell-first::before,.table-cards td.actions::before,.table-cards td.no-label::before{display:none}
}
@media (max-width:720px){
  /* En-tête « titre à gauche, action à droite » : sur téléphone, un libellé de bouton long
     (« Déconnecter tous les autres appareils ») déborde du corps de page s'il ne peut pas
     passer à la ligne (CDC §154, CA-43). */
  .flex.items-center.justify-between{flex-wrap:wrap}
  /* Un libellé de bouton long (souvent en arabe) ne peut pas rester insécable sur
     téléphone : il déborderait de sa colonne et du corps de page (CDC §154, CA-43). */
  .btn{max-width:100%;white-space:normal}
  /* Bandeau « Reprendre l'apprentissage » : la vignette de 180 px ne laisserait que
     95 px au titre du cours, qui déborderait de la carte (CDC §153-154, CA-43). */
  .card-gradient>.card-body>.flex-1{flex:1 1 100%}
  .card-gradient>.card-body>img{width:100%!important;max-width:280px}
}
.pagination{display:flex;gap:4px;align-items:center;justify-content:center;margin-top:var(--fs-space-lg);flex-wrap:wrap}
.pagination .page{min-width:40px;height:40px;padding:0 12px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--fs-radius-btn-sm);border:1px solid var(--fs-filter-border);background:var(--fs-surface);color:var(--fs-filter-text);font-weight:750;font-size:var(--fs-text-sm);transition:all .2s var(--fs-ease)}
.pagination .page:hover{border-color:var(--fs-filter-hover-border);color:var(--fs-filter-hover)}.pagination .page.active{background:var(--fs-grad-filter);border-color:transparent;color:var(--fs-on-solid);box-shadow:var(--fs-shadow-filter)}.pagination .gap{border-color:transparent;background:transparent}.pagination .page.disabled{opacity:.4;pointer-events:none}.pagination .gap{pointer-events:none}
[dir="rtl"] .pagination .ic{transform:scaleX(-1)}

/* ---------- Onglets ---------- */
.tabs{display:flex;gap:4px;border-bottom:1px solid var(--fs-border);margin-bottom:var(--fs-space-lg);overflow-x:auto;scrollbar-width:none;max-width:100%}
.tabs::-webkit-scrollbar{display:none}
/* Onglet de la maquette (.primary-nav a) : trait dégradé sous l'onglet actif, amorcé au survol. */
.tab{position:relative;padding:12px 14px;font-weight:700;color:var(--fs-text-muted);border-bottom:2px solid transparent;margin-bottom:-1px;white-space:nowrap;display:inline-flex;align-items:center;gap:8px;font-size:var(--fs-text-base);transition:color var(--fs-fast)}
.tab::after{content:"";position:absolute;inset-inline:14px;inset-block-end:-1px;height:3px;border-radius:var(--fs-radius-full);background:var(--fs-grad-primary);transform:scaleX(0);transition:transform .2s var(--fs-ease)}
.tab:hover{color:var(--fs-text)}.tab:hover::after{transform:scaleX(.35)}.tab.active{color:var(--fs-text);border-color:transparent}.tab.active::after{transform:none}
.tab .count{background:var(--fs-surface-sunken);padding:1px 8px;border-radius:var(--fs-radius-full);font-size:var(--fs-text-xs)}
.tab.active .count{background:var(--fs-primary-soft);color:var(--fs-primary-text)}
.tabs-pills{border:1px solid var(--fs-border);background:var(--fs-surface);padding:4px;border-radius:var(--fs-radius-full);display:inline-flex;gap:4px;max-width:100%}
.tabs-pills .tab{border:0;margin:0;border-radius:var(--fs-radius-full);padding:8px 16px;color:var(--fs-filter-text)}
.tabs-pills .tab::after{display:none}
.tabs-pills .tab:hover{color:var(--fs-filter-hover)}
.tabs-pills .tab.active{background:var(--fs-grad-filter);box-shadow:var(--fs-shadow-filter);color:var(--fs-on-solid)}
.tabs-pills .tab.active .count{background:rgba(255,255,255,.22);color:var(--fs-on-solid)}
.tab-pane{display:none}.tab-pane.active{display:block;animation:fadeIn .2s}
@keyframes fadeIn{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* ---------- Dropdown / menus ---------- */
.dropdown{position:relative}
.menu{position:absolute;inset-inline-end:0;top:calc(100% + 10px);min-width:220px;max-width:min(340px, calc(100vw - 24px));background:var(--fs-surface-raised);border:1px solid var(--fs-border);border-radius:var(--fs-radius-lg);box-shadow:var(--fs-shadow-lg);padding:8px;z-index:var(--fs-z-dropdown);display:none;animation:fadeIn .15s}
.menu.start{inset-inline-end:auto;inset-inline-start:0}
.dropdown.open>.menu,.menu.open{display:block}
.menu a,.menu button,.menu-item{display:flex;align-items:center;gap:10px;width:100%;min-block-size:2.5rem;padding:9px 12px;border-radius:var(--fs-radius-md);color:var(--fs-text-secondary);font-size:var(--fs-text-base);font-weight:600;text-align:start;transition:background var(--fs-fast),color var(--fs-fast)}
.menu a:hover,.menu button:hover,.menu-item:hover,.menu a:focus-visible,.menu button:focus-visible{background:var(--fs-bg);color:var(--fs-text)}
.menu a:hover .ic,.menu button:hover .ic,.menu-item:hover .ic{color:var(--fs-primary-text)}
.menu .ic{width:var(--fs-icon-md);height:var(--fs-icon-md);color:var(--fs-text-muted)}
.menu .danger{color:var(--fs-danger-text)}.menu .danger .ic{color:var(--fs-danger-text)}
.menu hr{margin:6px 0}
.menu .menu-title{padding:8px 12px 4px;font-size:var(--fs-text-xs);text-transform:uppercase;letter-spacing:.11em;color:var(--fs-kicker);font-weight:800}
[dir="rtl"] .menu .menu-title{letter-spacing:0}

/* ---------- Vues de tableau enregistrees (§135, §172, CA-47) ---------- */
.menu-views{min-width:280px;max-width:340px}
.menu-views .menu-head{padding:8px 12px 6px;font-size:var(--fs-text-xs);text-transform:uppercase;letter-spacing:.06em;color:var(--fs-text-faint);font-weight:700}
.menu-views .menu-empty{padding:10px 12px;color:var(--fs-text-muted);font-size:var(--fs-text-sm)}
.menu-views .menu-sep{border-top:1px solid var(--fs-divider);margin:6px 0}
.menu-views .view-row{display:flex;align-items:center;gap:6px;padding-block:2px;padding-inline:8px 4px}
.menu-views .view-row:hover{background:var(--fs-surface-sunken)}
.menu-views .view-row.is-default{background:var(--fs-primary-soft)}
.menu-views .view-name{flex:1;min-width:0;display:flex;align-items:center;gap:6px;padding:7px 4px;font-weight:600;color:var(--fs-text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.menu-views .view-name:hover{background:transparent}
.menu-views .view-star{color:var(--fs-warning-text);font-size:var(--fs-text-xs)}
.menu-views .view-acts{display:flex;gap:2px;flex:none}
.menu-views .view-acts .btn{width:26px;height:26px;min-block-size:0;padding:0;font-size:15px;line-height:1;color:var(--fs-text-muted)}
.menu-views .view-acts .btn:hover{color:var(--fs-text);background:var(--fs-surface-hover)}
.menu-views .view-save{color:var(--fs-primary-text);font-weight:600}
.menu-views .view-form{padding:8px 10px 4px;display:flex;flex-direction:column;gap:10px}
.menu-views .view-form .form-group{margin:0}
.menu-wide{min-width:360px}

/* ---------- Encre des pastilles d'icone en theme sombre (CA-50, 3:1 sur un element d'interface) ----------
   Le violet de marque (#6C3EF5) et le violet IA (#7C3AED) sont plus sombres que leur propre fond doux :
   sur fond sombre ils ne mesurent que 2,4 a 2,7:1. Les pastilles basculent donc sur l'encre claire de la
   meme teinte (--fs-primary-text), ce qui conserve l'identite violette. Les autres teintes (vert, corail,
   cyan, ambre, orange, magenta) sont deja au-dessus de 3:1 et ne sont pas touchees. */
[data-theme="dark"] .kpi-icon{color:var(--kpi-color,var(--fs-primary-text))}
[data-theme="dark"] .kpi.kpi-primary{--kpi-color:var(--fs-primary-text)}
[data-theme="dark"] .kpi.kpi-ai{--kpi-color:var(--fs-primary-text)}
[data-theme="dark"] .notif .n-icon{color:var(--n-color,var(--fs-primary-text))}
[data-theme="dark"] .notif.c-ai{--n-color:var(--fs-primary-text)}
[data-theme="dark"] .tl-icon{color:var(--tl-color,var(--fs-primary-text))}
[data-theme="dark"] .pill-icon{color:var(--pi-color,var(--fs-primary-text))}
[data-theme="dark"] .ai-conv .pill-icon{--pi-color:var(--fs-primary-text)}
[data-theme="dark"] .report-card .pill-icon{color:var(--rc-color,var(--fs-primary-text))}
[data-theme="dark"] .rc-primary{--rc-color:var(--fs-primary-text)}
[data-theme="dark"] .empty .empty-art{color:var(--fs-primary-text)}
/* Memes pastilles violettes hebergees par les feuilles de module (learner/commerce/admin) :
   corrigees ici, dans la feuille du design system, plutot qu'en modifiant leurs fichiers. */
[data-theme="dark"] .cart-thumb,
[data-theme="dark"] .view-switch a.active,
[data-theme="dark"] .cert-card .cert-ph,
[data-theme="dark"] .vote-box button:hover,
[data-theme="dark"] .org-logo,
[data-theme="dark"] .src-ai{color:var(--fs-primary-text)}
/* Meme correction pour la pastille violette du type de lecon (Course Builder) : le violet de
   marque ne mesure que 2,6:1 sur son propre fond doux en theme sombre. */
[data-theme="dark"] .lt-video{--lt-color:var(--fs-primary-text)}


/* ---------- Modales & drawers ---------- */
.modal-backdrop{position:fixed;inset:0;background:var(--fs-overlay);backdrop-filter:var(--fs-blur-overlay);-webkit-backdrop-filter:var(--fs-blur-overlay);z-index:var(--fs-z-modal);display:none;align-items:center;justify-content:center;padding:20px;animation:fadeIn .15s}
.modal-backdrop.open{display:flex}
.modal{background:var(--fs-surface-raised);border:1px solid var(--fs-border);border-radius:var(--fs-radius-2xl);box-shadow:var(--fs-shadow-xl);width:100%;max-width:560px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;animation:modalIn .25s var(--fs-ease)}
.modal-lg{max-width:860px}.modal-xl{max-width:1100px}.modal-sm{max-width:420px}
.modal-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:26px 30px 0}
.modal-header h3{margin:0;font-size:var(--fs-text-xl);font-weight:800;letter-spacing:-.025em}
.modal-body{padding:18px 30px;overflow:auto}
.modal-footer{padding:16px 30px 24px;display:flex;justify-content:flex-end;gap:10px;border-top:1px solid var(--fs-divider)}
@keyframes modalIn{from{opacity:0;transform:translateY(16px) scale(.98)}to{opacity:1;transform:none}}
.drawer-backdrop{position:fixed;inset:0;background:var(--fs-overlay);z-index:var(--fs-z-drawer);display:none}
.drawer-backdrop.open{display:block;animation:fadeIn .15s}
.drawer{position:fixed;top:0;inset-inline-end:0;height:100%;width:min(480px,100%);background:var(--fs-surface-raised);border-start-start-radius:var(--fs-radius-xl);border-end-start-radius:var(--fs-radius-xl);box-shadow:var(--fs-shadow-xl);z-index:calc(var(--fs-z-drawer) + 1);transform:translateX(100%);transition:transform var(--fs-slow) var(--fs-ease);display:flex;flex-direction:column}
[dir="rtl"] .drawer{transform:translateX(-100%)}
.drawer.open{transform:none}
.drawer-header{display:flex;align-items:center;justify-content:space-between;padding:20px 24px;border-bottom:1px solid var(--fs-divider)}
.drawer-header h3,.drawer-header h2{margin:0;font-weight:800;letter-spacing:-.025em}
.drawer-body{padding:20px 22px;overflow:auto;flex:1}
.drawer-footer{padding:14px 22px;border-top:1px solid var(--fs-divider);display:flex;gap:10px;justify-content:flex-end}
.drawer-lg{width:min(720px,100%)}

/* ---------- Tooltip ---------- */
[data-tip]{position:relative}
/* §154 / WCAG 1.4.10 — l'infobulle est retiree du flux tant qu'elle n'est pas demandee :
   en `opacity:0` elle restait comptee dans la zone de defilement (une carte du catalogue,
   avec son bouton en position absolue pres du bord, ajoutait 31 px de defilement horizontal
   a la page entiere sur mobile). `display` bascule, la transition reste douce la ou
   @starting-style est disponible. Le focus clavier l'affiche aussi (CA-50). */
[data-tip]::after{content:attr(data-tip);position:absolute;inset-block-end:calc(100% + 8px);inset-inline-start:50%;transform:translateX(-50%) translateY(4px);background:var(--fs-tooltip-bg);color:var(--fs-on-solid);padding:6px 10px;border-radius:var(--fs-radius-sm);box-shadow:0 10px 24px rgba(4,9,26,.28);font-size:var(--fs-text-xs);font-weight:600;white-space:nowrap;display:none;opacity:0;pointer-events:none;transition:opacity var(--fs-fast) var(--fs-ease),transform var(--fs-fast) var(--fs-ease),display var(--fs-fast) allow-discrete;z-index:60}
[dir="rtl"] [data-tip]::after{transform:translateX(50%) translateY(4px)}
[data-tip]:hover::after,[data-tip]:focus-visible::after{display:block;opacity:1;transform:translateX(-50%) translateY(0)}
[dir="rtl"] [data-tip]:hover::after,[dir="rtl"] [data-tip]:focus-visible::after{transform:translateX(50%) translateY(0)}
@starting-style{[data-tip]:hover::after,[data-tip]:focus-visible::after{opacity:0;transform:translateX(-50%) translateY(4px)}}
[data-tip-end]::after{inset-inline-start:auto;inset-inline-end:0;transform:none}

/* ---------- Stepper (§138) ---------- */
.stepper{display:flex;gap:0;align-items:flex-start;margin-bottom:var(--fs-space-xl);counter-reset:step}
.step{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;gap:8px;position:relative;text-align:center;font-size:var(--fs-text-sm);color:var(--fs-text-muted);font-weight:500;overflow-wrap:break-word}
.step::before{counter-increment:step;content:counter(step);width:36px;height:36px;border-radius:50%;display:grid;place-items:center;background:var(--fs-surface);border:2px solid var(--fs-border);font-weight:700;color:var(--fs-text-muted);z-index:1;transition:all var(--fs-normal)}
.step:not(:last-child)::after{content:"";position:absolute;top:18px;inset-inline-start:50%;width:100%;height:2px;background:var(--fs-border)}
.step.done::before{background:var(--fs-success-solid);border-color:var(--fs-success-solid);color:var(--fs-on-solid);content:"✓"}
.step.done:not(:last-child)::after{background:var(--fs-success)}
.step.active{color:var(--fs-primary-text);font-weight:700}.step.active::before{background:var(--fs-grad-filter);border-color:transparent;color:var(--fs-on-solid);box-shadow:0 0 0 5px var(--fs-primary-soft)}
.stepper-vertical{flex-direction:column;gap:14px}.stepper-vertical .step{flex-direction:row;text-align:start}.stepper-vertical .step::after{display:none}

/* ---------- Illustrations (§156) ----------
   Jeu cohérent dessiné en SVG en ligne : onboarding, état vide, recherche, 404, 500,
   paiement, certificat, IA, confirmation, maintenance. Aucune couleur en dur — tout vient
   des tokens, donc le thème sombre et une recoloration de marque sont gratuits (§168).
   Elles sont décoratives : le sens reste porté par le titre et le texte voisins. */
.illus{width:100%;max-width:240px;height:auto;display:block;margin-inline:auto}
.illus.illus-sm{max-width:150px}
.illus.illus-lg{max-width:340px}
.illus .il-ground{fill:var(--fs-text);opacity:.07}
.illus .il-soft{fill:var(--fs-primary-soft)}
.illus .il-soft2{fill:var(--fs-border)}
.illus .il-line{stroke:var(--fs-border-strong);stroke-width:2;fill:none}
.illus .il-fill{fill:var(--fs-text-faint)}
.illus .il-grad{stroke:none}
.illus .il-white{fill:var(--fs-on-solid)}
.illus .il-mark{stroke:var(--fs-on-solid);stroke-width:2.6;fill:none}
.illus .il-ok{stroke:var(--fs-success-text);stroke-width:3;fill:none}
.illus .il-ai{fill:var(--fs-ai)}
.illus .il-dot{fill:var(--fs-primary)}
.illus .il-dot2{fill:var(--fs-accent)}
.illus .il-dot3{fill:var(--fs-warning)}
.illus .il-code{fill:var(--fs-primary-text);font-family:var(--fs-font);font-size:44px;font-weight:800;letter-spacing:-.03em}
/* Sens de lecture : l'illustration est symétrique de composition, on ne la retourne pas —
   sauf les éléments explicitement directionnels (loupe, flèches), marqués .il-flip. */
[dir="rtl"] .illus .il-flip{transform:scaleX(-1);transform-origin:center}

/* ---------- États vides & skeleton (§146-147) ---------- */
.empty{display:flex;flex-direction:column;align-items:center;text-align:center;padding:48px 24px;gap:8px}
.empty .empty-icon{width:84px;height:84px;border-radius:var(--fs-radius-2xl);background:var(--fs-grad-primary);opacity:.12;display:grid;place-items:center;margin-bottom:8px;position:relative}
.empty .empty-art{width:96px;height:96px;border-radius:var(--fs-radius-2xl);background:linear-gradient(135deg,var(--fs-info-soft),var(--fs-primary-soft));box-shadow:inset 0 0 0 1px var(--fs-primary-border);display:grid;place-items:center;margin-bottom:10px;color:var(--fs-primary-text)}
.empty .empty-art .ic{width:var(--fs-icon-3xl);height:var(--fs-icon-3xl)}
/* Variante illustrée de l'état vide (§146, §156) : illustration au lieu de la pastille. */
.empty .illus{margin-bottom:14px}
.error-page .illus{margin-bottom:8px}
.error-code{font-size:var(--fs-text-5xl);font-weight:900;line-height:1;letter-spacing:-.05em}
.empty h3{margin:0;font-size:var(--fs-text-xl)}
/* Composant partials/empty_state : variantes de taille et rangée d'actions. */
.empty.empty-sm{padding:20px 12px;gap:6px}.empty.empty-sm h3{font-size:var(--fs-text-md)}.empty.empty-sm p{font-size:var(--fs-text-sm)}.empty.empty-sm .illus{max-width:120px;margin-bottom:6px}
.empty.empty-lg{padding:64px 24px}
/* Chantier vides4 (§33.3) : titre de niveau variable, pastille réduite en petit format, ligne de tableau vide. */
.empty h2,.empty h4{margin:0;font-size:var(--fs-text-xl)}.empty.empty-sm h2,.empty.empty-sm h4{font-size:var(--fs-text-md)}
.empty.empty-sm .empty-art{width:56px;height:56px;margin-bottom:4px}.empty.empty-sm .empty-art .ic{width:var(--fs-icon-lg);height:var(--fs-icon-lg)}
.empty.empty-sm p{margin-block-end:6px}
.empty[hidden]{display:none}
.table tr.empty-row td{padding:0;background:transparent}.table tr.empty-row:hover td{background:transparent}
.empty-actions{display:flex;flex-wrap:wrap;gap:8px;justify-content:center}
.empty p{color:var(--fs-text-muted);max-width:420px;margin:0 0 10px}
.skeleton{background:var(--fs-skeleton);background-size:400% 100%;animation:shimmer 1.4s infinite;border-radius:var(--fs-radius-sm);min-height:14px}
.skeleton.line{height:14px;margin-bottom:10px}.skeleton.title{height:22px;width:60%}.skeleton.block{height:120px;border-radius:var(--fs-radius-lg)}.skeleton.circle{width:44px;height:44px;border-radius:50%}
/* Gabarits composes servis par FS.skeleton() : liste d'elements, lignes, corps de tableau. */
.skeleton-item{display:flex;align-items:center;gap:12px;padding:10px 12px}
.skeleton-item .skeleton.line:last-child{margin-bottom:0}
.skeleton-row{padding:10px 0}.skeleton-row .skeleton.line{margin-bottom:0}
.table tbody tr.sk-row:hover{background:transparent}
.table tbody tr.sk-row td{padding-block:16px}
.table tbody tr.sk-row .skeleton.line{margin-bottom:0}
[aria-busy="true"]{cursor:progress}
@keyframes shimmer{0%{background-position:100% 0}100%{background-position:-100% 0}}

/* ---------- Breadcrumb ---------- */
.breadcrumb{display:flex;align-items:center;gap:6px;font-size:var(--fs-text-sm);font-weight:600;color:var(--fs-text-muted);flex-wrap:wrap;margin-bottom:8px}
.breadcrumb a{color:var(--fs-text-muted)}.breadcrumb a:hover{color:var(--fs-filter-hover)}
.breadcrumb [aria-current]{color:var(--fs-text)}
.breadcrumb .ic{width:var(--fs-icon-xs);height:var(--fs-icon-xs);color:var(--fs-text-faint)}
[dir="rtl"] .breadcrumb .ic{transform:scaleX(-1)}

/* ---------- Page header ---------- */
.page-head{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:var(--fs-space-lg)}
.page-head h1{margin:0;font-size:var(--fs-text-2xl);font-weight:800;letter-spacing:-.035em}
.page-head .sub{color:var(--fs-text-muted);margin:4px 0 0;font-size:var(--fs-text-md)}
.page-actions{display:flex;gap:10px;flex-wrap:wrap;max-width:100%}
.page-actions>form{flex-wrap:wrap;max-width:100%}
.greeting{font-size:var(--fs-text-3xl);font-weight:800;letter-spacing:-.04em;margin-block:0}
.greeting .wave{display:inline-block;animation:wave 1.8s ease-in-out 1;transform-origin:70% 70%}
@keyframes wave{0%,100%{transform:rotate(0)}20%{transform:rotate(14deg)}40%{transform:rotate(-8deg)}60%{transform:rotate(14deg)}80%{transform:rotate(-4deg)}}

/* ---------- Layout application (§122-125) ---------- */
.app{display:flex;min-height:100vh}
/* Barre latérale bleu nuit (ds6 §34.1, maquette .demo-sidebar) : ses jetons sont redéfinis dans sa portée (tokens.css). */
.sidebar{width:var(--fs-sidebar-w);background:var(--fs-sidebar-bg);background-image:radial-gradient(420px 260px at 0% 100%,rgba(68,52,229,.22),transparent 70%);color:var(--fs-text);border-inline-end:1px solid var(--fs-border-subtle);position:fixed;inset-block:0;inset-inline-start:0;z-index:var(--fs-z-sidebar);display:flex;flex-direction:column;transition:width var(--fs-normal) var(--fs-ease),transform var(--fs-normal) var(--fs-ease)}
.sidebar-brand{display:flex;align-items:center;gap:10px;padding:16px 18px;height:var(--fs-topbar-h);border-bottom:1px solid var(--fs-border-subtle)}
.sidebar-brand img{width:auto;height:38px;object-fit:contain;flex:none}
/* Le verrou existe en deux versions : le mot « Forma » est bleu nuit et se perdrait sur un fond
   sombre. Les classes nomment le FOND visé, pas le thème — certaines surfaces restent sombres en
   thème clair (panneau d'identification, lecteur, salle en direct) et c'est leur fond qui décide.
   La bascule est faite en CSS pour que le bon logo soit déjà en place au premier rendu ;
   l'alternance par script laissait apparaître le mauvais le temps d'un battement. */
.brand-on-dark{display:none}
[data-theme="dark"] .brand-on-light{display:none}
[data-theme="dark"] .brand-on-dark{display:inline-block}
/* Surfaces toujours sombres : le verrou clair y est imposé, thème clair compris. */
.on-dark-surface .brand-on-light{display:none}
.on-dark-surface .brand-on-dark{display:inline-block}
.sidebar-brand .brand-name{font-weight:800;font-size:17px;letter-spacing:-.02em;background:var(--fs-grad-accent);-webkit-background-clip:text;background-clip:text;color:transparent;white-space:nowrap}
.sidebar-nav{flex:1;overflow-y:auto;padding:12px 12px 20px;scrollbar-width:thin}
.nav-group{margin-bottom:14px}
.nav-title{padding:12px 12px 6px;font-size:var(--fs-text-xs);font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--fs-text-faint);white-space:nowrap}
.nav-item{display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:var(--fs-radius-md);color:var(--fs-sidebar-text);font-weight:600;font-size:var(--fs-text-base);position:relative;transition:all var(--fs-fast);white-space:nowrap;margin-bottom:2px}
.nav-item .ic{width:var(--fs-icon);height:var(--fs-icon);flex:none;color:var(--fs-text-faint);transition:color var(--fs-fast)}
.nav-item:hover{background:var(--fs-surface-sunken);color:var(--fs-text)}
.nav-item:hover .ic{color:var(--fs-primary-text)}
.nav-item.active{background:var(--fs-sidebar-active);color:var(--fs-sidebar-active-text);font-weight:700}
.nav-item.active .ic{color:var(--fs-primary-text)}
.nav-item.active::before{content:"";position:absolute;inset-inline-start:-12px;inset-block:8px;width:4px;border-radius:0 var(--fs-radius-2xs) var(--fs-radius-2xs) 0;background:var(--fs-grad-primary)}
[dir="rtl"] .nav-item.active::before{border-radius:var(--fs-radius-2xs) 0 0 var(--fs-radius-2xs)}
.nav-item .count{margin-inline-start:auto;background:var(--fs-accent-solid);color:var(--fs-on-solid);font-size:var(--fs-text-xs);font-weight:700;padding:1px 7px;border-radius:var(--fs-radius-full);min-width:20px;text-align:center}
.nav-item.nav-ai{background:linear-gradient(135deg,rgba(124,60,255,.16),rgba(9,216,245,.1));border:1px solid rgba(124,60,255,.3)}
.nav-item.nav-ai .ic{color:var(--fs-ai)}
.nav-item.nav-live .ic{color:var(--fs-mod-live)}
.sidebar-collapse{position:absolute;top:22px;inset-inline-end:-13px;width:26px;height:26px;border-radius:50%;background:var(--fs-surface);border:1px solid var(--fs-border);display:grid;place-items:center;color:var(--fs-text-muted);box-shadow:var(--fs-shadow-sm);z-index:2}
.sidebar-collapse:hover{color:var(--fs-primary-text);border-color:var(--fs-primary-border)}
[dir="rtl"] .sidebar-collapse .ic{transform:scaleX(-1)}
/* Fond bleu nuit : le verrou « néon » remplace le verrou pour fond clair ; un logo téléversé garde un écrin clair. */
.sidebar .brand-on-light{display:none}.sidebar .brand-on-dark{display:inline-block}
.sidebar-brand img:not(.brand-img){background:var(--fs-on-solid);border-radius:var(--fs-radius-sm);padding:4px 8px;box-sizing:content-box;max-block-size:30px}
.app.collapsed .sidebar{width:var(--fs-sidebar-w-collapsed)}
.app.collapsed .sidebar .brand-name,.app.collapsed .nav-title,.app.collapsed .nav-item span,.app.collapsed .nav-item .count{display:none}
.app.collapsed .nav-item{justify-content:center;padding:11px}
.app.collapsed .nav-item[data-tip]::after{inset-block-end:auto;top:50%;inset-inline-start:calc(100% + 12px);transform:translateY(-50%)}
/* §123 — la barre défile (overflow-y) et rognait l'infobulle ci-dessus : ux.js la rend hors du conteneur,
   en position fixe (.sidebar-tip). L'ancienne n'est neutralisée que lorsque le module est actif. */
.app.collapsed.has-sidebar-tip .sidebar [data-tip]:hover::after,.app.collapsed.has-sidebar-tip .sidebar [data-tip]:focus-visible::after{display:none}
.sidebar-tip{position:fixed;z-index:var(--fs-z-dropdown);transform:translateY(-50%);background:var(--fs-tooltip-bg);color:var(--fs-on-solid);padding:6px 10px;border-radius:var(--fs-radius-sm);font-size:var(--fs-text-xs);font-weight:500;white-space:nowrap;box-shadow:var(--fs-shadow-lg);opacity:0;transition:opacity var(--fs-fast) var(--fs-ease)}
.sidebar-tip.show{opacity:1}
.app.collapsed .sidebar-collapse .ic{transform:scaleX(-1)}
[dir="rtl"] .app.collapsed .sidebar-collapse .ic{transform:none}
.app.collapsed .sidebar-brand{justify-content:center;padding:14px}
.main{flex:1;min-width:0;margin-inline-start:var(--fs-sidebar-w);transition:margin var(--fs-normal) var(--fs-ease);display:flex;flex-direction:column}
.app.collapsed .main{margin-inline-start:var(--fs-sidebar-w-collapsed)}
.topbar{height:var(--fs-topbar-h);display:flex;align-items:center;gap:12px;padding:0 24px;position:sticky;top:0;z-index:var(--fs-z-sticky);background:var(--fs-topbar-bg);backdrop-filter:var(--fs-blur-sticky);-webkit-backdrop-filter:var(--fs-blur-sticky);border-bottom:1px solid var(--fs-border-subtle)}
.topbar-search{flex:1;max-width:520px;position:relative}
.topbar-search .input{padding-inline-start:42px;padding-inline-end:70px;background:var(--fs-bg);border-color:var(--fs-border);min-height:42px;padding-block:8px;border-radius:var(--fs-radius-btn)}
.topbar-search .input:hover{border-color:var(--fs-filter-hover-border)}
.topbar-search .input:focus{background:var(--fs-surface);border-color:var(--fs-focus-color)}
.topbar-search>.ic{position:absolute;inset-inline-start:14px;top:50%;transform:translateY(-50%);color:var(--fs-text-faint);width:var(--fs-icon-md);height:var(--fs-icon-md)}
.topbar-search kbd{position:absolute;inset-inline-end:10px;top:50%;transform:translateY(-50%)}
.topbar-search .input{cursor:text}
/* §126 — bouton de recherche mobile : n'apparait que lorsque la barre est masquee. */
.topbar .topbar-search-btn{display:none}
.topbar-actions{display:flex;align-items:center;gap:6px;margin-inline-start:auto}
.topbar-btn{width:42px;height:42px;border-radius:var(--fs-radius-btn-sm);display:grid;place-items:center;color:var(--fs-text-secondary);position:relative;border:1px solid transparent;transition:all .2s var(--fs-ease)}
.topbar-btn:hover{background:var(--fs-surface);border-color:var(--fs-border);color:var(--fs-filter-hover);box-shadow:var(--fs-shadow-xs)}
/* Sélecteur d'espace (21/09/2026) : descendu du bas de la barre latérale vers la barre du haut, à côté de
   l'avatar. Bouton large tant que la place le permet, réduit à sa seule icône sur petit écran. */
.space-switch-btn{width:auto;gap:8px;padding:0 10px;display:inline-flex;align-items:center;font-weight:600;font-size:var(--fs-text-sm)}
.space-switch-btn .space-switch-label{max-width:12ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.space-switch .menu a.active{color:var(--fs-primary-text);font-weight:600}
@media (max-width:900px){.space-switch-btn{width:42px;padding:0}.space-switch-btn .space-switch-label,.space-switch-btn .ic-sm{display:none}}
.dropdown.open>.topbar-btn,.topbar-btn[aria-expanded="true"]{background:var(--fs-primary-soft);border-color:var(--fs-primary-border);color:var(--fs-primary-text)}
.topbar-btn .dot-badge{position:absolute;top:8px;inset-inline-end:8px;min-width:8px;height:8px;border-radius:var(--fs-radius-full);background:var(--fs-accent);box-shadow:0 0 0 3px rgba(238,32,220,.14);border:2px solid var(--fs-surface);box-sizing:content-box}
.topbar-btn .dot-badge.num{min-width:16px;height:16px;font-size:var(--fs-text-xs);font-weight:700;background:var(--fs-accent-solid);color:var(--fs-on-solid);display:grid;place-items:center;padding:0 3px;top:4px;inset-inline-end:4px;border:0}
/* Compteur de la cloche : couleur du module « notifications » (§109), encre sombre (7,5:1 sur l’ambre). */
.topbar-btn .dot-badge.num[data-notif-count]{background:var(--fs-mod-notif);color:var(--fs-on-mod-notif)}
.menu-toggle{display:none}
.topbar-actions .dropdown>.avatar{border:2px solid var(--fs-surface);box-shadow:0 0 0 1px var(--fs-border),0 6px 16px rgba(28,47,90,.14)}
.topbar-actions .dropdown.open>.avatar{box-shadow:0 0 0 2px var(--fs-nav-active),0 6px 16px rgba(28,47,90,.14)}
.content{padding:24px 24px 80px;max-width:var(--fs-content-max);width:100%;margin-inline:auto;animation:fadeIn .25s}
.content-narrow{max-width:900px}
.impersonation-bar{background:var(--fs-warning);color:var(--fs-on-warning);padding:8px 16px;font-weight:600;display:flex;align-items:center;gap:12px;justify-content:center;font-size:var(--fs-text-sm)}
.announcement-bar{background:var(--fs-navy);color:var(--fs-on-navy);padding:9px 16px;text-align:center;font-weight:600;font-size:var(--fs-text-sm);border-bottom:1px solid rgba(255,255,255,.08)}
.announcement-bar a{color:var(--fs-on-solid);font-weight:800;text-decoration:underline;text-decoration-color:rgba(255,255,255,.38);text-underline-offset:4px}
/* Mobile (§152) */
.bottom-nav{display:none;position:fixed;inset-block-end:0;inset-inline:0;height:var(--fs-bottom-nav-h);background:var(--fs-surface-raised);border-top:1px solid var(--fs-border-subtle);z-index:var(--fs-z-sidebar);padding-bottom:env(safe-area-inset-bottom);box-shadow:0 -6px 24px rgba(15,23,42,.06)}
.bottom-nav a{flex:1 1 0;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;padding-inline:3px;font-size:var(--fs-text-xs);font-weight:600;color:var(--fs-text-muted);overflow:hidden;text-align:center;line-height:1.15;overflow-wrap:anywhere;hyphens:auto}
/* QA visuel §181 : a cinq entrees, les libelles se chevauchaient sous 420 px. Ils passent
   desormais sur deux lignes plutot que d'etre rognes — le plancher de 12 px est preserve (§120). */
@media (max-width:420px){.bottom-nav a{letter-spacing:-.01em}}
.bottom-nav a .ic{width:var(--fs-icon-lead);height:var(--fs-icon-lead)}
.bottom-nav a.active{color:var(--fs-primary-text);font-weight:800}
.bottom-nav a.nav-ai .ic{color:var(--fs-ai)}
.bottom-nav a.center .ic{width:48px;height:48px;padding:12px;border-radius:var(--fs-radius-full);background:var(--fs-grad-primary);color:var(--fs-on-solid);margin-top:-26px;box-shadow:var(--fs-shadow-primary)}
@media (max-width:1024px){
  .sidebar{transform:translateX(-100%);box-shadow:none}
  [dir="rtl"] .sidebar{transform:translateX(100%)}
  .sidebar.open{transform:none;box-shadow:var(--fs-shadow-xl)}
  .sidebar-collapse{display:none}
  .main,.app.collapsed .main{margin-inline-start:0}
  .app.collapsed .sidebar{width:var(--fs-sidebar-w)}
  .app.collapsed .sidebar .brand-name,.app.collapsed .nav-title,.app.collapsed .nav-item span{display:block}
  .app.collapsed .nav-item{justify-content:flex-start;padding:10px 12px}
  .menu-toggle{display:grid}
  .sidebar-overlay{position:fixed;inset:0;background:var(--fs-overlay);z-index:calc(var(--fs-z-sidebar) - 1);display:none}
  .sidebar-overlay.open{display:block}
  .topbar-search{display:none}
  .topbar .topbar-search-btn{display:grid}
}
@media (max-width:720px){
  .bottom-nav{display:flex}
  /* SC 2.4.11 : la navigation basse fixe masquerait le bas de page — la marge de défilement l'inclut. */
  :root:has(.bottom-nav){--fs-sticky-bottom:calc(var(--fs-bottom-nav-h) + env(safe-area-inset-bottom, 0px))}
  .content{padding:16px 16px 96px}
  .topbar{padding:0 12px}
  .page-head h1{font-size:var(--fs-text-xl)}
  .kpi-value{font-size:24px}
}

/* ---------- Command palette (§127) ---------- */
.palette-backdrop{position:fixed;inset:0;background:var(--fs-overlay);backdrop-filter:var(--fs-blur-overlay);-webkit-backdrop-filter:var(--fs-blur-overlay);z-index:var(--fs-z-palette);display:none;align-items:flex-start;justify-content:center;padding:12vh 16px 16px}
.palette-backdrop.open{display:flex;animation:fadeIn .12s}
.palette{width:100%;max-width:640px;background:var(--fs-surface-raised);border:1px solid var(--fs-border);border-radius:var(--fs-radius-xl);box-shadow:var(--fs-shadow-xl);overflow:hidden;animation:modalIn .2s var(--fs-ease)}
.palette-input{display:flex;align-items:center;gap:12px;padding:18px 22px;border-bottom:1px solid var(--fs-divider);background:linear-gradient(118deg,rgba(9,216,245,.06),rgba(124,60,255,.06) 60%,rgba(238,32,220,.05))}
.palette-input .ic{width:var(--fs-icon-lead);height:var(--fs-icon-lead);color:var(--fs-primary-text)}
.palette-input input{flex:1;border:0;outline:none;background:transparent;font-size:var(--fs-text-lg);color:var(--fs-text)}
.palette-list{max-height:420px;overflow:auto;padding:8px}
.palette-group{padding:12px 12px 6px;font-size:var(--fs-text-xs);font-weight:800;letter-spacing:.11em;text-transform:uppercase;color:var(--fs-kicker)}
.palette-item{position:relative;display:flex;align-items:center;gap:12px;padding:10px 12px;border-radius:var(--fs-radius-md);color:var(--fs-text-secondary);font-weight:600;cursor:pointer}
.palette-item .ic{width:var(--fs-icon-md);height:var(--fs-icon-md);color:var(--fs-text-muted)}
.palette-item.active,.palette-item:hover{background:var(--fs-primary-soft);color:var(--fs-primary-text)}
.palette-item.active::before{content:"";position:absolute;inset-inline-start:0;inset-block:9px;width:3px;border-radius:var(--fs-radius-full);background:var(--fs-grad-primary)}
.palette-item.active .ic{color:var(--fs-primary-text)}
.palette-item small{margin-inline-start:auto;color:var(--fs-text-faint);font-size:var(--fs-text-xs);max-width:45%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.palette-item.ai{background:linear-gradient(135deg,rgba(124,58,237,.08),rgba(6,182,212,.08))}
.palette-foot{display:flex;flex-wrap:wrap;gap:6px 16px;padding:10px 20px;border-top:1px solid var(--fs-divider);font-size:var(--fs-text-xs);color:var(--fs-text-faint)}
/* §121 — l’espacement des lettres rompt la liaison de l’écriture arabe : neutralisé en RTL. */
[dir="rtl"] .palette-group{letter-spacing:0}
/* Écran tactile : les raccourcis clavier du pied de palette n’ont pas d’objet ; petit écran : la liste occupe la hauteur utile. */
@media (hover:none) and (pointer:coarse){.palette-foot{display:none}}
@media (max-width:720px){.palette-backdrop{padding:8px}.palette-list{max-height:calc(100dvh - 96px)}}

/* ---------- Notifications (§149) ---------- */
.notif-list{max-height:440px;overflow:auto}
.notif{display:flex;gap:12px;padding:12px;border-radius:var(--fs-radius-md);align-items:flex-start;color:var(--fs-text-secondary)}
.notif:hover{background:var(--fs-surface-sunken)}
/* Non lu = nouveauté : fond « notifications » (§109). L’heure passe en encre atténuée, la plus pâle tombant sous 4,5:1 sur ce fond en thème sombre. */
.notif.unread{background:var(--fs-mod-notif-soft)}.notif.unread time{color:var(--fs-text-muted)}
.notif .n-icon{width:38px;height:38px;border-radius:var(--fs-radius-lg);display:grid;place-items:center;flex:none;background:var(--n-soft,var(--fs-primary-soft));color:var(--n-color,var(--fs-primary))}
.notif strong{display:block;font-size:var(--fs-text-sm);color:var(--fs-text)}
.notif p{margin:1px 0 0;font-size:var(--fs-text-xs);color:var(--fs-text-muted)}
.notif time{font-size:var(--fs-text-xs);color:var(--fs-text-faint);white-space:nowrap}
.notif.c-success{--n-soft:var(--fs-success-soft);--n-color:var(--fs-success)}.notif.c-warning{--n-soft:var(--fs-warning-soft);--n-color:var(--fs-warning)}.notif.c-danger{--n-soft:var(--fs-danger-soft);--n-color:var(--fs-danger)}.notif.c-info{--n-soft:var(--fs-info-soft);--n-color:var(--fs-info)}.notif.c-live{--n-soft:var(--fs-mod-live-soft);--n-color:var(--fs-mod-live)}.notif.c-cert{--n-soft:var(--fs-mod-cert-soft);--n-color:var(--fs-mod-cert)}.notif.c-ai{--n-soft:var(--fs-mod-ai-soft);--n-color:var(--fs-ai)}

/* ---------- IA (§140-142, §176) ---------- */
.ai-mark{display:inline-flex;align-items:center;gap:6px;font-weight:700;background:var(--fs-grad-ai);-webkit-background-clip:text;background-clip:text;color:transparent}
.ai-glow{position:relative}
.ai-glow::before{content:"";position:absolute;inset:-1px;border-radius:inherit;padding:1px;background:var(--fs-grad-ai);-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;pointer-events:none;opacity:.6}
.ai-panel{position:fixed;top:0;inset-inline-end:0;height:100%;width:min(440px,100%);background:var(--fs-surface-raised);box-shadow:var(--fs-shadow-xl);z-index:calc(var(--fs-z-drawer) + 2);transform:translateX(100%);transition:transform var(--fs-slow) var(--fs-ease);display:flex;flex-direction:column;border-inline-start:1px solid var(--fs-border-subtle)}
[dir="rtl"] .ai-panel{transform:translateX(-100%)}
.ai-panel.open{transform:none}
.ai-panel-head{padding:16px 20px;border-bottom:1px solid var(--fs-divider);display:flex;align-items:center;gap:10px;background:linear-gradient(135deg,rgba(124,58,237,.08),rgba(6,182,212,.06))}
.ai-panel-head .ic{color:var(--fs-ai)}
.ai-panel-body{flex:1;overflow:auto;padding:16px 20px;display:flex;flex-direction:column;gap:12px}
.ai-panel-foot{padding:12px 16px;border-top:1px solid var(--fs-divider)}
.ai-msg{max-width:92%;padding:12px 14px;border-radius:var(--fs-radius-lg);font-size:var(--fs-text-base);line-height:1.55}
.ai-msg.user{align-self:flex-end;background:var(--fs-primary);color:var(--fs-on-solid);border-end-end-radius:var(--fs-radius-2xs)}
.ai-msg.bot{align-self:flex-start;background:var(--fs-surface-sunken);border-end-start-radius:var(--fs-radius-2xs);color:var(--fs-text-secondary)}
.ai-msg.bot .src{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
.ai-msg.bot .src a{display:inline-flex;align-items:center;min-block-size:var(--fs-target-min);font-size:var(--fs-text-xs);padding:2px 8px;border-radius:var(--fs-radius-full);background:var(--fs-mod-ai-soft);color:var(--fs-primary-text)}
.ai-suggest{display:flex;flex-wrap:wrap;gap:8px}
.ai-suggest button{padding:8px 12px;border-radius:var(--fs-radius-md);background:var(--fs-mod-ai-soft);color:var(--fs-primary-text);font-size:var(--fs-text-sm);font-weight:500;border:1px solid transparent}
.ai-suggest button:hover{border-color:var(--fs-primary-border)}
.ai-suggest .ai-suggest-link{display:inline-flex;align-items:center;gap:6px;padding:8px 12px;border-radius:var(--fs-radius-md);background:var(--fs-mod-ai-soft);color:var(--fs-primary-text);font-size:var(--fs-text-sm);font-weight:500;border:1px solid transparent}
.ai-suggest .ai-suggest-link:hover{border-color:var(--fs-primary-border)}
.ai-typing span{display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--fs-primary);margin-inline-end:3px;animation:bounce 1s infinite}
.ai-typing span:nth-child(2){animation-delay:.15s}.ai-typing span:nth-child(3){animation-delay:.3s}
@keyframes bounce{0%,80%,100%{transform:translateY(0);opacity:.5}40%{transform:translateY(-5px);opacity:1}}
.ai-disclaimer{font-size:var(--fs-text-xs);color:var(--fs-text-faint);text-align:center;margin-top:6px}

/* ---------- Célébration (§145) ---------- */
.celebrate{text-align:center;padding:40px 24px}
.celebrate .emoji{font-size:64px;animation:pop .6s var(--fs-ease)}
@keyframes pop{0%{transform:scale(.3);opacity:0}60%{transform:scale(1.15)}100%{transform:scale(1);opacity:1}}
.confetti{position:fixed;inset:0;pointer-events:none;z-index:200;overflow:hidden}
.confetti i{position:absolute;top:-10px;width:8px;height:14px;border-radius:var(--fs-radius-2xs);animation:fall 2.4s linear forwards}
@keyframes fall{to{transform:translateY(110vh) rotate(720deg);opacity:.2}}

/* ---------- Cartes cours ---------- */
.course-card{display:flex;flex-direction:column;overflow:hidden;height:100%}
.course-card .cover{position:relative;aspect-ratio:16/9;background:var(--fs-surface-sunken);overflow:hidden}
.course-card .cover img{width:100%;height:100%;object-fit:cover;transition:transform .5s var(--fs-ease)}
.course-card:hover .cover img{transform:scale(1.04)}
.course-card .cover .badges{position:absolute;top:10px;inset-inline-start:10px;display:flex;gap:6px}
.course-card .cover .fav{position:absolute;top:10px;inset-inline-end:10px;width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.9);display:grid;place-items:center;color:var(--fs-on-light)}
.course-card .cover .fav.on{color:var(--fs-accent)}
.course-card .cover .fav .ic{width:var(--fs-icon-sm);height:var(--fs-icon-sm)}
.course-card .cover-ph{width:100%;height:100%;display:grid;place-items:center;background:var(--fs-grad-primary);color:var(--fs-on-solid);font-size:40px;font-weight:800;opacity:.9}
.course-card .body{padding:14px 16px 16px;display:flex;flex-direction:column;gap:8px;flex:1}
.course-card .cat{font-size:var(--fs-text-xs);font-weight:600;color:var(--cat,var(--fs-mod-course));text-transform:uppercase;letter-spacing:.05em}
.course-card h3{font-size:var(--fs-text-md);margin:0;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.course-card h3 a{color:var(--fs-text)}.course-card h3 a:hover{color:var(--fs-primary-text)}
.course-card .instr{display:flex;align-items:center;gap:8px;font-size:var(--fs-text-sm);color:var(--fs-text-muted)}
.course-card .meta{display:flex;align-items:center;gap:12px;font-size:var(--fs-text-xs);color:var(--fs-text-muted);flex-wrap:wrap}
.course-card .meta span{display:inline-flex;align-items:center;gap:4px}.course-card .meta .ic{width:var(--fs-icon-xs);height:var(--fs-icon-xs)}
.course-card .foot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:8px;padding-top:8px}
.price{font-weight:800;font-size:var(--fs-text-lg);color:var(--fs-text);font-variant-numeric:tabular-nums}
.price .old{font-weight:500;font-size:var(--fs-text-sm);color:var(--fs-text-faint);text-decoration:line-through;margin-inline-start:6px;white-space:nowrap}
.price.free{color:var(--fs-success-text)}
.stars{display:inline-flex;align-items:center;gap:2px;color:var(--fs-warning)}
.stars .ic{width:var(--fs-icon-xs);height:var(--fs-icon-xs);fill:currentColor;stroke:none}
.stars .ic.off{color:var(--fs-border-strong)}
/* §155 — pictogramme étoile isolé (note moyenne, modèle par défaut, mise en avant) : même dessin plein que .stars. */
.ic-star{fill:currentColor;stroke:none;color:var(--fs-warning);vertical-align:-2px}
.ic-star-ribbon{fill:currentColor;stroke:none;vertical-align:-2px}
.ic-medal-1{color:var(--fs-warning)}.ic-medal-2{color:var(--fs-text-muted)}.ic-medal-3{color:var(--fs-mod-course)}
.stars b{color:var(--fs-text);font-size:var(--fs-text-sm);margin-inline-start:4px}
.course-card .progress{margin-top:4px}
.course-row{display:flex;gap:16px;align-items:center}
.course-row .thumb{width:120px;aspect-ratio:16/9;border-radius:var(--fs-radius-md);object-fit:cover;flex:none;background:var(--fs-surface-sunken)}

/* ---------- Timeline / activité ---------- */
.timeline{display:flex;flex-direction:column;gap:0}
.tl-item{display:flex;gap:14px;padding:10px 0;position:relative}
.tl-item::before{content:"";position:absolute;inset-inline-start:17px;top:44px;bottom:-6px;width:2px;background:var(--fs-divider)}
.tl-item:last-child::before{display:none}
.tl-icon{width:36px;height:36px;border-radius:var(--fs-radius-md);display:grid;place-items:center;flex:none;background:var(--tl-soft,var(--fs-primary-soft));color:var(--tl-color,var(--fs-primary));position:relative;z-index:1}
.tl-icon .ic{width:var(--fs-icon-md);height:var(--fs-icon-md)}
.tl-body{flex:1;min-width:0;padding-top:4px}
.tl-body strong{font-weight:600}.tl-body p{margin:2px 0 0;font-size:var(--fs-text-sm);color:var(--fs-text-muted)}
.tl-body time{font-size:var(--fs-text-xs);color:var(--fs-text-faint)}
.tl-success{--tl-soft:var(--fs-success-soft);--tl-color:var(--fs-success)}.tl-accent{--tl-soft:var(--fs-accent-soft);--tl-color:var(--fs-accent)}.tl-info{--tl-soft:var(--fs-info-soft);--tl-color:var(--fs-info)}.tl-warning{--tl-soft:var(--fs-warning-soft);--tl-color:var(--fs-warning)}.tl-orange{--tl-soft:var(--fs-mod-course-soft);--tl-color:var(--fs-mod-course)}

/* ---------- Charts (§132) ---------- */
.chart{position:relative;width:100%}
.chart svg{width:100%;height:auto;overflow:visible;display:block;max-width:100%}
.chart .grid-line{stroke:var(--fs-divider);stroke-width:1}
.chart .axis{fill:var(--fs-text-faint);font-size:var(--fs-text-xs);font-family:var(--fs-font)}
.chart .area{fill:url(#areaGrad);opacity:.9}
.chart .line{fill:none;stroke:var(--fs-primary);stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round}
.chart .bar{fill:var(--fs-primary);rx:6}
.chart .bar:hover{opacity:.85}
.chart-tip{position:absolute;pointer-events:none;background:var(--fs-code-bg);color:var(--fs-on-solid);padding:6px 10px;border-radius:var(--fs-radius-sm);font-size:12px;white-space:nowrap;transform:translate(-50%,-120%);opacity:0;transition:opacity .1s;z-index:5}
.chart-tip.show{opacity:1}
.legend{display:flex;flex-wrap:wrap;gap:14px;font-size:var(--fs-text-sm);color:var(--fs-text-muted);margin-top:10px}
.legend span{display:inline-flex;align-items:center;gap:6px}.legend i{width:10px;height:10px;border-radius:var(--fs-radius-2xs);display:inline-block}
.donut{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:24px}
/* Sur téléphone, la légende passe sous l'anneau plutôt que de déborder de la carte. */
.donut>.legend{min-width:0;flex:1 1 130px}
.donut svg{width:160px;height:160px;flex:none}
/* §166 / WCAG 1.4.1 — la pastille de légende reproduit le trait, le marqueur ou le motif de la série :
   elle doit donc garder sa taille propre, que `.chart svg` et `.donut svg` étireraient sinon. */
.chart .legend .lg-key{inline-size:var(--fs-icon-lg);block-size:12px;flex:none;overflow:visible}
.chart .legend .lg-key-sq{inline-size:12px}
/* Tableau de repli (WCAG 1.1.1) : replié par défaut pour ne pas alourdir le tableau de bord, ouvert
   il donne chaque valeur en clair — au lecteur d'écran comme à la personne qui distingue mal les teintes. */
.chart-data{flex:1 1 100%;min-width:0;margin-block-start:var(--fs-space-xs);font-size:var(--fs-text-sm)}
.chart-data>summary{display:inline-flex;align-items:center;min-block-size:var(--fs-target-min);cursor:pointer;color:var(--fs-link);font-weight:600;border-radius:var(--fs-radius-xs)}
.chart-data>summary:hover{color:var(--fs-link-hover)}
.chart-data-scroll{max-block-size:280px;overflow:auto;margin-block-start:var(--fs-space-xs);border:1px solid var(--fs-border-subtle);border-radius:var(--fs-radius-md)}
.chart-data-scroll:focus-visible{outline:var(--fs-focus-outline);outline-offset:var(--fs-focus-offset)}
.chart-data .table th{position:static}
.chart-data .table tbody th{text-transform:none;letter-spacing:0;font-size:var(--fs-text-sm);font-weight:500;color:var(--fs-text);white-space:normal}
.chart-empty{margin:0;padding-block:var(--fs-space-lg);text-align:center;color:var(--fs-text-muted);font-size:var(--fs-text-sm)}
.heatmap{display:grid;grid-template-columns:repeat(auto-fill,12px);gap:3px}
.heatmap i{width:12px;height:12px;border-radius:var(--fs-radius-2xs);background:var(--fs-surface-sunken)}
.heatmap i[data-l="1"]{background:var(--fs-success-soft-2)}.heatmap i[data-l="2"]{background:var(--fs-success-mid)}.heatmap i[data-l="3"]{background:var(--fs-success)}.heatmap i[data-l="4"]{background:var(--fs-success-hover)}
.funnel{display:flex;flex-direction:column;gap:6px}
.funnel>div:not(.funnel-row){height:34px;border-radius:var(--fs-radius-sm);background:var(--fs-grad-primary);color:var(--fs-on-solid);display:flex;align-items:center;justify-content:space-between;padding:0 12px;font-size:var(--fs-text-sm);font-weight:600;margin-inline:auto}

/* ---------- Divers ---------- */
.stat-list{display:flex;flex-direction:column;gap:10px}
.stat-list .row{display:flex;justify-content:space-between;gap:12px;padding:8px 0;border-bottom:1px solid var(--fs-divider);font-size:var(--fs-text-base)}
.stat-list .row:last-child{border:0}.stat-list .row b{font-variant-numeric:tabular-nums}
.kv{display:grid;grid-template-columns:minmax(120px,200px) 1fr;gap:8px 16px;font-size:var(--fs-text-base)}
.kv dt{color:var(--fs-text-muted);font-weight:500}.kv dd{margin:0;font-weight:500}
.tag{display:inline-block;padding:2px 8px;border-radius:var(--fs-radius-xs);background:var(--fs-surface-sunken);font-size:var(--fs-text-xs);color:var(--fs-text-muted)}
.pill-icon{width:44px;height:44px;border-radius:var(--fs-radius-md);display:grid;place-items:center;background:var(--pi-soft,var(--fs-primary-soft));color:var(--pi-color,var(--fs-primary));flex:none}
.pill-icon .ic{width:var(--fs-icon-lead);height:var(--fs-icon-lead)}
/* Poignée de réordonnancement : cible de 24 px minimum (SC 2.5.8), focalisable et pilotable aux flèches
   (FS.sortable) — le glisser-déposer n'est plus le seul moyen de changer l'ordre. */
.dnd-handle{cursor:grab;color:var(--fs-text-faint);touch-action:none;display:inline-grid;place-items:center;flex:none;min-inline-size:var(--fs-target-min);min-block-size:var(--fs-target-min);border-radius:var(--fs-radius-xs)}
.dnd-handle:hover,.dnd-handle:focus-visible{color:var(--fs-text-muted);background:var(--fs-surface-sunken)}
.dnd-handle.is-moving{color:var(--fs-primary-text);background:var(--fs-primary-soft)}
.dnd-handle:active{cursor:grabbing}
.dragging{opacity:.5}.drop-target{outline:2px dashed var(--fs-primary);outline-offset:2px;border-radius:var(--fs-radius-md)}
.copy-field{display:flex;align-items:center;gap:8px;padding:10px 12px;border-radius:var(--fs-radius-md);background:var(--fs-surface-sunken);font-family:var(--fs-font-mono);font-size:var(--fs-text-sm);direction:ltr}
.copy-field span{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.countdown{display:inline-flex;flex-wrap:wrap;gap:8px;max-width:100%}
.countdown div{background:var(--fs-surface-sunken);border-radius:var(--fs-radius-md);padding:6px 10px;text-align:center;min-width:52px}
.countdown b{display:block;font-size:var(--fs-text-xl);font-variant-numeric:tabular-nums;line-height:1.1}.countdown small{font-size:var(--fs-text-xs);text-transform:uppercase;color:var(--fs-text-muted)}
.split{display:grid;grid-template-columns:minmax(0,2fr) minmax(0,1fr);gap:var(--fs-space-lg)}
.split-even{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
/* Un élément de grille a min-width:auto : un contenu insécable (titre tronqué, ligne de méta)
   élargit alors la colonne et fait déborder le corps de page sur téléphone (CDC §154). */
.split>*,.split-even>*{min-width:0}
@media (max-width:1024px){.split,.split-even{grid-template-columns:minmax(0,1fr)}}
.sticky-side{position:sticky;top:calc(var(--fs-topbar-h) + 16px)}
.density-compact .table td,.density-compact .table th{padding:8px 12px}
.density-compact .card-body{padding:16px}
.watermark-layer{position:absolute;inset:0;pointer-events:none;overflow:hidden;z-index:5}
.watermark-layer span{position:absolute;color:rgba(255,255,255,.35);font-size:13px;font-weight:600;text-shadow:0 1px 2px rgba(0,0,0,.5);white-space:nowrap;transition:opacity .6s ease;user-select:none}
/* Filigrane piloté par player.js : masqué le temps du changement de place (les calques statiques, rediffusions
   par exemple, restent visibles sans script). */
.watermark-layer.wm-js span{opacity:0}.watermark-layer.wm-js span.on{opacity:1}
.print-only{display:none}
/* ---------- Accessibilité renforcée (§6.3) : réglages du compte posés sur <html> par partials/head ----------
   Police adaptée : pile SYSTÈME très lisible (aucune police téléchargée), interlignage et espacements élargis ;
   taille du texte : l'échelle des jetons est redéfinie (tous les composants la suivent) ; animations : même
   neutralisation que prefers-reduced-motion, déclenchée par le compte. */
[data-font="readable"]{--fs-font:Verdana,Tahoma,'Segoe UI',Arial,'Noto Sans Arabic',sans-serif;--fs-leading:1.75}
[dir="rtl"][data-font="readable"]{--fs-font:Tahoma,'Segoe UI','Noto Sans Arabic',Arial,sans-serif}
[data-font="readable"]:not([dir="rtl"]) body{letter-spacing:.03em;word-spacing:.12em}
[data-font-size="lg"]{--fs-text-xs:14px;--fs-text-sm:15px;--fs-text-base:16px;--fs-text-md:17px;--fs-text-lg:19px;--fs-text-xl:23px;--fs-text-2xl:27px;--fs-text-3xl:34px}
[data-font-size="xl"]{--fs-text-xs:15px;--fs-text-sm:17px;--fs-text-base:18px;--fs-text-md:19px;--fs-text-lg:22px;--fs-text-xl:26px;--fs-text-2xl:30px;--fs-text-3xl:38px}
[data-motion="reduce"]{--fs-fast:0ms;--fs-normal:0ms;--fs-slow:0ms;scroll-behavior:auto}
[data-motion="reduce"] *,[data-motion="reduce"] *::before,[data-motion="reduce"] *::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}

@media print{.sidebar,.topbar,.bottom-nav,.toasts,.no-print{display:none!important}.main{margin:0!important}.content{padding:0}.print-only{display:block}}

/* --- Menus déroulants : rester lisibles quelles que soient la largeur et la position ---
   La barre latérale est fixée au plan 50 : un menu au plan 40 passait dessous et se
   retrouvait amputé de sa moitié gauche. Il monte donc au-dessus d'elle, et il bascule
   du côté opposé quand il n'y a plus la place, plutôt que de sortir de l'écran. */
.menu{overflow-wrap:anywhere}
.menu.flip-start{inset-inline-end:auto;inset-inline-start:0}
/* 24/09/2026 — un menu ouvert près du bas de la fenêtre (dernière ligne d'un tableau, encart de fin de page)
   débordait sous la carte. Il s'ouvre alors vers le haut, et sa hauteur reste bornée par la place disponible. */
.menu.flip-up{top:auto;bottom:calc(100% + 10px)}
.menu{max-height:var(--fs-menu-max, none);overflow-y:auto}
.menu a,.menu button,.menu-item{white-space:normal;line-height:1.35}

/* --- Accordéon des groupes du menu latéral (§123-124) ---
   Le titre de groupe devient un bouton : il ouvre et ferme sa liste. L'état est mémorisé
   par utilisateur, et le groupe qui contient la page courante s'ouvre toujours. En mode
   réduit (icônes seules), les titres disparaissent : l'accordéon ne s'applique plus. */
.nav-title{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  width:100%;background:none;border:0;cursor:pointer;
  border-radius:var(--fs-radius-sm);
  transition:color var(--fs-fast), background var(--fs-fast);
}
.nav-title:hover{color:var(--fs-sidebar-text);background:var(--fs-sidebar-hover, rgba(255,255,255,.05))}
.nav-title:focus-visible{outline:2px solid var(--fs-primary);outline-offset:2px}
.nav-title .nav-caret{
  width:14px;height:14px;flex:none;opacity:.65;
  transition:transform var(--fs-normal) var(--fs-ease);
}
.nav-group.closed .nav-title .nav-caret{transform:rotate(-90deg)}
:root[dir="rtl"] .nav-group.closed .nav-title .nav-caret,
[dir="rtl"] .nav-group.closed .nav-title .nav-caret{transform:rotate(90deg)}

/* Ouverture et fermeture animées, sans saut de mise en page. */
.nav-group-items{overflow:hidden}
.nav-group-items[hidden]{display:none}
.nav-group.animating .nav-group-items{transition:height var(--fs-normal) var(--fs-ease)}

/* Menu réduit : plus de titres, donc tous les groupes restent ouverts. */
.app.collapsed .nav-title{display:none}
.app.collapsed .nav-group-items[hidden]{display:block}

@media (prefers-reduced-motion:reduce){
  .nav-title .nav-caret,.nav-group.animating .nav-group-items{transition:none}
}

/* Barre de période (Analytics…) : pastilles, dates et bouton à la même hauteur, alignés par le bas (18/09). */
.period-bar{align-items:flex-end}
.period-bar .tabs-pills{padding:2px;align-items:stretch;margin-bottom:0}
.period-bar .tabs-pills .tab{display:inline-flex;align-items:center;min-height:calc(2.6875rem - 6px);padding-block:0}
.period-bar .form-group{margin:0}
.period-bar > small{align-self:center}
/* Ancre des listes filtrées : arrive juste sous l'en-tête figé (hauteur mesurée par p01-chrome.js). */
.list-anchor{display:block;height:0;scroll-margin-top:calc(var(--fs-sticky-top, 72px) + 12px)}
