/*
assistant.css

QUOI : Styles du widget conversationnel de l'assistant IA (bulle flottante + panneau de chat) — bulles de
       message, indicateur « réflexion », cartes d'événements cliquables et états d'erreur.

COMMENT : S'appuie sur les variables `:root` de style.css (chargé avant) avec valeurs de repli `var(--token, …)`
          pour rester robuste partout. Position fixe (bas-GAUCHE — bas-droite est réservé au bouton
          « retour en haut », cf. back-to-top.css) ; panneau ancré au-dessus de la bulle en desktop, feuille
          quasi plein écran + voile en mobile. Animations désactivées sous `prefers-reduced-motion`.

OÙ : Chargé par `_site_header.html.twig` (cache-busté via `asset()`), couplé à `_assistant_widget.html.twig` et `assistant.js`.

POURQUOI : Un accès discret et engageant à la recherche d'événements rédigée par l'IA, cohérent avec la charte
           graphique du site, sans dépendre d'un framework CSS.
*/

.assistant {
    --asst-marine: var(--c-marine, #0a3d62);
    --asst-mer: var(--c-mer, #1e6091);
    --asst-corail: var(--c-corail, #e07856);
    --asst-surface: var(--c-blanc, #ffffff);
    --asst-soft: var(--c-sable-clair, #faf4e8);
    --asst-text: var(--c-texte, #2c3e50);
    --asst-text-soft: var(--c-texte-doux, #5a6b7a);
    --asst-border: var(--c-bordure, #e8dec8);
    --asst-radius: var(--radius-md, 14px);
    --asst-shadow: var(--shadow-lg, 0 20px 48px rgba(10, 61, 98, .15), 0 6px 16px rgba(10, 61, 98, .08));
    --asst-ease: var(--ease-out, cubic-bezier(.16, 1, .3, 1));
    font-family: var(--font-base, system-ui, sans-serif);
}

/* ── Bulle ronde (déclencheur) ── */
.assistant__fab {
    position: fixed;
    left: 20px;
    bottom: 20px;
    z-index: 900;
    display: grid;
    place-items: center;
    width: 56px;
    height: 56px;
    border: 1px solid rgba(255, 255, 255, 0.25);   /* liseré verre cohérent avec l'en-tête */
    border-radius: 50%;
    background: linear-gradient(135deg, var(--asst-mer) 0%, var(--asst-marine) 100%);
    color: #fff;
    cursor: grab;
    /* `touch-action: none` : laisse le Pointer Events JS (assistant/index.js) piloter le glissement au
       doigt sans que le navigateur ne le confonde avec un scroll de page. */
    touch-action: none;
    box-shadow: var(--asst-shadow);
    transition: transform var(--duration-base, 220ms) var(--asst-ease),
                box-shadow var(--duration-base, 220ms) var(--asst-ease),
                opacity var(--duration-base, 220ms) var(--asst-ease);
}

.assistant__fab:hover {
    transform: translateY(-2px) scale(1.05);
    box-shadow: 0 14px 32px rgba(10, 61, 98, .28);
}

/* Glissement en cours (`assistant/index.js`) : suit le pointeur au pixel près, sans le lissage de
   `transition` (qui ferait « traîner » la bulle derrière le curseur) ni le survol qui la ferait flotter. */
.assistant__fab.is-dragging {
    cursor: grabbing;
    transition: none;
    transform: none;
    box-shadow: 0 18px 40px rgba(10, 61, 98, .32);
}

.assistant__fab:focus-visible {
    outline: 3px solid var(--c-focus, rgba(30, 96, 145, .35));
    outline-offset: 3px;
}

/* ── `hidden` doit gagner sur les `display` du composant ──
   L'attribut `hidden` est le seul interrupteur dont dispose le JS, et la règle UA qu'il déclenche
   (`display: none`) a la spécificité la plus faible qui soit : n'importe quel `display: flex` ou
   `grid` posé sur la même classe l'annule en silence. Bug vérifié en dev le 2026-09-09 — les
   suggestions de démarrage restaient affichées pendant toute la conversation alors que le JS les
   déclarait masquées depuis la première question. Chaque élément que le JS bascule par `hidden` doit
   donc figurer ici. */
.assistant__suggestions[hidden],
.assistant__teaser[hidden],
.assistant__reset[hidden] {
    display: none;
}

/* ── Mascotte (le petit robot) ──
   Aplat à trois couleurs, contrairement au reste des icônes du site qui sont au trait et héritent
   `currentColor`. Les trois variables sont posées ici plutôt que codées dans le tracé : le SVG est
   partagé entre la bulle et l'avatar du panneau, et un futur emplacement sur fond clair n'aura
   qu'à les redéfinir.

   Valeurs LITTÉRALES, pas `var(--c-sable-clair)` & compagnie : ces jetons-là sont des rôles de
   SURFACE, que `theme-dark.css` retourne pour la nuit (le sable clair y devient l'encre profonde) —
   la mascotte était donc noire en thème sombre, tête sur fond marine. La carrosserie d'une mascotte
   n'est pas une surface de page : c'est une couleur d'identité, elle ne suit pas le thème. Les trois
   valeurs restent celles de la charte (sable clair, marine, corail). */
.mascotte {
    --mascotte-corps: #faf4e8;
    --mascotte-trait: #0a3d62;
    --mascotte-accent: #e07856;
    display: block;
}

.assistant__fab-icon {
    width: 2.15rem;
    height: 2.15rem;
    /* L'antenne monte plus haut que le centre optique de la tête : sans ce décalage, la mascotte
       paraît posée trop bas dans le disque. */
    transform: translateY(-1px);
}

/* La mascotte penche la tête au survol : un seul moment animé, sur le seul élément qui a un visage. */
.assistant__fab:hover .mascotte,
.assistant__fab:focus-visible .mascotte {
    animation: mascotte-salut 620ms var(--asst-ease) 1;
}

@keyframes mascotte-salut {
    35% { transform: translateY(-1px) rotate(-7deg); }
    70% { transform: translateY(-1px) rotate(5deg); }
    100% { transform: translateY(-1px) rotate(0); }
}

/* ── Invitation (phylactère à côté de la bulle) ── */
.assistant__teaser {
    position: fixed;
    z-index: 899;   /* juste sous la bulle : elle ne doit jamais recouvrir son propre déclencheur */
    display: flex;
    align-items: center;
    gap: .1rem;
    max-width: min(17rem, calc(100vw - 6rem));
    padding: .1rem .1rem .1rem .2rem;
    background: var(--asst-surface);
    border: 1px solid var(--asst-border);
    border-radius: 999px;
    box-shadow: var(--asst-shadow);
    opacity: 0;
    transform: translateY(6px) scale(.96);
    transition: opacity var(--duration-base, 220ms) var(--asst-ease),
                transform var(--duration-base, 220ms) var(--asst-ease);
}

.assistant__teaser.is-visible {
    opacity: 1;
    transform: translateY(0) scale(1);
}

.assistant__teaser-text {
    border: 0;
    background: transparent;
    padding: .55rem .3rem .55rem .75rem;
    /* `--asst-text` et non `--asst-marine` : le marine reste sombre en thème sombre (il sert d'aplat
       à texte blanc ailleurs), il deviendrait illisible sur la surface encre de la phylactère.
       C'est le piège que DESIGN.md documente sous « La Règle de la Surface Sémantique ». */
    color: var(--asst-text);
    font-family: inherit;
    font-size: .86rem;
    font-weight: 600;
    line-height: 1.3;
    text-align: left;
    cursor: pointer;
}

.assistant__teaser-close {
    display: grid;
    place-items: center;
    width: 1.7rem;
    height: 1.7rem;
    flex: 0 0 auto;
    margin-right: .25rem;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--asst-text-soft);
    cursor: pointer;
    transition: background var(--duration-fast, 150ms) ease, color var(--duration-fast, 150ms) ease;
}

.assistant__teaser-close:hover {
    background: var(--asst-soft);
    color: var(--asst-text);
}

.assistant__teaser-close .nav-ico { width: .85rem; height: .85rem; }

/* Inversion : quand le chat est ouvert, la bulle se rétracte (le panneau prend le relais). */
.assistant.is-open .assistant__fab {
    opacity: 0;
    pointer-events: none;
    transform: scale(0);
}

/* ── Voile (mobile uniquement) ── */
.assistant__scrim {
    position: fixed;
    inset: 0;
    /* Hauteur visible réelle : avec `inset: 0` seul, le voile s'arrête au viewport de mise en page et
       laisse apparaître la page sous la barre d'adresse. */
    height: 100dvh;
    z-index: 940;
    background: rgba(6, 22, 36, .45);
    -webkit-backdrop-filter: blur(10px) saturate(140%);  /* même flou « verre » que le voile de navigation */
    backdrop-filter: blur(10px) saturate(140%);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--duration-base, 220ms) var(--asst-ease), visibility 0s linear var(--duration-base, 220ms);
}

/* ── Panneau de conversation ── */
.assistant__panel {
    position: fixed;
    left: 20px;
    bottom: 20px;
    z-index: 950;
    display: flex;
    flex-direction: column;
    width: min(380px, calc(100vw - 2rem));
    max-height: min(70vh, 560px);
    overflow: hidden;
    background: var(--asst-surface);
    border: 1px solid var(--asst-border);
    border-radius: var(--radius-lg, 22px);
    box-shadow: var(--asst-shadow);
    transform-origin: bottom left;

    /* État replié par défaut : masqué mais prêt à s'animer (pas de display:none → transition fluide). */
    opacity: 0;
    visibility: hidden;
    transform: translateY(20px) scale(.96);
    pointer-events: none;
    transition: opacity var(--duration-base, 220ms) var(--asst-ease),
                transform var(--duration-base, 220ms) var(--asst-ease),
                visibility 0s linear var(--duration-base, 220ms);
}

/* État déployé : le chat apparaît avec une transition fluide. */
.assistant.is-open .assistant__panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0) scale(1);
    pointer-events: auto;
    transition: opacity var(--duration-base, 220ms) var(--asst-ease),
                transform var(--duration-base, 220ms) var(--asst-ease),
                visibility 0s linear 0s;
}

/* En-tête */
.assistant__head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .85rem 1rem;
    background: linear-gradient(135deg, var(--asst-mer) 0%, var(--asst-marine) 100%);
    color: #fff;
}

.assistant__avatar {
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border-radius: 50%;
    background: rgba(255, 255, 255, .18);
}

.assistant__avatar .nav-ico { width: 1.1rem; height: 1.1rem; }
.assistant__avatar-mascotte { width: 1.55rem; height: 1.55rem; }

.assistant__head-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.assistant__title { font-weight: 700; font-size: .98rem; }
.assistant__subtitle { font-size: .78rem; opacity: .85; }

/* Les deux boutons d'en-tête forment un groupe : la marge automatique est portée UNE fois par le
   groupe. Deux `margin-left: auto` frères se partageraient l'espace libre et écarteraient les
   boutons l'un de l'autre. */
.assistant__head-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: .25rem;
    flex: 0 0 auto;
}

.assistant__reset {
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: rgba(255, 255, 255, .82);
    cursor: pointer;
    transition: background var(--duration-fast, 150ms) ease, color var(--duration-fast, 150ms) ease;
}

.assistant__reset:hover {
    background: rgba(255, 255, 255, .18);
    color: #fff;
}

.assistant__reset .nav-ico { width: 1rem; height: 1rem; }

.assistant__close {
    margin-left: 0;
    display: grid;
    place-items: center;
    width: 2rem;
    height: 2rem;
    flex: 0 0 auto;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .12);
    color: #fff;
    cursor: pointer;
    transition: background var(--duration-fast, 150ms) ease;
}

.assistant__close:hover { background: rgba(255, 255, 255, .25); }
.assistant__close .nav-ico { width: 1.05rem; height: 1.05rem; }

/* Fil de discussion */
.assistant__thread {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 1rem;
    display: flex;
    flex-direction: column;
    gap: .75rem;
    scroll-behavior: smooth;
}

.assistant__msg { display: flex; max-width: 90%; }
.assistant__msg--bot { align-self: flex-start; }
.assistant__msg--user { align-self: flex-end; }

/* Entrée douce des messages (et des cartes) — neutralisée sous prefers-reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
    .assistant__msg,
    .assistant__cards {
        animation: assistant-msg-in .3s var(--asst-ease) both;
    }
}

@keyframes assistant-msg-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.assistant__bubble {
    margin: 0;
    padding: .7rem .95rem;
    border-radius: var(--asst-radius);
    font-size: .92rem;
    line-height: 1.55;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.assistant__msg--bot .assistant__bubble {
    background: var(--asst-soft);
    color: var(--asst-text);
    border: 1px solid var(--asst-border);
    border-bottom-left-radius: 4px;
}

.assistant__msg--user .assistant__bubble {
    background: linear-gradient(135deg, var(--asst-mer) 0%, var(--asst-marine) 100%);
    color: #fff;
    border-bottom-right-radius: 4px;
}

.assistant__msg--error .assistant__bubble {
    background: rgba(224, 120, 86, .12);
    color: var(--c-corail-fonce, #c6603c);
    border: 1px solid rgba(224, 120, 86, .35);
}

/* Curseur clignotant pendant l'effet machine à écrire */
.assistant__bubble.is-typing::after {
    content: "▍";
    margin-left: 1px;
    animation: assistant-caret 1s steps(1) infinite;
    color: var(--asst-mer);
}

@keyframes assistant-caret { 50% { opacity: 0; } }

/* Indicateur « l'assistant réfléchit » (trois points) */
.assistant__typing {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    padding: .7rem .85rem;
}

.assistant__typing span {
    width: .45rem;
    height: .45rem;
    border-radius: 50%;
    background: var(--asst-mer);
    opacity: .5;
    animation: assistant-bounce 1.2s var(--asst-ease) infinite;
}

.assistant__typing span:nth-child(2) { animation-delay: .15s; }
.assistant__typing span:nth-child(3) { animation-delay: .3s; }

@keyframes assistant-bounce {
    0%, 60%, 100% { transform: translateY(0); opacity: .5; }
    30% { transform: translateY(-4px); opacity: 1; }
}

/* Cartes d'événements cités */
.assistant__cards {
    display: flex;
    flex-direction: column;
    gap: .5rem;
    margin-top: .15rem;
    align-self: flex-start;
    max-width: 90%;
}

.assistant__card {
    display: block;
    padding: .6rem .75rem;
    border: 1px solid var(--asst-border);
    border-radius: var(--asst-radius);
    background: var(--asst-surface);
    color: inherit;
    text-decoration: none;
    box-shadow: var(--shadow-xs, 0 1px 2px rgba(10, 61, 98, .06));
    transition: transform var(--duration-fast, 150ms) var(--asst-ease), box-shadow var(--duration-fast, 150ms) var(--asst-ease), border-color var(--duration-fast, 150ms) ease;
}

.assistant__card:hover {
    transform: translateY(-2px);
    border-color: var(--asst-mer);
    box-shadow: var(--shadow-sm, 0 2px 6px rgba(10, 61, 98, .07));
}

.assistant__card:focus-visible {
    outline: 3px solid var(--c-focus, rgba(30, 96, 145, .35));
    outline-offset: 2px;
}

.assistant__card-title {
    display: block;
    font-weight: 600;
    font-size: .88rem;
    color: var(--asst-marine);
    margin-bottom: .2rem;
}

.assistant__card-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .15rem .6rem;
    font-size: .78rem;
    color: var(--asst-text-soft);
}

