/* DVC-Web — feuille de style du site public.
   Systeme visuel repris de la maquette de reference : Nunito Sans, rayon de
   40px sur les grandes surfaces, trois surfaces (blanc / #f5f5f5 / aplat
   d'accent), titres a interlignage inferieur a 1. L'accent est le bleu de la
   charte, pas l'orange de la reference.
   Les textes russes viennent de content/site.ru.json et ne sont pas modifies. */

/* ---------------------------- Reset minimal ---------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ul,
ol {
  margin: 0;
}

ul,
ol {
  padding: 0;
}

img,
picture,
svg,
video {
  max-width: 100%;
  display: block;
}

/* L'attribut `hidden` de l'UA perd contre n'importe quelle regle d'auteur qui
   pose `display` (.button, .cookie-banner...). On lui redonne la priorite. */
[hidden] {
  display: none !important;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: 0;
  cursor: pointer;
}

table {
  border-collapse: collapse;
}

:focus-visible {
  outline: 3px solid rgba(7, 91, 204, 0.45);
  outline-offset: 2px;
  border-radius: 6px;
}

/* Sur un aplat bleu l'anneau bleu disparait : double anneau blanc + encre. */
.button:focus-visible {
  outline: 2px solid #fff;
  outline-offset: -4px;
  box-shadow: 0 0 0 3px var(--ink);
}

.button.secondary:focus-visible {
  outline-color: var(--blue);
  box-shadow: 0 0 0 3px rgba(7, 91, 204, 0.35);
}



/* ------------------------------- Tokens -------------------------------- */
:root {
  --ink: #101828;
  --blue: #0b5fc4;
  --blue-deep: #062a5e;
  --blue-bright: #2a7fe8;
  --line: #e4e4e4;
  --muted: #5f6b7a;

  /* Echelle de rayons de la maquette de reference : 40 domine, 20 pour les
     elements imbriques, 16 pour les champs, gelule pour tout ce qui est cible. */
  --r-xl: 40px;
  --r-lg: 20px;
  --r-md: 16px;
  --r-sm: 12px;
  --r-pill: 999px;

  /* Trois surfaces, pas davantage : blanc, gris tres clair, aplat d'accent. */
  --surface: #f5f5f5;
  --surface-2: #ebebeb;

  --shadow-sm: 0 1px 2px rgb(16 24 40 / 0.04), 0 2px 8px rgb(16 24 40 / 0.04);
  --shadow-md: 0 2px 4px rgb(16 24 40 / 0.04), 0 14px 32px rgb(16 24 40 / 0.07);
  --shadow-lg: 0 4px 12px rgb(16 24 40 / 0.06), 0 28px 64px rgb(6 42 94 / 0.18);

  --image-ring: inset 0 0 0 1px rgb(0 0 0 / 0.1);
  --ease: cubic-bezier(0.2, 0, 0, 1);

  /* ---------------------- Echelle de mouvement -------------------------
     transitions.dev — vocabulaire partage. Seuls les blocs semantiques des
     transitions reellement posees sont repris ; le reste du fichier
     `_root.css` de la bibliotheque n'est pas recopie. */
  --duration-stagger: 40ms;
  --duration-micro: 80ms;
  --duration-quick: 150ms;
  --duration-fast: 250ms;
  --duration-medium: 350ms;
  --duration-slow: 400ms;
  --duration-very-slow: 500ms;

  --ease-smooth-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: ease-in-out;
  --ease-out: ease-out;
  --ease-linear: linear;
  --ease-bounce: cubic-bezier(0.34, 1.36, 0.64, 1);

  --distance-micro: 4px;
  --distance-small: 6px;
  --distance-base: 8px;
  --distance-medium: 12px;

  --scale-large: 0.96;
  --scale-medium: 0.97;
  --scale-tiny: 0.99;

  --blur-small: 2px;
  --blur-medium: 3px;

  /* Menu dropdown */
  --dropdown-open-dur: 250ms;
  --dropdown-close-dur: 150ms;
  --dropdown-pre-scale: 0.97;
  --dropdown-closing-scale: 0.99;
  --dropdown-ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* Modal open / close */
  --modal-open-dur: 250ms;
  --modal-close-dur: 150ms;
  --modal-scale: 0.96;
  --modal-scale-close: 0.96;
  --modal-ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* Panel reveal */
  --panel-open-dur: 400ms;
  --panel-close-dur: 350ms;
  --panel-translate-y: 100px;
  --panel-blur: 2px;
  --panel-ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* Text states swap */
  --text-swap-dur: 150ms;
  --text-swap-translate-y: 4px;
  --text-swap-blur: 2px;
  --text-swap-ease: ease-in-out;
  /* Error state shake */
  --shake-distance: 6px;
  --shake-overshoot: 4px;
  --shake-dur-a: 80ms;
  --shake-dur-b: 60ms;
  --shake-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --revert-dur: 280ms;
  /* Texts reveal */
  --stagger-dur: 500ms;
  --stagger-distance: 12px;
  --stagger-stagger: 40ms;
  --stagger-blur: 3px;
  --stagger-ease: cubic-bezier(0.22, 1, 0.36, 1);
  /* Accordion expand */
  --acc-expand: 250ms;
  --acc-collapse: 250ms;
  --acc-chevron: 250ms;
  --acc-ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Nunito Sans, variable 400-800, sous-ensembles latin et cyrillique.
   Licence SIL Open Font, auto-hebergee comme l'etait Inter. */
@font-face {
  font-family: "Nunito Sans";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/fonts/nunito-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308,
    U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Nunito Sans";
  font-style: normal;
  font-weight: 400 800;
  font-display: swap;
  src: url("/fonts/nunito-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

body {
  color: var(--ink);
  background: #fff;
  margin: 0;
  font-family: "Nunito Sans", Arial, sans-serif;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

a {
  color: inherit;
  text-decoration: none;
}

.container {
  width: min(1320px, 100% - 48px);
  margin: auto;
}

.narrow {
  max-width: 900px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--blue);
  color: #fff;
  padding: 12px 18px;
  border-radius: 0 0 var(--r-md) 0;
  z-index: 60;
}

.skip-link:focus {
  left: 0;
}

/* ---------------------------- Typographie ------------------------------ */
/* Interlignage inferieur a 1 sur les grands titres : c'est la signature
   typographique de la maquette de reference. */
h1 {
  margin: 0;
  font-size: clamp(38px, 6.2vw, 90px);
  font-weight: 600;
  line-height: 0.92;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

h2 {
  margin: 0 0 clamp(28px, 3vw, 44px);
  font-size: clamp(30px, 4.2vw, 60px);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.012em;
  text-wrap: balance;
}

h3 {
  font-size: 20px;
  font-weight: 700;
  line-height: 1.25;
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

.lead {
  color: var(--muted);
  max-width: 42ch;
  font-size: clamp(16px, 1.3vw, 18px);
  line-height: 1.55;
}

.section-intro {
  color: var(--muted);
  max-width: 70ch;
  line-height: 1.6;
  margin: -20px 0 clamp(28px, 3vw, 44px);
}

.badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  color: var(--blue);
  border-radius: var(--r-pill);
  padding: 9px 18px;
  margin-bottom: 20px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.badge::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: currentColor;
}

.section-soft .badge {
  background: #fff;
}

/* ------------------------------- En-tete ------------------------------- */
header {
  z-index: 20;
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  backdrop-filter: blur(18px) saturate(1.4);
  background: rgb(255 255 255 / 0.82);
  position: sticky;
  top: 0;
  padding: 10px 0;
}

/* Un seul rang. La navigation et le bloc d'actions sont pousses a droite d'un
   bloc : l'identite garde le bord gauche, et rien ne se recentre quand une
   entree de navigation disparait. */
.header-bar {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.4vw, 24px);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 12px;
}

.header-actions address {
  font-style: normal;
}

.header-tel {
  color: var(--blue);
  white-space: nowrap;
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 4px;
}

.logo {
  align-items: center;
  display: flex;
  flex: none;
}

.logo img {
  object-fit: contain;
  width: auto;
  height: 44px;
  display: block;
}

/* Navigation en pastilles bordees, poussee contre le bloc d'actions. */
nav {
  gap: 6px;
  display: flex;
  align-items: center;
  margin-left: auto;
}

nav a {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  font-size: 14px;
  transition:
    background-color 0.16s var(--ease),
    border-color 0.16s var(--ease),
    color 0.16s var(--ease);
}

nav a:hover {
  background: var(--surface);
  border-color: var(--surface-2);
  color: var(--blue);
}

/* Le script pose `.t-dropdown` sur la nav pour le menu deroulant. Au-dessus du
   point de bascule la nav n'est qu'une rangee : sans cette annulation elle
   resterait a `opacity: 0` et hors de portee du clic. */
#site-nav.t-dropdown {
  transform: none;
  opacity: 1;
  pointer-events: auto;
}

/* Rappel de l'action dans le menu deroulant : seulement la ou l'en-tete est
   trop etroit pour garder son bouton. */
.nav-cta {
  display: none;
}

.nav-toggle {
  display: none;
  width: 46px;
  height: 46px;
  border-radius: var(--r-pill);
  background: var(--surface);
  align-items: center;
  justify-content: center;
}

.nav-toggle span {
  position: relative;
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  transition: background 0.2s var(--ease);
}

.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--ink);
  transition: transform 0.2s var(--ease);
}

.nav-toggle span::before {
  top: -6px;
}

.nav-toggle span::after {
  top: 6px;
}

.nav-toggle[aria-expanded="true"] span {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] span::before {
  transform: translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span::after {
  transform: translateY(-6px) rotate(-45deg);
}

/* ------------------------------- Boutons ------------------------------- */
.button {
  background: var(--blue);
  color: #fff;
  cursor: pointer;
  border: 1px solid #0000;
  border-radius: var(--r-pill);
  justify-content: center;
  align-items: center;
  gap: 10px;
  padding: 15px 30px;
  min-height: 54px;
  font-size: 15px;
  font-weight: 700;
  transition:
    background-color 0.18s var(--ease),
    border-color 0.18s var(--ease),
    color 0.18s var(--ease),
    box-shadow 0.18s var(--ease),
    translate 0.18s var(--ease),
    scale 0.12s var(--ease);
  display: inline-flex;
}

/* Fleche de la maquette de reference : un pseudo-element, pas une image. */
.button::after {
  content: "";
  width: 14px;
  height: 8px;
  flex: 0 0 auto;
  background: currentColor;
  clip-path: polygon(0 38%, 62% 38%, 62% 0, 100% 50%, 62% 100%, 62% 62%, 0 62%);
  transition: translate 0.18s var(--ease);
}

.button.compact::after,
.cookie-actions .button::after,
.form-actions .button::after,
.contact-tile::after {
  display: none;
}

.button:hover {
  background: #0951a8;
  box-shadow: var(--shadow-md);
}

.button:hover::after {
  translate: 3px 0;
}

.button:active {
  scale: 0.96;
}

.button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  scale: 1;
  box-shadow: none;
}

.button.secondary {
  color: var(--ink);
  background: #fff;
  border-color: var(--line);
}

.button.secondary:hover {
  background: var(--surface);
  border-color: var(--surface-2);
}

.button.invert {
  background: #fff;
  color: var(--blue-deep);
}

.button.invert:hover {
  background: #e8f0fb;
}

.button.ghost {
  background: rgb(255 255 255 / 0.12);
  color: #fff;
  border-color: rgb(255 255 255 / 0.34);
  font-variant-numeric: tabular-nums;
}

.button.ghost:hover {
  background: rgb(255 255 255 / 0.2);
  border-color: rgb(255 255 255 / 0.5);
}

.button.compact {
  padding: 11px 22px;
  min-height: 44px;
  font-size: 14px;
}

.button.wide {
  width: 100%;
}

/* -------------------------------- Promo -------------------------------- */
.promo {
  padding: clamp(32px, 4vw, 56px) 0 0;
  overflow: hidden;
}

.promo-head {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  align-items: end;
  gap: clamp(32px, 4vw, 72px);
  padding-bottom: clamp(36px, 4vw, 64px);
}

/* L'accroche est aussi une ligne du stagger, qui pose `display: block` : la
   pastille doit rester a la largeur de son texte. */
.promo-eyebrow.t-stagger-line {
  display: inline-flex;
}

.promo-aside {
  display: flex;
  flex-direction: column;
  gap: 26px;
  padding-bottom: 4px;
}

/* Les deux boutons restent sur une ligne : la colonne `1fr` de .promo-head a
   un minimum `auto` (min-content), elle s'elargit donc d'elle-meme a la largeur
   des deux boutons et le titre cede la place. Sous 620px ils passent en pile. */
.actions {
  gap: 12px;
  flex-wrap: nowrap;
  display: flex;
}

/* Le bloc est aussi une ligne du stagger (`display: block`, declare plus bas) :
   sans cette regle les boutons redeviennent des inline-flex qui se replient. */
.actions.t-stagger-line {
  display: flex;
}

.actions .button {
  white-space: nowrap;
}

/* Triptyque : trois photos hautes a grand rayon, avec la forme d'accent qui
   deborde par la gauche comme sur la maquette de reference. */
.promo-strip {
  position: relative;
  padding-bottom: clamp(48px, 6vw, 88px);
}

/* Bandeaux d'accent qui debordent des deux bords. Pseudo-elements : pas de
   noeud vide dans le balisage. */
.promo-strip > .container {
  position: relative;
  z-index: 1;
}

.promo-strip::before,
.promo-strip::after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 8%;
  bottom: 26%;
  width: min(6vw, 74px);
  background: var(--blue);
}

