@import "tailwindcss";

/* ---------- Design tokens ---------- */

:root {
  /* Surfaces — palette stone (chaude, douce sans être beige) */
  --background: #fafaf9;
  --surface: #ffffff;
  --surface-2: #f5f5f4;
  --surface-3: #e7e5e4;
  --foreground: #1c1917;
  --muted-foreground: #57534e;     /* stone-600, plus contrasté qu'avant pour rester lisible sur surface-2 */
  --subtle-foreground: #78716c;    /* stone-500, lisible mais clairement secondaire */

  /* Bordures */
  --border: #e7e5e4;
  --border-strong: #d6d3d1;

  /* Accent indigo */
  --accent: #4f46e5;
  --accent-hover: #4338ca;
  --accent-active: #3730a3;
  --accent-foreground: #ffffff;
  --accent-subtle: #eef2ff;
  --accent-ring: #c7d2fe;

  /* Sémantique */
  --success: #16a34a;
  --success-subtle: #f0fdf4;
  --warning: #d97706;
  --warning-subtle: #fffbeb;
  --danger: #dc2626;
  --danger-subtle: #fef2f2;
  --info: #0891b2;
  --info-subtle: #ecfeff;

  /* Catégories diff report-templates (calque coolcare) */
  --cat-xlsx: #dcfce7;          /* vert pâle — items qui viennent du XLSX seul */
  --cat-xlsx-bd: #16a34a;
  --cat-db: #dbeafe;             /* bleu pâle — orphelin BDD */
  --cat-db-bd: #2563eb;
  --cat-db-vol: #ede9fe;          /* violet pâle — db_only_volontaire (verrouillé migration_id) */
  --cat-db-vol-bd: #7c3aed;
  --cat-divergent-bd: #d97706;    /* amber — common_divergent marker */

  /* Sidebar (dark) */
  --sidebar: #18181b;
  --sidebar-foreground: #fafaf9;
  --sidebar-muted: #a1a1aa;
  --sidebar-active: #27272a;
  --sidebar-accent: #818cf8;

  /* Ombres — strates discrètes */
  --shadow-sm: 0 1px 2px 0 rgb(28 25 23 / 0.04);
  --shadow: 0 1px 3px 0 rgb(28 25 23 / 0.06), 0 1px 2px -1px rgb(28 25 23 / 0.04);
  --shadow-md: 0 4px 6px -1px rgb(28 25 23 / 0.08), 0 2px 4px -2px rgb(28 25 23 / 0.05);
  --shadow-lg: 0 10px 15px -3px rgb(28 25 23 / 0.08), 0 4px 6px -4px rgb(28 25 23 / 0.05);
}

/* ---------- Dark mode ---------- */
/* Activé via une classe `.dark` sur <html>, posée par ThemeProvider et
   par le script inline FOUC-prevention dans <body>. Surcharge des CSS
   vars seulement — toutes les utilities Tailwind héritent. */

:root.dark {
  --background: #0c0a09;
  --surface: #1c1917;
  --surface-2: #292524;
  --surface-3: #44403c;
  --foreground: #fafaf9;
  --muted-foreground: #d6d3d1;     /* stone-300, plus lumineux en dark pour meilleur contraste */
  --subtle-foreground: #a8a29e;    /* stone-400 */

  --border: #27272a;
  --border-strong: #3f3f46;

  --accent: #818cf8;
  --accent-hover: #6366f1;
  --accent-active: #4f46e5;
  --accent-foreground: #1e1b4b;
  --accent-subtle: rgba(129, 140, 248, 0.12);
  --accent-ring: #4f46e5;

  --success: #22c55e;
  --success-subtle: rgba(34, 197, 94, 0.12);
  --warning: #f59e0b;
  --warning-subtle: rgba(245, 158, 11, 0.12);
  --danger: #ef4444;
  --danger-subtle: rgba(239, 68, 68, 0.12);
  --info: #06b6d4;
  --info-subtle: rgba(6, 182, 212, 0.12);

  /* Catégories diff — variantes dark (rgba pour s'adapter au fond sombre) */
  --cat-xlsx: rgba(34, 197, 94, 0.14);
  --cat-xlsx-bd: #22c55e;
  --cat-db: rgba(59, 130, 246, 0.14);
  --cat-db-bd: #3b82f6;
  --cat-db-vol: rgba(168, 85, 247, 0.18);
  --cat-db-vol-bd: #a855f7;
  --cat-divergent-bd: #f59e0b;

  /* En dark, la sidebar fond avec le bg : seul le border sépare. Pattern
     Linear/Vercel — élégant en dark, le contenu central "flotte" sur la
     surface plus claire. */
  --sidebar: #0c0a09;
  --sidebar-foreground: #fafaf9;
  --sidebar-muted: #71717a;
  --sidebar-active: #1c1917;
  --sidebar-accent: #818cf8;

  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.3);
  --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.4), 0 1px 2px -1px rgb(0 0 0 / 0.3);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.45), 0 2px 4px -2px rgb(0 0 0 / 0.3);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.5), 0 4px 6px -4px rgb(0 0 0 / 0.35);
}