.assistant__card-meta span { display: inline-flex; align-items: center; gap: .25rem; }
.assistant__card-meta .nav-ico { width: .85rem; height: .85rem; }
.assistant__card-price { color: var(--asst-corail); font-weight: 600; }

/* Réessayer, sous un message d'erreur. Petit et discret : c'est une porte de sortie, pas l'action
   principale de la conversation — le champ de saisie le reste. */
/* `.assistant__msg` est une rangée : sans passage en colonne, le bouton se poserait À CÔTÉ de la
   bulle d'erreur au lieu de dessous. */
.assistant__msg--error {
    flex-direction: column;
    align-items: flex-start;
}

.assistant__retry {
    margin-top: .4rem;
    padding: .3rem .7rem;
    border: 1px solid var(--asst-border);
    border-radius: 999px;
    background: var(--asst-surface);
    color: var(--asst-text);
    font-family: inherit;
    font-size: .78rem;
    font-weight: 600;
    cursor: pointer;
    transition: border-color var(--duration-fast, 150ms) ease, background var(--duration-fast, 150ms) ease;
}

.assistant__retry:hover {
    border-color: var(--asst-mer);
    background: var(--asst-soft);
}

/* Carte « lieu permanent » : fond sable au lieu du blanc des événements datés. Le liseré marine
   latéral qui jouait ce rôle est parti (2026-09-09) — DESIGN.md interdit la bordure latérale colorée
   comme accent de carte, et la distinction est de toute façon déjà portée par le nom du type
   (`.assistant__card-tag`, posé par `cards.js`). Le fond suffit à séparer les deux familles sans
   ajouter une couleur d'accent là où aucune information ne la justifie. */