.promo-strip::before {
  left: 0;
  border-radius: 0 var(--r-xl) var(--r-xl) 0;
}

.promo-strip::after {
  right: 0;
  border-radius: var(--r-xl) 0 0 var(--r-xl);
}

/* Etat de repli, sans animation : les trois premieres photos en grille. C'est
   aussi ce que voit un visiteur qui demande moins de mouvement. */
.promo-gallery {
  --gap: 20px;
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap);
}

.promo-slide:nth-child(n + 4) {
  display: none;
}

.promo-slide {
  margin: 0;
  border-radius: var(--r-xl);
  overflow: hidden;
  position: relative;
  aspect-ratio: 3 / 4;
}

.promo-slide::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: var(--image-ring);
  pointer-events: none;
}

.promo-slide picture,
.promo-slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Bouton pose par le script sur chaque vignette : sans JavaScript il n'existe
   pas, donc aucune commande morte. */
.promo-open {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  background: #0000;
  transition: background-color 0.2s var(--ease);
}

.promo-open::after {
  content: "";
  position: absolute;
  inset: auto 16px 16px auto;
  width: 40px;
  height: 40px;
  border-radius: var(--r-pill);
  background: rgb(255 255 255 / 0.92) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%230b5fc4' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E") center / 18px no-repeat;
  opacity: 0;
  scale: 0.8;
  transition:
    opacity 0.2s var(--ease),
    scale 0.2s var(--ease);
}

.promo-open:hover {
  background: rgb(6 20 42 / 0.18);
}

.promo-open:hover::after,
.promo-open:focus-visible::after {
  opacity: 1;
  scale: 1;
}

/* ------------------------- Repere de position -------------------------- */
/* Sans carrousel il n'y a pas de position a indiquer : le repere n'apparait
   qu'avec le script, qui seul fait defiler les photos. */
.promo-dots {
  display: none;
  justify-content: center;
  align-items: center;
  gap: 12px;
  margin-top: 22px;
}

.promo-strip.is-js .promo-dots {
  display: flex;
}

/* Pilule grise, dans le gris des autres pastilles du site (badge, nav), a la
   maniere des lecteurs d'Apple : le repere actif s'etire en barre et se remplit
   d'encre au rythme de sa vignette. */
.promo-dots-pill {
  display: flex;
  align-items: center;
  height: 40px;
  padding: 0 8px;
  border-radius: var(--r-pill);
  background: var(--surface-2);
}

/* Le repere est fait de deux pseudo-elements : la piste (::before, dans le
   flux, centree) et le remplissage (::after, absolu, cale sur le bord gauche de
   la piste). La boite qui les porte reste une cible de 40px de haut. */
.promo-dot {
  /* Le script pose `--on` (0 au repos, 1 au centre) et `--fill` (avancee du
     palier). La piste s'etire donc entre le point et la barre, et le
     remplissage la suit : une seule source, la position du carrousel. */
  --w: calc(7px + var(--on, 0) * 29px);
  position: relative;
  height: 40px;
  padding: 0 8px;
  border: 0;
  background: none;
  color: var(--ink);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.promo-dot::before {
  content: "";
  display: block;
  width: var(--w);
  height: 7px;
  border-radius: var(--r-pill);
  background: rgb(16 24 40 / 0.3);
  transition: background-color 0.3s var(--ease);
}

.promo-dot::after {
  content: "";
  position: absolute;
  top: 50%;
  left: calc(50% - var(--w) / 2);
  width: calc(var(--w) * var(--fill, 0));
  height: 7px;
  border-radius: var(--r-pill);
  background: currentColor;
  translate: 0 -50%;
}

.promo-dot:hover::before {
  background: rgb(16 24 40 / 0.5);
}

/* L'anneau reste dans la pilule, qui a la meme hauteur que le bouton. */
.promo-dot:focus-visible {
  outline-offset: -4px;
}

/* Bouton pause : un disque du meme gris a cote de la pilule. L'icone lecture
   prend le relais quand `aria-pressed` est vrai. */
.promo-pause {
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 0.18s var(--ease);
}

.promo-pause:hover {
  background: color-mix(in srgb, var(--surface-2) 90%, var(--ink));
}

.promo-pause svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
}

.promo-pause .promo-play-icon,
.promo-pause[aria-pressed="true"] .promo-pause-icon {
  display: none;
}

.promo-pause[aria-pressed="true"] .promo-play-icon {
  display: block;
  /* Le triangle parait decale a gauche s'il est centre geometriquement. */
  translate: 1px 0;
}

/* Carrousel tenu par le script : il pose `--x`, `--s`, `--o` et `--z` sur
   chaque vignette a chaque image. Sans script, ou en mouvement reduit, la
   grille de trois photos ci-dessus reste en place et rien de ceci ne
   s'applique — c'est `.is-js` qui bascule d'une mise en page a l'autre. */
.promo-strip.is-js .promo-gallery {
  /* Les trois grandes gardent la largeur du triptyque d'origine : 32,3 % du
     conteneur, soit 427px pour 1320, gouttiere de 20px comprise. Il ne reste
     donc que la marge de page pour les reduites, qui passent DERRIERE les
     grandes et sont rognees par le bord de l'ecran. Elles s'ouvrent d'autant
     plus que l'ecran est large. */
  --slide: 32.3%;
  display: block;
  height: 0;
  /* Un padding en pourcentage se calcule sur la LARGEUR du parent : c'est ce
     qui donne au conteneur la hauteur d'une vignette sans la coder en dur. */
  padding-bottom: calc(var(--slide) * 4 / 3);
  /* Le geste horizontal revient au carrousel, le vertical reste a la page. */
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
}

.promo-strip.is-js .promo-gallery:active {
  cursor: grabbing;
}

.promo-strip.is-js .promo-slide,
.promo-strip.is-js .promo-slide:nth-child(n + 4) {
  display: block;
  position: absolute;
  top: 0;
  left: 50%;
  width: var(--slide);
  /* Les decalages sont en pourcentage de la vignette elle-meme : changer
     `--slide` suffit a adapter toute la mise en page. */
  translate: calc(-50% + var(--x, 0%)) 0;
  scale: var(--s, 1);
  opacity: var(--o, 1);
  z-index: var(--z, 0);
}

/* ------------------------------ Sections ------------------------------- */
[id] {
  scroll-margin-top: 120px;
}

.section {
  padding: clamp(52px, 6vw, 96px) 0;
}

.section-soft {
  background: var(--surface);
}

/* ------------------------------ A propos ------------------------------- */
.about-grid {
  display: grid;
  grid-template-columns: 1fr 1.15fr;
  /* Gouttiere large : les chiffres respirent a distance de la carte d'accent. */
  gap: clamp(32px, 5vw, 72px);
  align-items: stretch;
}

.panel {
  background: var(--surface);
  border-radius: var(--r-xl);
  padding: clamp(24px, 2.4vw, 40px);
}

.panel b {
  display: block;
  font-size: clamp(19px, 1.8vw, 26px);
  line-height: 1.25;
}

.panel p {
  color: var(--muted);
  line-height: 1.6;
  margin-top: 14px;
}

.panel-accent {
  background: linear-gradient(150deg, var(--blue-deep), #0b5fc4);
  color: #fff;
  box-shadow: var(--shadow-lg);
}

.panel-accent p {
  color: #fff;
  opacity: 0.9;
}

/* Lien de telechargement du КП, sous le texte du panneau. */
.panel-accent .button {
  margin-top: 22px;
}

/* Format et poids du document, en retrait du libelle. */
.button small {
  font-size: 0.86em;
  font-weight: 500;
  opacity: 0.8;
}

.stat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px 32px;
  /* Centres sur la hauteur de la carte, pas colles a son bord haut. */
  align-content: center;
}

.stat b {
  display: block;
  font-size: clamp(28px, 3vw, 44px);
  font-weight: 700;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.stat span {
  display: block;
  color: var(--muted);
  margin-top: 6px;
  font-size: 15px;
  line-height: 1.4;
}

/* Sous-titre du second rang de la section : les cinq avantages. */
.about-sub {
  font-size: clamp(20px, 2vw, 30px);
  margin: clamp(40px, 4vw, 64px) 0 20px;
}

/* ------------------------------- Services ------------------------------ */
/* Cinq cartes sur un rang, comme la maquette : numero et pictogramme en tete,
   titre au pied. Les hauteurs s'egalisent par la grille, sans hauteur forcee. */
.service-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 20px;
}

.service-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.service-num {
  color: var(--blue);
  font-size: 15px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  opacity: 0.6;
}

.service {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  padding: 26px 28px;
  min-height: 148px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.service .icon {
  color: var(--blue);
  width: 40px;
  height: 40px;
}

.service b {
  font-size: 17px;
  line-height: 1.3;
  margin-top: auto;
  text-wrap: balance;
}

/* Survol de la carte : un cran de gris sur le fond, et le numero qui passe de
   son bleu delave au bleu plein. Le pictogramme ne bouge pas.

   Plusieurs mouvements y ont ete essayes — bond, ressort echantillonne, puis
   pieces animees une a une a la maniere de Lottie — aucun ne convainquait a
   cette taille. Un pictogramme de 40px n'a pas la place de raconter quoi que ce
   soit ; ce qui marche a la taille d'une illustration se lit ici comme un
   tremblement. Ne pas y revenir sans changer d'abord l'echelle du dessin.

   `hover: hover` ecarte le tactile, ou l'etat de survol reste colle apres la
   pression. */
@media (hover: hover) {
  .service {
    transition:
      background-color var(--duration-fast) var(--ease),
      border-color var(--duration-fast) var(--ease);
  }

  .service-num {
    transition: opacity var(--duration-fast) var(--ease);
  }

  .service:hover {
    background: var(--surface);
    border-color: var(--surface-2);
  }

  /* Le numero passe de son gris d'attente au bleu plein. */
  .service:hover .service-num {
    opacity: 1;
  }
}

/* -------------------------------- Brief -------------------------------- */
/* Photo et formulaire reunis dans un seul conteneur a grand rayon. */
.brief-shell {
  display: grid;
  grid-template-columns: 1fr 1.05fr;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--surface);
}

.brief-photo {
  margin: 0;
  position: relative;
  min-height: 100%;
}

.brief-photo picture,
.brief-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.brief-form {
  padding: clamp(20px, 2.2vw, 36px);
}

/* Page /brief : le brief complet seul, sur fond blanc. La carte garde son
   blanc, un filet fin remplace l'ombre portee que le bloc gris justifiait. */
.brief-page {
  max-width: 960px;
}

/* Titre de page au gabarit des h2 de section : `.section-intro` remonte de 20px
   et compte sur cette marge basse. */
.page-title {
  margin: 0 0 clamp(28px, 3vw, 44px);
  font-size: clamp(30px, 4vw, 52px);
  font-weight: 700;
  line-height: 1;
}

.brief-page .form-card {
  border: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
  padding: clamp(20px, 3vw, 40px);
}

/* ------------------------------ Avantages ------------------------------ */
.advantage-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 20px;
  align-items: stretch;
}

.advantage-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  align-content: start;
}

.advantage-cards .panel {
  background: #fff;
  border: 1px solid var(--line);
}

.advantage-cards .panel:first-child {
  grid-column: 1 / -1;
}

.advantage-photo {
  margin: 0;
  border-radius: var(--r-xl);
  overflow: hidden;
  position: relative;
  min-height: 0;
  height: 100%;
}

.advantage-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: var(--image-ring);
  pointer-events: none;
  z-index: 1;
}

.advantage-photo picture,
.advantage-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ------------------------------ Directions ----------------------------- */
.industry-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.industry {
  border-radius: var(--r-xl);
  overflow: hidden;
  position: relative;
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: flex-end;
}

.industry picture,
.industry img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Voile sombre : sans lui le libelle blanc devient illisible sur les photos
   claires. Contraste verifie sur les six visuels. */
.industry::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgb(6 20 42 / 0.82) 0%, rgb(6 20 42 / 0.15) 55%, #0000 100%);
}

.industry b {
  position: relative;
  z-index: 1;
  color: #fff;
  padding: 24px 26px;
  font-size: 17px;
  line-height: 1.3;
  text-wrap: balance;
}

.chips {
  flex-wrap: wrap;
  gap: 12px;
  display: flex;
}

.chips span {
  background: var(--surface);
  border-radius: var(--r-pill);
  padding: 16px 24px;
  font-size: 16px;
  font-weight: 600;
  align-items: center;
  gap: 12px;
  display: inline-flex;
}

.chips span::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill);
  background: var(--blue);
}

/* -------------------------------- Etapes ------------------------------- */
.process {
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  padding: 0;
  list-style: none;
  display: grid;
}

.process li {
  background: #fff;
  border-radius: var(--r-xl);
  padding: 26px 28px;
  min-height: 150px;
  gap: 14px;
  flex-direction: column;
  align-items: flex-start;
  display: flex;
}

.process span {
  color: var(--blue);
  font-size: 34px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  opacity: 0.36;
}

.process b {
  font-size: 17px;
  line-height: 1.3;
  margin-top: auto;
  text-wrap: balance;
}

/* Survol de l'etape : le numero passe de son bleu delave au bleu plein. Rien
   d'autre ne bouge — la carte est blanche sur le gris de la section, la teinter
   comme celles des services l'effacerait de son fond. */
@media (hover: hover) {
  .process span {
    transition: opacity var(--duration-fast) var(--ease);
  }

  .process li:hover span {
    opacity: 1;
  }
}

/* ------------------------------ Formulaire ----------------------------- */
/* Carte blanche posee dans le bloc gris du brief : 28 (interne) + 44 (padding
   du bloc) depasse 40, on garde donc un cran net entre les deux rayons. */