@theme inline {
  --color-background: var(--background);
  --color-surface: var(--surface);
  --color-surface-2: var(--surface-2);
  --color-surface-3: var(--surface-3);
  --color-foreground: var(--foreground);
  --color-muted-foreground: var(--muted-foreground);
  --color-subtle-foreground: var(--subtle-foreground);

  --color-border: var(--border);
  --color-border-strong: var(--border-strong);

  --color-accent: var(--accent);
  --color-accent-hover: var(--accent-hover);
  --color-accent-active: var(--accent-active);
  --color-accent-foreground: var(--accent-foreground);
  --color-accent-subtle: var(--accent-subtle);
  --color-accent-ring: var(--accent-ring);

  --color-success: var(--success);
  --color-success-subtle: var(--success-subtle);
  --color-warning: var(--warning);
  --color-warning-subtle: var(--warning-subtle);
  --color-danger: var(--danger);
  --color-danger-subtle: var(--danger-subtle);
  --color-info: var(--info);
  --color-info-subtle: var(--info-subtle);

  --color-cat-xlsx: var(--cat-xlsx);
  --color-cat-xlsx-bd: var(--cat-xlsx-bd);
  --color-cat-db: var(--cat-db);
  --color-cat-db-bd: var(--cat-db-bd);
  --color-cat-db-vol: var(--cat-db-vol);
  --color-cat-db-vol-bd: var(--cat-db-vol-bd);
  --color-cat-divergent-bd: var(--cat-divergent-bd);

  --color-sidebar: var(--sidebar);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar-muted: var(--sidebar-muted);
  --color-sidebar-active: var(--sidebar-active);
  --color-sidebar-accent: var(--sidebar-accent);

  --shadow-sm: var(--shadow-sm);
  --shadow: var(--shadow);
  --shadow-md: var(--shadow-md);
  --shadow-lg: var(--shadow-lg);

  --font-sans: var(--font-geist-sans);
  --font-mono: var(--font-geist-mono);
}

/* ---------- Base ---------- */

html,
body {
  height: 100%;
}

body {
  background: var(--background);
  color: var(--foreground);
  font-feature-settings: "cv02", "cv03", "cv04", "cv11";
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Focus ring uniforme — anneau accent doux */
*:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: 2px;
  border-radius: 0.25rem;
}

/* Scrollbars sobres */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

/* Transitions par défaut sur les éléments interactifs */
button,
a,
input,
[role="button"] {
  transition:
    background-color 120ms ease,
    border-color 120ms ease,
    color 120ms ease,
    box-shadow 120ms ease,
    transform 120ms ease;
}

/* Sélection texte — accent subtil */
::selection {
  background: var(--accent-subtle);
  color: var(--accent-active);
}

/* ---------- Animations utilitaires ---------- */

