/*
 * La présentation, sur tout le site public — les effets joués par
 * assets/js/showcase.js, et le mouvement des icônes et des scènes du pack
 * (resources/svg/cmg, insérées par <x-cmg-icon> et <x-cmg-scene>).
 *
 * Les états de départ n'existent que sous html.ab-on, posée avant le premier
 * rendu par un extrait du <head> — jamais en mouvement réduit. Ils animent
 * translate, scale, opacity et filter, jamais transform : le survol des
 * cartes garde transform pour lui. Les transitions d'apparition listent
 * aussi celles du survol, sans délai, sinon elles les remplaceraient et le
 * survol sauterait.
 */

/* =====================================================================
   1. Les effets de présentation
   ===================================================================== */

/* Un titre reste invisible jusqu'à son découpage en mots, un terminal
   jusqu'à sa préparation. */
.ab-on [data-ab="words"]:not(.ab-split),
.ab-on [data-ab="type"]:not(.ab-ready) [data-line] { visibility: hidden; }

.ab-on [data-ab="words"] .ab-w {
    display: inline-block; overflow: hidden; vertical-align: top;
    /* De la marge autour de chaque mot : l'approche serrée des titres
       ferait sinon mordre le masque sur les lettres qui débordent. */
    padding: 0 .08em .12em; margin: 0 -.08em -.12em;
}
.ab-on [data-ab="words"] .ab-wi {
    display: inline-block;
    translate: 0 108%;
    opacity: 0;
    transition: translate 1s cubic-bezier(.2, .75, .15, 1), opacity .7s ease;
    transition-delay: calc(var(--i, 0) * 60ms + var(--d, 0ms));
}
.ab-on [data-ab="words"].is-in .ab-wi { translate: 0 0; opacity: 1; }

/* Les transitions ne sont posées qu'à l'arrivée (.is-in). Posées dès le
   départ, un bloc déjà visible quand il est pris en charge entamerait une
   transition 1→0 encore dans son délai ; le .is-in qui suit de quelques
   millisecondes l'annulerait et le bloc resterait à 1 — sans entrée. */
.ab-on [data-ab="fade"] { opacity: 0; filter: blur(12px); translate: 0 20px; }
.ab-on [data-ab="fade"].is-in {
    opacity: 1; filter: none; translate: 0 0;
    transition:
        opacity 1s ease var(--d, 0ms),
        filter 1s ease var(--d, 0ms),
        translate 1s cubic-bezier(.2, .75, .15, 1) var(--d, 0ms),
        transform .35s cubic-bezier(.2, .75, .15, 1),
        box-shadow .35s ease,
        border-color .35s ease,
        background-color .2s ease,
        color .2s ease;
}

.ab-on [data-ab="pop"] > * { opacity: 0; translate: 0 14px; scale: .96; }
.ab-on [data-ab="pop"].is-in > * {
    opacity: 1; translate: 0 0; scale: 1;
    transition:
        opacity .6s ease calc(var(--i, 0) * 80ms + var(--d, 0ms)),
        translate .7s cubic-bezier(.2, .75, .15, 1) calc(var(--i, 0) * 80ms + var(--d, 0ms)),
        scale .7s cubic-bezier(.2, .75, .15, 1) calc(var(--i, 0) * 80ms + var(--d, 0ms)),
        transform .25s ease,
        background-color .2s ease,
        border-color .25s ease,
        color .2s ease,
        box-shadow .25s ease;
}

/* Au clavier, ce qui a le focus s'affiche aussitôt — sans attendre le
   délai de la cascade. */
.ab-on [data-ab]:focus-within,
.ab-on [data-ab="pop"] > :focus-within {
    opacity: 1; filter: none; translate: 0 0; scale: 1;
    transition-delay: 0s; transition-duration: .15s;
}
.ab-on [data-ab="words"]:focus-within .ab-wi { transition-delay: 0s; }

/* Les entrées latérales d'animate.css (pages anciennes) partent de 100 %
   de large : sur un téléphone, la fenêtre de mise en page s'élargit et le
   bouton du menu sort de l'écran. En dessous du bureau, elles montent. */
@media (max-width: 1023px) {
    .animate__fadeInLeft, .animate__fadeInRight,
    .animate__fadeInLeftBig, .animate__fadeInRightBig { animation-name: fadeInUp; }
}

/* Les lignes décodées et le terminal (À propos). */
.ab-decode-visual { white-space: pre; }

/* À l'impression, tout est posé — les scènes aussi. */
@media print {
    .ab-on [data-ab], .ab-on [data-ab] .ab-wi, .ab-on [data-ab="pop"] > *,
    .ab-on [data-ab="words"]:not(.ab-split), .ab-on [data-ab="type"] [data-line],
    .cmg-scene-wrap svg > g, .cmg-scene-glow {
        opacity: 1 !important; filter: none !important; translate: none !important;
        scale: none !important; visibility: visible !important; transition: none !important;
        animation: none !important;
    }
    .cmg-scene-wrap svg [data-draw] { stroke-dashoffset: 0 !important; animation: none !important; }
}

