/* ==========================================================================
   UCHIMO — Design tokens v1.6 (2026-07-08)
   Source de vérité : « Design System — Uchimo (v1).md » (même dossier).
   Les couleurs de marque (SVG logo) sont intégrées telles quelles :
   #F67F60 (corail-400) · #E3634D (corail-500) · #F3EDDC (crème-100)
   #413434 (encre-700) · #E0245E (cœur — animations/affection uniquement)
   #FFD166 (or-400 — lumière de la porte, ornement uniquement)

   Règle d'or : aucun hex ne vit hors de ce fichier. Un hex de marque écrit
   en dur dans une app dérive silencieusement d'une plateforme à l'autre.
   ========================================================================== */

:root {
  /* ---- Couleur : échelles primitives ---------------------------------- */
  --coral-50:  #FEF3EF;
  --coral-100: #FDE3DA;
  --coral-200: #FBC8B7;
  --coral-300: #F9A78E;
  --coral-400: #F67F60; /* MARQUE — façade du logo */
  --coral-500: #E3634D; /* MARQUE — joues */
  --coral-600: #C24A37;
  --coral-700: #9C392B;
  --coral-800: #742A20;
  --coral-900: #4E1C15;

  --cream-50:  #FBF8EF;
  --cream-100: #F3EDDC; /* MARQUE — sclère, porte */
  --cream-200: #E9E1C9;
  --cream-300: #D9CFB3;
  --cream-400: #BFB294;
  --cream-500: #9C9077;
  --cream-600: #7A705B;
  --cream-700: #5C5445;
  --cream-800: #403A30;
  --cream-900: #2A261F;

  --ink-50:  #F7F3F2;
  --ink-100: #EBE3E1;
  --ink-200: #D6C9C6;
  --ink-300: #B7A5A1;
  --ink-400: #94807B;
  --ink-500: #73615C;
  --ink-600: #594A47;
  --ink-700: #413434; /* MARQUE — outline, texte */
  --ink-750: #453838;
  --ink-800: #2E2424;
  --ink-900: #1F1818;

  --heart: #E0245E;      /* MARQUE — affection/victoire. JAMAIS un bouton. */
  --heart-dark: #F27DA1; /* équivalent AA du cœur en mode sombre */

  /* Or de la porte : la lumière derrière la bouche-porte de la mascotte.
     ORNEMENT PUR. 1,36:1 sur crème-50, 1,23:1 sur crème-100 : jamais du texte,
     jamais une bordure porteuse de sens, jamais une surface d'action.
     Usages licites : `fill` d'un tracé du SVG (.doorlight), keyframe `doorglow`
     (crème-100 → or-400), particules de célébration. Rien d'autre.
     Sur encre-700 il monte à 8,25:1 : lisible, mais ce n'est pas une licence. */
  --gold-400: #FFD166;   /* MARQUE — lumière de la porte (SVG logo) */

  /* Sémantiques : succès / urgence (ambre, PAS rouge) / erreur / info */
  --success-50:  #EDF7EE;
  --success-100: #D5EDD8;
  --success-300: #7CCB9B;
  --success-500: #2E9E5B;
  --success-600: #1E7F48;
  --success-700: #166237;
  /* Cran ajouté 2026-07-08. Le succès en 16 px/600 n'est PAS du « large text »
     (le seuil AA à 3:1 commence à 18,66 px gras) : il lui faut 4,5:1 pleins.
     success-600 tombe à 4,29:1 sur crème-100 et 4,05:1 sur success-100.
     success-800 tient partout : 8,24:1 crème-50 · 7,48:1 crème-100 ·
     7,06:1 success-100 · 8,75:1 blanc. Cible : --success-fg-strong. */
  --success-800: #125630;

  --urgency-50:  #FFF6E5;
  --urgency-100: #FDE8C3;
  --urgency-300: #F6C169;
  --urgency-400: #F0A93C;
  --urgency-500: #E08A00;
  --urgency-600: #A85C00;
  --urgency-700: #8A4D00;

  --error-50:  #FBEDEC;
  --error-100: #F6D7D4;
  --error-300: #EC9088;
  --error-500: #C93A31;
  --error-600: #B3261E;
  --error-700: #8E1D17;

  --info-50:  #E9F4F5;
  --info-100: #CBE7EA;
  --info-300: #6FC0CC;
  --info-500: #1B8796;
  --info-600: #0E6B78;
  --info-700: #0A505A;

  /* Ornements de marque : décor, jamais information ni action.
     Un ornement n'a pas de seuil de contraste car il ne porte aucun sens :
     s'il en portait, il ne serait plus un ornement. */
  --ornament-door-glow: var(--gold-400);

  /* Confettis (palette validée anim « found ») */
  --confetti-yellow: #F5C242;
  --confetti-mint:   #7CC7A1;
  --confetti-blue:   #7FA3E8;
  /* + --coral-400 ; les cœurs --heart restent exclusifs à « welcome » */

  /* ---- Couleur : tokens sémantiques (mode clair) ----------------------- */
  --bg-page:            var(--cream-50);   /* jamais de blanc pur en fond de page */
  --bg-surface:         #FFFFFF;
  --bg-surface-alt:     var(--cream-100);
  --bg-brand-subtle:    var(--coral-50);
  --text-primary:       var(--ink-700);    /* 11,89:1 sur blanc — AAA */
  --text-secondary:     var(--ink-500);    /* 5,84:1 — AA */
  --text-disabled:      var(--ink-300);
  --text-brand:         var(--coral-700);  /* 6,92:1 — AA */
  --text-on-brand:      var(--ink-700);    /* JAMAIS de blanc sur corail (2,59:1) */
  --text-inverse:       var(--cream-100);
  --border-subtle:      var(--ink-100);
  --border-default:     var(--cream-300);
  --border-input:       var(--ink-400);    /* 3,73:1 — conforme composants */
  --interactive-primary:          var(--coral-400);
  --interactive-primary-hover:    var(--coral-500);
  --interactive-primary-active:   var(--coral-600);
  --interactive-primary-disabled: var(--coral-200);
  --focus-ring: var(--coral-600);          /* 4,85:1 blanc · ~4,15:1 crème-100 — ≥ 3:1 sur TOUS les fonds clairs du système */
  --focus-ring-on-brand: var(--ink-700);   /* anneau encre pour tout élément posé sur fond corail */
  --link: var(--coral-700);
  --link-hover: var(--coral-800);
  --overlay: rgba(65, 52, 52, 0.4);        /* voile brun, jamais noir */

  /* Couleurs d'illustration (annexe iconographie) */
  --illu-coral-soft: #FCDCD1;
  --illu-cream-deep: #E7DEC6;
  --illu-brown-soft: #7A6A66;

  /* Encre translucide (mapping officiel des « encre-XX » de l'annexe composants) */
  --ink-a05: rgba(65,52,52,0.05);
  --ink-a10: rgba(65,52,52,0.10);
  --ink-a12: rgba(65,52,52,0.12);
  --ink-a20: rgba(65,52,52,0.20);
  --ink-a40: rgba(65,52,52,0.40);
  --ink-a72: rgba(65,52,52,0.72);  /* scrim sous badges posés sur photo */

  /* ---- Typographie ------------------------------------------------------ */
  /* Baloo 2 sourit (display), Source Sans 3 travaille (texte, données, boutons) */
  --font-display: "Baloo 2", ui-rounded, -apple-system, "Segoe UI", Roboto,
                  "Helvetica Neue", Arial, sans-serif;
  --font-body: "Source Sans 3", "Source Sans Pro", -apple-system,
               BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
               Arial, sans-serif;
  --font-system: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", Arial, sans-serif;

  /* Échelle mobile-first ; desktop ≥ 768 px via media query (display/h1/h2/price-lg/num-hero) */
  --text-display: 700 2rem/1.15 var(--font-display);       /* 32→44 px */
  --text-h1:      700 1.75rem/1.2 var(--font-display);     /* 28→36 px */
  --text-h2:      600 1.375rem/1.25 var(--font-display);   /* 22→28 px */
  --text-h3:      700 1.125rem/1.3 var(--font-body);       /* 18→20 px */
  --text-h4:      600 1rem/1.4 var(--font-body);           /* 16 px */
  --text-body-lg: 400 1.125rem/1.55 var(--font-body);      /* 18 px */
  --text-body:    400 1rem/1.5 var(--font-body);           /* 16 px */
  --text-body-sm: 400 0.875rem/1.45 var(--font-body);      /* 14 px */
  --text-caption: 400 0.75rem/1.35 var(--font-body);       /* 12 px */
  --text-overline: 600 0.6875rem/1.2 var(--font-body);     /* 11 px, MAJUSCULES, ls +0.08em */
  --text-price:   700 1.25rem/1.2 var(--font-body);        /* 20 px + tabular-nums OBLIGATOIRE */
  --text-price-lg: 700 1.75rem/1.15 var(--font-body);      /* 28→32 px + tabular-nums */
  --text-num-hero: 700 2.5rem/1.1 var(--font-display);     /* 40→56 px — célébration SEULEMENT, jamais un prix */
  --text-button:  600 1rem/1 var(--font-body);             /* 16 px */
  --text-button-sm: 600 0.875rem/1 var(--font-body);       /* 14 px */

  /* ---- Espacement (base 4 px — aucune valeur hors échelle) -------------- */
  --space-0: 0;
  --space-05: 2px;  /* corrections optiques uniquement */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;  /* respiration par défaut */
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;

  /* ---- Rayons (le rectangle à petits coins n'existe pas chez Uchimo) ---- */
  --radius-xs: 8px;    /* minimum absolu — rien de plus carré */
  --radius-sm: 12px;   /* inputs, selects, items compacts */
  --radius-md: 16px;   /* DÉFAUT : cartes, bulles de chat, alertes */
  --radius-lg: 24px;   /* modales, bottom sheets (coins hauts) */
  --radius-xl: 32px;   /* panneaux héros, conteneurs mascotte */
  --radius-full: 999px;/* boutons = pilule, TOUJOURS ; barre de recherche, badges */
  /* Règle du rayon imbriqué : rayon interne = rayon externe − padding (min 8 px) */

  /* ---- Élévation (ombres teintées encre — jamais de noir pur) ----------- */
  --shadow-1: 0 1px 2px rgba(65,52,52,0.06), 0 1px 4px rgba(65,52,52,0.08);
  --shadow-2: 0 2px 4px rgba(65,52,52,0.06), 0 4px 12px rgba(65,52,52,0.10);
  --shadow-3: 0 4px 8px rgba(65,52,52,0.08), 0 12px 24px rgba(65,52,52,0.12);
  --shadow-4: 0 8px 16px rgba(65,52,52,0.10), 0 24px 48px rgba(65,52,52,0.16);
  --shadow-brand: 0 4px 16px rgba(246,127,96,0.35); /* CTA décisif : max 1/écran */

  /* ---- Bordures ---------------------------------------------------------- */
  --border-w-hairline: 1px;
  --border-w-input: 1.5px;
  --border-w-strong: 2px;
  --border-w-signature: 3px; /* outline « façon logo » : 1–2 éléments max/écran */

  /* ---- Breakpoints (référence — utiliser en media queries) --------------- */
  /* base 0 · sm 480px · md 768px · lg 1024px · xl 1280px */
  --container-text: 640px;
  --container-form: 480px;
  --container-app: 1120px;
  --container-full: 1440px;
  --touch-target-min: 44px;
  --touch-target-comfort: 48px;

  /* ---- Motion ------------------------------------------------------------ */
  --duration-instant: 100ms;
  --duration-fast: 150ms;
  --duration-base: 200ms;
  --duration-gentle: 300ms;
  --duration-slow: 450ms;
  --duration-celebrate: 700ms;
  --duration-grand: 1200ms;      /* séquences mascotte uniquement */

  --ease-uchi-out: cubic-bezier(0.22, 1, 0.36, 1);        /* défaut entrées */
  --ease-uchi-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-uchi-exit: cubic-bezier(0.4, 0, 1, 1);
  --ease-uchi-bounce: cubic-bezier(0.34, 1.56, 0.64, 1);  /* joie uniquement */
  --ease-uchi-anticipation: cubic-bezier(0.36, 0, 0.66, -0.56);

  --motion-rise-sm: 8px;
  --motion-rise-md: 16px;
  --motion-scale-press: 0.97;
  --motion-scale-pop-from: 0.92;
  --motion-stagger: 60ms; /* plafonné à 5 items */

  /* ---- Tailles d'icônes -------------------------------------------------- */
  --icon-xs: 16px;
  --icon-sm: 20px;
  --icon-md: 24px;
  --icon-lg: 32px;
  --icon-xl: 40px;

  /* ---- Z-index (échelle fermée — aucune valeur hors échelle) ------------- */
  --z-base: 0;
  --z-header: 100;
  --z-sticky-bar: 200;   /* bottom bar d'actions */
  --z-tab-bar: 300;
  --z-sheet: 400;        /* bottom sheets, modales */
  --z-toast: 500;
  --z-overlay: 390;      /* sous la sheet qu'il accompagne */

  /* ---- Sémantiques d'état (mode clair) ----------------------------------- */
  --success-fg: var(--success-600);
  --urgency-fg: var(--urgency-600);
  --error-fg:   var(--error-600);
  --info-fg:    var(--info-600);
  /* Succès en gras (≥ 600) ou posé sur crème-100 / success-100 : prendre CELUI-CI.
     --success-fg suffit pour du 400 sur crème-50 (4,73:1) et pour une icône (≥ 3:1).
     Dès qu'on graisse ou qu'on quitte le fond de page, il passe sous 4,5:1. */
  --success-fg-strong: var(--success-800);
  --success-bg: var(--success-50);
  --urgency-bg: var(--urgency-50);
  --error-bg:   var(--error-50);
  --info-bg:    var(--info-50);
}