@keyframes mf-fade-in {
  from {
    opacity: 0;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes mf-pulse-soft {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.55;
  }
}

@keyframes mf-shimmer {
  from {
    background-position: -200% 0;
  }
  to {
    background-position: 200% 0;
  }
}

.mf-fade-in {
  animation: mf-fade-in 200ms ease-out both;
}

.mf-pulse-soft {
  animation: mf-pulse-soft 1.6s ease-in-out infinite;
}

.mf-shimmer {
  background: linear-gradient(
    90deg,
    var(--surface-2) 0%,
    var(--surface-3) 50%,
    var(--surface-2) 100%
  );
  background-size: 200% 100%;
  animation: mf-shimmer 1.4s linear infinite;
}

/* ---------- Login scene ----------
   Voitures en boucle infinie (période 6s, ~3s visible + 3s off-screen).
   Stagger : Car1 delay 0, Car2 delay 1.5s, Car3 delay 3s — provoque
   des croisements continus (RTL haute lane, LTR basse lane).
   Timeline du piéton :
     1.5→9.5s    : piéton entre par la gauche, marche 8s
     9.3→9.7s    : il lève le bras et tire la ficelle
     9.5→11.0s   : ampoule → soleil → sunrise → fenêtres
     10.5s       : modale fade-in
     10.5→12.3s  : piéton détale vers la droite hors-écran
*/

.mf-scene {
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: #080a1f;
  color: #fafaf9;
}

.mf-scene__svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* Ciel sunrise — opacité animée par-dessus le ciel nuit */
.mf-sky-dawn {
  opacity: 0;
  animation: mf-sky-shift 1500ms cubic-bezier(0.33, 1, 0.68, 1) 9500ms forwards;
}

@keyframes mf-sky-shift {
  to {
    opacity: 1;
  }
}

/* Étoiles : twinkle léger puis fade-out à l'aube */
.mf-star {
  animation:
    mf-star-twinkle 3.5s ease-in-out infinite,
    mf-star-fade 1200ms ease-out 9400ms forwards;
  transform-origin: center;
}

@keyframes mf-star-twinkle {
  0%,
  100% {
    opacity: var(--mf-star-op, 0.7);
  }
  50% {
    opacity: 0.25;
  }
}

@keyframes mf-star-fade {
  to {
    opacity: 0;
  }
}

/* Lune : fade-out à l'aube */
.mf-moon {
  animation: mf-moon-fade 1500ms ease-out 9400ms forwards;
}

@keyframes mf-moon-fade {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-30px);
  }
}

/* Skylines : couleurs qui tirent vers le chaud à l'aube */
.mf-skyline--far {
  fill: #1a1d3f;
  animation: mf-skyline-far-warm 1500ms ease-out 9500ms forwards;
}
@keyframes mf-skyline-far-warm {
  to {
    fill: #6d3a5c;
  }
}

.mf-skyline--mid {
  fill: #0e1135;
  animation: mf-skyline-mid-warm 1500ms ease-out 9500ms forwards;
}
@keyframes mf-skyline-mid-warm {
  to {
    fill: #2b1638;
  }
}

.mf-skyline--front {
  fill: #050617;
  animation: mf-skyline-front-warm 1500ms ease-out 9500ms forwards;
}
@keyframes mf-skyline-front-warm {
  to {
    fill: #0e0b22;
  }
}

/* Fenêtres : s'allument une par une à l'aube */
.mf-window {
  fill: #ffd784;
  opacity: 0;
  animation: mf-window-on 600ms ease-out forwards;
}
@keyframes mf-window-on {
  0% {
    opacity: 0;
    filter: brightness(0.6);
  }
  60% {
    opacity: 1;
    filter: brightness(1.2);
  }
  100% {
    opacity: 0.85;
    filter: brightness(1);
  }
}

/* Ampoule / soleil : couleur change quand le piéton tire la ficelle */
.mf-bulb {
  animation: mf-bulb-on 700ms cubic-bezier(0.34, 1.56, 0.64, 1) 9500ms forwards;
  transform-origin: 800px 450px;
}
@keyframes mf-bulb-on {
  0% {
    fill: #1a1d3f;
    stroke: #3a3f6a;
  }
  60% {
    fill: #fff5d0;
    stroke: #fff5d0;
    transform: scale(1.4);
  }
  100% {
    fill: #ffd57a;
    stroke: #ffd57a;
    transform: scale(1.2);
  }
}

/* Halo du soleil : invisible puis explose */
.mf-sun-glow {
  opacity: 0;
  transform-origin: 800px 450px;
  animation: mf-sun-glow-in 1400ms cubic-bezier(0.22, 1, 0.36, 1) 9700ms forwards;
}
@keyframes mf-sun-glow-in {
  0% {
    opacity: 0;
    transform: scale(0.2);
  }
  100% {
    opacity: 0.95;
    transform: scale(1);
  }
}

/* Rayons */
.mf-sun-ray {
  opacity: 0;
  transform-origin: 800px 450px;
  animation: mf-ray-pop 600ms ease-out forwards;
}
@keyframes mf-ray-pop {
  0% {
    opacity: 0;
    transform: scale(0.4);
  }
  100% {
    opacity: 0.85;
    transform: scale(1);
  }
}