.assistant__card--lieu { background: var(--asst-soft); }
.assistant__card-thumb {
    width: 100%;
    height: 84px;
    object-fit: cover;
    border-radius: 8px;
    margin-bottom: .4rem;
    display: block;
}
.assistant__card-tag {
    padding: .05rem .4rem;
    border-radius: 999px;
    background: var(--asst-border);
    color: var(--asst-marine);
    font-size: .72rem;
    font-weight: 600;
}

/* Suggestions de démarrage */
.assistant__suggestions {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    padding: 0 1rem .25rem;
}

.assistant__chip {
    padding: .35rem .7rem;
    border: 1px solid var(--asst-border);
    border-radius: 999px;
    background: var(--asst-soft);
    color: var(--asst-marine);
    font: inherit;
    font-size: .8rem;
    cursor: pointer;
    transition: background var(--duration-fast, 150ms) ease, border-color var(--duration-fast, 150ms) ease;
}

.assistant__chip:hover { background: #fff; border-color: var(--asst-mer); }

/* Formulaire de saisie */
.assistant__form {
    display: flex;
    align-items: flex-end;
    gap: .5rem;
    padding: .75rem 1rem 1rem;
    border-top: 1px solid var(--asst-border);
}

.assistant__input {
    flex: 1 1 auto;
    resize: none;
    max-height: 96px;
    padding: .6rem .75rem;
    border: 1px solid var(--asst-border);
    border-radius: var(--asst-radius);
    background: var(--asst-soft);
    color: var(--asst-text);
    font: inherit;
    font-size: .9rem;
    line-height: 1.4;
    transition: border-color var(--duration-fast, 150ms) ease, box-shadow var(--duration-fast, 150ms) ease;
}

.assistant__input:focus {
    outline: none;
    border-color: var(--asst-mer);
    box-shadow: 0 0 0 3px var(--c-focus, rgba(30, 96, 145, .35));
    background: #fff;
}

.assistant__send {
    display: grid;
    place-items: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: 0 0 auto;
    border: 0;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--asst-mer) 0%, var(--asst-marine) 100%);
    color: #fff;
    cursor: pointer;
    transition: transform var(--duration-fast, 150ms) var(--asst-ease), opacity var(--duration-fast, 150ms) ease;
}