/* =====================================================================
   2. Les icônes du pack (<x-cmg-icon>)

   Trois tailles ; les couleurs viennent de currentColor (traits) et de
   --cmg-icon-accent (accent) : un parent sombre les passe en clair. Au
   repos, un dessin net. À l'écran (.is-live, posée par showcase.js), une
   entrée courte : la plaque s'allume, un reflet la traverse, l'accent se
   pose, la barre de lumière s'étire. Rien ne boucle. Au survol d'une
   carte, l'icône rejoue.
   ===================================================================== */
.cmg-ic {
    position: relative;
    display: inline-flex;
    flex: none;
    line-height: 0;
    color: #0A2540;
    --cmg-icon-accent: #087EAC;
}
.cmg-ic-small  { width: 1.25rem; height: 1.25rem; }
.cmg-ic-medium { width: 3.5rem;  height: 3.5rem; }
.cmg-ic-large  { width: 7rem;    height: 7rem; }
.cmg-ic > svg { width: 100%; height: 100%; overflow: visible; display: block; }
.cmg-ic svg [data-part] { transform-box: fill-box; transform-origin: center; }

/* Le reflet : une bande claire qui traverse la plaque une fois. */
.cmg-ic-medium::after,
.cmg-ic-large::after {
    content: '';
    position: absolute;
    inset: 3% 3% 3% 3%;
    border-radius: 26%;
    background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, .85) 50%, transparent 62%);
    background-size: 260% 100%;
    background-position: 120% 0;
    opacity: 0;
    pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
    .cmg-icon [data-part="accent"] { transition: transform .24s cubic-bezier(.2, .7, .2, 1); }

    .cmg-ic svg.is-live [data-part="plate"] { animation: cmg-plate 1.4s ease-out 1; }
    .cmg-ic svg.is-live [data-part="accent"] { animation: cmg-accent 1.1s cubic-bezier(.2, .75, .15, 1) 1; }
    .cmg-ic svg.is-live [data-part="highlight"] { animation: cmg-highlight 1s cubic-bezier(.2, .75, .15, 1) .25s 1 both; }
    .cmg-ic svg.is-live [data-part="detail"] { animation: cmg-detail 1.2s ease-out .15s 1 both; }
    .cmg-ic:has(> svg.is-live)::after { animation: cmg-shine 1.3s cubic-bezier(.4, 0, .2, 1) .2s 1 both; }
    /* Les petites icônes n'ont ni plaque ni barre : leur accent se pose. */
    .cmg-ic-small svg.is-live [data-part="accent"] { animation: cmg-accent .9s cubic-bezier(.2, .75, .15, 1) .25s 1 both; }

    @media (hover: hover) {
        .cmg-icon:hover [data-part="accent"],
        a:hover .cmg-icon [data-part="accent"],
        button:hover .cmg-icon [data-part="accent"],
        .site-card:hover .cmg-icon [data-part="accent"],
        .hover-card:hover .cmg-icon [data-part="accent"],
        .cmg-hover:hover .cmg-icon [data-part="accent"] { transform: translateY(-1px); }
    }
}
@keyframes cmg-plate {
    0%   { filter: drop-shadow(0 0 0 rgba(39, 197, 223, 0)); }
    35%  { filter: drop-shadow(0 4px 14px rgba(39, 197, 223, .45)); }
    100% { filter: drop-shadow(0 0 0 rgba(39, 197, 223, 0)); }
}
@keyframes cmg-accent {
    0%   { opacity: 0; transform: translateY(6px) scale(.85); }
    60%  { opacity: 1; transform: translateY(-1.5px) scale(1.04); }
    100% { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes cmg-highlight {
    0%   { transform: scaleX(0); opacity: 0; }
    100% { transform: scaleX(1); opacity: .7; }
}
@keyframes cmg-detail {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}
@keyframes cmg-shine {
    0%   { opacity: 0; background-position: 120% 0; }
    15%  { opacity: 1; }
    100% { opacity: 0; background-position: -60% 0; }
}

/* Sur fond sombre : traits clairs, accent cyan. */
.cmg-ic-dark { color: #E6F1F8; --cmg-icon-accent: #27C5DF; }

/* =====================================================================
   3. Les scènes du pack (<x-cmg-scene>)

   Entrée une fois (.is-in) : le sol apparaît, les plaques se posent en
   cascade, les connexions se tracent (pathLength=1 sur leurs tracés), les
   signaux pulsent trois fois. Puis la profondeur : sous le curseur, le
   premier plan se déplace plus que les plaques, qui se déplacent plus que
   le sol (--px/--py, de -1 à 1, posés par showcase.js sur grand écran).
   translate pour la profondeur, transform pour l'entrée : les deux se
   composent.
   ===================================================================== */
.cmg-scene-wrap {
    position: relative;
    display: block;
    width: 100%;
    --px: 0;
    --py: 0;
}
.cmg-scene-wrap > svg {
    position: relative;
    display: block;
    width: 100%;
    height: auto;
    overflow: visible;
}
.cmg-scene-glow {
    position: absolute;
    inset: 8% 0 4% 0;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(39, 197, 223, .22), rgba(8, 126, 172, .08) 60%, transparent);
    filter: blur(6px);
    pointer-events: none;
}
.cmg-scene-wrap svg [data-part] { transform-box: fill-box; transform-origin: center; }
/* Les points de signal pulsent sur place : sans repère propre, leur scale
   partirait de l'origine du dessin et les ferait traverser la scène. */
.cmg-scene-wrap svg [data-part="signal"] circle { transform-box: fill-box; transform-origin: center; }

/* Les plaques : chaque groupe de premier niveau, dans l'ordre du fichier. */
.cmg-scene-wrap svg > g:not([data-part="ground"]):not([data-part="connectors"]):not([data-part="signal"]) {
    translate: calc(var(--px) * 6px) calc(var(--py) * 4px);
    transition: translate .6s cubic-bezier(.2, .7, .2, 1);
}
.cmg-scene-wrap svg > g[data-part="foreground"] {
    translate: calc(var(--px) * 16px) calc(var(--py) * 11px);
}
.cmg-scene-wrap svg > g[data-part="ground"] {
    translate: calc(var(--px) * -4px) 0;
    transition: translate .6s cubic-bezier(.2, .7, .2, 1);
}

@media (prefers-reduced-motion: no-preference) {
    .ab-on .cmg-scene-wrap:not(.is-in) svg > g { opacity: 0; }
    .ab-on .cmg-scene-wrap:not(.is-in) svg [data-draw] { stroke-dasharray: 1; stroke-dashoffset: 1; }
    .ab-on .cmg-scene-wrap:not(.is-in) .cmg-scene-glow { opacity: 0; }

    /* --sd : le départ de la cascade. Dans un hero, la scène répond au titre
       (les mots montent d'abord) ; ailleurs, elle part tout de suite. */
    .cmg-scene-wrap { --sd: 0s; }
    .site-hero .cmg-scene-wrap, .hp-hero .cmg-scene-wrap { --sd: .4s; }
    .cmg-scene-wrap.is-in svg > g { animation: cmg-plate-in .9s cubic-bezier(.2, .75, .15, 1) var(--sd) both; }
    .cmg-scene-wrap.is-in svg > g[data-part="ground"] { animation-name: cmg-ground-in; animation-duration: 1.2s; }
    .cmg-scene-wrap.is-in svg > g:nth-of-type(2) { animation-delay: calc(var(--sd) + .08s); }
    .cmg-scene-wrap.is-in svg > g:nth-of-type(3) { animation-delay: calc(var(--sd) + .18s); }
    .cmg-scene-wrap.is-in svg > g:nth-of-type(4) { animation-delay: calc(var(--sd) + .30s); }
    .cmg-scene-wrap.is-in svg > g:nth-of-type(5) { animation-delay: calc(var(--sd) + .42s); }
    .cmg-scene-wrap.is-in svg > g:nth-of-type(6) { animation-delay: calc(var(--sd) + .56s); }
    .cmg-scene-wrap.is-in svg > g:nth-of-type(7) { animation-delay: calc(var(--sd) + .70s); }
    .cmg-scene-wrap.is-in svg > g[data-part="connectors"] { animation: cmg-detail .4s ease-out calc(var(--sd) + .5s) both; }
    .cmg-scene-wrap.is-in svg [data-draw] {
        stroke-dasharray: 1;
        animation: cmg-draw 1.4s cubic-bezier(.4, 0, .2, 1) calc(var(--sd) + .6s) both;
    }
    .cmg-scene-wrap.is-in svg > g[data-part="signal"] { animation: cmg-detail .3s ease-out calc(var(--sd) + 1.5s) both; }
    .cmg-scene-wrap.is-in svg [data-part="signal"] circle { animation: cmg-signal 1.6s ease-in-out calc(var(--sd) + 1.7s) 3; }
    .cmg-scene-wrap.is-in svg [data-part="signal"] circle:nth-child(2) { animation-delay: calc(var(--sd) + 2.3s); }
    .cmg-scene-wrap.is-in .cmg-scene-glow { transition: opacity 1.6s ease calc(var(--sd) + .4s); opacity: 1; }

    /* Le premier plan respire, une fois posé. */
    .cmg-scene-wrap.is-in svg > g[data-part="foreground"] { animation: cmg-plate-in .9s cubic-bezier(.2, .75, .15, 1) calc(var(--sd) + .5s) both, cmg-breathe 4.5s ease-in-out calc(var(--sd) + 1.6s) 2; }
}
@keyframes cmg-plate-in {
    from { opacity: 0; transform: translateY(26px) scale(.96); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes cmg-ground-in {
    from { opacity: 0; transform: scaleX(.6); }
    to   { opacity: 1; transform: scaleX(1); }
}
@keyframes cmg-draw {
    from { stroke-dashoffset: 1; }
    to   { stroke-dashoffset: 0; }
}
@keyframes cmg-signal {
    0%, 100% { transform: scale(1); opacity: 1; }
    50%      { transform: scale(1.6); opacity: .55; }
}
@keyframes cmg-breathe {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
}

/* =====================================================================
   4. Le hero à deux colonnes des pages de service : texte à gauche, scène
   à droite (à partir de 1024 px) ; en dessous, la scène suit le texte et
   ses boutons. Le texte garde la plus grande part et un titre borné, pour
   que le bouton reste au-dessus de la ligne de flottaison d'un portable.
   ===================================================================== */
.hero-scene {
    display: grid;
    gap: clamp(2rem, 5vw, 4rem);
    align-items: center;
}
.hero-scene > .cmg-scene-wrap { max-width: 30rem; margin-inline: auto; }
/* Les heros historiques (fond navy, texte centré) qui reçoivent une scène :
   le texte reste centré sur un écran étroit, se cale à gauche dès que la
   scène prend la colonne de droite. */
.hp-hero > .hero-scene { padding-bottom: 3rem; }
.hero-scene-copy { text-align: center; }
.hero-scene-copy .hero-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: .75rem; }
@media (min-width: 1024px) {
    .hero-scene-copy { text-align: left; }
    .hero-scene-copy > p { margin-left: 0; margin-right: 0; }
    .hero-scene-copy .hero-actions { justify-content: flex-start; }
}
@media (min-width: 1024px) {
    .hero-scene { grid-template-columns: minmax(0, 1.22fr) minmax(0, .78fr); }
    .hero-scene > .cmg-scene-wrap { max-width: none; margin: 0; }
    .hero-scene .site-h1 { font-size: clamp(2.1rem, 3.5vw, 3.3rem); }
}

@media (prefers-reduced-motion: reduce) {
    .cmg-ic svg [data-part], .cmg-ic::after, .cmg-scene-wrap svg > g, .cmg-scene-wrap svg [data-draw] {
        animation: none !important; transition: none !important;
    }
    .cmg-scene-wrap svg > g { translate: none !important; opacity: 1 !important; }
    .cmg-scene-wrap svg [data-draw] { stroke-dashoffset: 0 !important; }
}

/* =====================================================================
   5. Le lien vers l'estimateur de /pricing (<x-estimate-link>)
   ===================================================================== */
.est-cta {
    display: inline-flex; align-items: center; gap: .75rem;
    padding: .7rem .8rem .7rem 1rem; border-radius: 1rem;
    background: linear-gradient(120deg, #F0FAFF, #FFFFFF 70%);
    border: 1px solid #CFE6F3; color: #0A2540; text-align: left;
    transition: transform .35s cubic-bezier(.2, .75, .15, 1), box-shadow .35s ease, border-color .25s ease;
}
.est-cta:hover { transform: translateY(-2px); border-color: #7CC4E4; box-shadow: 0 18px 34px -24px rgba(3, 105, 161, .6); }
.est-cta:focus-visible { outline: 3px solid #0369A1; outline-offset: 3px; }
.est-cta-dark:focus-visible { outline-color: #22D3EE; }
.est-cta-text b { display: block; font-size: 15px; font-weight: 700; line-height: 1.3; }
.est-cta-text small { display: block; font-size: 12.5px; font-weight: 500; color: #47617A; }
.est-cta-go {
    flex: none; width: 2rem; height: 2rem; border-radius: 50%; display: grid; place-items: center;
    background: #0369A1; color: #FFFFFF; transition: transform .3s ease;
}
.est-cta:hover .est-cta-go { transform: translateX(3px); }
.est-cta-dark { background: rgba(255, 255, 255, .06); border-color: rgba(255, 255, 255, .18); color: #FFFFFF; }
.est-cta-dark:hover { border-color: rgba(125, 211, 252, .6); box-shadow: 0 18px 34px -24px rgba(0, 0, 0, .6); }
.est-cta-dark .est-cta-text small { color: #B9C9DA; }
.est-cta-dark .cmg-ic { color: #FFFFFF; --cmg-icon-accent: #22D3EE; }
.est-cta-dark .est-cta-go { background: #22D3EE; color: #06283F; }
@media (prefers-reduced-motion: reduce) { .est-cta, .est-cta-go { transition: none; } }