/* Reflet du sol à l'aube */
.mf-ground-glow {
  opacity: 0;
  animation: mf-ground-glow-in 1500ms ease-out 9800ms forwards;
}
@keyframes mf-ground-glow-in {
  to {
    opacity: 0.45;
  }
}

/* Ficelle qui se tend / rebondit quand le piéton tire */
.mf-string {
  transform-origin: 800px 0px;
  animation: mf-string-pull 600ms ease-in-out 9300ms;
}
@keyframes mf-string-pull {
  0%,
  100% {
    transform: scaleY(1);
  }
  50% {
    transform: scaleY(1.04);
  }
  70% {
    transform: scaleY(0.985);
  }
}

/* Voitures en boucle infinie. Pattern : 0%→50% traversée visible,
   50.01% snap hors-écran à la position de départ, 50.01%→100% idle off-screen.
   Période 6s. Stagger via animation-delay. */

/* Positions hors-écran étendues (2000 / -550) pour que le cône de phares
   reste hors viewport pendant les phases d'attente. animation-delay est
   surchargé en inline-style côté React pour un démarrage aléatoire. */

.mf-car--1 {
  /* RTL voie du fond */
  transform: translateX(2000px);
  animation: mf-car-1 6s linear 0s infinite both;
}
@keyframes mf-car-1 {
  0% {
    transform: translateX(2000px);
  }
  50% {
    transform: translateX(-550px);
  }
  50.01% {
    transform: translateX(2000px);
  }
  100% {
    transform: translateX(2000px);
  }
}

.mf-car--2 {
  /* LTR voie de devant — translateY +70 pour passer sous le marquage */
  transform: translate(-550px, 70px);
  animation: mf-car-2 6s linear 1.5s infinite both;
}
@keyframes mf-car-2 {
  0% {
    transform: translate(-550px, 70px);
  }
  50% {
    transform: translate(2000px, 70px);
  }
  50.01% {
    transform: translate(-550px, 70px);
  }
  100% {
    transform: translate(-550px, 70px);
  }
}

.mf-car--3 {
  /* RTL voie du fond, en alternance avec Car 1 */
  transform: translateX(2000px);
  animation: mf-car-3 6s linear 3s infinite both;
}
@keyframes mf-car-3 {
  0% {
    transform: translateX(2000px);
  }
  50% {
    transform: translateX(-550px);
  }
  50.01% {
    transform: translateX(2000px);
  }
  100% {
    transform: translateX(2000px);
  }
}

.mf-car--4 {
  /* LTR voie de devant, alternance avec Car 2 */
  transform: translate(-550px, 70px);
  animation: mf-car-4 6s linear 4.5s infinite both;
}
@keyframes mf-car-4 {
  0% {
    transform: translate(-550px, 70px);
  }
  50% {
    transform: translate(2000px, 70px);
  }
  50.01% {
    transform: translate(-550px, 70px);
  }
  100% {
    transform: translate(-550px, 70px);
  }
}

/* Faisceau de phares : opacité fixe (le scintillement était trop rapide) */
.mf-car__beam {
  opacity: 0.85;
}

/* Piéton : marche lente 8s, puis détale 1.8s à l'apparition du modal */
.mf-pedestrian {
  transform: translate(-80px, 770px);
  animation:
    mf-pedestrian-walk 8000ms cubic-bezier(0.4, 0, 0.5, 1) 1500ms forwards,
    mf-pedestrian-flee 1800ms cubic-bezier(0.5, 0, 0.4, 1) 10500ms forwards;
}
@keyframes mf-pedestrian-walk {
  0% {
    transform: translate(-80px, 770px);
  }
  100% {
    transform: translate(770px, 770px);
  }
}
@keyframes mf-pedestrian-flee {
  0% {
    transform: translate(770px, 770px);
  }
  100% {
    transform: translate(1900px, 770px);
  }
}

/* Bob vertical : 13 cycles × 0.6s = 7.8s en marche, puis 8 cycles × 0.22s = 1.76s en course */
.mf-pedestrian__bob {
  animation:
    mf-pedestrian-bob 0.6s ease-in-out 1500ms 13,
    mf-pedestrian-bob-run 0.22s ease-in-out 10500ms 8;
}
@keyframes mf-pedestrian-bob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-3px);
  }
}
@keyframes mf-pedestrian-bob-run {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-6px);
  }
}