/* ---- Mode sombre (chaud et enveloppant : on plonge dans l'encre) --------
   Sélecteur renforcé (0,2,0) : gagne sur :root quel que soit l'ordre source. */
:root[data-theme="dark"] {
  --bg-page:        var(--ink-900);
  --bg-surface:     var(--ink-800);
  --bg-surface-alt: var(--ink-750);
  --bg-brand-subtle: #3A2A25;
  --text-primary:   var(--cream-100);  /* 14,94:1 — AAA */
  --text-secondary: var(--cream-400);  /* 8,33:1 — AAA */
  --text-disabled:  var(--ink-500);
  --text-brand:     var(--coral-300);  /* 9,11:1 — AAA */
  --text-on-brand:  var(--ink-800);    /* sur bouton corail-400 : 5,83:1 */
  --text-inverse:   var(--ink-700);
  --border-subtle:  var(--ink-750);
  --border-default: var(--ink-750);
  --border-input:   var(--ink-400);
  --interactive-primary:        var(--coral-400); /* la marque ne change pas */
  --interactive-primary-hover:  var(--coral-300); /* en sombre on éclaircit */
  --interactive-primary-active: var(--coral-500);
  --interactive-primary-disabled: #5A423B;
  --focus-ring: var(--coral-300);
  --focus-ring-on-brand: var(--ink-800);
  --link: var(--coral-300);
  --link-hover: var(--coral-200);
  --overlay: rgba(20, 14, 14, 0.6); /* noir TEINTÉ encre (exception dark documentée §9) */

  /* Sémantiques : texte/icône = cran 300 ; fonds = teinte mélangée à l'encre.
     En sombre « fort » veut dire plus CLAIR : success-100 donne 14,09:1 sur
     encre-900 et 10,47:1 sur le fond de succès sombre. */
  --success-fg-strong: var(--success-100);
  --success-fg: var(--success-300);
  --urgency-fg: var(--urgency-300);
  --error-fg:   var(--error-300);
  --info-fg:    var(--info-300);
  --success-bg: #24352A;
  --urgency-bg: #3E3020;
  --error-bg:   #3C2523;
  --info-bg:    #1F3336;
  --heart: var(--heart-dark);

  /* Élévation sombre : surface + bordure crème, l'ombre (teintée encre,
     jamais noir pur) ne détache que les overlays */
  --shadow-1: 0 0 0 1px rgba(243,237,220,0.08);
  --shadow-2: 0 0 0 1px rgba(243,237,220,0.08);
  --shadow-3: 0 4px 12px rgba(20,14,14,0.45), 0 0 0 1px rgba(243,237,220,0.10);
  --shadow-4: 0 12px 32px rgba(20,14,14,0.6), 0 0 0 1px rgba(243,237,220,0.12);
}