.assistant__send:hover:not(:disabled) { transform: scale(1.06); }
.assistant__send:disabled { opacity: .45; cursor: not-allowed; }
.assistant__send .nav-ico { width: 1.15rem; height: 1.15rem; }

.assistant__send:focus-visible,
.assistant__chip:focus-visible,
.assistant__close:focus-visible {
    outline: 3px solid var(--c-focus, rgba(30, 96, 145, .35));
    outline-offset: 2px;
}

/* ── Mobile : feuille quasi plein écran (la bulle ronde, elle, ne bouge pas : bottom/left 20px) ── */
@media (max-width: 600px) {
    .assistant__panel {
        right: 0;
        left: 0;
        /* `--asst-clavier` est posé par `assistant/index.js` à partir de `visualViewport` : c'est la
           hauteur réellement masquée par le clavier virtuel. Le clavier ne modifie PAS le viewport de
           mise en page sur iOS — sans ce décalage, la feuille reste ancrée sous le clavier, saisie
           comprise, et le visiteur écrit à l'aveugle. */
        bottom: var(--asst-clavier, 0px);
        width: 100%;
        /* `dvh` d'abord (hauteur visible réelle), `vh` en repli : `vh` se mesure barre d'adresse
           MASQUÉE, si bien qu'à 85vh le bas de la feuille — donc le champ de saisie — passait sous la
           barre d'adresse. */
        max-height: 85vh;
        max-height: 85dvh;
        border-radius: var(--radius-lg, 22px) var(--radius-lg, 22px) 0 0;
        transform: translateY(100%);
        transition: opacity var(--duration-base, 220ms) var(--asst-ease),
                    transform var(--duration-base, 220ms) var(--asst-ease),
                    bottom var(--duration-fast, 150ms) var(--asst-ease),
                    visibility 0s linear var(--duration-base, 220ms);
    }

    /* Le champ de saisie est relevé à 16 px par `base/ios-zoom.css`, qui traite le seuil de zoom
       automatique d'iOS pour TOUS les champs du site. Une règle locale de plus ici aurait fait deux
       mécaniques pour une seule contrainte, donc deux endroits à corriger le jour où le seuil bouge. */

    .assistant.is-open .assistant__panel {
        transform: translateY(0);
    }

    /* Voile tactile derrière la feuille. */
    .assistant.is-open .assistant__scrim {
        opacity: 1;
        visibility: visible;
        transition: opacity var(--duration-base, 220ms) var(--asst-ease), visibility 0s linear 0s;
    }
}