/* Jambes : marche lente, puis course rapide à la fuite */
.mf-pedestrian__legs {
  transform-origin: 0 -25px;
  animation:
    mf-pedestrian-legs 0.6s ease-in-out 1500ms 13,
    mf-pedestrian-legs 0.18s ease-in-out 10500ms 10;
}
@keyframes mf-pedestrian-legs {
  0%,
  100% {
    transform: scaleX(1);
  }
  50% {
    transform: scaleX(-1);
  }
}

/* Piétons d'ambiance — démarrent au lever du soleil (delay ≥ 11s, donc invisibles la nuit).
   1 & 2 : passants simples (LTR + RTL).
   3 & 4 : paire qui se rencontre au milieu, fait une pause, et repart ensemble vers la droite. */

.mf-walker--1 {
  transform: translate(-60px, 778px);
  animation: mf-walker-1 14s linear 11s infinite both;
}
@keyframes mf-walker-1 {
  0% {
    transform: translate(-60px, 778px);
  }
  100% {
    transform: translate(1760px, 778px);
  }
}

.mf-walker--2 {
  transform: translate(1760px, 772px);
  animation: mf-walker-2 12s linear 13s infinite both;
}
@keyframes mf-walker-2 {
  0% {
    transform: translate(1760px, 772px);
  }
  100% {
    transform: translate(-60px, 772px);
  }
}

.mf-walker--3 {
  transform: translate(-60px, 776px);
  animation: mf-walker-3 24s linear 11s infinite both;
}
@keyframes mf-walker-3 {
  0% {
    transform: translate(-60px, 776px);
  }
  33% {
    transform: translate(740px, 776px);
  }
  53% {
    transform: translate(740px, 776px);
  }
  100% {
    transform: translate(1860px, 776px);
  }
}

.mf-walker--4 {
  transform: translate(1760px, 776px);
  animation: mf-walker-4 24s linear 11s infinite both;
}
@keyframes mf-walker-4 {
  0% {
    transform: translate(1760px, 776px);
  }
  33% {
    transform: translate(795px, 776px);
  }
  53% {
    transform: translate(795px, 776px);
  }
  100% {
    transform: translate(1900px, 776px);
  }
}

/* Bob + jambes pour les walkers passants (1 & 2) : marche continue */
.mf-walker--1 .mf-walker__bob,
.mf-walker--2 .mf-walker__bob {
  animation: mf-pedestrian-bob 0.6s ease-in-out infinite;
}
.mf-walker--1 .mf-walker__legs,
.mf-walker--2 .mf-walker__legs {
  transform-origin: 0 -25px;
  animation: mf-pedestrian-legs 0.6s ease-in-out infinite;
}

/* Bob + jambes pour la paire (3 & 4) : une seule animation 24s qui suit
   exactement le cycle parent, avec une zone explicitement figée pendant la
   "discussion" (33-53%). Cadence ~0.6s par cycle de bob (= 2.5% du cycle 24s).
   Phase 1 : 0-33% → 13 bobs ; Pause : 33-53% → figé ; Phase 2 : 53-100% → 18 bobs. */
.mf-walker--3 .mf-walker__bob,
.mf-walker--4 .mf-walker__bob {
  animation: mf-walker-pair-bob 24s linear 11s infinite both;
}
.mf-walker--3 .mf-walker__legs,
.mf-walker--4 .mf-walker__legs {
  transform-origin: 0 -25px;
  animation: mf-walker-pair-legs 24s linear 11s infinite both;
}