/* ---- Typographie : classes utilitaires ------------------------------------
   OBLIGATOIRES pour price/overline : le shorthand `font:` réinitialise
   font-variant et ne porte ni letter-spacing ni text-transform. */
.text-display  { font: var(--text-display);  letter-spacing: -0.01em; text-wrap: balance; }
.text-h1       { font: var(--text-h1);       letter-spacing: -0.005em; text-wrap: balance; }
.text-h2       { font: var(--text-h2); text-wrap: balance; }
.text-h3       { font: var(--text-h3); }
.text-h4       { font: var(--text-h4); }
.text-body-lg  { font: var(--text-body-lg); }
.text-body     { font: var(--text-body); }
.text-body-sm  { font: var(--text-body-sm); }
.text-caption  { font: var(--text-caption);  letter-spacing: 0.01em; }
.text-overline { font: var(--text-overline); letter-spacing: 0.08em; text-transform: uppercase; }
.text-price    { font: var(--text-price);    font-variant-numeric: tabular-nums lining-nums; }
.text-price-lg { font: var(--text-price-lg); font-variant-numeric: tabular-nums lining-nums; letter-spacing: -0.005em; }
.text-num-hero { font: var(--text-num-hero); letter-spacing: -0.01em; }
.text-button   { font: var(--text-button);   letter-spacing: 0.005em; }
.text-button-sm{ font: var(--text-button-sm);letter-spacing: 0.01em; }