.form-card {
  background: #fff;
  border-radius: var(--r-lg);
  padding: clamp(20px, 2.2vw, 32px);
  box-shadow: var(--shadow-md);
}

.progress {
  color: var(--muted);
  margin-bottom: 28px;
  padding-top: 13px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  position: relative;
}

.progress::before,
.progress > div {
  content: "";
  border-radius: 5px;
  height: 5px;
  position: absolute;
  top: 0;
  left: 0;
}

.progress::before {
  background: var(--surface-2);
  right: 0;
}

.progress > div {
  background: linear-gradient(90deg, #075bcc, #27a4e6);
  transition: width 0.3s var(--ease);
}

.fields {
  grid-template-columns: 1fr 1fr;
  gap: 17px;
  display: grid;
}

/* Libelle flottant : a vide il occupe le champ, comme un texte indicatif ;
   des la mise au point ou la premiere lettre il se retire en haut a gauche et
   retrecit. Le champ garde son aplat, son rayon et sa hauteur — rien ne bouge
   sous le curseur, seul le libelle se deplace. */
.fields label {
  position: relative;
  display: block;
  /* Hauteur du libelle au repos, mesuree depuis le haut du champ. */
  --label-rest: 28px;
  --label-lift: 12px;
}

.fields label:has(textarea) {
  --label-rest: 30px;
  --label-lift: 14px;
}

.fields label > span {
  position: absolute;
  top: var(--label-rest);
  left: 17px;
  right: 17px;
  color: var(--muted);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transform: translateY(-50%);
  transform-origin: 0 50%;
  pointer-events: none;
  transition:
    transform var(--duration-quick, 0.18s) var(--ease),
    color var(--duration-quick, 0.18s) var(--ease);
}

/* Un champ date affiche toujours son gabarit : son libelle reste en haut. */
.fields label:focus-within > span,
.fields label:has(input:not(:placeholder-shown)) > span,
.fields label:has(textarea:not(:placeholder-shown)) > span,
.fields label:has(input[type="date"]) > span {
  transform: translateY(calc(-50% - var(--label-lift))) scale(0.75);
}

/* Le gabarit attendu (le format du telephone) ne parait qu'une fois le champ
   actif : a vide, la place est au libelle. */
.fields input::placeholder,
.fields textarea::placeholder {
  color: var(--muted);
  opacity: 0;
  transition: opacity 0.15s var(--ease);
}

.fields input:focus::placeholder,
.fields textarea:focus::placeholder {
  opacity: 1;
}

/* Le haut du champ est reserve au libelle retreci. */
.fields input,
.fields textarea {
  min-height: 56px;
  padding: 24px 16px 8px;
  border-radius: var(--r-md);
  font-size: 16px;
}

.fields textarea {
  padding-top: 26px;
  min-height: 104px;
}

.fields .wide {
  grid-column: 1 / -1;
}

fieldset {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0;
}

/* Le padding en ligne de l'UA decalait la legende par rapport aux champs. */
legend {
  padding: 0;
}

fieldset + fieldset {
  margin-top: 28px;
}

.step-title {
  font-size: 15px;
  font-weight: 700;
  margin-bottom: 16px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Un seul aplat, ni liseré ni anneau : le fond ne change pas au survol ni a la
   mise au point. Le champ actif se signale par le curseur et par son libelle
   retreci — un ecran qui ne clignote pas quand on passe d'un champ a l'autre. */
input,
textarea,
select {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 0;
  border-radius: var(--r-sm);
  outline: none;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
  padding: 14px 16px;
}

input:focus,
input:focus-visible,
input:active,
textarea:focus,
textarea:focus-visible,
textarea:active,
select:focus,
select:focus-visible,
select:active,
.fields input:focus,
.fields input:focus-visible,
.fields input:active,
.fields textarea:focus,
.fields textarea:focus-visible,
.fields textarea:active {
  outline: none;
  box-shadow: none;
  border: 0;
}

textarea {
  resize: vertical;
  min-height: 100px;
}

.form-actions {
  justify-content: flex-end;
  gap: 10px;
  margin-top: 26px;
  display: flex;
}

.review section {
  border-bottom: 1px solid rgb(10 24 48 / 0.1);
  padding: 4px 0 18px;
  position: relative;
}

.review section button {
  color: var(--blue);
  cursor: pointer;
  background: 0 0;
  border: 0;
  position: absolute;
  top: 0;
  right: 0;
  padding: 10px 0 10px 12px;
  min-height: 40px;
}

.review h3 {
  font-size: 17px;
}

.review p {
  grid-template-columns: 1fr 1fr;
  gap: 15px;
  font-size: 13px;
  display: grid;
}

.review p b {
  color: var(--muted);
}

.consent {
  gap: 12px;
  margin-top: 22px;
  font-size: 13px;
  line-height: 1.5;
  display: flex;
}

/* La case native est remplacee par un carre dessine : meme rayon que les
   champs, meme bleu que le bouton une fois cochee. Le crochet est un angle
   droit incline, pose par un `::after` — pas d'image, pas de script.

   Trois etats se lisent au doigt comme a la souris : survol (le liseré prend
   l'accent), enfoncement (la case se tasse), coche (le carre se remplit et le
   crochet se deploie). Le mouvement est annule par la garde
   `prefers-reduced-motion` en fin de fichier. */
.consent input {
  appearance: none;
  width: 20px;
  height: 20px;
  min-height: 0;
  /* Les champs du formulaire portent une garniture ; une case n'en a pas. */
  padding: 0;
  flex: 0 0 auto;
  margin: 1px 0 0;
  position: relative;
  cursor: pointer;
  background: #fff;
  border: 1.5px solid #cfd4dc;
  border-radius: 6px;
  transition:
    background-color var(--duration-quick) var(--ease),
    border-color var(--duration-quick) var(--ease),
    box-shadow var(--duration-quick) var(--ease),
    scale var(--duration-micro) var(--ease);
}

.consent input:hover {
  border-color: var(--blue);
  box-shadow: 0 0 0 4px rgb(11 95 196 / 0.08);
}

.consent input:active {
  scale: 0.9;
}

.consent input:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

.consent input:checked {
  background: var(--blue);
  border-color: var(--blue);
  animation: consent-pop var(--duration-fast) var(--ease-bounce);
}

/* Le crochet : deux cotes d'un carre, tournes d'un huitieme de tour. Il est
   toujours dans le DOM, replie et transparent ; le cochage le deploie. */
.consent input::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 5px;
  height: 10px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  rotate: 45deg;
  scale: 0.3;
  opacity: 0;
  transition:
    scale var(--duration-fast) var(--ease-bounce),
    opacity var(--duration-micro) var(--ease);
}

.consent input:checked::after {
  scale: 1;
  opacity: 1;
}

@keyframes consent-pop {
  0% {
    scale: 1;
  }

  45% {
    scale: 0.86;
  }

  100% {
    scale: 1;
  }
}

.consent a {
  color: var(--blue);
  text-decoration: underline;
}

.honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.error {
  color: #b42318;
  background: #fff2f0;
  border-radius: var(--r-sm);
  padding: 14px 16px;
  margin-top: 16px;
  line-height: 1.5;
}

.success {
  text-align: center;
  padding: clamp(40px, 6vw, 72px) 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.success > span {
  color: var(--blue);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.success h3 {
  font-size: clamp(20px, 2.2vw, 26px);
  font-variant-numeric: tabular-nums;
}

.success p {
  color: var(--muted);
  line-height: 1.6;
  max-width: 42ch;
  margin: 0;
}

.success p:last-child {
  margin-top: 10px;
}



/* --------------------------------- FAQ --------------------------------- */
.faq details {
  border-top: 1px solid var(--line);
}

.faq summary {
  cursor: pointer;
  font-size: clamp(17px, 1.5vw, 20px);
  font-weight: 700;
  padding: 24px 0;
  gap: 24px;
  align-items: center;
  justify-content: space-between;
  display: flex;
  transition: color 0.15s var(--ease);
}

.faq .t-acc-chevron {
  flex: 0 0 auto;
  color: var(--blue);
}

.faq summary:hover {
  color: var(--blue);
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::marker {
  content: "";
}

.faq p {
  color: var(--muted);
  line-height: 1.7;
  margin: 0 0 24px;
  max-width: 70ch;
}

.legal-note {
  background: var(--surface);
  color: var(--muted);
  border-radius: var(--r-lg);
  padding: 24px 28px;
  margin-top: 32px;
  line-height: 1.6;
}

/* ------------------------------- Contacts ------------------------------- */
.contacts-card {
  background: linear-gradient(140deg, var(--blue-deep) 0%, #0b5fc4 100%);
  color: #fff;
  border-radius: var(--r-xl);
  padding: clamp(28px, 3.4vw, 56px);
  gap: clamp(28px, 3vw, 56px);
  grid-template-columns: 0.8fr 1.2fr;
  align-items: center;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  display: grid;
}

/* Courbes de niveau, a la maniere d'une carte topographique : un champ lisse
   echantillonne hors ligne puis fige en chemins SVG, une teinte pour les
   courbes ordinaires, une plus marquee toutes les cinq. Le motif tient dans la
   feuille de style, aucun fichier a charger. */
.contacts-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 420' preserveAspectRatio='xMidYMid slice'%3E%3Cg fill='none' stroke='%23fff' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath stroke-opacity='.05' stroke-width='1.2' d='M1112 0L1160 18L1200 44M1055 0L1103 12L1144 27L1176 45L1200 65M1002 0L1087 22L1128 36L1168 58L1200 86M932 0L974 17L1079 46L1120 61L1144 74L1166 92L1200 132M906 0L958 24L1079 58L1119 75L1144 90L1163 107L1182 130L1200 159M882 0L950 33L1071 68L1119 90L1144 107L1166 130L1184 156L1200 188M859 0L899 23L934 39L1071 81L1119 104L1144 124L1167 153L1185 183L1200 221M815 0L862 29L902 50L950 68L1055 99L1087 113L1113 130L1143 160L1166 199L1186 252L1200 306M0 376L32 401L71 420M574 420L620 395L652 389L685 396L724 420M41 0L20 23L0 56M360 0L403 8L435 10L467 7L492 0M792 0L846 34L886 55L934 75L1063 115L1095 132L1120 153L1139 176L1157 206L1172 244L1184 283L1191 321L1194 359L1193 389L1187 420M0 348L16 367L40 387L71 405L107 420M554 420L612 381L636 372L652 371L668 373L693 382L744 420M58 0L24 37L0 84M324 0L387 17L435 22L475 18L527 0M768 0L870 61L926 84L1051 122L1087 141L1111 162L1130 183L1147 214L1163 252L1174 290L1183 359L1181 389L1175 420M0 314L18 344L49 374L86 397L138 420M536 420L604 367L628 356L652 352L677 357L701 369L762 420M78 0L56 17L32 46L12 84L0 123M291 0L387 28L443 35L491 28L558 0M742 0L862 71L918 93L1039 130L1071 145L1103 171L1120 191L1138 221L1163 290L1170 328L1172 359L1170 389L1163 420M0 266L17 313L32 336L48 354L97 388L166 420M520 420L604 348L628 336L652 332L677 337L701 349L733 375L778 420M150 0L118 8L89 22L64 43L45 69L28 107L20 145L17 183L21 229L27 260L39 290L53 313L72 336L122 374L214 420M202 0L266 13L395 52L451 60L483 58L507 53L588 18L620 8L652 4L677 7L725 24L805 72L854 96L1033 153L1063 169L1089 191L1112 221L1130 260L1144 305L1149 344L1147 382L1137 420M487 420L523 389L580 327L604 305L628 292L652 288L677 293L709 312L809 420M237 420L144 374L89 333L65 305L52 283L40 252L33 221L29 176L33 137L44 99L60 69L81 44L113 23L145 13L177 9L242 17L395 63L459 74L491 72L515 67L588 35L620 25L644 21L671 23L717 38L797 86L838 105L1023 161L1055 179L1079 199L1102 229L1121 267L1134 313L1138 351L1134 389L1124 420M470 420L516 382L596 287L620 269L636 264L652 262L685 271L709 287L825 420M260 420L209 398L165 374L130 351L105 330L82 305L67 283L54 252L46 221L42 183L45 145L54 107L70 76L90 53L121 33L153 23L185 21L250 30L403 77L443 86L475 89L507 87L532 81L620 44L644 41L668 42L709 56L781 98L821 116L974 157L1015 171L1047 188L1071 209L1093 237L1111 275L1122 313L1126 351L1121 389L1109 420M452 420L483 399L509 374L596 257L620 240L652 233L685 241L717 266L798 374L840 420M286 420L246 405L201 383L161 359L130 336L106 313L88 290L72 260L62 229L56 191L57 153L66 115L81 85L102 61L125 46L153 36L185 33L250 40L419 94L491 107L540 103L628 68L668 68L695 76L757 113L789 127L830 138L950 163L1007 181L1039 199L1065 221L1087 252L1101 283L1111 321L1113 359L1108 389L1094 420M430 420L470 397L508 359L534 321L576 244L596 218L620 203L652 198L685 205L701 214L717 228L741 260L801 359L830 394L857 420M895 420L858 389L823 344L798 290L787 244L789 214L797 200L805 193L830 184L870 180L926 185L983 200L1023 220L1055 251L1070 275L1079 298L1087 344L1085 367L1079 386L1070 405L1057 420M169 60L143 69L120 84L101 107L88 137L83 168L85 206L96 244L111 275L135 305L161 330L200 359L242 383L282 400L322 411L354 415L387 413L419 404L451 386L480 359L502 328L522 283L532 237L532 199L523 176L507 159L475 142L314 82L234 60L201 57L177 59M922 420L885 397L849 359L827 321L814 275L814 244L820 229L830 217L854 204L894 199L942 203L991 219L1029 244L1054 275L1064 298L1070 321L1071 359L1064 382L1056 397L1031 420M169 75L145 85L121 106L107 130L100 153L98 183L102 214L111 244L129 276L153 305L187 336L219 359L262 382L298 396L330 404L362 406L395 402L427 389L451 373L473 351L492 321L507 283L513 244L511 214L499 187L482 168L451 149L330 99L282 83L242 74L209 71L177 73M177 90L155 99L137 115L122 137L116 160L114 191L119 221L129 247L145 275L169 304L196 328L227 351L268 374L306 388L338 395L370 395L395 391L419 382L443 366L464 344L482 313L492 283L496 252L492 221L482 199L467 180L441 160L397 137L340 115L290 98L250 88L217 85L185 87M886 220L870 224L854 234L845 244L838 260L836 275L839 298L853 336L878 371L910 398L950 415L991 417L1023 405L1039 390L1049 374L1054 359L1056 336L1052 313L1044 290L1022 260L1004 244L983 232L942 220L894 218M185 105L165 115L149 130L139 145L132 168L131 191L136 221L145 245L163 275L189 305L215 328L274 365L298 375L330 384L362 385L387 382L411 373L435 357L455 336L468 313L476 290L480 260L476 229L465 206L446 183L425 168L395 151L346 129L298 113L258 103L226 100L193 103M894 242L878 251L870 259L861 283L864 313L878 344L902 372L928 389L958 399L991 398L1007 391L1019 382L1033 359L1036 328L1031 305L1023 290L1004 267L974 248L934 238L902 240M217 137L201 143L188 153L177 168L172 183L171 199L174 221L182 244L195 267L234 311L281 344L330 361L370 361L395 353L411 344L427 328L441 305L447 283L448 260L443 238L435 221L423 206L403 188L346 157L282 137L250 133L226 135M942 309L938 313L938 321L942 328L950 334L958 335L966 329L967 321L962 313L950 307M258 153L242 154L222 160L210 168L201 179L194 206L203 244L227 283L266 319L306 340L346 349L370 346L387 341L413 321L423 305L430 283L430 260L426 244L407 214L370 185L314 162L265 153M266 175L240 183L226 200L222 214L223 229L234 260L257 290L290 316L322 329L354 332L370 329L386 321L403 303L411 275L405 244L387 219L354 196L314 180L274 175M274 205L262 214L255 229L259 252L272 275L290 292L313 305L338 311L354 310L376 298L385 283L386 267L378 244L362 226L338 211L306 202L282 203'/%3E%3Cpath stroke-opacity='.1' stroke-width='2' d='M963 0L1087 35L1128 50L1168 75L1200 108M837 0L878 25L918 44L964 61L1063 90L1113 115L1139 137L1163 168L1182 206L1200 258M600 420L628 409L652 407L677 411L697 420M104 0L81 13L56 34L36 61L21 92L10 130L5 168L6 214L11 252L20 283L31 305L46 328L64 348L111 382L191 420M256 0L387 39L419 45L451 47L483 44L507 37L593 0M708 0L741 15L813 60L854 81L902 100L1031 139L1063 155L1091 176L1111 199L1125 221L1139 252L1152 291L1159 328L1161 359L1158 389L1150 420M503 420L604 328L628 315L652 311L677 316L709 335L794 420M320 420L282 410L242 393L201 372L159 344L129 318L105 290L91 267L78 237L70 199L69 160L75 130L88 99L106 76L129 60L161 48L193 45L234 48L274 58L435 111L556 142L574 153L576 160L573 176L546 260L528 305L511 336L488 367L463 389L435 407L399 420M875 420L835 382L802 336L775 283L747 206L742 183L745 168L761 160L797 158L878 164L958 178L1007 195L1047 222L1067 244L1081 267L1091 290L1098 321L1100 351L1098 374L1090 397L1077 420M201 120L185 126L169 138L159 153L151 176L150 199L154 221L166 252L181 275L225 321L274 353L306 367L330 373L354 375L379 372L403 364L423 351L438 336L453 313L461 290L464 260L460 237L450 214L435 195L411 176L346 143L306 129L266 119L234 116L209 118M910 267L894 281L889 298L892 321L902 342L918 359L942 373L966 378L983 375L999 366L1009 351L1013 328L1006 305L991 285L966 269L942 263L918 264'/%3E%3C/g%3E%3C/svg%3E") center / cover no-repeat;
  pointer-events: none;
}

.contacts-head {
  position: relative;
  z-index: 1;
}

.contacts-head h2 {
  margin-bottom: 0;
}

.contacts-list {
  position: relative;
  z-index: 1;
  display: grid;
  gap: 14px;
}

/* Tuiles translucides sur l'aplat, rayon d'un cran sous celui de la carte. */
.contact-tile {
  background: rgb(255 255 255 / 0.12);
  border: 1px solid rgb(255 255 255 / 0.22);
  border-radius: var(--r-lg);
  padding: 18px 24px;
  color: #fff;
  text-align: left;
  cursor: pointer;
  display: block;
  width: 100%;
  transition:
    background-color 0.16s var(--ease),
    border-color 0.16s var(--ease);
}

.contact-tile:hover {
  background: rgb(255 255 255 / 0.2);
  border-color: rgb(255 255 255 / 0.4);
}

.contact-tile small {
  display: block;
  color: #fff;
  font-size: 13px;
  letter-spacing: 0.04em;
}

.contact-tile b {
  display: block;
  margin-top: 4px;
  font-size: clamp(18px, 1.8vw, 24px);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* -------------------------------- Footer ------------------------------- */
footer {
  color: var(--ink);
  background: var(--surface);
  padding: clamp(48px, 5vw, 72px) 0 24px;
}

.footer-grid {
  grid-template-columns: 1.5fr 1fr 1fr;
  gap: clamp(28px, 4vw, 56px);
  display: grid;
}

.footer-grid > div {
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  display: flex;
}

.footer-brand p {
  color: var(--muted);
  font-size: 15px;
  max-width: 30ch;
  padding: 12px 0 4px;
}

.footer-brand .logo img {
  height: 58px;
}

.footer-col b {
  font-size: 16px;
  padding-bottom: 10px;
}

.footer-col a,
.footer-link {
  color: var(--muted);
  background: none;
  border: 0;
  font-size: 15px;
  line-height: 1.35;
  padding: 12px 0;
  text-align: left;
  cursor: pointer;
  transition: color 0.15s var(--ease);
}

.footer-col a:hover,
.footer-link:hover {
  color: var(--blue);
}

.footer-bottom {
  border-top: 1px solid var(--line);
  justify-content: space-between;
  margin-top: clamp(32px, 4vw, 56px);
  padding-top: 24px;
  color: var(--muted);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  gap: 16px;
  flex-wrap: wrap;
  display: flex;
}


/* ------------------------- Pages documentaires ------------------------- */
.document {
  max-width: 820px;
  padding: 70px 0;
}

.document h1 {
  font-size: 48px;
}

.document h2 {
  font-size: 22px;
  margin: 34px 0 10px;
}

.document p,
.document li {
  color: #42546a;
  line-height: 1.75;
}

.document p + p {
  margin-top: 14px;
}

.document table {
  width: 100%;
  margin-top: 20px;
  font-size: 14px;
}

.document th,
.document td {
  text-align: left;
  border-bottom: 1px solid var(--line);
  padding: 12px 10px;
  vertical-align: top;
}

.document th {
  color: var(--muted);
  font-size: 13px;
}

.revision {
  color: var(--muted);
  font-size: 13px;
  margin-top: 28px;
}

/* ------------------------- Bandeau cookie / modale --------------------- */
.cookie-banner {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 50;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 20px;
  box-shadow: var(--shadow-lg);
  padding: 20px 22px;
  display: flex;
  gap: 20px;
  align-items: center;
  flex-wrap: wrap;
  max-width: 1180px;
  margin: 0 auto;
}

.cookie-banner p {
  color: var(--muted);
  font-size: 13px;
  line-height: 1.55;
  flex: 1 1 320px;
  margin: 0;
}

.cookie-banner b {
  display: block;
  color: var(--ink);
  font-size: 14px;
  margin-bottom: 4px;
}

.cookie-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.cookie-prefs {
  flex: 1 1 100%;
}

/* Marges et bordure vivent sur l'interieur : posees sur la piste a `0fr`,
   elles laisseraient une bande residuelle et le panneau ne fermerait jamais. */
.cookie-prefs .t-acc-panel-inner {
  border-top: 1px solid var(--line);
  margin-top: 6px;
  padding-top: 14px;
  display: grid;
  gap: 12px;
}

.cookie-prefs label {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 13px;
}

.cookie-prefs input {
  width: 18px;
  height: 18px;
  flex: 0 0 auto;
  margin-top: 2px;
}

.cookie-prefs small {
  display: block;
  color: var(--muted);
}

/* `showModal()` rend la page inerte mais ne l'empeche pas de defiler sous la
   fenetre : sur telephone le geste vertical entrainait la page derriere la
   feuille. Le script pose la classe tant qu'une fenetre est ouverte. */
html.has-modal {
  overflow: hidden;
}

dialog.modal {
  border: 0;
  border-radius: 24px;
  padding: 0;
  max-width: 460px;
  width: calc(100% - 32px);
  box-shadow: 0 30px 80px #0d3c7038;
  /* Sur un petit ecran la fenetre defile, le bouton d'envoi reste
     atteignable. */
  max-height: 92dvh;
  overflow-y: auto;
}

/* La fenetre de demande est plus large que les autres : le formulaire y tient
   sur deux colonnes, comme dans la section, et la fenetre garde la hauteur
   d'un ecran d'ordinateur au lieu de defiler. */
dialog.modal#request-modal {
  max-width: 780px;
}

dialog.modal .form-actions {
  margin-top: 22px;
}

dialog.modal::backdrop {
  background: rgba(9, 32, 68, 0.45);
}

dialog.modal .modal-body {
  padding: 28px;
}

dialog.modal h3 {
  font-size: 20px;
  margin-bottom: 8px;
}

dialog.modal p {
  color: var(--muted);
  font-size: 14px;
  line-height: 1.55;
  margin-bottom: 18px;
}

dialog.modal label {
  display: block;
  margin-bottom: 14px;
}

/* Le formulaire dans la fenetre : l'espacement de la grille remplace celui
   des libelles, et la case de consentement garde sa disposition en ligne au
   lieu d'heriter du style des libelles de champ. */
dialog.modal .quick-form {
  padding: 0;
  box-shadow: none;
}

dialog.modal .fields label {
  margin-bottom: 0;
}

dialog.modal .modal-body > p {
  margin-bottom: 22px;
}

dialog.modal .quick-form textarea {
  min-height: 72px;
}

/* La fenetre defile : un panneau de selection ouvert pres du bas doit pouvoir
   depasser la carte, sinon le calendrier serait rogne. */
dialog.modal .callback-grid {
  position: relative;
  z-index: 1;
}

dialog.modal label.consent {
  display: flex;
  margin-bottom: 0;
}

dialog.modal label.consent span {
  font-weight: 400;
  margin: 0;
}

/* ------------------------- Fenetre des vignettes ----------------------- */
/* La photo porte la fenetre : elle occupe la surface, cernee d'un liseré fin,
   et le texte se limite a une phrase et deux actions posees en dessous. */
dialog.promo-modal {
  width: min(980px, 100% - 32px);
  max-width: none;
  padding: clamp(14px, 1.4vw, 20px);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
  /* La fenetre ne touche jamais le bord de l'ecran ; au besoin elle defile. */
  max-height: 92dvh;
  overflow-y: auto;
}

dialog.promo-modal[open]::backdrop {
  background: rgb(6 20 42 / 0.68);
}

.promo-modal-figure {
  margin: 0;
  position: relative;
  border-radius: calc(var(--r-xl) - 16px);
  overflow: hidden;
  background: var(--surface);
  aspect-ratio: 16 / 9;
}

/* Liseré fin autour de la photo, peint par-dessus : une ombre `inset` sur le
   conteneur passerait sous le contenu remplace. */
.promo-modal-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: var(--image-ring);
  pointer-events: none;
}

.promo-modal-figure picture,
.promo-modal-figure img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.promo-modal-body {
  padding: clamp(20px, 2.2vw, 30px) clamp(6px, 1vw, 16px) clamp(6px, 0.8vw, 10px);
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: clamp(16px, 2vw, 40px);
}

.promo-modal-body h3 {
  font-size: clamp(19px, 1.9vw, 26px);
}

.promo-modal-body p {
  color: var(--muted);
  line-height: 1.55;
  margin-top: 8px;
  max-width: 56ch;
}

.promo-modal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.promo-modal .modal-close {
  top: 26px;
  right: 28px;
  background: rgb(255 255 255 / 0.92);
  box-shadow: var(--shadow-sm);
  z-index: 2;
}

@media (width <= 860px) {
  .promo-modal-body {
    grid-template-columns: 1fr;
    align-items: start;
  }

  .promo-modal-actions .button {
    flex: 1 1 auto;
  }
}

/* ------------------------ Visionneuse du КП (PDF) ---------------------- */
/* Meme dessin que la visionneuse de l'ERP : voile sombre plein ecran, nom du
   fichier et actions rondes en haut, pages en feuilles blanches ombrees. Sur
   telephone les actions descendent en barre basse, zone du pouce ; la croix
   reste en haut. Le fond ferme, le document non (script). */
dialog.media-viewer {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: rgb(0 0 0 / 0.9);
  color: #fff;
  overflow: hidden;
  opacity: 0;
  transition:
    opacity var(--modal-open-dur) var(--modal-ease),
    overlay var(--modal-open-dur) allow-discrete,
    display var(--modal-open-dur) allow-discrete;
}

dialog.media-viewer[open] {
  display: flex;
  flex-direction: column;
  opacity: 1;
}

@starting-style {
  dialog.media-viewer[open] {
    opacity: 0;
  }
}

dialog.media-viewer.is-closing {
  opacity: 0;
  transition: opacity var(--modal-close-dur) var(--modal-ease);
}

/* Le voile est la fenetre elle-meme : pas de second fond. */
dialog.media-viewer::backdrop {
  background: transparent;
}

.media-viewer [hidden] {
  display: none !important;
}

.media-viewer-scrim {
  position: absolute;
  inset-inline: 0;
  height: 96px;
  pointer-events: none;
  z-index: 5;
}

.media-viewer-scrim--top {
  top: 0;
  background: linear-gradient(to bottom, rgb(0 0 0 / 0.85), transparent);
}

.media-viewer-scrim--bottom {
  bottom: 0;
  display: none;
  background: linear-gradient(to top, rgb(0 0 0 / 0.85), transparent);
}

.media-viewer-bar {
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: max(16px, calc(env(safe-area-inset-top) + 8px)) 16px 16px;
}

.media-viewer-name {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 2px rgb(0 0 0 / 0.6);
}

.media-viewer-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}

.media-viewer-btn {
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: var(--r-pill);
  background: rgb(0 0 0 / 0.4);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  outline: none;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color 0.15s var(--ease);
}

.media-viewer-btn:hover {
  background: rgb(0 0 0 / 0.55);
}

.media-viewer-btn:focus,
.media-viewer-btn:focus-visible,
.media-viewer-btn:active {
  outline: none;
  box-shadow: none;
  border: 0;
}

.media-viewer-btn svg {
  width: 20px;
  height: 20px;
}

.media-viewer-stage {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  padding: max(80px, calc(env(safe-area-inset-top) + 64px)) 24px 24px;
}

/* `max-content` : une feuille zoomee plus large que l'ecran deborde a droite
   et se parcourt au defilement, au lieu de perdre son bord gauche. */
.media-viewer-pages {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
  width: max-content;
  margin: 0 auto;
}

.media-viewer-page {
  flex: none;
  background: #fff;
  box-shadow: 0 24px 64px rgb(0 0 0 / 0.55);
  /* Avant le dessin, la feuille tient deja sa place. */
  min-height: 120px;
}

.media-viewer-page canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.media-viewer-pill {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  border-radius: var(--r-pill);
  background: rgb(0 0 0 / 0.6);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
}

.media-viewer-spinner {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid rgb(255 255 255 / 0.3);
  border-top-color: #fff;
  animation: media-viewer-spin 0.8s linear infinite;
}

@keyframes media-viewer-spin {
  to {
    rotate: 360deg;
  }
}

.media-viewer-error {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: min(480px, calc(100% - 48px));
  padding: 32px;
  border-radius: var(--r-xl);
  border: 1px solid rgb(255 255 255 / 0.1);
  background: rgb(20 20 20 / 0.95);
  text-align: center;
}

.media-viewer-error b {
  display: block;
  font-size: 16px;
}

.media-viewer-error p {
  margin-top: 8px;
  font-size: 14px;
  color: rgb(255 255 255 / 0.7);
}

.media-viewer-error-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 20px;
}

.media-viewer-actions--bottom {
  display: none;
}

@media (width <= 767px) {
  .media-viewer-actions--top {
    display: none;
  }

  .media-viewer-scrim--bottom {
    display: block;
    height: 112px;
  }

  /* Les memes actions, en barre basse au-dessus de la zone de securite :
     aucune commande perdue, seule leur place change. */
  .media-viewer-actions--bottom {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    z-index: 10;
    display: flex;
    justify-content: center;
    gap: 12px;
    padding: 12px 16px max(16px, calc(env(safe-area-inset-bottom) + 12px));
  }

  .media-viewer-stage {
    padding: max(72px, calc(env(safe-area-inset-top) + 60px)) 16px 112px;
  }
}

/* --------------------------- Feuille du bas ---------------------------- */
/* Sur telephone, les deux fenetres deviennent une feuille ancree au bord bas :
   elle monte depuis le bas, se referme d'un glissement du pouce, et ses actions
   restent dans la moitie basse de l'ecran, la seule atteignable d'une main. Au
   dessus de 620px rien ne change, la fenetre reste centree.

   La barre de prise vit dans le balisage des trois fenetres. Sur ordinateur elle
   est en `display: contents` : elle disparait de la mise en page et le bouton de
   fermeture se positionne comme avant, par rapport au `dialog`. */
.sheet-grab {
  display: contents;
}


.modal-close {
  position: absolute;
  top: 8px;
  right: 10px;
  width: 40px;
  height: 40px;
  border-radius: var(--r-pill);
  font-size: 22px;
  color: var(--muted);
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  outline: none;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  transition: color 0.15s var(--ease);
}

.modal-close:hover {
  color: var(--ink);
}

.modal-close:focus,
.modal-close:focus-visible,
.modal-close:active {
  outline: none;
  box-shadow: none;
  border: 0;
}


/* ======================================================================
   transitions.dev — transitions posees sur le site
   Chaque bloc est repris de la bibliotheque ; seuls les selecteurs sont
   relies au balisage existant. Les gardes `prefers-reduced-motion` sont
   conservees telles quelles.
   ====================================================================== */

/* --- Menu dropdown : navigation mobile ------------------------------- */
/* Adaptation : la nav reste dans le flux avec `visibility` plutot que
   `display: none`, sinon il n'y aurait rien a interpoler a l'ouverture. */
.t-dropdown {
  transform-origin: top right;
  transform: scale(var(--dropdown-pre-scale));
  opacity: 0;
  pointer-events: none;
  transition:
    transform var(--dropdown-open-dur) var(--dropdown-ease),
    opacity var(--dropdown-open-dur) var(--dropdown-ease);
  will-change: transform, opacity;
}

.t-dropdown.is-open {
  transform: scale(1);
  opacity: 1;
  pointer-events: auto;
}

.t-dropdown.is-closing {
  transform: scale(var(--dropdown-closing-scale));
  opacity: 0;
  pointer-events: none;
  transition:
    transform var(--dropdown-close-dur) var(--dropdown-ease),
    opacity var(--dropdown-close-dur) var(--dropdown-ease);
}

/* --- Modal : rappel telephonique et fenetre des vignettes ------------- */
/* Adaptation : sur un `<dialog>` ouvert par `showModal()`, l'element passe
   de `display: none` a `block`. L'ouverture emprunte donc `@starting-style`
   et la fermeture la classe `.is-closing` de la bibliotheque. Les valeurs
   — echelle 0,96, 250ms a l'ouverture, 150ms a la fermeture — sont celles
   du modele. */
dialog.modal {
  transform: scale(var(--modal-scale));
  opacity: 0;
  transition:
    transform var(--modal-open-dur) var(--modal-ease),
    opacity var(--modal-open-dur) var(--modal-ease),
    overlay var(--modal-open-dur) allow-discrete,
    display var(--modal-open-dur) allow-discrete;
}

dialog.modal[open] {
  transform: scale(1);
  opacity: 1;
}

@starting-style {
  dialog.modal[open] {
    transform: scale(var(--modal-scale));
    opacity: 0;
  }
}

dialog.modal.is-closing {
  transform: scale(var(--modal-scale-close));
  opacity: 0;
  transition:
    transform var(--modal-close-dur) var(--modal-ease),
    opacity var(--modal-close-dur) var(--modal-ease);
}

dialog.modal::backdrop {
  background: rgb(6 20 42 / 0);
  transition:
    background-color var(--modal-open-dur) var(--modal-ease),
    overlay var(--modal-open-dur) allow-discrete,
    display var(--modal-open-dur) allow-discrete;
}

dialog.modal[open]::backdrop {
  background: rgb(6 20 42 / 0.5);
}

@starting-style {
  dialog.modal[open]::backdrop {
    background: rgb(6 20 42 / 0);
  }
}

dialog.modal.is-closing::backdrop {
  background: rgb(6 20 42 / 0);
  transition: background-color var(--modal-close-dur) var(--modal-ease);
}

/* La feuille du bas, suite : la geometrie est declaree plus haut, le mouvement
   ici. L'ordre compte. Les regles de transitions.dev juste au-dessus posent le
   `transform` des fenetres avec la meme specificite (`dialog.modal[open]`) ;
   remontees avant elles, celles qui suivent seraient sans effet et la feuille
   reprendrait l'echelle d'une fenetre au lieu de glisser. */
@media (width <= 620px) {
  /* La photo monte jusqu'au bord haut de la feuille : elle en reprend donc les
     coins arrondis. */
  .promo-modal-figure {
    aspect-ratio: 4 / 3;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
  }

  .promo-modal-actions .button {
    width: 100%;
  }

  /* Le mouvement de la feuille n'est pas celui d'une fenetre : plus long, et
     l'assouplissement des panneaux d'iOS. Les jetons etant relus par le script
     pour cadencer la fermeture, les redefinir ici suffit — rien a synchroniser. */
  :root {
    --modal-open-dur: 320ms;
    --modal-close-dur: 220ms;
    --modal-ease: cubic-bezier(0.32, 0.72, 0, 1);
  }

  dialog.modal,
  dialog.promo-modal {
    width: 100%;
    max-width: none;
    /* La feuille laisse toujours voir un peu de la page derriere elle. */
    max-height: 88dvh;
    margin: auto auto 0;
    padding: 0 0 max(12px, env(safe-area-inset-bottom));
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    /* Le defilement interieur ne se propage pas a la page. */
    overscroll-behavior: contain;
    /* Glissement seul : une feuille qui se fond en plus du mouvement donne
       l'impression de deux gestes pour un. */
    opacity: 1;
    transform: translateY(100%);
    transition:
      transform var(--modal-open-dur) var(--modal-ease),
      overlay var(--modal-open-dur) allow-discrete,
      display var(--modal-open-dur) allow-discrete;
  }

  dialog.modal[open] {
    opacity: 1;
    transform: translateY(0);
  }

  @starting-style {
    dialog.modal[open] {
      opacity: 1;
      transform: translateY(100%);
    }
  }

  dialog.modal.is-closing {
    opacity: 1;
    transform: translateY(100%);
    transition: transform var(--modal-close-dur) var(--modal-ease);
  }

  /* Pendant le geste, la feuille suit le doigt : le script pose la distance
     dans `--sheet-drag` a chaque `touchmove`, la transition doit se taire. */
  dialog.modal.is-dragging {
    transform: translateY(var(--sheet-drag, 0px));
    transition: none;
  }

  /* Barre de prise : elle reste en haut quand le contenu defile, sinon la
     poignee et le bouton de fermeture sortiraient de l'ecran. */
  .sheet-grab {
    display: block;
    position: sticky;
    top: 0;
    z-index: 3;
    height: 30px;
    background: #fff;
    border-radius: inherit;
    /* Le navigateur ne doit pas prendre le geste vertical pour du defilement :
       c'est le script qui le lit. */
    touch-action: none;
  }

  .sheet-grab::before {
    content: "";
    position: absolute;
    top: 10px;
    left: 50%;
    width: 40px;
    height: 4px;
    translate: -50% 0;
    border-radius: var(--r-pill);
    background: var(--surface-2);
  }

  /* Le bouton se cale dans la barre, qui est son bloc conteneur ici. Le
     selecteur porte le nom de l'element : la regle de repos est declaree plus
     bas dans la feuille, il faut la depasser en specificite et non en ordre. */
  dialog.modal .modal-close {
    top: -3px;
    right: 4px;
    width: 36px;
    height: 36px;
    background: none;
    box-shadow: none;
  }

  dialog.modal .modal-body {
    padding: 2px 20px 20px;
  }

  .promo-modal-body {
    padding: 18px 20px 4px;
  }

  /* Fenetres a photo : la barre de prise ne prend plus de hauteur, elle se pose
     par-dessus l'image. La poignee et la croix se lisent alors sur la photo,
     detachees par un voile sombre degrade vers le bas. Le `sticky` est conserve
     — a hauteur nulle il garde poignee et croix a l'ecran quand le corps
     defile. */
  dialog.promo-modal .sheet-grab {
    height: 0;
    background: none;
    overflow: visible;
  }

  dialog.promo-modal .sheet-grab::after {
    content: "";
    position: absolute;
    inset: 0 0 auto;
    height: 88px;
    border-radius: inherit;
    background: linear-gradient(rgb(6 20 42 / 0.45), rgb(6 20 42 / 0));
    pointer-events: none;
  }

  /* Poignee et croix passent devant le voile : celui-ci est peint apres eux. */
  dialog.promo-modal .sheet-grab::before {
    background: rgb(255 255 255 / 0.85);
    z-index: 1;
  }

  dialog.promo-modal .modal-close {
    top: 2px;
    right: 6px;
    color: #fff;
    z-index: 1;
  }

  dialog.promo-modal .modal-close:hover {
    color: #fff;
  }
}

/* --- Panel reveal : bandeau cookie ------------------------------------ */
.t-panel-slide {
  transform: translateY(var(--panel-translate-y));
  opacity: 0;
  filter: blur(var(--panel-blur));
  pointer-events: none;
  transition:
    transform var(--panel-close-dur) var(--panel-ease),
    opacity var(--panel-close-dur) var(--panel-ease),
    filter var(--panel-close-dur) var(--panel-ease);
  will-change: transform, opacity, filter;
}

.t-panel-slide[data-open="true"] {
  transform: translateY(0);
  opacity: 1;
  filter: blur(0);
  pointer-events: auto;
  transition:
    transform var(--panel-open-dur) var(--panel-ease),
    opacity var(--panel-open-dur) var(--panel-ease),
    filter var(--panel-open-dur) var(--panel-ease);
}

/* --- Text states swap : libelles qui changent en place ---------------- */
.t-text-swap {
  display: inline-block;
  transform: translateY(0);
  filter: blur(0);
  opacity: 1;
  transition:
    transform var(--text-swap-dur) var(--text-swap-ease),
    filter var(--text-swap-dur) var(--text-swap-ease),
    opacity var(--text-swap-dur) var(--text-swap-ease);
  will-change: transform, filter, opacity;
}

.t-text-swap.is-exit {
  transform: translateY(calc(var(--text-swap-translate-y) * -1));
  filter: blur(var(--text-swap-blur));
  opacity: 0;
}

.t-text-swap.is-enter-start {
  transform: translateY(var(--text-swap-translate-y));
  filter: blur(var(--text-swap-blur));
  opacity: 0;
  transition: none;
}

/* --- Error state shake : messages d'erreur des formulaires ------------ */
/* Adaptation : ici l'element secoue EST le message, il n'y a pas de champ
   encadre a teinter. Le mouvement et ses paliers sont ceux du modele. */
.t-input {
  will-change: transform;
}

.t-input.is-shaking {
  animation: t-input-shake calc(var(--shake-dur-a) * 2 + var(--shake-dur-b) * 2) linear;
}

@keyframes t-input-shake {
  0% {
    transform: translateX(0);
    animation-timing-function: var(--shake-ease);
  }
  28.57% {
    transform: translateX(var(--shake-distance));
    animation-timing-function: var(--shake-ease);
  }
  57.14% {
    transform: translateX(calc(var(--shake-distance) * -1));
    animation-timing-function: var(--shake-ease);
  }
  78.57% {
    transform: translateX(var(--shake-overshoot));
    animation-timing-function: var(--shake-ease);
  }
  100% {
    transform: translateX(0);
  }
}

/* --- Texts reveal : accroche de l'en-tete ----------------------------- */
.t-stagger-line {
  display: block;
  opacity: 0;
  transform: translateY(var(--stagger-distance));
  filter: blur(var(--stagger-blur));
  transition:
    opacity var(--stagger-dur) var(--stagger-ease),
    transform var(--stagger-dur) var(--stagger-ease),
    filter var(--stagger-dur) var(--stagger-ease);
  will-change: transform, opacity, filter;
}

.t-stagger-line--2 {
  transition-delay: var(--stagger-stagger);
}

.t-stagger-line--3 {
  transition-delay: calc(var(--stagger-stagger) * 2);
}

.t-stagger.is-shown .t-stagger-line {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* --- Accordion expand : FAQ et preferences cookie --------------------- */
/* `grid-template-rows: 0fr -> 1fr` anime la hauteur sans mesure JS. Le
   padding vit sur `.t-acc-panel-inner` : pose sur la piste a `0fr` il
   laisserait une bande residuelle et le panneau ne fermerait jamais. */
.t-acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--acc-collapse) var(--acc-ease);
}