@keyframes mf-walker-pair-bob {
  /* Phase 1 : 13 bobs sur 0-32.5% */
  0%      { transform: translateY(0); }
  1.25%   { transform: translateY(-3px); }
  2.5%    { transform: translateY(0); }
  3.75%   { transform: translateY(-3px); }
  5%      { transform: translateY(0); }
  6.25%   { transform: translateY(-3px); }
  7.5%    { transform: translateY(0); }
  8.75%   { transform: translateY(-3px); }
  10%     { transform: translateY(0); }
  11.25%  { transform: translateY(-3px); }
  12.5%   { transform: translateY(0); }
  13.75%  { transform: translateY(-3px); }
  15%     { transform: translateY(0); }
  16.25%  { transform: translateY(-3px); }
  17.5%   { transform: translateY(0); }
  18.75%  { transform: translateY(-3px); }
  20%     { transform: translateY(0); }
  21.25%  { transform: translateY(-3px); }
  22.5%   { transform: translateY(0); }
  23.75%  { transform: translateY(-3px); }
  25%     { transform: translateY(0); }
  26.25%  { transform: translateY(-3px); }
  27.5%   { transform: translateY(0); }
  28.75%  { transform: translateY(-3px); }
  30%     { transform: translateY(0); }
  31.25%  { transform: translateY(-3px); }
  32.5%   { transform: translateY(0); }
  /* Pause 33-53% : figé */
  53%     { transform: translateY(0); }
  /* Phase 2 : 18 bobs sur 53-98% */
  54.25%  { transform: translateY(-3px); }
  55.5%   { transform: translateY(0); }
  56.75%  { transform: translateY(-3px); }
  58%     { transform: translateY(0); }
  59.25%  { transform: translateY(-3px); }
  60.5%   { transform: translateY(0); }
  61.75%  { transform: translateY(-3px); }
  63%     { transform: translateY(0); }
  64.25%  { transform: translateY(-3px); }
  65.5%   { transform: translateY(0); }
  66.75%  { transform: translateY(-3px); }
  68%     { transform: translateY(0); }
  69.25%  { transform: translateY(-3px); }
  70.5%   { transform: translateY(0); }
  71.75%  { transform: translateY(-3px); }
  73%     { transform: translateY(0); }
  74.25%  { transform: translateY(-3px); }
  75.5%   { transform: translateY(0); }
  76.75%  { transform: translateY(-3px); }
  78%     { transform: translateY(0); }
  79.25%  { transform: translateY(-3px); }
  80.5%   { transform: translateY(0); }
  81.75%  { transform: translateY(-3px); }
  83%     { transform: translateY(0); }
  84.25%  { transform: translateY(-3px); }
  85.5%   { transform: translateY(0); }
  86.75%  { transform: translateY(-3px); }
  88%     { transform: translateY(0); }
  89.25%  { transform: translateY(-3px); }
  90.5%   { transform: translateY(0); }
  91.75%  { transform: translateY(-3px); }
  93%     { transform: translateY(0); }
  94.25%  { transform: translateY(-3px); }
  95.5%   { transform: translateY(0); }
  96.75%  { transform: translateY(-3px); }
  98%     { transform: translateY(0); }
  100%    { transform: translateY(0); }
}

@keyframes mf-walker-pair-legs {
  /* Phase 1 : 13 cycles scaleX */
  0%      { transform: scaleX(1); }
  1.25%   { transform: scaleX(-1); }
  2.5%    { transform: scaleX(1); }
  3.75%   { transform: scaleX(-1); }
  5%      { transform: scaleX(1); }
  6.25%   { transform: scaleX(-1); }
  7.5%    { transform: scaleX(1); }
  8.75%   { transform: scaleX(-1); }
  10%     { transform: scaleX(1); }
  11.25%  { transform: scaleX(-1); }
  12.5%   { transform: scaleX(1); }
  13.75%  { transform: scaleX(-1); }
  15%     { transform: scaleX(1); }
  16.25%  { transform: scaleX(-1); }
  17.5%   { transform: scaleX(1); }
  18.75%  { transform: scaleX(-1); }
  20%     { transform: scaleX(1); }
  21.25%  { transform: scaleX(-1); }
  22.5%   { transform: scaleX(1); }
  23.75%  { transform: scaleX(-1); }
  25%     { transform: scaleX(1); }
  26.25%  { transform: scaleX(-1); }
  27.5%   { transform: scaleX(1); }
  28.75%  { transform: scaleX(-1); }
  30%     { transform: scaleX(1); }
  31.25%  { transform: scaleX(-1); }
  32.5%   { transform: scaleX(1); }
  /* Pause : figé */
  53%     { transform: scaleX(1); }
  /* Phase 2 : 18 cycles scaleX */
  54.25%  { transform: scaleX(-1); }
  55.5%   { transform: scaleX(1); }
  56.75%  { transform: scaleX(-1); }
  58%     { transform: scaleX(1); }
  59.25%  { transform: scaleX(-1); }
  60.5%   { transform: scaleX(1); }
  61.75%  { transform: scaleX(-1); }
  63%     { transform: scaleX(1); }
  64.25%  { transform: scaleX(-1); }
  65.5%   { transform: scaleX(1); }
  66.75%  { transform: scaleX(-1); }
  68%     { transform: scaleX(1); }
  69.25%  { transform: scaleX(-1); }
  70.5%   { transform: scaleX(1); }
  71.75%  { transform: scaleX(-1); }
  73%     { transform: scaleX(1); }
  74.25%  { transform: scaleX(-1); }
  75.5%   { transform: scaleX(1); }
  76.75%  { transform: scaleX(-1); }
  78%     { transform: scaleX(1); }
  79.25%  { transform: scaleX(-1); }
  80.5%   { transform: scaleX(1); }
  81.75%  { transform: scaleX(-1); }
  83%     { transform: scaleX(1); }
  84.25%  { transform: scaleX(-1); }
  85.5%   { transform: scaleX(1); }
  86.75%  { transform: scaleX(-1); }
  88%     { transform: scaleX(1); }
  89.25%  { transform: scaleX(-1); }
  90.5%   { transform: scaleX(1); }
  91.75%  { transform: scaleX(-1); }
  93%     { transform: scaleX(1); }
  94.25%  { transform: scaleX(-1); }
  95.5%   { transform: scaleX(1); }
  96.75%  { transform: scaleX(-1); }
  98%     { transform: scaleX(1); }
  100%    { transform: scaleX(1); }
}