@media (min-width: 768px) {
  :root {
    --text-display: 700 2.75rem/1.15 var(--font-display);   /* 44 px */
    --text-h1:      700 2.25rem/1.2 var(--font-display);    /* 36 px */
    --text-h2:      600 1.75rem/1.25 var(--font-display);   /* 28 px */
    --text-h3:      700 1.25rem/1.3 var(--font-body);       /* 20 px */
    --text-price-lg: 700 2rem/1.15 var(--font-body);        /* 32 px */
    --text-num-hero: 700 3.5rem/1.1 var(--font-display);    /* 56 px */
  }
}

/* ---- Focus visible universel (non négociable) ----------------------------
   :where() = spécificité nulle : facile à surcharger, donc règle d'équipe :
   INTERDIT d'écrire `outline: none` sans alternative :focus-visible (stylelint). */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--focus-ring);
  outline-offset: 2px;
}
/* Élément posé sur fond corail (bouton primaire…) : anneau encre. */
:where([data-on-brand]):focus-visible {
  outline-color: var(--focus-ring-on-brand);
}
/* Heading d'étape focalisé PROGRAMMATIQUEMENT (tabIndex=-1 posé par le JS des
   parcours connexion/inscription pour l'annonce lecteur d'écran) : cible non
   interactive, l'anneau corail y ressemble à une erreur (« Ton code » encadré
   rouge). Même motif que `outline-none` sur les cibles de focus du dashboard
   (src/app/dashboard/layout.tsx). Le déplacement de focus, lui, est conservé. */