.t-acc[data-open="true"] .t-acc-panel {
  grid-template-rows: 1fr;
  transition: grid-template-rows var(--acc-expand) var(--acc-ease);
}

/* Sans JavaScript, `data-open` n'est jamais pose : le panneau suit alors
   simplement l'etat natif de `details`, sans animation mais lisible. */
.t-acc:not(.is-js)[open] .t-acc-panel {
  grid-template-rows: 1fr;
}

.t-acc:not(.is-js)[open] .t-acc-panel-inner {
  opacity: 1;
  filter: none;
}

.t-acc:not(.is-js)[open] .t-acc-chevron {
  transform: scaleY(-1);
}

.t-acc-panel-inner {
  overflow: hidden;
  opacity: 0;
  filter: blur(2px);
  transition:
    opacity var(--acc-collapse) var(--acc-ease),
    filter var(--acc-collapse) var(--acc-ease);
}

.t-acc[data-open="true"] .t-acc-panel-inner {
  opacity: 1;
  filter: blur(0);
  transition:
    opacity var(--acc-expand) var(--acc-ease),
    filter var(--acc-expand) var(--acc-ease);
}

/* Le chevron bascule verticalement plutot que de morpher son trace : le
   `d:` anime n'existe que sur Chromium. Le retournement passe par une
   ligne plate a mi-course, exactement comme le morphing. */