/* Bras droit qui se lève vers la ficelle au moment du pull */
.mf-pedestrian__arm {
  transform-origin: 0 -52px;
  animation: mf-pedestrian-arm 800ms cubic-bezier(0.34, 1.56, 0.64, 1) 9300ms forwards;
}
@keyframes mf-pedestrian-arm {
  0% {
    transform: rotate(0deg);
  }
  60% {
    transform: rotate(-150deg);
  }
  100% {
    transform: rotate(-130deg);
  }
}

/* ---------- Modale et overlays ---------- */

.mf-modal-wrap {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 1rem;
  opacity: 0;
  transform: translateY(8px) scale(0.98);
  pointer-events: none;
  transition:
    opacity 600ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
}

.mf-modal-wrap--in {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.mf-overlay {
  position: absolute;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: #fafaf9;
  pointer-events: none;
  font-size: 0.75rem;
}

.mf-overlay--top {
  top: 1.5rem;
  left: 1.5rem;
}

.mf-overlay--bottom {
  bottom: 1.25rem;
  left: 1.5rem;
  right: 1.5rem;
  justify-content: space-between;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  opacity: 0.55;
  font-size: 0.7rem;
}

.mf-logo {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.mf-logo__chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 0.625rem;
  background: rgba(129, 140, 248, 0.18);
  color: #c7d2fe;
  font-weight: 700;
  font-size: 0.85rem;
  letter-spacing: -0.04em;
  box-shadow: inset 0 0 0 1px rgba(129, 140, 248, 0.4);
}

.mf-logo__text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}

.mf-logo__brand {
  font-size: 0.625rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.mf-logo__sub {
  font-size: 0.85rem;
  font-weight: 600;
}

/* ---------- prefers-reduced-motion : on saute la chorégraphie ---------- */

@media (prefers-reduced-motion: reduce) {
  .mf-scene__svg .mf-sky-dawn,
  .mf-scene__svg .mf-sun-glow,
  .mf-scene__svg .mf-sun-ray,
  .mf-scene__svg .mf-ground-glow,
  .mf-scene__svg .mf-window {
    animation: none;
    opacity: 1;
  }
  .mf-scene__svg .mf-bulb {
    animation: none;
    fill: #ffd57a;
    stroke: #ffd57a;
  }
  .mf-scene__svg .mf-skyline--far {
    fill: #6d3a5c;
    animation: none;
  }
  .mf-scene__svg .mf-skyline--mid {
    fill: #2b1638;
    animation: none;
  }
  .mf-scene__svg .mf-skyline--front {
    fill: #0e0b22;
    animation: none;
  }
  .mf-scene__svg .mf-stars,
  .mf-scene__svg .mf-moon,
  .mf-scene__svg .mf-car--1,
  .mf-scene__svg .mf-car--2,
  .mf-scene__svg .mf-car--3,
  .mf-scene__svg .mf-car--4,
  .mf-scene__svg .mf-walker,
  .mf-scene__svg .mf-pedestrian {
    display: none;
  }
  .mf-modal-wrap {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    transition: none;
  }
}

/* ---------- Bottom dock (panel admin) ----------
   Barre de navigation flottante centrée en bas. macOS-like : bg
   translucide + backdrop-blur, items qui scale au hover, label
   tooltip. Le dock a son propre `view-transition-name` pour
   persister visuellement entre les navigations. */

.mf-dock {
  position: fixed;
  bottom: 1.25rem;
  left: 50%;
  z-index: 40;
  transform: translateX(-50%);
  pointer-events: none;
  view-transition-name: mf-dock;
}

.mf-dock__inner {
  display: flex;
  align-items: flex-end;
  gap: 0.25rem;
  padding: 0.5rem 0.625rem;
  border-radius: 1.25rem;
  background: rgba(255, 255, 255, 0.65);
  border: 1px solid rgba(0, 0, 0, 0.06);
  backdrop-filter: blur(20px) saturate(1.6);
  -webkit-backdrop-filter: blur(20px) saturate(1.6);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    0 18px 40px -18px rgba(0, 0, 0, 0.25),
    0 4px 12px -4px rgba(0, 0, 0, 0.1);
  pointer-events: auto;
}

:root.dark .mf-dock__inner {
  background: rgba(28, 25, 23, 0.72);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.08),
    0 22px 50px -20px rgba(0, 0, 0, 0.6),
    0 4px 16px -4px rgba(0, 0, 0, 0.4);
}

