/*
 * public/safety-net.css
 * ---------------------------------------------------------------------------
 * FILET DE SECURITE DES TOKENS + styles du pre-loader et du hero de secours.
 *
 * POURQUOI CE FICHIER EXISTE (et n'est plus un <style> inline dans index.html) :
 *   La CSP de production est servie en en-tete HTTP par /vercel.json :
 *     style-src 'self' https://fonts.googleapis.com
 *   Ni 'unsafe-inline', ni hash, ni nonce. `middleware.ts` ne sert AUCUN
 *   en-tete `x-nonce`, donc le placeholder `data-nonce="__NONCE__"` que posait
 *   le plugin Vite n'etait jamais resolu (et de toute facon un nonce applique
 *   apres coup par JS n'aurait rien debloque : le navigateur tranche au
 *   moment du parsing). Resultat : le <style> inline etait SILENCIEUSEMENT
 *   BLOQUE sur le web en production — verifie au navigateur, 0 <style> inline
 *   dans document.styleSheets sur renovhub.app — tout en fonctionnant en dev
 *   et en Capacitor (WebView locale : aucun en-tete CSP ne s'applique). D'ou
 *   un defaut invisible. Un fichier same-origin de /public est couvert par
 *   `'self'`. Meme parade que /theme-init.js.
 *
 * ORDRE DE CHARGEMENT — INVARIANT CRITIQUE :
 *   Ce fichier DOIT rester reference AVANT les feuilles de style de l'app.
 *   Vite injecte ses <link rel="stylesheet"> juste avant </head>, donc tout
 *   <link> ecrit dans le <head> source passe avant. C'est un FILET : les vraies
 *   valeurs (src/styles/design-tokens.css) doivent gagner sur celles-ci par
 *   ordre de cascade. Deplace APRES, il ecraserait les vrais tokens.
 *
 * BONUS : /public est copie tel quel, sans passer par PostCSS/PurgeCSS. Le
 *   filet est donc structurellement immunise contre le purge — ce qui est
 *   exactement la raison d'etre annoncee par le commentaire d'origine.
 *
 * SYNCHRONISATION : ces valeurs sont IDENTIQUES a src/styles/design-tokens.css
 *   (source de verite). Toute modification DOIT etre repercutee dans les deux.
 */

/* ROADMAP-V2 Sprint 1 (2026-04-14) : SAFETY-NET TOKENS
   Les tokens critiques sont dupliqués inline pour garantir leur présence
   même si PurgeCSS ou Vite CSS-chunking en fait disparaître de certains bundles.
   Ces valeurs sont IDENTIQUES à design-tokens.css (source de vérité) — toute
   modification DOIT être répercutée dans les deux fichiers. */