.t-acc-chevron {
  display: inline-flex;
  transform: scaleY(1);
  transform-origin: center;
  transition: transform var(--acc-chevron) var(--acc-ease);
}

.t-acc-chevron path {
  vector-effect: non-scaling-stroke;
}

.t-acc[data-open="true"] .t-acc-chevron {
  transform: scaleY(-1);
}

@media (prefers-reduced-motion: reduce) {
  .t-dropdown,
  dialog.modal,
  .t-panel-slide,
  .t-text-swap,
  .t-acc-panel,
  .t-acc-panel-inner,
  .t-acc-chevron {
    transition: none !important;
  }

  .t-input {
    animation: none !important;
    transform: none !important;
  }

  .t-stagger-line {
    transition: none !important;
  }
}

/* ------------------------------ Animations ----------------------------- */
.reveal {
  opacity: 0;
  translate: 0 12px;
  transition:
    opacity 0.5s var(--ease),
    translate 0.5s var(--ease);
}

.reveal.is-visible {
  opacity: 1;
  translate: none;
}

.route-line {
  stroke-dasharray: 6 6;
  animation: route-dash 2.4s linear infinite;
}

@keyframes route-dash {
  to {
    stroke-dashoffset: -24;
  }
}

/* ============================== Consultation ============================= */
/* Le formulaire de demande pose une question a la fois, dans une fenetre
   ancree au coin bas droit. Le lanceur est la photo de la consultante, en
   disque, avec son point de disponibilite : ni cartouche blanc ni libelle — le
   nom de l'action est porte par `aria-label` ; sans JavaScript il reste un lien
   vers la section du formulaire.

   Rien ici n'est un composant de messagerie generique : les bulles, la barre
   d'avancement et la zone de saisie reprennent les jetons de la feuille de
   style — rayons, surfaces, mouvement. */