.mf-dock__item {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 0.875rem;
  color: var(--foreground);
  text-decoration: none;
  outline: none;
  transition:
    transform 220ms cubic-bezier(0.34, 1.56, 0.64, 1),
    background-color 150ms ease,
    color 150ms ease;
}

.mf-dock__item:hover,
.mf-dock__item:focus-visible {
  background: var(--accent-subtle);
  transform: translateY(-8px) scale(1.12);
}

.mf-dock__item:focus-visible {
  outline: 2px solid var(--accent-ring);
  outline-offset: 2px;
}

.mf-dock__item--active {
  background: var(--accent);
  color: var(--accent-foreground);
}

.mf-dock__item--active:hover,
.mf-dock__item--active:focus-visible {
  background: var(--accent-hover);
}

.mf-dock__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Label en tooltip au-dessus du bouton */
.mf-dock__label {
  position: absolute;
  bottom: calc(100% + 0.5rem);
  left: 50%;
  transform: translate(-50%, 4px);
  padding: 0.25rem 0.625rem;
  border-radius: 0.5rem;
  background: rgba(15, 14, 12, 0.92);
  color: #fafaf9;
  font-size: 0.7rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition:
    opacity 140ms ease,
    transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.mf-dock__item:hover .mf-dock__label,
.mf-dock__item:focus-visible .mf-dock__label {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (max-width: 480px) {
  .mf-dock__item {
    width: 2.625rem;
    height: 2.625rem;
  }
  .mf-dock__inner {
    gap: 0.125rem;
    padding: 0.375rem 0.5rem;
  }
}

/* ---------- View transitions : effet sur navigation ----------
   Wrap des children dans <ViewTransition key={pathname} enter="mf-page-in"
   exit="mf-page-out"> (cf. page-transition.tsx).

   Animations GPU-only (transform + opacity + clip-path) → 60fps stable.
   Pas de filter (blur/hue/saturate) : ça plombait le frame rate.

   - Old page : 220ms, fade + scale 0.96, ease-in
   - New page : 520ms, iris circle depuis bas-centre, scale 1.04 → 1,
                fade in. Bezier 0.22/1/0.36/1 (ease-out fort) pour
                arrivée snappy mais douce. */

::view-transition-old(.mf-page-out) {
  animation: 220ms cubic-bezier(0.4, 0, 1, 1) both mf-page-out-kf;
  transform-origin: 50% 100%;
}

::view-transition-new(.mf-page-in) {
  animation: 520ms cubic-bezier(0.22, 1, 0.36, 1) both mf-page-in-kf;
  transform-origin: 50% 100%;
}

@keyframes mf-page-out-kf {
  to {
    opacity: 0;
    transform: scale(0.96);
  }
}

@keyframes mf-page-in-kf {
  from {
    opacity: 0;
    clip-path: circle(0% at 50% 100%);
    transform: scale(1.04);
  }
  60% {
    opacity: 1;
  }
  to {
    opacity: 1;
    clip-path: circle(160% at 50% 100%);
    transform: scale(1);
  }
}

/* Dock : view-transition-name dédié, transition rapide stable */
::view-transition-group(mf-dock) {
  animation-duration: 280ms;
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(*),
  ::view-transition-new(*),
  ::view-transition-group(*) {
    animation-duration: 0s !important;
    animation-delay: 0s !important;
  }
}