.step h1:focus-visible {
  outline: none;
}

/* ---- Cibles tactiles : toute commande visuellement < 44 px étend sa zone --- */
:where(.hit-extend) { position: relative; }
:where(.hit-extend)::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  translate: -50% -50%;
  min-width: var(--touch-target-min);
  min-height: var(--touch-target-min);
  width: 100%;
  height: 100%;
}

/* ---- Contrastes forcés (Windows High Contrast / forced-colors) -------------
   En contrastes forcés, le système REMPLACE nos couleurs. Disparaissent donc :
   `background-color`, `border-color`, `color`, `box-shadow` (forcé à `none`),
   et avec eux --shadow-brand, les fonds sémantiques et les liserés d'état.
   Survivent : la géométrie, le texte, les glyphes, et les couleurs SYSTÈME
   qu'on nomme explicitement (Canvas, CanvasText, Highlight, ButtonBorder…).

   LOI : un état ne peut jamais reposer sur la seule couleur.
   Un « choisi » se lit à un GLYPHE (point de radio, coche) ou à un mot.
   C'est déjà WCAG 1.4.1 en mode normal ; les contrastes forcés se contentent
   de rendre l'oubli mortel. Cas connu : les cartes 2FA de l'inscription,
   dont le `:checked` n'est porté que par `border-color` + `background` avec
   un `<input>` en `opacity:0`. En forced-colors, l'état choisi s'évapore. */