.chat-launcher {
  position: fixed;
  right: 24px;
  bottom: 24px;
  z-index: 30;
  display: block;
  color: var(--blue);
  transition:
    scale var(--duration-fast) var(--ease-bounce),
    filter var(--duration-fast) var(--ease);
  /* Pas de cartouche : le disque est la photo elle-meme. L'ombre porte sur la
     forme rendue, c'est elle seule qui detache le lanceur du fond. */
  filter: drop-shadow(0 4px 12px rgb(16 24 40 / 0.1)) drop-shadow(0 18px 40px rgb(6 42 94 / 0.22));
}

.chat-launcher-photo {
  display: block;
  width: 64px;
  height: 64px;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--surface);
}

/* Le rayon est repete sur la photo elle-meme, en plus du detourage du bloc :
   une image ronde ne depend alors d'aucun conteneur, et le disque tient meme
   la ou le balisage differe. */
.chat-launcher picture,
.chat-launcher img,
.chat-avatar picture,
.chat-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* La source est deja carree et cadree sur le visage : le disque la prend
     entiere, sans recadrage supplementaire. */
  object-position: 50% 50%;
  border-radius: var(--r-pill);
  display: block;
}

/* Pastille de disponibilite, avec deux ondes qui s'en echappent. Elle ne dit
   rien du delai de reponse : elle signale que la conversation est ouverte. */
.chat-launcher-dot {
  position: absolute;
  left: 45px;
  top: 45px;
  width: 15px;
  height: 15px;
  border-radius: var(--r-pill);
  background: #16a34a;
}

.chat-launcher-dot::before,
.chat-launcher-dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: #16a34a;
  /* Deux ondes decalees d'une demi-periode : l'une part quand l'autre s'eteint,
     le rayonnement n'a donc pas de temps mort. */
  animation: chat-radiate 2.4s var(--ease-smooth-out) infinite;
}

.chat-launcher-dot::after {
  animation-delay: 1.2s;
}

@keyframes chat-radiate {
  from {
    opacity: 0.55;
    scale: 1;
  }
  to {
    opacity: 0;
    scale: 2.8;
  }
}

@media (hover: hover) {
  .chat-launcher:hover {
    scale: 1.06;
  }
}

.chat-launcher:active {
  scale: 0.97;
}

/* --- Bulle d'appel ---------------------------------------------------- */
.chat-teaser {
  position: fixed;
  right: 24px;
  bottom: 96px;
  z-index: 30;
  width: min(270px, calc(100% - 48px));
  padding: 12px 34px 12px 16px;
  background: #fff;
  border-radius: var(--r-md);
  box-shadow: 0 4px 20px rgb(6 20 42 / 0.14);
  cursor: pointer;
  animation: chat-teaser-in var(--duration-medium) var(--ease-smooth-out) both;
}

.chat-teaser p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--ink);
}

.chat-teaser-close {
  position: absolute;
  top: 6px;
  right: 8px;
  width: 28px;
  height: 28px;
  border-radius: var(--r-pill);
  color: var(--muted);
  font-size: 18px;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  outline: none;
  box-shadow: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}

.chat-teaser-close:hover {
  color: var(--ink);
}

.chat-teaser-close:focus,
.chat-teaser-close:focus-visible,
.chat-teaser-close:active {
  outline: none;
  box-shadow: none;
  border: 0;
}

@keyframes chat-teaser-in {
  from {
    opacity: 0;
    translate: 0 10px;
    scale: 0.96;
  }
}

/* --- Fenetre ---------------------------------------------------------- */
/* Ancree au coin du lanceur, elle en sort et y retourne : `transform-origin`
   au coin bas droit fait toute la continuite du geste. */
dialog.chat-panel {
  width: min(400px, 100% - 32px);
  max-width: none;
  height: min(620px, 78dvh);
  max-height: none;
  margin: auto 24px 24px auto;
  padding: 0;
  border: 0;
  border-radius: var(--r-xl);
  background: #fff;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  flex-direction: column;
  transform-origin: 100% 100%;
  transform: translateY(12px) scale(0.94);
  opacity: 0;
  transition:
    transform var(--modal-open-dur) var(--modal-ease),
    opacity var(--modal-open-dur) var(--modal-ease),
    overlay var(--modal-open-dur) allow-discrete,
    display var(--modal-open-dur) allow-discrete;
}

dialog.chat-panel[open] {
  display: flex;
  transform: none;
  opacity: 1;
}

@starting-style {
  dialog.chat-panel[open] {
    transform: translateY(12px) scale(0.94);
    opacity: 0;
  }
}

dialog.chat-panel.is-closing {
  transform: translateY(12px) scale(0.94);
  opacity: 0;
  transition:
    transform var(--modal-close-dur) var(--modal-ease),
    opacity var(--modal-close-dur) var(--modal-ease);
}

/* Le fond s'assombrit a peine : la page reste lisible derriere la fenetre,
   qui n'en occupe qu'un coin. */
dialog.chat-panel::backdrop {
  background: rgb(6 20 42 / 0);
  transition:
    background-color var(--modal-open-dur) var(--modal-ease),
    overlay var(--modal-open-dur) allow-discrete,
    display var(--modal-open-dur) allow-discrete;
}

dialog.chat-panel[open]::backdrop {
  background: rgb(6 20 42 / 0.28);
}

@starting-style {
  dialog.chat-panel[open]::backdrop {
    background: rgb(6 20 42 / 0);
  }
}

dialog.chat-panel.is-closing::backdrop {
  background: rgb(6 20 42 / 0);
  transition: background-color var(--modal-close-dur) var(--modal-ease);
}

.chat-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 20px 14px;
  flex: 0 0 auto;
}

.chat-avatar {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border-radius: var(--r-pill);
  overflow: hidden;
  background: var(--surface);
  display: block;
}

.chat-identity {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.chat-identity b {
  font-size: 16px;
  line-height: 1.2;
}

/* La disponibilite porte le meme point vert que le lanceur : c'est le seul
   lien visuel a tenir entre le bouton et la fenetre. */
.chat-identity small {
  color: var(--muted);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.chat-identity small::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: var(--r-pill);
  background: #16a34a;
}

/* La fenetre porte deja son bouton de fermeture ; sur ordinateur la barre de
   prise est en `display: contents` et le bouton se pose sur le coin. */
.chat-panel .modal-close {
  top: 14px;
  right: 12px;
  z-index: 2;
}

/* Une fenetre est ouverte : le lanceur et sa bulle n'ont plus rien a proposer,
   et ils resteraient visibles sous le fond assombri. */
html.has-modal .chat-launcher,
html.has-modal .chat-teaser {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-quick) var(--ease);
}

.chat-log {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 8px 20px 14px;
}

/* La conversation part du bas, comme dans une messagerie : sans cela les deux
   premieres bulles flottaient en haut d'une fenetre vide. `margin-top: auto`
   plutot que `justify-content` — le second rogne le haut du contenu des qu'il
   deborde. */
.chat-log > :first-child {
  margin-top: auto;
}

/* --- Bulles ----------------------------------------------------------- */
/* Le coin proche de l'interlocuteur est resserre : c'est ce qui donne le sens
   de lecture sans avoir a coller une pointe sur la bulle. */
