*{box-sizing:border-box;margin:0;padding:0}

/* --vh : hauteur RÉELLEMENT visible, mesurée en JS (window.innerHeight) par le
   script placé dans le <head> du PHP.
   Indispensable : sur Chrome Android, 100vh vaut la hauteur SANS la barre
   d'URL — soit ~60px de trop. Combiné à overflow:hidden, le bas de la page
   (les boutons) devenait inaccessible. 100dvh corrige le problème mais
   n'existe qu'à partir de Chrome 108 ; window.innerHeight, lui, est juste
   partout, y compris dans les vieilles WebView.
   La valeur ci-dessous n'est qu'un filet de sécurité si le JS ne tourne pas.

   --app-nav-h : hauteur de la barre de navigation de l'application Android.
   Vaut 0 (la WebView est déjà dimensionnée par le layout natif). Si elle
   passait un jour en overlay, l'app injecterait :
   document.documentElement.style.setProperty('--app-nav-h','56px'); */
:root{--vh:100vh;--app-nav-h:0px;--keyboard-h:0px}

body{font-family:'Segoe UI',sans-serif;background:#0f172a;color:#e2e8f0;min-height:100vh}

header{background:#111827;padding:10px 20px;display:flex;align-items:center;justify-content:space-between;gap:12px}
header a{text-decoration:none}
.back{color:#94a3b8;font-size:13px;white-space:nowrap}
.back:hover{color:#fbbf24}

.container{max-width:1100px;margin:0 auto;padding:14px}
h1{font-size:21px;font-weight:800;color:#fbbf24;text-align:center;margin-bottom:3px}
.subtitle{text-align:center;color:#64748b;font-size:13px;margin-bottom:14px}

.progress{display:flex;gap:4px;margin-bottom:12px}
.progress .dot{flex:1;height:4px;border-radius:2px;background:#1e293b;transition:background .3s}
.progress .dot.active{background:#fbbf24}
.progress .dot.done{background:#16a34a}

.work-area{display:grid;gap:14px}
@media(min-width:900px){
  .work-area{grid-template-columns:360px 1fr;align-items:start}
  .preview-panel{position:sticky;top:12px}
}

.preview-panel{background:#111827;border:1px solid #1e293b;border-radius:14px;padding:10px}
.preview-title{font-size:12px;font-weight:700;color:#94a3b8;margin-bottom:8px;text-align:center}
.preview-canvas-box{width:100%;max-width:360px;margin:0 auto;aspect-ratio:1754/1240;background:#fff;border-radius:8px;overflow:hidden}
.preview-note{font-size:11px;color:#64748b;margin-top:8px;text-align:center;line-height:1.35}

.step-card{background:#111827;border:1px solid #1e293b;border-radius:14px;padding:14px;height:430px;display:flex;flex-direction:column;overflow:hidden}
.step{display:none;height:100%;min-height:0}
.step.active{display:flex;flex-direction:column;min-height:0;overflow:hidden}
.step-title{font-size:16px;font-weight:700;color:#f8fafc;margin-bottom:4px;flex-shrink:0}
.step-desc{font-size:12px;color:#64748b;margin-bottom:12px;flex-shrink:0}

.grid-cadres{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;flex:1;min-height:0;overflow-y:auto;padding-right:3px;align-content:start;align-items:start;grid-auto-rows:max-content}
@media(min-width:480px){.grid-cadres{grid-template-columns:repeat(4,1fr)}}
.grid-cadres .item{background:#1e293b;border:2px solid #334155;border-radius:10px;overflow:hidden;cursor:pointer;transition:all .2s;aspect-ratio:1754/1240}
.grid-cadres .item:hover{border-color:#fbbf24}
.grid-cadres .item.selected{border-color:#fbbf24;box-shadow:0 0 12px rgba(251,191,36,0.3)}
.grid-cadres .item img{width:100%;height:100%;object-fit:cover}

.grid-illus,.grid-trophees{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:10px;flex:1;min-height:0;overflow-y:auto;padding-right:3px;align-content:start;align-items:start;grid-auto-rows:max-content}
@media(min-width:480px){.grid-illus,.grid-trophees{grid-template-columns:repeat(5,1fr)}}
.grid-illus .item,.grid-trophees .item{background:#1e293b;border:2px solid #334155;border-radius:10px;padding:6px;cursor:pointer;transition:all .2s;aspect-ratio:1;display:flex;align-items:center;justify-content:center;text-align:center;font-size:11px;color:#94a3b8}
.grid-illus .item:hover,.grid-trophees .item:hover{border-color:#fbbf24}
.grid-illus .item.selected,.grid-trophees .item.selected{border-color:#fbbf24;box-shadow:0 0 12px rgba(251,191,36,0.3)}
.grid-illus .item img,.grid-trophees .item img{width:100%;height:100%;object-fit:contain}

.grid-fonts{display:grid;grid-template-columns:repeat(2,1fr);gap:8px;flex:1;min-height:0;overflow-y:auto;padding-right:3px;align-content:start;align-items:start;grid-auto-rows:max-content}
@media(min-width:480px){.grid-fonts{grid-template-columns:repeat(3,1fr)}}
.grid-fonts .item{background:#1e293b;border:2px solid #334155;border-radius:10px;padding:10px 8px;cursor:pointer;transition:all .2s;text-align:center;min-height:48px;display:flex;align-items:center;justify-content:center}
.grid-fonts .item:hover{border-color:#fbbf24}
.grid-fonts .item.selected{border-color:#fbbf24;box-shadow:0 0 12px rgba(251,191,36,0.3)}
.grid-fonts .item span{font-size:18px;color:#f1f5f9}

/* ────────────────────────────────────────────────────────────────────────
   .step-body : zone scrollable des étapes SANS grille (textes, couleurs).
   Elle joue exactement le rôle des .grid-* : c'est le maillon qui cède quand
   la place manque, ce qui garantit que .nav-btns reste visible.
   Sans elle, les .form-group / .color-row (flex-shrink:0) poussaient les
   boutons hors du step-card.
   ⚠ Nécessite les <div class="step-body"> ajoutés dans le PHP.
   ──────────────────────────────────────────────────────────────────────── */
.step-body{flex:1;min-height:0;overflow-y:auto;padding-right:3px;scrollbar-width:thin;scrollbar-color:#334155 transparent}
.step-body::-webkit-scrollbar{width:3px}
.step-body::-webkit-scrollbar-track{background:transparent}
.step-body::-webkit-scrollbar-thumb{background:#334155;border-radius:3px}
.step-body .form-group,.step-body .color-row{flex-shrink:0}

.color-row{display:flex;align-items:center;gap:12px;margin-bottom:12px}
.color-row.color-text-start{margin-top:6px}
.color-row label{font-size:13px;color:#94a3b8;flex:0 0 110px;min-width:0}
.color-row input[type="color"]{width:44px;height:34px;border:none;border-radius:6px;cursor:pointer;background:transparent}

/* Champs Coloris (input[data-coloris]) : Coloris enveloppe l'input dans un
   .clr-field. Sans ces règles, l'ensemble label + champ + code hexa dépassait
   la largeur du step-card. Le champ occupe la place restante et peut rétrécir
   (min-width:0), au lieu de garder sa largeur naturelle. */
.color-row .clr-field{flex:1;min-width:0;display:block}
.color-row .clr-field input,
.color-row input[data-coloris]{width:100%;min-width:0;background:#1e293b;border:1px solid #334155;color:#f1f5f9;padding:8px 10px;border-radius:8px;font-size:13px;outline:none}
.color-row .clr-field input:focus,
.color-row input[data-coloris]:focus{border-color:#fbbf24}

/* Le code hexa était affiché deux fois : dans le champ ET dans ce <span>.
   On masque le doublon, qui ne servait à rien et prenait de la largeur. */
.color-row span{display:none}

.form-group{margin-bottom:12px}
.form-group label{display:block;font-size:12px;font-weight:600;color:#94a3b8;margin-bottom:4px;text-transform:uppercase;letter-spacing:.05em}
.form-group input,.select{width:100%;background:#1e293b;border:1px solid #334155;color:#f1f5f9;padding:10px 12px;border-radius:8px;font-size:14px;outline:none;transition:border-color .2s}
.form-group input:focus,.select:focus{border-color:#fbbf24}

.nav-btns{display:flex;gap:10px;margin-top:auto;padding-top:16px;position:static;flex-shrink:0}
.btn{flex:1;padding:11px;border-radius:10px;font-weight:700;font-size:14px;cursor:pointer;border:none;transition:all .2s}
.btn:disabled{opacity:.6;cursor:not-allowed}
.btn-prev{background:#1e293b;color:#94a3b8;border:1px solid #334155}
.btn-prev:hover{background:#334155}
.btn-next{background:#fbbf24;color:#111}
.btn-next:hover{background:#f59e0b}
.btn-create{background:#16a34a;color:#fff;font-size:15px}
.btn-create:hover{background:#15803d}

/* Lien « Accueil » de l'étape 1 : n'existe que sur smartphone, où le <header>
   est masqué. Sur desktop, le header assure déjà le retour à l'accueil.
   Vrai <a> et non un bouton avec location.href : reste un lien crawlable,
   ouvrable dans un nouvel onglet, avec clic-milieu. */
.btn-accueil{display:none;text-decoration:none;align-items:center;justify-content:center;line-height:1.2}

.help{font-size:12px;color:#64748b;background:#0f172a;border:1px solid #1e293b;border-radius:10px;padding:9px;margin-bottom:10px;line-height:1.45}
.msg{font-size:12px;margin-top:10px;display:none;flex-shrink:0}
.msg.show{display:block}
.msg.error{color:#fca5a5}
.msg.ok{color:#86efac}

/* ────────────────────────────────────────────────────────────────────────
   SMARTPHONE / WEBVIEW
   Chaîne de contraintes FERMÉE, de body jusqu'aux zones scrollables : la page
   ne scrolle jamais, seules les grilles et .step-body scrollent, et les
   boutons restent donc toujours visibles.
   La hauteur de départ vient de --vh (window.innerHeight) et non de 100vh :
   c'est ce qui fait la différence entre la WebView (où 100vh était juste) et
   Chrome Android (où 100vh dépasse de la hauteur de la barre d'URL).
   Chaque maillon porte min-height:0 — sans quoi le minimum automatique du
   contenu rouvre la chaîne et le scroll interne disparaît.
   ──────────────────────────────────────────────────────────────────────── */
@media(max-width:899px){
  body{
    height:var(--vh);
    min-height:0;          /* NEUTRALISE le min-height:100vh de la règle de base.
                              Sans lui, Chrome Android imposait 849px de body pour
                              777px visibles : les boutons finissaient 49px trop bas,
                              inatteignables puisque la page ne scrolle pas. */
    overflow:hidden;
    display:flex;
    flex-direction:column;
  }

  header{display:none}   /* ~60px repris, rendus au step-card.
                            Le retour à l'accueil passe par le bouton
                            « ← Accueil » de l'étape 1. */

  .btn-accueil{display:flex}

  .container{
    flex:1;
    min-height:0;
    display:flex;
    flex-direction:column;
    width:100%;
    padding:10px;
    padding-bottom:calc(10px + var(--app-nav-h) + env(safe-area-inset-bottom,0px));
  }

  h1,.subtitle,.progress{flex-shrink:0}

  /* minmax(0,1fr) et non 1fr : sans le 0, la piste conserve un minimum égal
     au contenu, et le step-card reprendrait une hauteur infinie. */
  .work-area{
    flex:1;
    min-height:0;
    grid-template-rows:auto minmax(0,1fr);
  }

  .preview-panel{padding:8px;flex-shrink:0}

  /* Aperçu piloté par la hauteur et non plus par la largeur (max-width:310px) :
     il ne peut plus manger l'écran. La largeur découle de l'aspect-ratio, et
     resizePreviewCanvas() suit tout seul via son ResizeObserver. */
  .preview-canvas-box{
    width:auto;
    max-width:100%;
    height:clamp(150px,calc(var(--vh) * 0.24),210px);
  }

  /* Hauteur FERMÉE (100% de la piste minmax(0,1fr)) au lieu des 390px codés en
     dur : c'est elle qui donne leur borne aux zones scrollables. */
  .step-card{
    padding:12px;
    height:100%;
    min-height:0;
    overflow:hidden;
  }

  .nav-btns{padding-top:14px}

  /* Polices : plus compactes sur smartphone */
  .grid-fonts{grid-template-columns:repeat(3,1fr)}
  .grid-fonts .item{padding:7px 5px;min-height:40px}
  .grid-fonts .item span{font-size:15px}

  /* Illustrations : déjà compactées */
  .grid-illus{grid-template-columns:repeat(4,1fr)}
  .grid-illus .item{padding:4px}

  /* Trophées : compactés séparément, sans toucher aux cadres */
  .grid-trophees{grid-template-columns:repeat(4,1fr)}
  .grid-trophees .item{padding:4px}

  /* Chrome Android : l'interface garde sa hauteur normale pendant la saisie.
     On autorise seulement la page à défiler et on ajoute sous elle une réserve
     équivalente à la hauteur du clavier, afin de pouvoir remonter le champ actif. */
  body.keyboard-open{
    height:auto;
    min-height:calc(var(--vh) + var(--keyboard-h) + 80px);
    overflow-x:hidden;
    overflow-y:auto;
    display:flex;
    flex-direction:column;
    padding-bottom:0;
  }

  /* La page devient plus longue pour permettre le défilement, mais la vraie
     interface conserve exactement sa hauteur et son organisation habituelles. */
  body.keyboard-open .container{
    flex:0 0 var(--vh);
    height:var(--vh);
    min-height:var(--vh);
  }

  body.keyboard-open .form-group input{
    scroll-margin-top:105px;
    scroll-margin-bottom:28px;
  }
}

/* Écrans courts (petit mobile, ou hauteur amputée par la barre d'URL) :
   on récupère de la place en masquant le sous-titre décoratif. */
@media(max-width:899px) and (max-height:700px){
  h1{font-size:18px}
  .subtitle{display:none}
}

@media(max-width:380px){
  .grid-fonts .item span{font-size:14px}
}

/* Smartphone uniquement : l’interface reste utilisable seulement en portrait.
   Une page web classique ne peut pas imposer physiquement l’orientation,
   mais cet écran bloque l’utilisation en paysage et disparaît à la rotation. */
@media (orientation:landscape) and (max-height:600px) and (max-width:950px) and (hover:none) and (pointer:coarse){
  body:not(.keyboard-open){
    overflow:hidden !important;
    background:#0f172a;
  }

  body:not(.keyboard-open)::before{
    content:"↻\A\ATournez votre téléphone\A\APour créer votre diplôme, utilisez le mode portrait.";
    position:fixed;
    inset:0;
    z-index:99999;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:32px;
    background:#0f172a;
    color:#f8fafc;
    text-align:center;
    white-space:pre-line;
    font-family:'Segoe UI',sans-serif;
    font-size:18px;
    font-weight:700;
    line-height:1.5;
    pointer-events:auto;
  }
}