@media (forced-colors: active) {
  /* 1. Focus : Highlight est la seule couleur d'anneau que le système garde. */
  :where(a, button, input, select, textarea, [tabindex]):focus-visible,
  :where([data-on-brand]):focus-visible {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }

  /* 2. État choisi : contour système (offset négatif, donc jamais confondu
        avec l'anneau de focus qui, lui, sort de la boîte). Le glyphe du
        point 3 reste OBLIGATOIRE : ce contour ne fait que le doubler. */
  :where(
    [aria-checked="true"], [aria-selected="true"],
    [aria-pressed="true"], [data-selected="true"]
  ) {
    border-color: Highlight;
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }

  /* 3. Contrôles natifs masqués : on rend la main au système.
        Sur un `<input type="radio">` caché derrière une carte dessinée,
        poser `.fc-native` sur l'input et `.fc-custom` sur le faux indicateur :
        le système redessine son propre indicateur, toujours visible.
        À défaut de `.fc-native`, l'indicateur maison doit être un GLYPHE
        (`content: "✓"`, `currentColor`), pas un aplat de couleur. */
  .fc-native {
    opacity: 1 !important;
    forced-color-adjust: auto;
  }
  .fc-custom { display: none !important; }

  /* 4. Ornements de marque : la mascotte et la lumière de la porte gardent
        leurs couleurs. Réservé à ce qui ne porte AUCUNE information : appliquer
        `forced-color-adjust: none` à un contrôle est un bug d'accessibilité. */
  .fc-keep-colors,
  [data-brand-art] { forced-color-adjust: none; }

  /* 5. `--shadow-brand` n'existe plus : le CTA décisif perd son relief.
        Tout bouton doit donc porter une bordure (au besoin transparente en
        mode normal) pour que le système lui donne un `ButtonBorder`. */
  :where(button, [role="button"], .btn) { border: 1px solid ButtonBorder; }
}

/* ---- Accessibilité motion --------------------------------------------------
   Doctrine : on supprime le DÉPLACEMENT, jamais l'information (annexe motion §5).
   1) Bloc universel : neutralise déplacements, staggers et boucles. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  /* 2) Équivalents autorisés (cascade postérieure : ces règles regagnent).
        `.rm-safe` = animations d'OPACITÉ pure définies par le système :
        pulse des 3 points de frappe (1600 ms), pulse du squelette (2000 ms),
        fondus d'apparition ≤ 150 ms. Aucun transform n'est admis ici. */
  .rm-safe {
    animation-duration: var(--rm-duration, 1600ms) !important;
    animation-delay: 0s !important;
    animation-iteration-count: var(--rm-iterations, infinite) !important;
  }
  .rm-fade {
    transition-duration: 150ms !important;
    transition-property: opacity !important;
  }
  /* Les séquences Rive/canvas se désactivent en JS (frame statique), pas ici. */
}