.chat-msg {
  max-width: 84%;
  padding: 11px 15px;
  border-radius: var(--r-lg);
  font-size: 15px;
  line-height: 1.5;
  white-space: pre-line;
  animation: chat-msg-in var(--duration-fast) var(--ease-smooth-out) both;
}

.chat-msg--bot {
  background: var(--surface);
  border-bottom-left-radius: 6px;
}

.chat-msg--user {
  align-self: flex-end;
  background: var(--blue);
  color: #fff;
  border-bottom-right-radius: 6px;
}

.chat-msg .button {
  margin-top: 12px;
}

@keyframes chat-msg-in {
  from {
    opacity: 0;
    translate: 0 8px;
  }
}

/* Trois points qui rebondissent, decales d'un tiers de cycle. */
.chat-typing {
  display: flex;
  gap: 4px;
  padding: 15px;
}

.chat-typing i {
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--muted);
  opacity: 0.5;
  animation: chat-typing 1s var(--ease-in-out) infinite;
}

.chat-typing i:nth-child(2) {
  animation-delay: 0.16s;
}

.chat-typing i:nth-child(3) {
  animation-delay: 0.32s;
}

@keyframes chat-typing {
  0%,
  60%,
  100% {
    translate: 0;
    opacity: 0.5;
  }
  30% {
    translate: 0 -4px;
    opacity: 1;
  }
}

/* --- Zone de reponse --------------------------------------------------- */
.chat-foot {
  flex: 0 0 auto;
  padding: 8px 16px max(14px, env(safe-area-inset-bottom));
  display: grid;
  gap: 10px;
}

.chat-entry {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

.chat-field {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 46px;
  padding: 12px 18px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--surface);
  /* 16px : en dessous, iOS agrandit la page a la mise au point du champ. */
  font: inherit;
  font-size: 16px;
  line-height: 1.4;
  resize: none;
}

.chat-field:focus,
.chat-field:focus-visible,
.chat-field:active {
  outline: none;
  box-shadow: none;
  border: 0;
}

.chat-send {
  flex: 0 0 auto;
  width: 46px;
  height: 46px;
  border-radius: var(--r-pill);
  background: var(--blue);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  transition:
    background-color 0.16s var(--ease),
    scale var(--duration-quick) var(--ease-bounce);
}

/* Meme fleche que les boutons du site, decoupee dans un aplat. */
.chat-send::after {
  content: "";
  width: 14px;
  height: 8px;
  background: currentColor;
  clip-path: polygon(0 38%, 62% 38%, 62% 0, 100% 50%, 62% 100%, 62% 62%, 0 62%);
}

.chat-send:hover {
  background: #0951a8;
}

.chat-send:active {
  scale: 0.94;
}

/* Posees dans le journal : elles s'alignent sur le bord des bulles de reponse,
   a droite, puisque c'est le visiteur qui parle. */
.chat-chips {
  align-self: stretch;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}

.chat-chip {
  min-height: 42px;
  padding: 0 18px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
  text-align: left;
  transition:
    background-color 0.16s var(--ease),
    color 0.16s var(--ease),
    scale var(--duration-quick) var(--ease-bounce);
}

.chat-chip:hover {
  background: var(--surface-2);
  color: var(--blue);
}

.chat-chip:active {
  scale: 0.97;
}

/* La sortie de liste n'est pas une reponse : elle s'efface d'un cran. */
.chat-chip--other {
  background: none;
  color: var(--muted);
  font-weight: 600;
}

.chat-chip--other:hover {
  background: var(--surface);
}

/* Actions secondaires : retour en arriere, question passee. */
.chat-aside {
  display: flex;
  gap: 14px;
}

.chat-back {
  color: var(--muted);
  font-size: 13px;
  padding: 4px 0;
  min-height: 32px;
  transition: color 0.15s var(--ease);
}

.chat-back:hover {
  color: var(--blue);
}

.chat-consent {
  display: grid;
  gap: 12px;
}

.chat-consent .consent {
  font-size: 13px;
}

.chat-foot .error {
  margin: 0;
}

/* Le repli, sous la zone de reponse : si la conversation ne suffit pas. */
.chat-phone {
  margin: 0;
  font-size: 13px;
  color: var(--muted);
  text-align: center;
}

.chat-phone a {
  color: var(--blue);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* Calendrier pose dans le journal, sous les pastilles du jour. */
.chat-calendar {
  align-self: stretch;
}

.chat-calendar .calendar {
  max-width: none;
}

/* ======================= Selecteurs jour et heure ======================== */
/* Deux selecteurs maison, au gabarit exact d'un champ : un bouton qui porte la
   valeur et une icone, puis un panneau ancre dessous — un calendrier d'un mois
   pour le jour, une liste pour le creneau.

   Le champ natif reste dans le formulaire, cache par le script : c'est lui qui
   part a l'envoi. Sans script c'est lui qui s'affiche, et le navigateur ouvre
   son propre selecteur, celui du systeme sur telephone. */
.field-label {
  display: block;
  margin: 0 0 7px;
  font-size: 13px;
  font-weight: 700;
}

/* Selecteur monte par le script : son libelle rejoint le champ et se comporte
   comme celui d'un champ de saisie — au repos il occupe le champ, centre ;
   des qu'une valeur est posee, ou que le panneau s'ouvre, il monte en haut a
   gauche et retrecit. Sans script il reste pose au-dessus du champ natif. */
.picker[data-enhanced] .field-label {
  position: absolute;
  /* Le bouton est un frere positionne, ecrit apres dans le document : sans cet
     etage son aplat opaque recouvrirait le libelle, et le champ paraitrait
     vide. */
  z-index: 1;
  top: 28px;
  left: 17px;
  right: 44px;
  margin: 0;
  font-size: 16px;
  font-weight: 400;
  line-height: 1.2;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
  transform: translateY(calc(-50% - 12px)) scale(0.75);
  transform-origin: 0 50%;
  transition: transform var(--duration-quick, 0.18s) var(--ease);
}

/* Rien de choisi, panneau ferme : le libelle tient la place du texte
   indicatif, et la valeur — « Выберите дату » — attend son tour. */
.picker[data-enhanced].is-empty:not(.is-open) .field-label {
  transform: translateY(-50%);
}

.picker.is-empty:not(.is-open) .picker-value {
  visibility: hidden;
}

.callback {
  display: grid;
  gap: 4px;
}

.callback-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 17px;
  align-items: start;
}

.picker {
  position: relative;
}

/* Le panneau ouvert passe devant les champs qui le suivent. */
.picker.is-open {
  z-index: 3;
}

.picker input[hidden],
.picker select[hidden] {
  display: none;
}

/* Meme fond, meme rayon, meme hauteur qu'un champ : le selecteur ne se
   distingue d'un `input` que par son icone. */
.picker-trigger {
  position: relative;
  display: block;
  width: 100%;
  min-height: 56px;
  padding: 24px 44px 8px 16px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
  line-height: 1.5;
  text-align: left;
  cursor: pointer;
}

.picker-value {
  display: block;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* Aucune date choisie : le libelle se lit comme un texte indicatif. */
.picker-trigger.is-empty .picker-value {
  color: var(--muted);
}

.picker-trigger::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 16px;
  width: 20px;
  height: 20px;
  transform: translateY(-50%);
  background: center / contain no-repeat;
}

[data-picker="date"] .picker-trigger::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6b7a' stroke-width='1.8' stroke-linecap='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='3'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");
}

[data-picker="time"] .picker-trigger::after {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6b7a' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3 2'/%3E%3C/svg%3E");
}

.picker-trigger {
  -webkit-tap-highlight-color: transparent;
}

.picker-trigger:focus,
.picker-trigger:focus-visible,
.picker-trigger:active {
  outline: none;
  box-shadow: none;
  border: 0;
}

.picker-panel {
  position: absolute;
  z-index: 5;
  top: calc(100% + 8px);
  left: 0;
  min-width: 100%;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: #fff;
  box-shadow: var(--shadow-md);
}

/* Le calendrier tient sept colonnes lisibles meme sous un champ etroit. */
[data-picker="date"] .picker-panel {
  width: max(100%, 288px);
}

/* Dans le panneau, le calendrier n'a ni cadre ni ombre : le panneau les porte. */
.picker-panel .calendar {
  max-width: none;
  padding: 0;
  border: 0;
  box-shadow: none;
}

.picker-clear {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 10px 0 2px;
  border: 0;
  border-top: 1px solid var(--line);
  background: 0 0;
  color: var(--blue);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.picker-clear:hover {
  color: var(--ink);
}

.picker-list {
  display: grid;
  gap: 2px;
}

.picker-option {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--r-sm);
  background: 0 0;
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  text-align: left;
  cursor: pointer;
  transition: background-color 0.15s var(--ease);
}

.picker-option:hover {
  background: var(--surface);
}

.picker-option[aria-selected="true"] {
  background: var(--blue);
  color: #fff;
  font-weight: 700;
}

.picker-option:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: -2px;
}

.calendar {
  max-width: 340px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: #fff;
  box-shadow: var(--shadow-md);
}

.calendar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 8px;
}

.calendar-head b {
  font-size: 14px;
  text-transform: capitalize;
}

.calendar-nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
}

.calendar-nav:hover:not(:disabled) {
  background: var(--surface-2);
}

.calendar-nav:disabled {
  opacity: 0.35;
  cursor: default;
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}

.calendar-grid small {
  padding: 4px 0;
  color: var(--muted);
  font-size: 11px;
  text-align: center;
  text-transform: capitalize;
}

.calendar-day {
  aspect-ratio: 1;
  border: 0;
  border-radius: var(--r-sm);
  background: #0000;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.calendar-day:hover:not(:disabled) {
  background: var(--surface-2);
}

.calendar-day:disabled {
  color: var(--muted);
  opacity: 0.4;
  cursor: default;
}

.calendar-day.is-weekend:not(:disabled) {
  color: #b42318;
}

.calendar-day.is-today {
  box-shadow: inset 0 0 0 1px var(--blue);
}

.calendar-day[aria-pressed="true"] {
  background: var(--blue);
  color: #fff;
  font-weight: 700;
}

.calendar-day:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 1px;
}

/* Pied du formulaire de demande : la case de consentement a gauche, le bouton
   a droite, sur un seul rang. Sur telephone ils s'empilent (plus bas). */
.form-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-top: 24px;
}

.form-foot .consent {
  flex: 1 1 auto;
  margin-top: 0;
}

.form-foot .form-actions {
  flex: none;
  margin: 0;
}

/* Tant qu'un champ obligatoire manque ou que la case de consentement n'est pas
   cochee, le bouton reste gris : l'oeil voit qu'il reste quelque chose a faire.

   Il n'est pas desactive pour autant. Un bouton mort ne dit pas ce qui manque ;
   celui-ci, une fois clique, laisse le navigateur — ou `reportValidity()` cote
   script — designer le premier champ en faute. Le formulaire garde donc son
   comportement sans JavaScript. */
.quick-form:invalid .form-actions .button {
  color: var(--muted);
  background: var(--surface-2);
  box-shadow: none;
}

.quick-form:invalid .form-actions .button:hover {
  background: #e2e4e8;
  box-shadow: none;
}

/* Le lanceur du chat s'efface devant la section du formulaire (script) :
   il n'a rien de plus a proposer, et couvrirait le bouton sur telephone. */
html.form-in-view .chat-launcher,
html.form-in-view .chat-teaser {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--duration-quick) var(--ease);
}

/* Le navigateur marque un champ seulement apres que le visiteur y a touche :
   pas de rouge a l'ouverture, un signal des que l'on quitte un champ vide. */
/* Le fond reste le meme : la faute se lit sur le libelle et sur un trait pose
   sous le champ, sans faire clignoter la carte entiere. */
.quick-form input:user-invalid,
.quick-form textarea:user-invalid,
.brief-form input:user-invalid,
.brief-form textarea:user-invalid {
  box-shadow: inset 0 -2px 0 #b42318;
}

.fields label:has(:user-invalid) > span {
  color: #b42318;
}

/* ---------------------------- Points de rupture ------------------------ */
@media (width <= 1200px) {
  /* Cinq cartes en 3 + 2. */
  .service-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  nav a {
    padding: 0 15px;
    font-size: 14px;
  }
}

/* Sous ~1036px, le mot le plus long du titre (0.39 x largeur a 6.2vw) et les
   deux boutons cote a cote (540px) ne tiennent plus dans la grille de l'en-tete
   avec sa gouttiere : une colonne, avec une marge pour les polices. */
@media (width <= 1060px) {
  .promo-head {
    grid-template-columns: 1fr;
    align-items: start;
    gap: 24px;
  }
}

@media (width <= 1024px) {
  .about-grid,
  .advantage-grid {
    grid-template-columns: 1fr;
  }

  /* En colonne, la gouttiere large devient un blanc vertical : on la reduit. */
  .about-grid {
    gap: 32px;
  }

  .advantage-photo {
    min-height: 260px;
  }
}

/* Point de bascule de la navigation : identite 154px, six pastilles 657px et
   bloc d'actions 328px, gouttieres comprises, ne tiennent plus cote a cote en
   dessous de ~1210px. La nav passe alors en menu deroulant. Ce point est propre
   a l'en-tete, les autres reglages restent a 900px. */