/* ── Accessibilité : mouvement réduit ── */
@media (prefers-reduced-motion: reduce) {
    .assistant__fab,
    .assistant__fab .mascotte,
    .assistant__teaser,
    .assistant__panel,
    .assistant__scrim,
    .assistant__card,
    .assistant__send,
    .assistant__typing span {
        animation: none !important;
        transition: none !important;
    }

    .assistant__bubble.is-typing::after { animation: none; }
}

/* ── Mode sombre : surface en encre marine, dégradés « marque » SATURÉS conservés ──
   Piloté par [data-theme="dark"] sur <html> (cf. style.css). On fige --asst-marine/--asst-mer
   (les tokens globaux deviennent clairs en sombre, ce qui rendrait le texte blanc illisible). */
[data-theme="dark"] .assistant {
    --asst-marine: #0a3d62;
    --asst-mer: #1e6091;
    --asst-surface: #16242f;
    --asst-soft: #1d2e3b;
    --asst-text: #e7eef6;
    --asst-text-soft: #a3b6c6;
    --asst-border: rgba(160, 196, 224, 0.18);
}

/* Libellés qui pointaient vers le marine (désormais clair → texte clair explicite). */
[data-theme="dark"] .assistant__card-title { color: #bcd6ea; }
[data-theme="dark"] .assistant__chip { color: #cfe2f1; }
[data-theme="dark"] .assistant__chip:hover { background: #20323f; border-color: var(--asst-mer); }
[data-theme="dark"] .assistant__card-tag { background: #23394a; color: #cfe2f1; }

/* Le focus de l'input forçait un fond blanc codé en dur → encre. */
[data-theme="dark"] .assistant__input:focus { background: #1d2e3b; }
