:root {
    /* Mêmes couleurs que le dégradé de fond (voir body ci-dessous), pour que
       les bulles restent dans la même palette que la scène. */
    --teal:      #083639;
    --teal-rgb:  8, 54, 57;
    --violet:    #2f0634;
    --violet-rgb:47, 6, 52;
    --encre:     #f2eefb;
    --sourdine:  #a99fc4;

    /* Versions éclaircies des couleurs ci-dessus, réservées aux bulles :
       le fond brut du dégradé est trop sombre/"brut" une fois posé en
       pastille de conversation à côté du reste de l'interface. */
    --teal-bulle-rgb:   77, 110, 112;
    --violet-bulle-rgb: 105, 76, 109;
  }

  * { box-sizing: border-box; }

  html, body {
    margin: 0;
    height: 100%;
    overflow: hidden;
    font: 15px/1.5 -apple-system, "Segoe UI", Georgia, serif;
    color: var(--encre);
  }

  body {
    background: linear-gradient(135deg, var(--teal) 0%, var(--violet) 100%) #000000;
    position: relative;
  }

  /* Lueur ambrée, calquée sur l'overlay de horizontale.net : coins bas
     gauche/droite et un peu au centre haut/bas. Passe derrière les
     braises et la galaxie (z-index négatif), au-dessus du seul dégradé
     de fond. */
  #lueur {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
      radial-gradient(1500px 500px at 50% -10%, #E1A02738, transparent 60%),
      radial-gradient(2000px 500px at 50% 110%, #E1A02738, transparent 40%),
      radial-gradient(900px 600px at 0 110%, #E1A02738, transparent 60%),
      radial-gradient(900px 600px at 100% 110%, #E1A02738, transparent 60%);
  }

  #braises, #galaxie {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
  }
  #braises { z-index: 0; filter: blur(3px); }
  #galaxie { z-index: 1; }

  #etat, #horloge, #local, #bascule, #conversation { z-index: 2; }

  /* --------------------------------------------------------------- */
  /* État (discret, sous la galaxie)                                  */
  /* --------------------------------------------------------------- */

  #etat {
    position: fixed;
    top: 1.4rem;
    /* Ancré via "right" (jamais "left: auto") pour que le passage à la
       vue mobile reste une valeur numérique interpolable par la
       transition ci-dessous, plutôt qu'un saut instantané. */
    right: 50%;
    transform: translateX(50%);
    margin: 0;
    font-size: .78rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--sourdine);
    text-align: center;
    pointer-events: none;
    transition: color .3s, right .3s linear, transform .3s linear;
  }

  /* Horloge + date façon réveil digital : police 7 segments, avec les
     segments éteints visibles en fond (comme un vrai afficheur LCD/LED)
     derrière le texte allumé. Un cadran 7 segments a physiquement les
     mêmes segments pour chaque caractère qu'il affiche un chiffre ou une
     lettre : le fond "éteint" est donc toujours un bloc de "8" de même
     longueur que le texte réel. */
  #horloge {
    position: fixed;
    top: 1.4rem;
    left: calc(1.6rem - 10px);
    margin: 0;
    font-family: 'DSEG7 Classic', 'Courier New', monospace;
    pointer-events: none;
  }

  .cadran {
    position: relative;
    display: block;
    width: max-content;
    white-space: nowrap;
    line-height: 1.15;
  }

  .cadran--heure { font-size: 2.4rem; }         /* x2,5 par rapport à la taille d'origine */

  /* La date revient à la police normale de l'interface (plus lisible
     qu'en 7 segments) ; seule l'heure garde le style réveil digital. Pas
     de fond "segments éteints" ici, ça n'a de sens qu'en police 7
     segments — décalée de 5px pour s'aligner visuellement sur l'heure. */
  .cadran--date {
    font-family: -apple-system, "Segoe UI", Georgia, serif;
    font-size: .95rem;      /* taille d'origine de l'horloge */
    margin-top: .35rem;
    margin-left: 5px;
    min-height: 1.15em;     /* pas de contenu en flux normal (tout est en absolute) */
    letter-spacing: .04em;
    text-transform: uppercase;
  }

  .segments-fond {
    color: rgba(169, 159, 196, .12);   /* segments "éteints" */
  }

  /* Les ":" de l'heure clignotent, comme sur un vrai réveil digital. */
  #deuxpoints {
    animation: clignoter 1s steps(1, end) infinite;
  }
  @keyframes clignoter {
    50%, 100% { opacity: 0; }
  }
  @media (prefers-reduced-motion: reduce) {
    #deuxpoints { animation: none; }
  }

  .segments-actifs {
    position: absolute;
    top: 0;
    left: 0;
    color: #cfeadf;
    text-shadow: 0 0 .35em rgba(126, 224, 201, .55);
  }

  /* --------------------------------------------------------------- */
  /* Bouton on/off, bas gauche                                        */
  /* --------------------------------------------------------------- */

  #bascule {
    position: fixed;
    left: 1.6rem;
    bottom: 1.6rem;
    width: 3.6rem;
    height: 3.6rem;
    border-radius: 50%;
    border: 1px solid rgba(242,238,251,.25);
    background: rgba(255,255,255,.05);
    backdrop-filter: blur(6px);
    color: var(--encre);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    /* Sur iOS, un appui maintenu ("maintenir pour parler") est sinon
       interprété comme une sélection de texte / déclenche la loupe de
       sélection native, ce qui coupe l'appui en plein milieu. */
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
    touch-action: none;
    transition: background .2s, border-color .2s, box-shadow .3s,
                width .3s linear, height .3s linear,
                left .3s linear, bottom .3s linear;
  }
  #bascule svg {
    width: 1.5rem;
    height: 1.5rem;
    transition: width .3s linear, height .3s linear, transform .3s linear;
  }
  #bascule:hover { border-color: rgba(242,238,251,.5); }
  #bascule:focus-visible { outline: 2px solid var(--encre); outline-offset: 3px; }
  #bascule.actif {
    border-color: #7ee0c9;
    box-shadow: 0 0 1.4rem rgba(126,224,201,.35);
  }
  #bascule.actif svg { color: #7ee0c9; }

  /* Mode local : masqué pour l'instant (toute la logique reste active en
     JS — supprimer cette ligne "display" pour le rendre visible à nouveau,
     par ex. dans un futur panneau de réglages). */
  #local {
    display: none;

    position: fixed;
    left: 1.6rem;
    bottom: 5.6rem;
    font-size: .72rem;
    letter-spacing: .04em;
    color: var(--sourdine);
    background: none;
    border: none;
    cursor: pointer;
    padding: .2rem 0;
    opacity: .75;
    transition: opacity .2s, color .2s;
  }
  #local:hover { opacity: 1; }
  #local.actif { color: #7ee0c9; opacity: 1; }
  #local[disabled] { opacity: .35; cursor: default; }

  /* --------------------------------------------------------------- */
  /* Bulles de conversation, bas droite                                */
  /* --------------------------------------------------------------- */

  #conversation {
    position: fixed;
    right: 1.4rem;
    top: 0;
    bottom: 0;                 /* pleine hauteur : plus d'arrêt net à 20px du bord */
    padding-bottom: 1.6rem;
    width: min(20rem, calc(100vw - 3rem));
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: .55rem;
    overflow: hidden;
    pointer-events: none;
    /* Fondu vertical uniquement : plein (bas) jusqu'à ~60% de l'écran, puis
       disparaît progressivement bien avant le haut. Pas de composante
       horizontale — les bulles de gauche restent aussi nettes que celles
       de droite, quelle que soit leur position verticale. */
    -webkit-mask-image: linear-gradient(to top, black 0%, black 60%, transparent 85%);
            mask-image: linear-gradient(to top, black 0%, black 60%, transparent 85%);
  }

  .bulle {
    max-width: 88%;
    padding: .6rem .85rem;
    border-radius: 1.1rem;
    font-size: .88rem;
    line-height: 1.4;
    backdrop-filter: blur(18px) saturate(1.3);
    -webkit-backdrop-filter: blur(18px) saturate(1.3);
    box-shadow: 0 2px 14px rgba(0,0,0,.35);
    animation: apparition .35s ease-out;
    word-wrap: break-word;
  }

  @keyframes apparition {
    from { opacity: 0; transform: translateY(.5rem); }
    to   { opacity: 1; transform: translateY(0); }
  }

  .bulle.vous {
    align-self: flex-end;
    background: rgba(var(--teal-bulle-rgb), .88);
    border: 1px solid rgba(126,224,201,.4);
    border-bottom-right-radius: .3rem;
  }
  /* La reconnaissance vocale rend tout en minuscules : on majuscule
     juste la première lettre à l'affichage, sans toucher au texte
     envoyé à l'API. */
  .bulle.vous::first-letter {
    text-transform: uppercase;
  }

  .bulle.guideon {
    align-self: flex-start;
    background: rgba(var(--violet-bulle-rgb), .88);
    border: 1px solid rgba(220,170,255,.35);
    border-bottom-left-radius: .3rem;
  }

  @media (prefers-reduced-motion: reduce) {
    .bulle { animation: none; }
  }

  /* --------------------------------------------------------------- */
  /* Vue mobile (< 700px)                                             */
  /* --------------------------------------------------------------- */

  @media (max-width: 700px) {
    /* Le titre d'état change de longueur ("Éteint" vs "Attente de
       confirmation") : centré, ça fait bouger tout le bloc à chaque
       changement. Ancré à droite, le bord droit reste toujours au même
       endroit, seul le bord gauche respire. "right" et "transform" restent
       tous les deux des valeurs numériques (jamais "auto") pour que la
       transition ci-dessus les anime au lieu de sauter d'un coup. */
    #etat {
      right: 1.4rem;
      transform: translateX(0);
      text-align: right;
    }

    /* Bouton on/off plus discret et plus proche du coin en mobile. */
    #bascule {
      width: 2.6rem;
      height: 2.6rem;
      left: .9rem;
      bottom: .9rem;
    }
    #bascule svg {
      width: 1.15rem;
      height: 1.15rem;
      /* Le pictogramme n'est pas parfaitement centré dans son cadre 24x24
         d'origine (le trait du dessus pèse un peu plus que l'arc du bas,
         et légèrement plus à droite aussi) ; à cette taille réduite, le
         léger décalage devient perceptible. */
      transform: translate(1px, 1px);
    }

    /* La lueur ambrée des coins prend trop le dessus sur un petit écran
       de téléphone — on la retire simplement en vue mobile. */
    #lueur {
      display: none;
    }
  }

  /* --------------------------------------------------------------- */
  /* Mode iOS : bouton « maintenir pour parler » centré en bas de     */
  /* l'écran, plus grand, et zone de messages pleine largeur au-dessus. */
  /* (classe posée par configurerPourIOS() dans le script)             */
  /* --------------------------------------------------------------- */

  /* Position/taille du bouton centralisées ici en variables : le bas de
     la zone de conversation (plus loin) s'aligne dessus automatiquement,
     sans dupliquer les valeurs à deux endroits. */
  body.mode-ios {
    --ios-bouton-bas:   calc(2.6rem - 10px);
    --ios-bouton-taille: 5.4rem;
  }

  body.mode-ios #bascule {
    left: 50%;
    top: auto;
    bottom: var(--ios-bouton-bas);
    transform: translateX(-50%);
    width: var(--ios-bouton-taille);
    height: var(--ios-bouton-taille);
  }
  body.mode-ios #bascule svg {
    width: 2.3rem;
    height: 2.3rem;
    /* Le recentrage de 1px (voir plus haut) était calibré pour le
       pictogramme "power" — le micro est déjà équilibré dans son cadre. */
    transform: none;
  }

  /* La zone de conversation passe en pleine largeur, cantonnée entre la
     date (en haut) et le bouton (en bas, toujours centré horizontalement
     mais désormais proche du bord bas plutôt qu'au milieu de l'écran) :
     elle reste ancrée en bas de cet espace (les messages les plus
     récents juste au-dessus du bouton). Le fondu est étiré (opaque
     jusqu'à 78%, transparent à partir de 96%) pour que les messages
     restent visibles bien plus haut, jusque vers la date, au lieu de
     s'effacer dès le milieu de l'écran. */
  body.mode-ios #conversation {
    left: 0;
    right: 0;
    width: auto;
    top: 6rem;
    bottom: calc(var(--ios-bouton-bas) + var(--ios-bouton-taille) + 1rem + 10px);
    padding: 0 1.2rem;
    -webkit-mask-image: linear-gradient(to top, black 0%, black 78%, transparent 96%);
            mask-image: linear-gradient(to top, black 0%, black 78%, transparent 96%);
  }
  body.mode-ios .bulle {
    max-width: min(26rem, 85%);
  }