@media (width <= 1240px) {
  .nav-toggle {
    display: inline-flex;
  }

  /* La nav passe en menu deroulant et quitte le flux : sa marge automatique
     part avec elle, et le bloc de droite retombait contre l'identite. Il
     reprend la marge a son compte pour rester colle au bord. */
  .header-actions {
    margin-left: auto;
  }

  /* La nav reste posee et invisible plutot que `display: none` : sans boite a
     interpoler, l'ouverture ne pourrait pas s'animer. `visibility` la retire
     du parcours clavier tant qu'elle est fermee. */
  nav {
    display: flex;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin-left: 0;
    background: #fff;
    box-shadow: 0 20px 40px rgb(16 24 40 / 0.12);
    border-radius: 0 0 var(--r-lg) var(--r-lg);
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    padding: 14px 20px 22px;
    visibility: hidden;
    transition:
      transform var(--dropdown-close-dur) var(--dropdown-ease),
      opacity var(--dropdown-close-dur) var(--dropdown-ease),
      visibility 0s linear var(--dropdown-close-dur);
  }

  /* L'annulation posee plus haut ne vaut qu'au-dessus du point de bascule : ici
     la nav redevient un vrai dropdown, replie tant qu'il n'est pas ouvert. */
  #site-nav.t-dropdown {
    transform: scale(var(--dropdown-pre-scale));
    opacity: 0;
    pointer-events: none;
  }

  #site-nav.t-dropdown.is-open {
    transform: scale(1);
    opacity: 1;
    pointer-events: auto;
  }

  #site-nav.t-dropdown.is-closing {
    transform: scale(var(--dropdown-closing-scale));
    opacity: 0;
    pointer-events: none;
  }

  nav.is-open {
    visibility: visible;
    transition:
      transform var(--dropdown-open-dur) var(--dropdown-ease),
      opacity var(--dropdown-open-dur) var(--dropdown-ease),
      visibility 0s linear 0s;
  }

  nav a {
    min-height: 48px;
    border-radius: var(--r-pill);
    font-size: 16px;
  }
}

@media (width <= 900px) {
  .brief-shell,
  .contacts-card {
    grid-template-columns: 1fr;
  }

  .promo-gallery {
    --gap: 14px;
  }

  /* Une seule grande tient a l'ecran : on elargit la vignette, les voisines
     depassent des bords. Les decalages ne changent pas, etant exprimes en
     pourcentage de la vignette. */
  .promo-strip.is-js .promo-gallery {
    --slide: 68%;
  }

  .promo-bleed {
    display: none;
  }

  .brief-photo {
    aspect-ratio: 16 / 9;
    min-height: 0;
  }

  .service-grid,
  .process,
  .industry-grid,
  .advantage-cards {
    grid-template-columns: 1fr 1fr;
  }

  /* Cinq cartes sur deux colonnes : la derniere prend le rang entier. */
  .service:last-child {
    grid-column: 1 / -1;
  }

  .advantage-cards .panel:first-child {
    grid-column: auto;
  }

  .footer-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (width <= 620px) {
  .container {
    width: min(100% - 28px, 1320px);
  }

  :root {
    --r-xl: 24px;
    --r-lg: 16px;
  }

  .logo img {
    height: 36px;
  }

  .header-bar {
    gap: 8px;
  }

  .header-tel {
    font-size: 14px;
  }

  /* Le bouton ne tient plus a cote de l'identite, du numero et du menu : il
     quitte l'en-tete. L'action reste atteignable par les deux boutons du hero,
     par le menu deroulant qui la reprend, et par la section du formulaire. */
  .header-actions > .button {
    display: none;
  }

  .nav-cta {
    display: inline-flex;
    justify-content: center;
  }

  .actions {
    flex-direction: column;
    align-items: stretch;
  }

  .actions .button {
    width: 100%;
  }

  .process,
  .fields {
    grid-template-columns: 1fr;
  }

  .promo-gallery {
    grid-template-columns: 1fr;
  }

  .promo-slide {
    aspect-ratio: 4 / 5;
  }

  .promo-strip.is-js .promo-gallery {
    --slide: 74%;
    grid-template-columns: none;
  }

  .industry {
    aspect-ratio: 3 / 2;
  }

  .form-card {
    padding: 0;
  }

  .review p {
    grid-template-columns: 1fr;
    gap: 3px;
  }

  /* Formulaire court : le numero de telephone ne tient pas a cote du bouton
     d'envoi ; on empile, l'envoi d'abord. */
  .quick-form .form-actions {
    flex-direction: column-reverse;
  }

  .quick-form .form-actions .button {
    width: 100%;
  }

  .cookie-banner {
    left: 8px;
    right: 8px;
    bottom: 8px;
    padding: 16px;
  }

  /* ====================== Mise en page telephone ======================= */
  /* Trois leviers, dans cet ordre d'effet sur la longueur de la page :
     — deux colonnes la ou une seule etirait le contenu (directions, chiffres,
       pied de page) ;
     — densite : hauteurs minimales retirees, rembourrages resserres, cartes
       remises en ligne quand leur contenu tient sur un rang ;
     — empilement colle pour les deux series de cartes qui restent hautes.
     Les textes courts se centrent : sur une colonne etroite, le fer a gauche
     laissait un drapeau irregulier sous chaque titre. */

  /* --- Rythme des sections ------------------------------------------- */
  .section {
    padding: 44px 0;
  }

  h2 {
    margin-bottom: 22px;
  }

  [id] {
    scroll-margin-top: 72px;
  }

  /* Les en-tetes de section se centrent, cartes et paragraphes longs non. */
  .section > .container > .badge,
  .section > .container > h2,
  .section > .container > h3,
  .section > .container > .section-intro,
  .page-title,
  .promo-head {
    text-align: center;
  }

  /* `inline-flex` ne se centre pas par `text-align` : la pastille prend sa
     largeur de contenu et se centre par ses marges. */
  .badge {
    display: flex;
    width: fit-content;
    margin-inline: auto;
    margin-bottom: 14px;
  }

  .section-intro {
    margin: -14px auto 24px;
  }

  .lead {
    margin-inline: auto;
  }

  .about-sub {
    margin: 34px 0 18px;
  }

  /* --- Empilement colle ----------------------------------------------- */
  /* Les cartes quittent la grille pour le flux : dans une grille a une colonne
     chaque carte est enfermee dans sa rangee et ne peut pas coller au dela.
     En flux, le bloc conteneur devient la serie entiere, et chaque carte tient
     sous l'en-tete jusqu'a ce que la suivante vienne la recouvrir. `--i`, pose
     sur la carte par la vue, decale chaque arret de 8px : les cartes deja
     posees restent visibles par la tranche, comme un jeu de cartes etale. Le
     filet d'un pixel suffit a les separer, sans ombre portee. */
  .service-grid,
  .advantage-cards {
    display: block;
  }

  .service,
  .advantage-cards .panel {
    position: sticky;
    top: calc(72px + var(--i, 0) * 8px);
  }

  .service + .service,
  .advantage-cards .panel + .panel {
    margin-top: 12px;
  }

  /* --- Services : numero et pictogramme a gauche, titre a droite -------- */
  .service {
    flex-direction: row;
    align-items: center;
    gap: 16px;
    min-height: 0;
    padding: 18px 20px;
  }

  .service-head {
    flex: 0 0 auto;
    flex-direction: column;
    align-items: center;
    gap: 6px;
  }

  .service .icon {
    width: 32px;
    height: 32px;
  }

  .service b {
    margin-top: 0;
    font-size: 16px;
  }

  /* --- Etapes : six blocs hauts devenaient une colonne interminable ---- */
  .process {
    gap: 10px;
  }

  .process li {
    flex-direction: row;
    align-items: center;
    gap: 16px;
    min-height: 0;
    padding: 16px 20px;
  }

  .process span {
    flex: 0 0 34px;
    font-size: 26px;
  }

  .process b {
    margin-top: 0;
    font-size: 16px;
  }

  /* --- Directions : deux colonnes carrees plutot que six bandeaux ------ */
  .industry-grid {
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }

  .industry {
    aspect-ratio: 1;
    border-radius: var(--r-lg);
  }

  .industry b {
    padding: 14px;
    font-size: 14px;
  }

  /* --- Chiffres : deux colonnes, centres --------------------------------- */
  .stat-grid {
    grid-template-columns: 1fr 1fr;
    gap: 20px 14px;
    text-align: center;
  }

  .stat span {
    font-size: 14px;
  }

  /* --- Avantages ------------------------------------------------------ */
  /* Le bloc le plus long de la page : cinq panneaux de texte. Faute de pouvoir
     raccourcir la copie, on resserre le pave — un cran de corps et
     d'interlignage rend un peu plus d'un ecran sur la section. */
  .advantage-cards .panel {
    padding: 22px;
  }

  .panel b {
    font-size: 18px;
  }

  .panel p {
    margin-top: 10px;
    font-size: 15px;
    line-height: 1.55;
  }

  .advantage-photo {
    min-height: 200px;
  }

  /* --- Demande courte -------------------------------------------------- */
  /* La photo n'est plus qu'un bandeau : elle situe la section sans reprendre
     un ecran entier avant le formulaire. */
  .brief-photo {
    aspect-ratio: 21 / 9;
  }

  .brief-form {
    padding: 16px;
  }

  /* --- FAQ -------------------------------------------------------------- */
  .faq summary {
    gap: 14px;
    padding: 18px 0;
    font-size: 16px;
  }

  .faq p {
    margin-bottom: 18px;
  }

  .legal-note {
    padding: 18px 20px;
    margin-top: 22px;
    font-size: 14px;
  }

  /* --- Contacts --------------------------------------------------------- */
  .contacts-card {
    padding: 26px 20px;
    gap: 22px;
    text-align: center;
  }

  .contact-tile {
    padding: 14px 18px;
    text-align: center;
  }

  /* --- Pied de page : deux colonnes de liens sous l'identite ------------ */
  .footer-grid {
    grid-template-columns: 1fr 1fr;
    gap: 26px 16px;
    text-align: center;
  }

  .footer-grid > div {
    align-items: center;
  }

  .footer-brand {
    grid-column: 1 / -1;
  }

  .footer-brand p {
    max-width: 34ch;
    margin-inline: auto;
  }

  .footer-col a,
  .footer-link {
    padding: 9px 0;
    text-align: center;
  }

  .footer-bottom {
    justify-content: center;
    text-align: center;
  }

  .document {
    padding: 40px 0;
  }

  /* --- Consultation : la fenetre devient une feuille du bas ------------- */
  .chat-launcher {
    right: 16px;
    bottom: 16px;
  }

  .chat-launcher-photo {
    width: 56px;
    height: 56px;
  }

  .chat-launcher-dot {
    left: 39px;
    top: 39px;
  }

  .chat-teaser {
    left: auto;
    right: 16px;
    bottom: 78px;
    width: auto;
    max-width: min(230px, calc(100vw - 84px));
    padding: 9px 28px 9px 12px;
    border-radius: var(--r-md);
    box-shadow: 0 4px 16px rgb(6 20 42 / 0.16);
  }

  .chat-teaser p {
    font-size: 12.5px;
    line-height: 1.35;
  }

  /* Hauteur fixe plutot qu'ajustee au contenu : une feuille qui grandit a
     chaque message donnerait un a-coup a chaque tour d'echange. */
  dialog.chat-panel {
    width: 100%;
    height: 82dvh;
    margin: auto auto 0;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    transform-origin: 50% 100%;
    transform: translateY(100%);
    opacity: 1;
  }

  dialog.chat-panel[open] {
    transform: translateY(0);
    opacity: 1;
  }

  @starting-style {
    dialog.chat-panel[open] {
      transform: translateY(100%);
      opacity: 1;
    }
  }

  dialog.chat-panel.is-closing {
    transform: translateY(100%);
    opacity: 1;
  }

  dialog.chat-panel.is-dragging {
    transform: translateY(var(--sheet-drag, 0px));
    transition: none;
  }

  /* La barre de prise est le premier element de la colonne : elle ne se
     comprime pas, et le bouton de fermeture se cale dedans. */
  .chat-panel .sheet-grab {
    flex: 0 0 auto;
  }

  dialog.chat-panel .modal-close {
    top: -3px;
    right: 4px;
  }

  .chat-head {
    padding-top: 6px;
  }

}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }

  .button:hover,
  .button:active {
    scale: 1;
  }

  .button:hover::after {
    translate: 0;
  }

  .reveal {
    opacity: 1;
    translate: none;
  }

  .route-line {
    animation: none;
  }
}

/* ------------------------ Formulaire sur telephone ---------------------- */
/* Plus d'air : marges de la carte, ecart entre les champs, jour et creneau
   l'un sous l'autre, consentement puis bouton pleine largeur. */
@media (width <= 620px) {
  /* La coque de la section et la carte du formulaire etaient deux surfaces
     grises identiques emboitees : les champs, gris eux aussi, venaient toucher
     le bord de la coque sans separation visible. Une seule surface, blanche,
     et l'ecart du formulaire pour seul retrait. */
  .brief-shell {
    background: #fff;
  }

  .brief-form {
    padding: 24px 20px 28px;
  }

  .brief-form .form-card {
    box-shadow: none;
  }

  .fields {
    gap: 20px;
  }

  .callback > .field-label {
    margin-bottom: 9px;
  }

  .callback {
    gap: 8px;
  }

  .callback-grid {
    grid-template-columns: 1fr;
    gap: 20px;
  }

  /* Cible du pouce : un cran au-dessus du gabarit d'un champ. */
  .picker-option {
    min-height: 48px;
  }

  .form-foot {
    display: grid;
    gap: 20px;
    margin-top: 22px;
  }

  .form-foot .form-actions .button {
    width: 100%;
  }

  dialog.modal .modal-body {
    padding: 24px 20px 30px;
  }
}

@media print {
  header,
  footer,
  .cookie-banner,
  .contacts-section,
  .form-actions {
    display: none !important;
  }
}