:root {
    color-scheme: light dark;
    /* Surfaces — DARK (défaut) */
    --surface-0: #090d1a;
    --surface-1: #0e1425;
    --surface-2: #131a2e;
    --surface-3: #182038;
    --surface-4: #1e2844;
    /* Borders */
    --border-subtle:  rgba(255, 255, 255, 0.04);
    --border-default: rgba(255, 255, 255, 0.07);
    --border-strong:  rgba(255, 255, 255, 0.12);
    --border-focus:   rgba(129, 140, 248, 0.5);
    /* Text */
    --text-primary:   #f0f2f5;
    --text-secondary: #a0a8c0;
    --text-tertiary:  #9ba3bc;
    --text-muted:     #9ba3bc;
    --text-inverse:   #090d1a;
    --text-on-brand:  #ffffff;
    /* Brand */
    --brand-primary:  #818cf8;
    --brand-secondary:#67e8f9;
    --brand-accent:   #8b5cf6;
    --brand-gradient: linear-gradient(135deg, #818cf8 0%, #67e8f9 100%);
    --brand-gradient-soft: linear-gradient(135deg, rgba(129,140,248,0.15) 0%, rgba(103,232,249,0.08) 100%);
    --brand-glow:     0 0 20px rgba(129, 140, 248, 0.15);
    --primary:        #818cf8;
    /* Semantic */
    --success: #66bb6a;   --warning: #ff9e5e;  --danger: #ef4444;  --info: #3b82f6;
    /* Shadows */
    --shadow-xs: 0 1px 2px rgba(0,0,0,0.08);
    --shadow-sm: 0 2px 8px rgba(0,0,0,0.15);
    --shadow-md: 0 4px 16px rgba(0,0,0,0.2);
    --shadow-lg: 0 8px 32px rgba(0,0,0,0.25);
    --shadow-xl: 0 16px 48px rgba(0,0,0,0.3);
    /* Radius */
    --radius-sm: 8px;  --radius-md: 12px;  --radius-lg: 16px;  --radius-xl: 20px;  --radius-full: 9999px;
    /* Text sizes */
    --text-xs: 11px; --text-sm: 13px; --text-base: 15px; --text-lg: 17px; --text-xl: 20px;
    --text-2xl: 24px; --text-3xl: 28px; --text-4xl: 32px;
    /* Spacing — échelle 4px */
    --space-0: 0;      --space-1: 4px;   --space-2: 8px;   --space-3: 12px;
    --space-4: 16px;   --space-5: 20px;  --space-6: 24px;  --space-8: 32px;
    --space-10: 40px;  --space-12: 48px; --space-16: 64px;
    /* Line heights */
    --leading-tight: 1.25; --leading-snug: 1.4; --leading-normal: 1.55; --leading-relaxed: 1.7;
    /* Transitions */
    --transition-fast: 120ms;  --transition-base: 200ms;  --transition-slow: 320ms;
    --transition-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Light mode overrides (safety net) */
[data-theme="light"] {
    --surface-0: #f8f9fc;  --surface-1: #ffffff;  --surface-2: #f1f4f9;
    --surface-3: #e8ecf4;  --surface-4: #dde3ef;
    --border-subtle: rgba(0,0,0,0.04);  --border-default: rgba(0,0,0,0.08);
    --border-strong: rgba(0,0,0,0.14);  --border-focus: rgba(67,56,202,0.8);
    --text-primary: #111827;  --text-secondary: #4b5563;  --text-tertiary: #6b7280;
    --text-muted: #6b7280;    --text-inverse: #f0f2f5;
    --brand-primary: #6366f1; --brand-secondary: #0ea5e9; --brand-accent: #7c3aed;
    --brand-gradient: linear-gradient(135deg, #6366f1 0%, #0ea5e9 100%);
    --brand-glow: 0 0 20px rgba(99,102,241,0.12);
    --primary: #6366f1;
    --shadow-xs: 0 1px 2px rgba(17,24,39,0.05);
    --shadow-sm: 0 2px 6px rgba(17,24,39,0.08);
    --shadow-md: 0 4px 12px rgba(17,24,39,0.10);
    --shadow-lg: 0 12px 32px rgba(17,24,39,0.12);
    --shadow-xl: 0 20px 48px rgba(17,24,39,0.16);
}
/* Auto mode suit prefers-color-scheme */
@media (prefers-color-scheme: light) {
    :root:not([data-theme]),
    [data-theme="auto"] {
        --surface-0: #f8f9fc;  --surface-1: #ffffff;  --surface-2: #f1f4f9;
        --surface-3: #e8ecf4;  --surface-4: #dde3ef;
        --border-subtle: rgba(0,0,0,0.04);  --border-default: rgba(0,0,0,0.08);
        --text-primary: #111827;  --text-secondary: #4b5563;  --text-tertiary: #6b7280;
        --brand-primary: #6366f1; --brand-gradient: linear-gradient(135deg, #6366f1 0%, #0ea5e9 100%);
        --primary: #6366f1;
    }
}

/* Le fond du pre-loader suit les tokens, donc le theme pose par
   /theme-init.js : plus aucune couleur sombre codee en dur ici (elle
   gagnait sur `@media (prefers-color-scheme: light)` ci-dessus, qui ne
   redefinissait que les tokens et jamais `background-color`). Les
   valeurs de repli ne servent que si les tokens manquent. */
body {
    font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
    background-color: var(--surface-0, #090d1a);
    color: var(--text-primary, #f0f2f5);
    min-height: 100vh;
    min-height: 100dvh;
    margin: 0;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    /* Prevent pull-to-refresh on Android Chrome */
    overscroll-behavior-y: contain;
    transition: background-color 0.35s cubic-bezier(0.4, 0, 0.2, 1), color 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Les trois regles `body` par theme qui vivaient ici ont ete retirees :
   - `@media (prefers-color-scheme: dark) body` imposait un fond sombre
     aux bases CLAIRES autres que `light` (high-contrast, pastel, pro),
     qu'aucune regle `[data-theme=...] body` ne rattrapait ;
   - `[data-theme="dark"] body` (#0f1629) et `[data-theme="light"] body`
     (#f8f9fa) divergeaient de --surface-0 (#090d1a / #f8f9fc), d'ou un
     leger saut de teinte au montage de React.
   `background-color: var(--surface-0)` ci-dessus couvre desormais les
   cinq bases, via les tokens de design-tokens.css et styles/themes/*.css. */

#root {
    /* FIX QA-02: min-height instead of height so #root can grow beyond
       100dvh when form content is taller (QuickStart, etc.).
       Fixed height was clipping overflow content on mobile. */
    min-height: 100vh;
    min-height: 100dvh;
}
/* Initial loading spinner (shown before React mounts) */
.app-preloader {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    height: 100dvh;
}
.app-preloader-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid rgba(255,255,255,0.08);
    border-top-color: #818cf8;
    border-radius: 50%;
    animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* P0-LAND-004 (2026-05-03) — Hero de secours affiché uniquement si React
   ne mount pas dans les 12 s (crash JS, bundle bloqué, navigateur trop ancien).
   React efface #root avec root.render() avant que le timer ne se déclenche,
   donc ces styles ne sont visibles qu'en cas de problème réel.
   Déclenchés aussi via <noscript> si JS est désactivé. */
.app-fallback-hero {
    max-width: 640px;
    margin: 0 auto;
    padding: 48px 24px;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    text-align: center;
    font-family: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
}
.app-fallback-hero h1 {
    font-size: 32px;
    line-height: 1.2;
    margin: 0 0 16px;
    font-weight: 700;
    background: linear-gradient(135deg, #818cf8 0%, #67e8f9 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}
.app-fallback-hero p {
    font-size: 16px;
    line-height: 1.55;
    color: #a0a8c0;
    margin: 0 0 12px;
}
.app-fallback-hero a {
    color: #818cf8;
    text-decoration: underline;
}
.app-fallback-hero .app-fallback-cta {
    display: inline-block;
    margin-top: 24px;
    padding: 12px 24px;
    background: linear-gradient(135deg, #818cf8 0%, #67e8f9 100%);
    color: #0f1629;
    border-radius: 12px;
    text-decoration: none;
    font-weight: 600;
    transition: transform 200ms ease;
}
.app-fallback-hero .app-fallback-cta:hover {
    transform: translateY(-2px);
}
