/* ==========================================================================
   55 · agency — 2026 brand stylesheet
   ========================================================================== */

:root {
  --bg: #07070b;
  --bg-soft: #0d0d14;
  --bg-elev: #14141c;
  --surface: rgba(255, 255, 255, 0.04);
  --surface-strong: rgba(255, 255, 255, 0.07);
  --border: rgba(255, 255, 255, 0.08);
  --border-strong: rgba(255, 255, 255, 0.16);

  --text: #f5f5f7;
  --text-soft: #b5b5c3;
  --text-muted: #7c7c8c;

  --accent-1: #ff4d6d;   /* magenta */
  --accent-2: #ff8a3d;   /* warm orange */
  --accent-3: #7c5cff;   /* electric violet */
  --accent-4: #2ddcff;   /* cyan */

  --grad-brand: linear-gradient(120deg, #7c5cff 0%, #ff4d6d 55%, #ff8a3d 100%);
  --grad-initials: linear-gradient(100deg, #7c5cff 0%, #ff4d6d 28%, #ff8a3d 50%, #ff4d6d 72%, #7c5cff 100%);
  --grad-brand-soft: linear-gradient(120deg, rgba(124,92,255,.14), rgba(255,77,109,.14) 55%, rgba(255,138,61,.14));
  --grad-ai: linear-gradient(120deg, #2ddcff 0%, #7c5cff 100%);

  --radius-xs: 8px;
  --radius-sm: 14px;
  --radius-md: 22px;
  --radius-lg: 32px;
  --radius-pill: 999px;

  --shadow-1: 0 1px 0 rgba(255,255,255,.05) inset, 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 30px 60px -20px rgba(0,0,0,.55), 0 8px 24px -12px rgba(0,0,0,.4);
  --shadow-glow: 0 0 0 1px rgba(255,255,255,.06), 0 40px 120px -30px rgba(124,92,255,.35);

  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --font-display: 'Manrope', 'Inter', -apple-system, sans-serif;

  --container: 1240px;
  --gutter: clamp(20px, 4vw, 48px);

  --ease: cubic-bezier(.2, .8, .2, 1);
  --ease-out: cubic-bezier(.16, 1, .3, 1);

  /* --- Theme-dependent tokens (dark = default) --------------------------- */
  color-scheme: dark;

  --border-hover: rgba(255,255,255,.28);
  --on-accent: #ffffff;          /* text/icons sitting on a brand gradient */
  --on-ai: #07070b;              /* icon colour on the AI gradient */
  --ai-ink: #2ddcff;             /* cyan used as text */
  --ok: #6df7c1;
  --err: #ff8a8a;

  --body-glow:
    radial-gradient(1200px 600px at 80% -10%, rgba(124,92,255,.18), transparent 60%),
    radial-gradient(800px 400px at 10% 10%, rgba(255,77,109,.12), transparent 60%),
    radial-gradient(1000px 500px at 50% 110%, rgba(255,138,61,.10), transparent 60%);
  --orb-opacity: .55;

  --header-bg: rgba(7,7,11,.7);
  --nav-pill-bg: rgba(20,20,28,.55);
  --menu-bg: rgba(7,7,11,.96);
  --glass-bg: rgba(7,7,11,.75);
  --marquee-bg: rgba(13,13,20,.4);
  --footer-fade: linear-gradient(180deg, transparent, rgba(13,13,20,.6));
  --frame-fade: rgba(7,7,11,.4);
  --scrim: linear-gradient(180deg, rgba(7,7,11,.58) 0%, rgba(7,7,11,.16) 34%, rgba(7,7,11,0) 58%);

  --btn-solid-bg: #ffffff;
  --btn-solid-fg: #0d0d14;
  --btn-solid-shadow: 0 10px 30px -10px rgba(255,255,255,.4);
  --btn-solid-shadow-hover: 0 16px 40px -12px rgba(255,255,255,.55);

  --logo-filter: brightness(0) invert(1);
  --logo-opacity: .72;
  /* Logos multicolores : nuances de gris plutot qu'aplat, pour que les
     formes superposees restent distinctes (cf. .logo-color). */
  --logo-filter-tone: grayscale(1) invert(1) brightness(1.3);

  /* Mockups (phone / browser / design canvas / mini cards) */
  --mock-frame-bg: linear-gradient(160deg, #14141c 0%, #0d0d14 100%);
  --mock-bg: linear-gradient(160deg, #0d0d14, #07070b);
  --mock-screen: #07070b;
  --mock-bezel: #1a1a24;
  --mock-chrome: #14141c;
  --mock-page: #0d0d14;
  --mock-hero: #1a1a24;
  --mock-surface: rgba(255,255,255,.04);
  --mock-surface-2: rgba(255,255,255,.06);
  --mock-border: rgba(255,255,255,.08);
  --mock-line: rgba(255,255,255,.13);
  --mock-line-strong: rgba(255,255,255,.18);
  --mock-ink: #ffffff;
  --mock-phone-shadow: 0 30px 80px -20px rgba(0,0,0,.7), 0 0 0 1px rgba(255,255,255,.06) inset;
  --mock-shadow: 0 30px 80px -20px rgba(0,0,0,.6);

  --canvas-bg: #0a0a12;
  --canvas-grid: rgba(255,255,255,.025);
  --canvas-frame-bg: rgba(20,20,28,.8);

  --tile-bg: linear-gradient(160deg, #14141c, #0a0a12);
  --vision-bg: linear-gradient(160deg, #14141c, #07070b);
}

/* Reset --------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; -moz-tab-size: 4; tab-size: 4; scroll-behavior: smooth; }
body { margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; padding: 0; }
img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, h5, p { margin: 0; }

/* Base ---------------------------------------------------------------------- */
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.55;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  background-image: var(--body-glow);
  background-attachment: fixed;
}

::selection { background: var(--accent-3); color: #fff; }

/* Typography ---------------------------------------------------------------- */
.eyebrow {
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--text-soft);
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.eyebrow::before {
  content: "";
  display: inline-block;
  width: 28px;
  height: 1px;
  background: var(--grad-brand);
}

h1, h2, h3 { font-family: var(--font-display); letter-spacing: -.02em; line-height: 1.05; font-weight: 700; }
.h-display {
  font-size: clamp(2.4rem, 6.4vw, 5.5rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1;
}
.h-1 { font-size: clamp(2rem, 4.6vw, 3.4rem); }
.h-2 { font-size: clamp(1.6rem, 3.2vw, 2.3rem); line-height: 1.15; }
/* Trailing qualifier inside a hero headline — steps down from the main line.
   Sized in em so it tracks the heading's own clamp() as the viewport changes. */
.h-tail { font-size: .7em; letter-spacing: -.02em; }

.h-3 { font-size: clamp(1.2rem, 2vw, 1.45rem); line-height: 1.25; }
.lead { font-size: clamp(1.05rem, 1.5vw, 1.25rem); color: var(--text-soft); max-width: 62ch; }

/* Le corps des descriptions est volontairement adouci (--text-soft) : les mots
   mis en avant reprennent la couleur pleine du texte. C'est ce contraste de
   VALEUR, plus que la graisse seule, qui les fait ressortir — un simple bold
   sur du texte déjà gris se voit à peine. */
.lead strong,
.lead b {
  font-weight: 650;
  color: var(--text);
}
.text-muted { color: var(--text-muted); }
.text-gradient {
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.text-gradient-ai {
  background: var(--grad-ai);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Layout -------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}
.section { padding: clamp(80px, 12vw, 160px) 0; position: relative; }
.section--tight { padding: clamp(60px, 9vw, 110px) 0; }
.section-header { max-width: 760px; margin-bottom: clamp(40px, 6vw, 72px); }
.section-header > * + * { margin-top: 18px; }
.divider { height: 1px; background: linear-gradient(90deg, transparent, var(--border-strong), transparent); border: 0; margin: 0; }

/* Buttons ------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 17px 28px;
  border-radius: var(--radius-pill);
  font-weight: 600;
  font-size: 15.5px;
  letter-spacing: .01em;
  line-height: 1;
  transition: transform .25s var(--ease), background .25s var(--ease), color .25s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
  white-space: nowrap;
  will-change: transform;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn-primary {
  color: var(--btn-solid-fg);
  background: var(--btn-solid-bg);
  box-shadow: var(--btn-solid-shadow);
}
.btn-primary:hover { background: var(--btn-solid-bg); box-shadow: var(--btn-solid-shadow-hover); }

.btn-gradient {
  color: var(--on-accent);
  background: var(--grad-brand);
  box-shadow: 0 10px 30px -10px rgba(255,77,109,.5);
}
.btn-gradient:hover { box-shadow: 0 20px 50px -16px rgba(255,77,109,.65); }

.btn-ghost {
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  backdrop-filter: blur(10px);
}
.btn-ghost:hover { background: var(--surface-strong); border-color: var(--border-hover); }

.btn .arrow { display: inline-block; transition: transform .3s var(--ease); }

/* Bouton de retour en tête des articles. Le fil d'Ariane a été retiré du blog :
   ce bouton garde une sortie vers l'accueil sans réintroduire de hiérarchie. */
.btn-back { padding: 9px 18px; font-size: 13.5px; }
.btn .arrow--left { display: inline-block; transition: transform .3s var(--ease); }
.btn:hover .arrow--left { transform: translateX(-4px); }
.btn:hover .arrow { transform: translateX(4px); }
.btn:hover .arrow--down { transform: translateY(3px); }

/* Icône téléphone — même tracé dans le bouton d'en-tête et dans la carte
   contact. Le SVG porte aria-hidden : le numéro juste à côté fait le libellé. */
.icon-phone,
.icon-mail { width: 16px; height: 16px; flex: none; }
.btn .icon-phone,
.btn .icon-mail { margin-right: -2px; }
.info-card h4 a { display: inline-flex; align-items: center; gap: 10px; }
.info-card h4 .icon-phone,
.info-card h4 .icon-mail { width: 17px; height: 17px; color: var(--accent-3); }

/* Header / Nav -------------------------------------------------------------- */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  padding: 18px 0;
  transition: padding .3s var(--ease), background .3s var(--ease), backdrop-filter .3s var(--ease), border-color .3s var(--ease);
  border-bottom: 1px solid transparent;
}
.site-header.is-scrolled {
  padding: 12px 0;
  background: var(--header-bg);
  backdrop-filter: saturate(180%) blur(18px);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  border-bottom-color: var(--border);
}
.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
/* Wordmark — "55·agency" with a coloured accent dot */
.brand {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 24px;
  letter-spacing: -.045em;
  color: var(--text);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}
.brand-dot {
  display: inline-block;
  width: 8px; height: 8px;
  background: var(--grad-brand);
  border-radius: 50%;
  margin: 0 8px;
  vertical-align: middle;
  position: relative;
  top: -3px;
  box-shadow: 0 0 18px rgba(255,77,109,.55);
  flex: 0 0 auto;
}
/* Legacy redundant badge — kept hidden in case any page still uses it */
.brand-mark { display: none; }

/* Header logo — two variants of the same mark, swapped with the theme so the
   ink always contrasts. Both are decorative; the link carries the accessible
   name via aria-label, which keeps working whichever variant is hidden. */
.brand-logo { height: 30px; width: auto; display: none; }
.brand-logo--light { display: block; }
:root[data-theme="dark"] .brand-logo--light { display: none; }
:root[data-theme="dark"] .brand-logo--dark  { display: block; }
@media (max-width: 480px) { .brand-logo { height: 26px; } }

/* Footer wordmark uses the same two-variant mark, a touch larger. */
.footer-brand .brand-logo { height: 34px; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--nav-pill-bg);
  border: 1px solid var(--border);
  padding: 6px;
  border-radius: var(--radius-pill);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.nav-links a {
  padding: 10px 18px;
  font-size: 14.5px;
  font-weight: 500;
  color: var(--text-soft);
  border-radius: var(--radius-pill);
  transition: color .2s var(--ease), background .2s var(--ease);
}
.nav-links a:hover { color: var(--text); }
.nav-links a.is-active { color: var(--text); background: var(--surface-strong); }

.nav-cta { display: flex; align-items: center; gap: 12px; }
.lang-switch {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  overflow: hidden;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .06em;
}
.lang-switch a {
  padding: 8px 12px;
  color: var(--text-muted);
  transition: color .2s var(--ease), background .2s var(--ease);
}
.lang-switch a.is-active { background: var(--surface-strong); color: var(--text); }
.lang-switch a:hover { color: var(--text); }

.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border-strong);
  align-items: center; justify-content: center;
}
.nav-toggle span {
  display: block;
  width: 18px; height: 2px;
  background: var(--text);
  position: relative;
}
.nav-toggle span::before, .nav-toggle span::after {
  content: "";
  position: absolute; left: 0;
  width: 18px; height: 2px; background: var(--text);
  transition: transform .25s var(--ease), top .25s var(--ease);
}
.nav-toggle span::before { top: -6px; }
.nav-toggle span::after { top: 6px; }

/* Mobile menu --------------------------------------------------------------- */
.mobile-menu {
  position: fixed; inset: 0;
  z-index: 99;
  background: var(--menu-bg);
  backdrop-filter: blur(20px);
  display: flex; flex-direction: column;
  padding: 100px var(--gutter) 40px;
  transform: translateY(-100%);
  transition: transform .45s var(--ease-out);
  visibility: hidden;
}
.mobile-menu.is-open { transform: translateY(0); visibility: visible; }
.mobile-menu a {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 8vw, 3rem);
  letter-spacing: -.02em;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
  display: block;
}
.mobile-menu .mobile-footer {
  margin-top: auto;
  display: flex; flex-direction: column; gap: 18px;
  color: var(--text-soft);
  font-size: 14px;
}

/* Hero ---------------------------------------------------------------------- */
.hero {
  position: relative;
  padding: clamp(140px, 18vw, 200px) 0 clamp(80px, 10vw, 140px);
  overflow: hidden;
}
.hero-bg-orbs {
  position: absolute; inset: -10%; pointer-events: none; z-index: 0;
}
.hero-bg-orbs::before, .hero-bg-orbs::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  filter: blur(80px);
  opacity: var(--orb-opacity);
}
.hero-bg-orbs::before {
  width: 520px; height: 520px;
  background: radial-gradient(circle, #7c5cff, transparent 60%);
  top: 0; right: -10%;
  animation: float1 16s ease-in-out infinite;
}
.hero-bg-orbs::after {
  width: 460px; height: 460px;
  background: radial-gradient(circle, #ff4d6d, transparent 60%);
  bottom: 0; left: -10%;
  animation: float2 18s ease-in-out infinite;
}
@keyframes float1 { 0%,100%{transform:translate(0,0)} 50%{transform:translate(-40px,30px)} }
@keyframes float2 { 0%,100%{transform:translate(0,0)} 50%{transform:translate(50px,-30px)} }

.hero-grid {
  position: relative; z-index: 1;
  display: grid;
  /* Colonne texte élargie pour laisser respirer un titre volontairement grand.
     C'est le mot tournant le plus long (« sites e-commerce », en nowrap) qui
     fixe le plafond : à 1440 px il mesure 637 px pour 718 px de colonne. */
  grid-template-columns: 1.35fr .65fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
@media (max-width: 1024px) { .hero-grid { grid-template-columns: 1fr; } }

.hero-title { margin-top: 24px; }
.hero-sub { margin-top: 24px; }
.hero-actions { margin-top: 36px; display: flex; gap: 14px; flex-wrap: wrap; }
.hero-meta {
  margin-top: 56px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: 24px;
  padding-top: 32px;
  border-top: 1px solid var(--border);
}
.hero-meta .stat strong {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  font-weight: 800;
  letter-spacing: -.02em;
  display: block;
}
/* Direct child only: the counter lives in .stat > strong > span[data-count],
   and a bare descendant selector shrank the number to the label size. */
.hero-meta .stat > span { color: var(--text-muted); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; }

/* Hero showcase ------------------------------------------------------------- */
/* Le cadre (fond dégradé, bordure, lueur) a sauté : les trois maquettes
   flottent directement sur la page. Le padding reste — il ne dessine plus
   rien, mais les cartes sont positionnées en % de la boîte de padding, et
   le retirer les décalerait. overflow visible pour que le mouvement de
   dérive ne soit pas rogné une fois la bordure disparue. */
.hero-showcase {
  position: relative;
  aspect-ratio: 4 / 5;
  padding: 22px;
  overflow: visible;
  /* Remontée par la marge et non par un transform : GSAP anime .hero-showcase
     à l'ouverture et poserait son propre transform inline par-dessus. */
  margin-top: -48px;
}
/* En dessous, la grille du hero passe sur une colonne : les maquettes se
   retrouvent sous le texte, où une marge négative les ferait chevaucher. */
@media (max-width: 1024px) { .hero-showcase { margin-top: 0; } }
.hero-showcase .showcase-card {
  position: absolute;
  background: var(--bg-elev);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-2);
  overflow: hidden;
}
.showcase-card img { width: 100%; height: 100%; object-fit: cover; display:block; }
.showcase-card-1 { top: 8%; left: 6%; width: 52%; aspect-ratio: 9/16; transform: rotate(-5deg); animation: drift1 9s ease-in-out infinite; }
.showcase-card-2 { top: 28%; right: 6%; width: 46%; aspect-ratio: 9/16; transform: rotate(4deg); animation: drift2 11s ease-in-out infinite; }
.showcase-card-3 {
  bottom: 6%; left: 24%; width: 60%; aspect-ratio: 16/10; transform: rotate(-2deg);
  animation: drift3 13s ease-in-out infinite;
}
@keyframes drift1 { 0%,100%{transform:rotate(-5deg) translateY(0)} 50%{transform:rotate(-5deg) translateY(-10px)} }
@keyframes drift2 { 0%,100%{transform:rotate(4deg) translateY(0)} 50%{transform:rotate(4deg) translateY(12px)} }
@keyframes drift3 { 0%,100%{transform:rotate(-2deg) translateY(0)} 50%{transform:rotate(-2deg) translateY(-8px)} }

.showcase-badge {
  position: absolute;
  bottom: 22px; right: 22px;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border-strong);
  padding: 10px 14px;
  border-radius: var(--radius-pill);
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--text-soft);
  display: inline-flex; align-items: center; gap: 8px;
}
.live-dot { width: 7px; height: 7px; border-radius: 50%; background: #2ddcff; box-shadow: 0 0 12px #2ddcff; }

/* Marquee ------------------------------------------------------------------- */
.marquee {
  overflow: hidden;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 26px 0;
  background: var(--marquee-bg);
}
.marquee-track {
  display: flex;
  gap: 64px;
  white-space: nowrap;
  animation: marquee 40s linear infinite;
}
.marquee span {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1rem, 1.6vw, 1.3rem);
  color: var(--text-muted);
  letter-spacing: -.01em;
  display: inline-flex; align-items: center; gap: 64px;
}
.marquee span::after { content: "✦"; color: var(--accent-1); opacity: .6; }
@keyframes marquee { to { transform: translateX(-50%); } }

/* Services ------------------------------------------------------------------ */
.services-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 18px;
}
.svc-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 32px;
  overflow: hidden;
  transition: transform .35s var(--ease), border-color .35s var(--ease), background .35s var(--ease);
  min-height: 280px;
  display: flex; flex-direction: column;
}
.svc-card:hover { transform: translateY(-4px); border-color: var(--border-strong); background: var(--surface-strong); }
.svc-card .svc-icon {
  width: 52px; height: 52px;
  border-radius: 14px;
  background: var(--surface-strong);
  border: 1px solid var(--border-strong);
  display: grid; place-items: center;
  margin-bottom: 22px;
  transition: background .35s var(--ease), border-color .35s var(--ease), color .35s var(--ease);
}
.svc-card .svc-icon svg { width: 24px; height: 24px; }
.svc-card h3 { margin-bottom: 10px; }
.svc-card p { color: var(--text-soft); font-size: 15.5px; }
.svc-card .svc-link {
  margin-top: auto;
  padding-top: 22px;
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 14px; font-weight: 600;
  color: var(--text);
}
.svc-card .svc-link .arrow { transition: transform .25s var(--ease); }
.svc-card:hover .svc-link .arrow { transform: translateX(4px); }

/* Colour treatment: permanent on the AI card, revealed on hover everywhere
   else. A gradient background can't be transitioned, so the tint lives on an
   ::after layer whose opacity fades. Hues cycle by position so a six-card grid
   never repeats two identical cards side by side. */
.svc-card > * { position: relative; z-index: 1; }
.svc-card:not(.svc-ai)::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  transition: opacity .4s var(--ease);
  background:
    radial-gradient(700px 200px at 100% 0%, var(--svc-glow-a), transparent 60%),
    radial-gradient(560px 200px at 0% 100%, var(--svc-glow-b), transparent 60%);
}
.svc-card:not(.svc-ai):hover::after { opacity: 1; }
.svc-card:not(.svc-ai):hover { border-color: var(--svc-border); }
.svc-card:not(.svc-ai):hover .svc-icon {
  background: var(--svc-grad);
  border-color: transparent;
  color: var(--on-ai);
}

.services-grid > .svc-card {                 /* violet -> cyan */
  --svc-glow-a: rgba(124,92,255,.20); --svc-glow-b: rgba(45,220,255,.18);
  --svc-border: rgba(124,92,255,.32); --svc-grad: linear-gradient(120deg,#7c5cff,#2ddcff);
}
.services-grid > .svc-card:nth-child(4n+2) { /* cyan -> violet */
  --svc-glow-a: rgba(45,220,255,.20); --svc-glow-b: rgba(124,92,255,.18);
  --svc-border: rgba(45,220,255,.32); --svc-grad: linear-gradient(120deg,#2ddcff,#7c5cff);
}
.services-grid > .svc-card:nth-child(4n+3) { /* orange -> magenta */
  --svc-glow-a: rgba(255,138,61,.20); --svc-glow-b: rgba(255,77,109,.18);
  --svc-border: rgba(255,138,61,.34); --svc-grad: linear-gradient(120deg,#ff8a3d,#ff4d6d);
}
.services-grid > .svc-card:nth-child(4n+4) { /* magenta -> violet */
  --svc-glow-a: rgba(255,77,109,.20); --svc-glow-b: rgba(124,92,255,.20);
  --svc-border: rgba(255,77,109,.32); --svc-grad: linear-gradient(120deg,#ff4d6d,#7c5cff);
}

.svc-card.col-6 { grid-column: span 6; }
.svc-card.col-4 { grid-column: span 4; }
.svc-card.col-8 { grid-column: span 8; }
.svc-card.col-12 { grid-column: span 12; }
@media (max-width: 900px) {
  .svc-card.col-6, .svc-card.col-4, .svc-card.col-8, .svc-card.col-12 { grid-column: span 12; }
}

.svc-card.svc-ai {
  background:
    radial-gradient(800px 200px at 100% 0%, rgba(45,220,255,.18), transparent 60%),
    radial-gradient(600px 200px at 0% 100%, rgba(124,92,255,.18), transparent 60%),
    var(--bg-elev);
  border-color: rgba(45,220,255,.25);
}
.svc-card.svc-ai .svc-icon { background: var(--grad-ai); border-color: transparent; color: var(--on-ai); }
.svc-card.svc-ai .ai-pill {
  position: absolute; top: 24px; right: 24px;
  font-size: 11px; letter-spacing: .18em; text-transform: uppercase;
  padding: 6px 12px;
  background: rgba(45,220,255,.12);
  border: 1px solid rgba(45,220,255,.4);
  border-radius: var(--radius-pill);
  color: var(--ai-ink);
}

/* Portfolio grid ------------------------------------------------------------ */
.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 18px;
}
.case {
  grid-column: span 6;
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  aspect-ratio: 4/3;
  transition: transform .4s var(--ease), border-color .4s var(--ease);
}
/* Les visuels font tous 1900×1332. La grande carte adopte ce rapport exact :
   elle ne recadre plus rien (le logo en bas de l'image était coupé).
   La carte haute n'impose aucun rapport et s'étire sur la hauteur de rangée,
   qui est donc celle de sa voisine — leurs bas s'alignent au pixel, quelle
   que soit la largeur de la fenêtre. Un rapport fixe des deux côtés ne
   pouvait s'aligner qu'à une seule largeur. */
.case.case-wide { grid-column: span 7; aspect-ratio: 1900 / 1332; }
.case.case-tall {
  grid-column: span 5;
  aspect-ratio: auto;
  align-self: stretch;
  min-height: 280px;   /* filet si elle se retrouve seule sur sa rangée */
}
.case.case-full { grid-column: span 12; aspect-ratio: 2 / 1; }
@media (max-width: 900px) {
  .case, .case.case-wide, .case.case-tall, .case.case-full {
    grid-column: span 12;
    aspect-ratio: 1900 / 1332;
    align-self: auto;
    min-height: 0;
  }
}
.case:hover { transform: translateY(-4px); border-color: var(--border-strong); }
.case-bg {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  transition: transform .8s var(--ease-out), filter .4s var(--ease);
  filter: saturate(1.05);
}
.case:hover .case-bg { transform: scale(1.05); filter: saturate(1.2); }
.case-overlay {
  position: absolute; inset: 0;
  background: var(--scrim);
}
.case-content {
  position: absolute; inset: 0 0 auto 0;
  padding: 18px;
  z-index: 2;
  color: #fff; /* artwork stays dark in both themes */
}
/* The client's own logo is baked into every mockup, so the card carries only a
   small category badge — the project name stays in the DOM for screen readers
   and crawlers via .sr-only. */
.case-tag {
  display: inline-block;
  font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  color: rgba(255,255,255,.88);
  padding: 5px 11px;
  border: 1px solid rgba(255,255,255,.22);
  border-radius: var(--radius-pill);
  background: rgba(7,7,11,.55);
  backdrop-filter: blur(6px);
  margin-bottom: 0;
}
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.case h3 { font-size: clamp(1.3rem, 2vw, 1.7rem); }
.case p { color: rgba(255,255,255,.78); margin-top: 6px; font-size: 14.5px; }

/* Stats / numbers ----------------------------------------------------------- */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  overflow: hidden;
}
@media (max-width: 768px) { .stats { grid-template-columns: repeat(2, 1fr); } }
.stat-cell {
  padding: 36px 28px;
  border-right: 1px solid var(--border);
}
.stat-cell:last-child { border-right: 0; }
@media (max-width: 768px) {
  .stat-cell { border-right: 0; border-bottom: 1px solid var(--border); }
  .stat-cell:nth-child(2n) { border-right: 0; }
}
.stat-cell strong {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2rem, 4vw, 2.8rem);
  letter-spacing: -.025em;
  display: block;
  background: var(--grad-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* Same here — it also overrode the gradient on the number. */
.stat-cell > span { color: var(--text-soft); font-size: 14px; }

/* Logos cloud --------------------------------------------------------------- */
.logo-cloud {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
@media (max-width: 768px) { .logo-cloud { grid-template-columns: repeat(2, 1fr); } }
.logo-cell {
  background: var(--bg-soft);
  display: grid; place-items: center;
  padding: 28px;
  min-height: 110px;
}
/* Force every logo to a uniform monochrome treatment (white on dark, ink on light) */
.logo-cell img {
  max-height: 38px;
  width: auto;
  opacity: var(--logo-opacity);
  transition: opacity .25s var(--ease), transform .25s var(--ease);
  filter: var(--logo-filter);
}
.logo-cell:hover img { opacity: 1; transform: scale(1.04); }

/* Logos dont les formes se chevauchent (M6) : l'aplat noir les rend illisibles,
   le 6 disparaissant dans le M. On conserve leurs couleurs, l'opacite commune
   suffisant a les fondre dans la grille. */
.logo-cell img.logo-color { filter: var(--logo-filter-tone); }

/* Process / steps ----------------------------------------------------------- */
.steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 18px;
}
@media (max-width: 900px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px) { .steps { grid-template-columns: 1fr; } }
.step {
  padding: 28px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--border);
  position: relative;
}
.step .step-num {
  font-family: var(--font-display);
  font-size: 13px; letter-spacing: .12em;
  color: var(--text-muted);
  margin-bottom: 18px;
}
/* FAQ variant of the step card: an icon badge replaces the step number, so the
   modifier is scoped — plain .step blocks stay untouched as process phases. */
.step--faq { transition: transform .4s var(--ease-out), border-color .4s var(--ease); }
.step--faq:hover { transform: translateY(-4px); border-color: var(--border-strong); }
.step--faq .step-icon {
  width: 42px; height: 42px;
  border-radius: 12px;
  display: grid; place-items: center;
  background: var(--surface-strong);
  border: 1px solid var(--border-strong);
  color: var(--text);
  margin-bottom: 18px;
  transition: background .35s var(--ease), border-color .35s var(--ease), color .35s var(--ease);
}
.step--faq .step-icon svg { width: 20px; height: 20px; }
.step--faq:hover .step-icon {
  background: var(--grad-brand);
  border-color: transparent;
  color: var(--on-ai);
}

.step h3 { font-size: 1.2rem; }
.step p { color: var(--text-soft); margin-top: 8px; font-size: 14.5px; }

/* Testimonials -------------------------------------------------------------- */
.testimonials {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
}
@media (max-width: 900px) { .testimonials { grid-template-columns: 1fr; } }
.testimonial {
  padding: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  display: flex; flex-direction: column;
}
.testimonial blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.5;
  font-weight: 500;
  letter-spacing: -.01em;
}
.testimonial .who {
  margin-top: auto;
  padding-top: 28px;
  display: flex; align-items: center; gap: 14px;
}
.testimonial .avatar {
  width: 44px; height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--grad-brand);
  display: grid; place-items: center;
  font-weight: 700;
  color: var(--on-accent);
  overflow: hidden;
}
/* Portrait client : l'image recouvre le dégradé, qui reste visible en fallback
   (chargement, image manquante) ou quand la carte n'affiche que des initiales. */
.testimonial .avatar img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 50%;
}
.testimonial .who-text small { color: var(--text-muted); font-size: 12.5px; display: block; }

/* CTA banner ---------------------------------------------------------------- */
.cta {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  padding: clamp(48px, 7vw, 90px);
  background:
    radial-gradient(600px 300px at 0% 0%, rgba(124,92,255,.28), transparent 60%),
    radial-gradient(600px 300px at 100% 100%, rgba(255,77,109,.28), transparent 60%),
    var(--bg-elev);
  border: 1px solid var(--border-strong);
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 40px;
  align-items: center;
}
@media (max-width: 900px) { .cta { grid-template-columns: 1fr; } }
.cta-actions { display: flex; gap: 14px; flex-wrap: wrap; }
.cta-actions .btn { white-space: nowrap; }
/* La colonne d'actions valait 1fr sur 1.4fr : à quelques pixels près, les deux
   boutons n'y tenaient pas et le numéro tombait à la ligne. Elle est désormais
   dimensionnée par son contenu, et c'est le texte qui cède la largeur. */
@media (min-width: 901px) {
  .cta { grid-template-columns: minmax(0, 1fr) max-content; }
  .cta-actions { flex-wrap: nowrap; }
}

/* Form / contact ------------------------------------------------------------ */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 72px);
  align-items: start;
}
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; } }

.contact-info { display: flex; flex-direction: column; gap: 28px; }
.info-card {
  padding: 26px;
  border-radius: var(--radius-md);
  background: var(--surface);
  border: 1px solid var(--border);
}
.info-card small { color: var(--text-muted); font-size: 12px; letter-spacing: .14em; text-transform: uppercase; }
.info-card h4 { font-family: var(--font-display); font-weight: 700; font-size: 1.15rem; margin-top: 8px; }
.info-card p { color: var(--text-soft); margin-top: 4px; }
.info-card a { color: var(--text); text-decoration: none; }
.info-card a:hover { color: var(--text); }

/* Quick-response band — full width, sits above the contact form */
.contact-banner {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 32px;
  padding: 26px clamp(24px, 4vw, 40px);
  margin-bottom: clamp(36px, 5vw, 56px);
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
  background: linear-gradient(135deg, rgba(124,92,255,.20), rgba(255,77,109,.18) 55%, rgba(255,138,61,.16));
}
.contact-banner::before {
  content: "";
  position: absolute; inset: 0 auto 0 0;
  width: 4px;
  background: var(--grad-brand);
}
.contact-banner-text { flex: 1 1 320px; }
.contact-banner .eyebrow-sm {
  display: block;
  font-size: 11.5px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-muted);
}
.contact-banner h2 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(1.35rem, 2.6vw, 1.9rem);
  line-height: 1.15;
  margin-top: 8px;
}
.contact-banner p { color: var(--text-soft); margin-top: 6px; }

/* Small heading introducing the contact form.
   scroll-margin-top : filet de sécurité si agency-2026.js ne s'exécute pas —
   le saut d'ancre natif passerait sinon sous l'en-tête fixe. Quand le JS est
   là, c'est lui qui calcule l'offset (hauteur réelle de l'en-tête). */
#form-projet { scroll-margin-top: 120px; }
.form-header { margin-bottom: 26px; }
.form-header h2 { margin-top: 12px; }
.form-header p { color: var(--text-muted); margin-top: 8px; font-size: 14.5px; }

/* reCAPTCHA notice (replaces the floating Google badge) */
.grecaptcha-badge { visibility: hidden !important; }
.recaptcha-notice {
  font-size: 11.5px;
  color: var(--text-muted);
  margin-top: 14px;
  line-height: 1.5;
  letter-spacing: .01em;
}
.recaptcha-notice a { color: var(--text-soft); text-decoration: underline; text-decoration-color: var(--border-strong); }
.recaptcha-notice a:hover { color: var(--text); }

form .field { margin-bottom: 18px; position: relative; }
form label {
  display: block;
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 8px;
}
form input, form textarea, form select {
  width: 100%;
  background: var(--bg-soft);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
  color: var(--text);
  font-size: 15.5px;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
form input:focus, form textarea:focus, form select:focus {
  outline: none;
  border-color: var(--accent-3);
  background: rgba(124,92,255,.06);
}
form textarea { min-height: 140px; resize: vertical; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 600px) { .field-row { grid-template-columns: 1fr; } }
.form-status { font-size: 14px; color: var(--text-soft); margin-top: 10px; min-height: 20px; }
.form-status.is-success { color: var(--ok); }
.form-status.is-error { color: var(--err); }

/* Footer -------------------------------------------------------------------- */
.site-footer {
  margin-top: 60px;
  padding: 80px 0 40px;
  border-top: 1px solid var(--border);
  background: var(--footer-fade);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 48px;
  margin-bottom: 60px;
}
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .footer-grid { grid-template-columns: 1fr; } }
.footer-grid h5 {
  font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-muted); margin-bottom: 18px;
}
.footer-grid ul li { margin-bottom: 10px; font-size: 14.5px; color: var(--text-soft); }
.footer-grid ul a { transition: color .2s var(--ease); }
.footer-grid ul a:hover { color: var(--text); }
.footer-bottom {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 18px;
  padding-top: 30px;
  border-top: 1px solid var(--border);
  font-size: 13px; color: var(--text-muted);
}
.footer-brand p { color: var(--text-soft); margin-top: 14px; max-width: 32ch; font-size: 14.5px; }
.footer-socials { display: flex; gap: 10px; margin-top: 22px; }
.footer-socials a {
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface); border: 1px solid var(--border);
  transition: background .2s var(--ease), border-color .2s var(--ease);
}
.footer-socials a:hover { background: var(--surface-strong); border-color: var(--border-strong); }
.footer-socials svg { width: 16px; height: 16px; }

/* Inner banner -------------------------------------------------------------- */
.inner-banner {
  padding: clamp(160px, 18vw, 220px) 0 clamp(60px, 8vw, 100px);
  position: relative;
  overflow: hidden;
}
.inner-banner h1 {
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 6vw, 4.4rem);
  font-weight: 800;
  letter-spacing: -.035em;
  line-height: 1;
  max-width: 18ch;
}
/* h1 est en line-height:1 — sans descente de ligne, 22px collaient le chapô
   au titre, surtout quand celui-ci finit par une ligne .h-tail plus petite. */
.inner-banner .lead { margin-top: clamp(26px, 2.4vw, 34px); }
.crumb { color: var(--text-muted); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; }
.crumb a:hover { color: var(--text); }
.crumb span { margin: 0 8px; opacity: .5; }

/* Two-column content -------------------------------------------------------- */
.two-col {
  display: grid;
  grid-template-columns: 1.1fr .9fr;
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
}
@media (max-width: 900px) { .two-col { grid-template-columns: 1fr; } }
.two-col.reverse { direction: rtl; }
.two-col.reverse > * { direction: ltr; }

.feature-list { display: grid; gap: 12px; margin-top: 24px; }
.feature-list li {
  display: flex; align-items: flex-start; gap: 14px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: var(--radius-sm);
}
.feature-list .check {
  flex: 0 0 24px;
  width: 24px; height: 24px;
  border-radius: 50%;
  background: var(--grad-brand);
  display: grid; place-items: center;
  margin-top: 1px;
}
.feature-list .check svg { width: 12px; height: 12px; }

/* Apparition des blocs un par un -------------------------------------------
   La classe .is-staggered est posee par assets/js/agency-2026.js : sans JS
   (ou en prefers-reduced-motion) les items restent visibles tels quels. */
.feature-list.is-staggered > li {
  opacity: 0;
  transform: translateY(22px) scale(.97);
  filter: blur(6px);
  transition: opacity .7s var(--ease-out), transform .7s var(--ease-out), filter .7s var(--ease-out);
}
.feature-list.is-staggered > li.is-in {
  opacity: 1;
  transform: none;
  filter: none;
}
/* La pastille se deploie juste apres le bloc, avec un leger rebond */
.feature-list.is-staggered > li .check {
  opacity: 0;
  transform: scale(.2);
  transition: transform .55s cubic-bezier(.34, 1.56, .64, 1) .14s, opacity .3s linear .14s;
}
.feature-list.is-staggered > li.is-in .check { opacity: 1; transform: scale(1); }
/* ... puis la coche se dessine */
.feature-list.is-staggered > li .check polyline {
  stroke-dasharray: 26;
  stroke-dashoffset: 26;
  transition: stroke-dashoffset .45s var(--ease-out) .34s;
}
.feature-list.is-staggered > li.is-in .check polyline { stroke-dashoffset: 0; }

/* Visual block (image with frame) ------------------------------------------ */
.framed {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border-strong);
  background: var(--bg-elev);
  box-shadow: var(--shadow-2);
}
.framed::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 60%, var(--frame-fade));
  pointer-events: none;
}
.framed img { width: 100%; display: block; }

/* Reveal animations --------------------------------------------------------- */
/* Vanilla-fallback reveals (active when GSAP isn't loaded). GSAP version
   uses gsap.fromTo() and sets the same .is-in flag so styles match. */
.reveal { opacity: 0; transform: translateY(28px); transition: opacity .8s var(--ease-out), transform .8s var(--ease-out); will-change: opacity, transform; }
.reveal.is-in { opacity: 1; transform: none; }
.reveal-delay-1 { transition-delay: .05s; }
.reveal-delay-2 { transition-delay: .1s; }
.reveal-delay-3 { transition-delay: .15s; }
.reveal-delay-4 { transition-delay: .2s; }
.reveal-delay-5 { transition-delay: .25s; }

/* When GSAP is in control, strip the CSS transition so the two don't race */
html.gsap-enabled .reveal { transition: none; will-change: auto; }

/* GSAP-driven elements get hardware-accelerated transforms */
.hero-showcase, .case-bg, .svc-card, .btn-gradient, .btn-primary { will-change: transform; }

/* Responsive nav ------------------------------------------------------------ */
@media (max-width: 1024px) {
  .nav-links { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-cta .btn { display: none; }
  .lang-switch { display: inline-flex; }
}

/* =====================================================================
   Branded mockups — replaces stock photography with on-topic UI shells
   ===================================================================== */

/* Common frame */
.mockup {
  position: relative;
  border-radius: var(--radius-lg);
  background: var(--mock-frame-bg);
  border: 1px solid var(--border-strong);
  padding: 26px;
  overflow: hidden;
  aspect-ratio: 16 / 11;
  box-shadow: var(--shadow-2);
  display: grid;
  place-items: center;
}
.mockup::before {
  /* Soft brand glow */
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(600px 200px at 0% 0%, rgba(124,92,255,.18), transparent 60%),
    radial-gradient(600px 200px at 100% 100%, rgba(255,77,109,.14), transparent 60%);
  pointer-events: none;
}
.mockup > * { position: relative; z-index: 1; }

.mockup--portrait { aspect-ratio: 4 / 5; }

/* ---- Phone shell ---- */
.mockup-phone {
  width: 62%;
  aspect-ratio: 9 / 18;
  background: var(--mock-screen);
  border: 8px solid var(--mock-bezel);
  border-radius: 36px;
  box-shadow: var(--mock-phone-shadow);
  padding: 14px 12px;
  display: flex; flex-direction: column;
  gap: 10px;
  position: relative;
}
.mockup-phone::before {
  content: "";
  position: absolute;
  top: 4px; left: 50%; transform: translateX(-50%);
  width: 80px; height: 18px;
  background: var(--mock-bezel);
  border-radius: 0 0 14px 14px;
}
.mockup-phone .ph-status {
  display: flex; justify-content: space-between; align-items: center;
  padding: 0 6px;
  font-family: var(--font-display);
  font-size: 10px; font-weight: 700;
  color: var(--text-soft);
  letter-spacing: .02em;
  margin-top: 14px;
}
.mockup-phone .ph-status .ph-icons { display: flex; gap: 4px; }
.mockup-phone .ph-status .ph-icons span { width: 4px; height: 4px; background: var(--text-soft); border-radius: 50%; opacity: .8; }
.mockup-phone .ph-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 4px 4px;
}
.mockup-phone .ph-header .ph-title {
  font-family: var(--font-display);
  font-size: 13px; font-weight: 700;
  color: var(--mock-ink);
}
.mockup-phone .ph-header .ph-avatar {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--grad-brand);
}
.mockup-phone .ph-card {
  background: var(--mock-surface);
  border: 1px solid var(--mock-border);
  border-radius: 12px;
  padding: 10px;
  display: flex; flex-direction: column; gap: 6px;
}
.mockup-phone .ph-card .ph-cat {
  font-size: 8.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-muted);
}
.mockup-phone .ph-card .ph-line {
  height: 6px; background: var(--mock-line); border-radius: 3px;
}
.mockup-phone .ph-card .ph-line.short { width: 60%; }
.mockup-phone .ph-card .ph-bar {
  height: 28px;
  background: var(--grad-brand);
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-size: 10px; font-weight: 700;
  color: var(--on-accent);
}
.mockup-phone .ph-tabs {
  margin-top: auto;
  background: var(--mock-surface);
  border-radius: 16px;
  display: flex; justify-content: space-around;
  padding: 8px 0;
}
.mockup-phone .ph-tabs span {
  width: 16px; height: 16px;
  background: var(--mock-line-strong);
  border-radius: 4px;
}
.mockup-phone .ph-tabs span.is-active {
  background: var(--grad-brand);
}

/* ---- Browser shell ---- */
.mockup-browser {
  width: 92%;
  background: var(--mock-page);
  border-radius: 14px;
  border: 1px solid var(--border-strong);
  overflow: hidden;
  box-shadow: var(--mock-shadow);
  display: flex; flex-direction: column;
}
.mockup-browser .br-chrome {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px;
  background: var(--mock-chrome);
  border-bottom: 1px solid var(--mock-border);
}
.mockup-browser .br-chrome .br-dot {
  width: 10px; height: 10px; border-radius: 50%;
}
.mockup-browser .br-chrome .br-dot.r { background: #ff5f57; }
.mockup-browser .br-chrome .br-dot.y { background: #febc2e; }
.mockup-browser .br-chrome .br-dot.g { background: #28c840; }
.mockup-browser .br-chrome .br-url {
  flex: 1; margin-left: 10px;
  background: var(--mock-surface-2);
  border-radius: 6px;
  padding: 5px 10px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--text-soft);
}
.mockup-browser .br-body {
  padding: 22px;
  display: flex; flex-direction: column; gap: 14px;
}
.mockup-browser .br-hero {
  height: 110px;
  border-radius: 10px;
  background:
    radial-gradient(300px 120px at 30% 50%, rgba(124,92,255,.5), transparent 70%),
    radial-gradient(300px 120px at 80% 50%, rgba(255,77,109,.45), transparent 70%),
    var(--mock-hero);
  display: grid; place-items: center;
}
.mockup-browser .br-hero strong {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 22px;
  letter-spacing: -.025em;
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.mockup-browser .br-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.mockup-browser .br-grid > div {
  height: 56px;
  border-radius: 8px;
  background: var(--mock-surface);
  border: 1px solid var(--mock-border);
  display: flex; flex-direction: column; gap: 4px;
  padding: 8px;
}
.mockup-browser .br-grid > div::before {
  content: ""; width: 18px; height: 18px;
  border-radius: 5px; background: var(--grad-brand); opacity: .9;
}
.mockup-browser .br-grid > div::after {
  content: ""; height: 4px; width: 60%;
  border-radius: 2px; background: var(--mock-line-strong);
}

/* ---- Design canvas (Figma style) ---- */
.mockup-figma {
  width: 92%; height: 92%;
  background:
    linear-gradient(var(--canvas-grid) 1px, transparent 1px) 0 0 / 20px 20px,
    linear-gradient(90deg, var(--canvas-grid) 1px, transparent 1px) 0 0 / 20px 20px,
    var(--canvas-bg);
  border: 1px solid var(--border-strong);
  border-radius: 14px;
  position: relative;
  overflow: hidden;
}
.mockup-figma .fg-frame {
  position: absolute;
  border: 1.5px solid rgba(124,92,255,.7);
  border-radius: 6px;
  background: var(--canvas-frame-bg);
  padding: 10px;
  display: flex; flex-direction: column; gap: 6px;
}
.mockup-figma .fg-frame::before {
  content: attr(data-label);
  position: absolute;
  top: -18px; left: 0;
  font-family: var(--font-display);
  font-size: 10px; font-weight: 700;
  color: rgba(124,92,255,.9);
  letter-spacing: .04em;
}
.mockup-figma .fg-card-1 { top: 8%; left: 8%; width: 38%; height: 36%; }
.mockup-figma .fg-card-2 { top: 12%; right: 8%; width: 42%; height: 28%; }
.mockup-figma .fg-card-3 { bottom: 10%; left: 18%; width: 64%; height: 32%; }
.mockup-figma .fg-line { height: 6px; background: var(--mock-line); border-radius: 3px; }
.mockup-figma .fg-line.s { width: 55%; }
.mockup-figma .fg-line.xs { width: 35%; }
.mockup-figma .fg-btn {
  margin-top: auto;
  height: 22px; border-radius: 6px;
  background: var(--grad-brand);
}
.mockup-figma .fg-swatches {
  display: flex; gap: 6px;
}
.mockup-figma .fg-swatches span {
  width: 18px; height: 18px; border-radius: 5px;
}
.mockup-figma .fg-swatches span:nth-child(1){ background:#7c5cff; }
.mockup-figma .fg-swatches span:nth-child(2){ background:#ff4d6d; }
.mockup-figma .fg-swatches span:nth-child(3){ background:#ff8a3d; }
.mockup-figma .fg-swatches span:nth-child(4){ background:#2ddcff; }
.mockup-figma .fg-cursor {
  position: absolute;
  top: 30%; left: 42%;
  width: 18px; height: 18px;
  border-left: 2px solid #2ddcff;
  border-top: 2px solid #2ddcff;
  transform: rotate(-30deg);
  filter: drop-shadow(0 0 6px rgba(45,220,255,.6));
}
.mockup-figma .fg-cursor::after {
  content: "Designer";
  position: absolute;
  top: 14px; left: 8px;
  background: #2ddcff;
  color: #07070b;
  padding: 3px 6px;
  border-radius: 4px;
  font-family: var(--font-display); font-size: 9px; font-weight: 700;
  transform: rotate(30deg);
  white-space: nowrap;
}

/* ---- Terminal / code window ---- */
/* The terminal deliberately stays dark in both themes (a code window reads
   as dark UI even on a light page). */
.mockup-terminal {
  width: 92%;
  background: #07070b;
  border: 1px solid rgba(255,255,255,.16);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 30px 80px -20px rgba(0,0,0,.7);
}
.mockup-terminal .tm-chrome {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px;
  background: #14141c;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.mockup-terminal .tm-chrome .tm-dot {
  width: 10px; height: 10px; border-radius: 50%;
}
.mockup-terminal .tm-chrome .tm-dot.r { background: #ff5f57; }
.mockup-terminal .tm-chrome .tm-dot.y { background: #febc2e; }
.mockup-terminal .tm-chrome .tm-dot.g { background: #28c840; }
.mockup-terminal .tm-chrome .tm-title {
  flex: 1; text-align: center;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px; color: #7c7c8c;
}
.mockup-terminal .tm-body {
  padding: 18px 20px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.7;
  color: #b5b5c3;
}
.mockup-terminal .tm-line { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mockup-terminal .tm-prompt { color: #7c5cff; user-select: none; }
.mockup-terminal .tm-cmd { color: #f5f5f7; }
.mockup-terminal .tm-str { color: #2ddcff; }
.mockup-terminal .tm-num { color: #ff8a3d; }
.mockup-terminal .tm-key { color: #ff4d6d; }
.mockup-terminal .tm-com { color: #7c7c8c; }
.mockup-terminal .tm-ok { color: #6df7c1; }
.mockup-terminal .tm-cursor {
  display: inline-block;
  width: 8px; height: 14px;
  background: #f5f5f7;
  vertical-align: text-bottom;
  margin-left: 3px;
  animation: blink 1s steps(2) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

/* ---- Case-card branded placeholder (replaces stock photos) ---- */
.case .case-bg.case-art {
  background-size: cover;
  background-position: center;
}
.case-art {
  background:
    radial-gradient(circle at 30% 30%, rgba(124,92,255,.5), transparent 60%),
    radial-gradient(circle at 70% 70%, rgba(255,77,109,.45), transparent 60%),
    linear-gradient(135deg, #14141c, #0a0a12);
}
.case-art--mobile  { background: radial-gradient(circle at 30% 30%, rgba(45,220,255,.45), transparent 60%), radial-gradient(circle at 70% 70%, rgba(124,92,255,.55), transparent 60%), #0d0d14; }
.case-art--ai      { background: radial-gradient(circle at 50% 30%, rgba(124,92,255,.55), transparent 60%), radial-gradient(circle at 50% 80%, rgba(45,220,255,.5), transparent 60%), #0a0a16; }
.case-art--web     { background: radial-gradient(circle at 25% 75%, rgba(255,77,109,.5), transparent 60%), radial-gradient(circle at 80% 30%, rgba(255,138,61,.45), transparent 60%), #100a14; }
.case-art--ecom    { background: radial-gradient(circle at 25% 25%, rgba(255,77,109,.45), transparent 60%), radial-gradient(circle at 75% 75%, rgba(255,138,61,.5), transparent 60%), #1a0d14; }
.case-art--fintech { background: radial-gradient(circle at 30% 50%, rgba(45,220,255,.45), transparent 60%), radial-gradient(circle at 80% 30%, rgba(124,92,255,.4), transparent 60%), #0a1018; }
.case-art--real    { background: radial-gradient(circle at 20% 80%, rgba(255,138,61,.45), transparent 60%), radial-gradient(circle at 80% 20%, rgba(124,92,255,.4), transparent 60%), #14100a; }
.case-art--fit     { background: radial-gradient(circle at 30% 30%, rgba(255,77,109,.5), transparent 60%), radial-gradient(circle at 70% 70%, rgba(45,220,255,.4), transparent 60%), #0d0d14; }
.case-art--saas    { background: radial-gradient(circle at 50% 50%, rgba(124,92,255,.4), transparent 60%), linear-gradient(135deg, #0d0d14, #14141c); }
.case-art--food    { background: radial-gradient(circle at 30% 70%, rgba(255,138,61,.55), transparent 60%), radial-gradient(circle at 70% 30%, rgba(255,77,109,.45), transparent 60%), #14100a; }

/* Real project mockup layered over the branded gradient. If the file is
   missing the gradient below simply shows through — no broken-image icon. */
.case-photo {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  transition: transform .8s var(--ease-out), filter .4s var(--ease);
  filter: saturate(1.05);
  z-index: 1;
}
.case:hover .case-photo { transform: scale(1.05); filter: saturate(1.2); }
.case-tall .case-photo { background-position: 38% center; }
.case-photo ~ .case-mono { display: none; }
.case-photo ~ .case-overlay { z-index: 1; }

/* Les visuels projet sont passés de background-image à de vraies <picture> :
   indexables par Google Images, porteuses d'un alt, et servies en WebP
   responsive (800/1600px) au lieu d'un JPEG 1900px systématique.
   .case-photo garde son positionnement ; l'image le remplit. */
.case-photo picture { position: absolute; inset: 0; display: block; }
.case-photo img {
  width: 100%; height: 100%; display: block;
  object-fit: cover; object-position: center;
}
.case-tall .case-photo img { object-position: 38% center; }


/* Decorative monogram in the bottom-right of each case */
.case .case-mono {
  position: absolute;
  bottom: 14px; right: 18px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(80px, 14vw, 160px);
  line-height: 1;
  letter-spacing: -.05em;
  background: linear-gradient(180deg, rgba(255,255,255,.18), rgba(255,255,255,0));
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  pointer-events: none;
  z-index: 1;
}

/* ---- Hero showcase mini-mockups (replace stock images in floating cards) ---- */
.showcase-card .mini-mockup {
  position: absolute; inset: 0;
  padding: 14px;
  display: flex; flex-direction: column;
  gap: 8px;
  background: var(--mock-bg);
  color: var(--text);
  overflow: hidden;
}
.showcase-card .mini-mockup::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(220px 100px at 30% 0%, rgba(124,92,255,.28), transparent 60%),
    radial-gradient(220px 100px at 70% 100%, rgba(255,77,109,.22), transparent 60%);
  pointer-events: none;
}
.showcase-card .mm-head {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-display); font-weight: 700; font-size: 12px;
}
.showcase-card .mm-head .mm-dot { width: 24px; height: 24px; border-radius: 50%; background: var(--grad-brand); }
.showcase-card .mm-card {
  background: var(--mock-surface);
  border: 1px solid var(--mock-border);
  border-radius: 10px;
  padding: 10px;
  display: flex; flex-direction: column; gap: 6px;
  position: relative;
}
.showcase-card .mm-card .mm-cat { font-size: 9px; letter-spacing: .12em; text-transform: uppercase; color: var(--text-muted); }
.showcase-card .mm-card .mm-line { height: 6px; background: var(--mock-line); border-radius: 3px; }
.showcase-card .mm-card .mm-line.s { width: 60%; }
.showcase-card .mm-bar {
  height: 28px; border-radius: 8px;
  background: var(--grad-brand);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-size: 10px; font-weight: 700; color: var(--on-accent);
}
.showcase-card .mm-stat {
  margin-top: auto;
  display: flex; gap: 8px;
}
.showcase-card .mm-stat > div {
  flex: 1; padding: 8px;
  background: var(--mock-surface); border: 1px solid var(--mock-border);
  border-radius: 8px; text-align: center;
}
.showcase-card .mm-stat strong {
  font-family: var(--font-display); font-weight: 800;
  font-size: 13px; letter-spacing: -.02em; display: block;
}
.showcase-card .mm-stat small { font-size: 8px; color: var(--text-muted); letter-spacing: .06em; }

/* AI chat variant */
.showcase-card .mm-ai .mm-bubble {
  font-size: 10px; line-height: 1.4;
  padding: 8px 10px; border-radius: 10px;
  background: var(--mock-surface-2);
  max-width: 88%;
}
.showcase-card .mm-ai .mm-bubble.user {
  align-self: flex-end;
  background: var(--grad-brand);
  color: var(--on-accent);
}

/* Web showcase (3rd card is wider) */
.showcase-card .mm-web {
  padding: 0;
  background: var(--mock-page);
}
.showcase-card .mm-web .mm-chrome {
  display: flex; gap: 4px; padding: 8px 10px;
  background: var(--mock-chrome); border-bottom: 1px solid var(--mock-border);
}
.showcase-card .mm-web .mm-chrome span { width: 7px; height: 7px; border-radius: 50%; }
.showcase-card .mm-web .mm-chrome span:nth-child(1){ background:#ff5f57; }
.showcase-card .mm-web .mm-chrome span:nth-child(2){ background:#febc2e; }
.showcase-card .mm-web .mm-chrome span:nth-child(3){ background:#28c840; }
.showcase-card .mm-web .mm-page {
  padding: 14px;
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.showcase-card .mm-web .mm-hero {
  grid-column: span 2;
  position: relative;
  height: 60px; border-radius: 8px;
  background: radial-gradient(200px 80px at 50% 50%, rgba(124,92,255,.5), rgba(255,77,109,.3));
  display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800; font-size: 14px;
  background-clip: padding-box;
  /* Le bandeau portait .text-gradient, dont le color:transparent survivait au
     fond radial déclaré ici : le mot était bien là, mais invisible. */
  color: var(--mock-ink);
}
/* Les mots se relaient en fondu, empilés au même endroit. Aucun JS : trois
   fois la même animation, décalée d'un tiers de cycle. */
.showcase-card .mm-web .mm-word {
  position: absolute;
  inset: 0;
  display: grid; place-items: center;
  opacity: 0;
  animation: mm-word 9s var(--ease) infinite;
}
/* En reduced-motion, l'animation saute et c'est cette valeur qui reste : la
   fenêtre garde un mot au lieu de redevenir vide. */
.showcase-card .mm-web .mm-word:nth-child(1) { opacity: 1; }
.showcase-card .mm-web .mm-word:nth-child(2) { animation-delay: 3s; }
.showcase-card .mm-web .mm-word:nth-child(3) { animation-delay: 6s; }
@keyframes mm-word {
  0%        { opacity: 0; transform: translateY(5px); }
  6%, 27%   { opacity: 1; transform: none; }
  34%, 100% { opacity: 0; transform: translateY(-5px); }
}
.showcase-card .mm-web .mm-tile {
  height: 36px; border-radius: 6px;
  background: var(--mock-surface); border: 1px solid var(--mock-border);
}

/* ---- Team monogram cards (no photos) ---- */
.team-tile {
  position: relative;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--tile-bg);
  border: 1px solid var(--border);
  aspect-ratio: 4/5;
  display: flex; flex-direction: column;
  padding: 28px;
  /* These tiles sit in the 12-column .portfolio-grid. Without an explicit span
     each one collapsed to a single column (~90px) and the labels were clipped. */
  grid-column: span 3;
  transition: transform .45s var(--ease-out), border-color .45s var(--ease);
}
.team-tile:hover { transform: translateY(-6px); border-color: var(--border-strong); }
@media (max-width: 900px) { .team-tile { grid-column: span 6; } }
@media (max-width: 560px) { .team-tile { grid-column: span 12; aspect-ratio: 3/2; } }
.team-tile::before {
  content: "";
  position: absolute; inset: 0;
  background:
    radial-gradient(500px 200px at 100% 0%, rgba(124,92,255,.20), transparent 60%),
    radial-gradient(500px 200px at 0% 100%, rgba(255,77,109,.16), transparent 60%);
  pointer-events: none;
}
/* Real headshot variant. Add .team-tile--photo plus a .team-photo layer and the
   gradient initials step aside; without it the tile keeps the initials. */
.team-tile .team-photo {
  position: absolute; inset: 0;
  background-size: cover; background-position: center top;
  z-index: 0;
  transition: transform .6s var(--ease-out);
}
.team-tile--photo:hover .team-photo { transform: scale(1.04); }
.team-tile--photo .team-initials { display: none; }
.team-tile--photo::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(7,7,11,0) 45%, rgba(7,7,11,.85) 100%);
  z-index: 0;
}
.team-tile--photo .team-meta strong { color: #fff; }
.team-tile--photo .team-meta small { color: rgba(255,255,255,.75); }

.team-tile .team-initials {
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(4rem, 7vw, 6rem);
  letter-spacing: -.04em;
  line-height: 1;
  /* 300% wide so the gradient has somewhere to travel; the token's first and
     last stops match, so the sweep reverses without a visible seam. */
  background: var(--grad-initials);
  background-size: 300% 100%;
  background-position: 0% 50%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  margin: auto auto 0;
  text-align: center;
  /* Entrance state — lifted, small and out of focus until the tile scrolls in. */
  opacity: 0;
  transform: translateY(20px) scale(.92);
  filter: blur(12px);
}
.team-tile.is-in .team-initials {
  opacity: 1;
  transform: none;
  filter: blur(0);
  transition:
    opacity .9s var(--ease-out) .12s,
    transform 1s var(--ease-out) .12s,
    filter .9s var(--ease-out) .12s;
}
@media (prefers-reduced-motion: no-preference) {
  .team-tile.is-in .team-initials { animation: initials-drift 7s var(--ease) 1.1s infinite alternate; }
}
@keyframes initials-drift { to { background-position: 100% 50%; } }

/* Hover: the letters step forward and a soft bloom lights up behind them. */
.team-tile.is-in:hover .team-initials { transform: scale(1.07) translateY(-4px); }
.team-tile:not(.team-tile--photo)::after {
  content: "";
  position: absolute;
  left: 50%; top: 52%;
  width: 62%; aspect-ratio: 1;
  transform: translate(-50%, -50%) scale(.55);
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,77,109,.50), rgba(124,92,255,.30) 45%, transparent 70%);
  filter: blur(34px);
  opacity: 0;
  transition: opacity .55s var(--ease), transform .7s var(--ease-out);
  pointer-events: none;
  z-index: 0;
}
.team-tile:not(.team-tile--photo):hover::after { opacity: 1; transform: translate(-50%, -50%) scale(1); }

@media (prefers-reduced-motion: reduce) {
  .team-tile .team-initials { opacity: 1; transform: none; filter: none; }
}
.team-tile .team-tag {
  position: relative; z-index: 1;
  align-self: flex-start;
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-soft);
  padding: 6px 10px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--glass-bg);
  backdrop-filter: blur(6px);
}
.team-tile .team-meta {
  position: relative; z-index: 1;
  margin-top: auto;
  padding-top: 22px;
  text-align: center;
}
.team-tile .team-meta strong {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
  display: block;
}
.team-tile .team-meta small { color: var(--text-muted); font-size: 13px; }

/* ---- About / vision composition ---- */
/* Height follows the content. A fixed 4/5 ratio left a large void whenever the
   card held only the headline figure and the three pills. */
.vision-composition {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background:
    radial-gradient(600px 300px at 0% 0%, rgba(124,92,255,.28), transparent 60%),
    radial-gradient(600px 300px at 100% 100%, rgba(255,77,109,.22), transparent 60%),
    var(--vision-bg);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-2);
  padding: 32px;
  display: flex; flex-direction: column; gap: 20px;
}
.vision-composition .vc-stat {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.4rem, 5vw, 4rem);
  letter-spacing: -.035em;
  line-height: 1;
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
.vision-composition .vc-label {
  font-size: 12px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-muted);
}
.vision-composition .vc-row {
  margin-top: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.vision-composition .vc-pill {
  padding: 12px 10px;
  border-radius: 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  text-align: center;
}
.vision-composition .vc-pill strong {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.1rem;
  display: block;
}
.vision-composition .vc-pill small { color: var(--text-muted); font-size: 11px; }

/* =====================================================================
   Light theme
   ---------------------------------------------------------------------
   Applied when <html data-theme="light"> — which is the site default, set
   directly in the markup so it holds even without JS. The inline snippet in
   each page's <head> switches the attribute to "dark" before first paint
   when the visitor stored that choice, so there is no flash.
   Only tokens are redefined here — no component rules are duplicated.
   ===================================================================== */
:root[data-theme="light"] {
  color-scheme: light;

  --bg: #ffffff;
  --bg-soft: #f4f4f8;
  --bg-elev: #ffffff;
  --surface: rgba(14, 14, 40, 0.035);
  --surface-strong: rgba(14, 14, 40, 0.065);
  --border: rgba(14, 14, 40, 0.10);
  --border-strong: rgba(14, 14, 40, 0.17);
  --border-hover: rgba(14, 14, 40, 0.30);

  --text: #101018;
  --text-soft: #4b4b5c;
  --text-muted: #71718a;

  /* Deeper accents so brand colours stay readable on white */
  --accent-1: #e30f4c;
  --accent-2: #d9600c;
  --accent-3: #5f34f0;
  --accent-4: #0a95bd;
  --ai-ink: #077c9c;
  --on-accent: #ffffff;
  --on-ai: #ffffff;
  --ok: #06795a;
  --err: #c31232;

  --grad-brand: linear-gradient(120deg, #5f34f0 0%, #e30f4c 55%, #d9600c 100%);
  --grad-initials: linear-gradient(100deg, #5f34f0 0%, #e30f4c 28%, #d9600c 50%, #e30f4c 72%, #5f34f0 100%);
  --grad-brand-soft: linear-gradient(120deg, rgba(95,52,240,.12), rgba(227,15,76,.10) 55%, rgba(217,96,12,.12));
  --grad-ai: linear-gradient(120deg, #0a95bd 0%, #5f34f0 100%);

  --shadow-1: 0 1px 2px rgba(16,16,45,.08);
  --shadow-2: 0 30px 60px -22px rgba(16,16,45,.18), 0 8px 24px -12px rgba(16,16,45,.10);
  --shadow-glow: 0 0 0 1px rgba(16,16,45,.06), 0 40px 120px -34px rgba(95,52,240,.28);

  --body-glow:
    radial-gradient(1200px 600px at 80% -10%, rgba(95,52,240,.10), transparent 60%),
    radial-gradient(800px 400px at 10% 10%, rgba(227,15,76,.07), transparent 60%),
    radial-gradient(1000px 500px at 50% 110%, rgba(217,96,12,.07), transparent 60%);
  --orb-opacity: .3;

  --header-bg: rgba(255,255,255,.78);
  --nav-pill-bg: rgba(255,255,255,.72);
  --menu-bg: rgba(255,255,255,.97);
  --glass-bg: rgba(255,255,255,.72);
  --marquee-bg: rgba(244,244,248,.7);
  --footer-fade: linear-gradient(180deg, transparent, rgba(244,244,248,.9));
  --frame-fade: rgba(16,16,45,.16);
  /* --scrim stays dark: case artwork keeps its dark treatment in both themes */

  --btn-solid-bg: #101018;
  --btn-solid-fg: #ffffff;
  --btn-solid-shadow: 0 10px 30px -12px rgba(16,16,45,.45);
  --btn-solid-shadow-hover: 0 18px 42px -14px rgba(16,16,45,.55);

  --logo-filter: brightness(0);
  --logo-opacity: .55;
  --logo-filter-tone: grayscale(1) contrast(1.25) brightness(.45);

  --mock-frame-bg: linear-gradient(160deg, #f8f8fc 0%, #eeeef5 100%);
  --mock-bg: linear-gradient(160deg, #ffffff, #f4f4f8);
  --mock-screen: #ffffff;
  --mock-bezel: #dcdce6;
  --mock-chrome: #f1f1f6;
  --mock-page: #ffffff;
  --mock-hero: #ededf4;
  --mock-surface: rgba(14,14,40,.035);
  --mock-surface-2: rgba(14,14,40,.06);
  --mock-border: rgba(14,14,40,.10);
  --mock-line: rgba(14,14,40,.13);
  --mock-line-strong: rgba(14,14,40,.20);
  --mock-ink: #101018;
  --mock-phone-shadow: 0 30px 80px -24px rgba(16,16,45,.30), 0 0 0 1px rgba(16,16,45,.06) inset;
  --mock-shadow: 0 30px 70px -24px rgba(16,16,45,.25);

  --canvas-bg: #fbfbff;
  --canvas-grid: rgba(14,14,40,.05);
  --canvas-frame-bg: rgba(255,255,255,.92);

  --tile-bg: linear-gradient(160deg, #f8f8fc, #eeeef6);
  --vision-bg: linear-gradient(160deg, #f7f7fc, #ffffff);
}

/* A few surfaces need a touch more definition on white ---------------------- */
:root[data-theme="light"] .site-header.is-scrolled {
  box-shadow: 0 1px 0 rgba(14,14,40,.06), 0 10px 30px -22px rgba(16,16,45,.35);
}
:root[data-theme="light"] .brand-dot { box-shadow: 0 0 14px rgba(227,15,76,.35); }
:root[data-theme="light"] .svc-card.svc-ai { border-color: rgba(10,149,189,.30); }
:root[data-theme="light"] .svc-card.svc-ai .ai-pill {
  background: rgba(10,149,189,.10);
  border-color: rgba(10,149,189,.35);
}
:root[data-theme="light"] .logo-cell:hover img { opacity: .85; }
:root[data-theme="light"] .mockup-figma .fg-frame::before { color: rgba(95,52,240,.95); }
:root[data-theme="light"] .mockup-figma .fg-frame { border-color: rgba(95,52,240,.55); }
:root[data-theme="light"] .mockup-figma .fg-cursor {
  border-left-color: #0a95bd; border-top-color: #0a95bd;
  filter: drop-shadow(0 0 6px rgba(10,149,189,.45));
}
:root[data-theme="light"] .mockup-figma .fg-cursor::after { background: #0a95bd; color: #ffffff; }
:root[data-theme="light"] .live-dot { background: #0a95bd; box-shadow: 0 0 12px rgba(10,149,189,.6); }
:root[data-theme="light"] form input:focus,
:root[data-theme="light"] form textarea:focus,
:root[data-theme="light"] form select:focus { background: rgba(95,52,240,.04); }
:root[data-theme="light"] .recaptcha-notice a { text-decoration-color: var(--border-strong); }
:root[data-theme="light"] ::selection { background: rgba(95,52,240,.22); color: #101018; }

/* Theme toggle -------------------------------------------------------------- */
.theme-toggle {
  width: 40px; height: 40px;
  border-radius: 50%;
  display: inline-grid; place-items: center;
  flex: 0 0 auto;
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text-soft);
  transition: color .2s var(--ease), background .2s var(--ease),
              border-color .2s var(--ease), transform .2s var(--ease);
}
.theme-toggle:hover {
  color: var(--text);
  background: var(--surface-strong);
  border-color: var(--border-strong);
  transform: translateY(-1px);
}
.theme-toggle:focus-visible { outline: 2px solid var(--accent-3); outline-offset: 3px; }
.theme-toggle svg { width: 18px; height: 18px; }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="light"] .theme-toggle .icon-sun { display: none; }
:root[data-theme="light"] .theme-toggle .icon-moon { display: block; }

/* Cross-fade when the visitor flips the theme (class is removed after 400ms) */
@media (prefers-reduced-motion: no-preference) {
  html.theme-switching,
  html.theme-switching *,
  html.theme-switching *::before,
  html.theme-switching *::after {
    transition: background-color .3s var(--ease), background-image .3s var(--ease),
                border-color .3s var(--ease), color .3s var(--ease),
                box-shadow .3s var(--ease), fill .3s var(--ease) !important;
  }
}

/* Rotating headline word ---------------------------------------------------
   The first word is real text in the HTML, so crawlers and no-JS visitors get
   a complete sentence; the JS only swaps it. No overflow:hidden here — it
   would clip descenders (the "p" of "applications") — the words cross-fade
   and slide instead, and the container animates its width to the next word. */
.rotator {
  display: inline-block;
  position: relative;
  white-space: nowrap;
  vertical-align: top;
  perspective: 900px;                 /* profondeur du basculement 3D */
  transform-origin: 0% 50%;           /* le mot gonfle sans quitter sa marge */
  transition: width .6s var(--ease-out), transform .52s var(--ease-out);
}
.rotator-word {
  display: inline-block;
  transform-style: preserve-3d;       /* laisse la perspective atteindre les lettres */
}

/* Le mot sortant est sorti du flux le temps de s'envoler : le mot entrant
   prend sa place immédiatement, les deux se croisent. Sans cela le titre
   resterait vide ~0,5 s entre les deux mots. */
.rotator-word.is-leaving {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
}

/* Le mot est découpé lettre par lettre pour pouvoir les faire basculer en
   décalé. Une synthèse vocale lirait « a-p-p-s » : le vrai mot est donc
   conservé ici, hors écran, et la version découpée est masquée en aria. */
.rotator-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Chaque lettre s'anime séparément. Le décalage d'une lettre à l'autre est
   posé en JS (transitionDelay) : c'est lui qui produit la vague, sans quoi le
   mot bougerait d'un seul bloc. */
.rotator-char {
  display: inline-block;
  backface-visibility: hidden;
  transform: none;
  opacity: 1;
  filter: none;
  transition: transform .64s var(--ease-out),
              opacity .36s var(--ease),
              filter .38s var(--ease);
}

/* ---------------------------------------------------------------------------
   Six transitions distinctes, choisies à tour de rôle par le JS via
   data-anim : deux changements de mot consécutifs ne se ressemblent jamais.
   Pour chaque effet, .is-out est l'état de fuite du mot sortant et .is-in
   l'état d'arrivée du mot entrant — pensés dans le MÊME sens de mouvement,
   pour que le regard suive une continuité plutôt qu'un aller-retour.
   ------------------------------------------------------------------------ */

/* 1 — bascule autour de l'axe horizontal, façon palette d'affichage */
.rotator-word[data-anim="flip"].is-out .rotator-char {
  transform: rotateX(90deg) translateY(-.3em);
  opacity: 0;
}
.rotator-word[data-anim="flip"].is-in .rotator-char {
  transform: rotateX(-90deg) translateY(.3em);
  opacity: 0;
}

/* 2 — grossissement : la lettre fonce vers le lecteur et sort du cadre,
       la suivante surgit du fond. Le flou vend la profondeur. */
.rotator-word[data-anim="zoom"].is-out .rotator-char {
  transform: scale(2.1) translateZ(140px);
  opacity: 0;
  filter: blur(7px);
}
.rotator-word[data-anim="zoom"].is-in .rotator-char {
  transform: scale(.3) translateZ(-160px);
  opacity: 0;
  filter: blur(5px);
}

/* 3 — éclatement : chaque lettre part dans SA direction, tirée au sort en JS
       (--bx / --by / --br). Le mot entrant se recompose depuis ces mêmes
       directions, en sens inverse. */
.rotator-word[data-anim="burst"].is-out .rotator-char {
  transform: translate(var(--bx, 0px), var(--by, 0px)) rotate(var(--br, 0deg)) scale(.35);
  opacity: 0;
}
.rotator-word[data-anim="burst"].is-in .rotator-char {
  transform: translate(calc(var(--bx, 0px) * -.75), calc(var(--by, 0px) * -.75))
             rotate(calc(var(--br, 0deg) * -1)) scale(.45);
  opacity: 0;
}

/* 4 — glissement latéral avec cisaillement, comme emporté par la vitesse */
.rotator-word[data-anim="slide"].is-out .rotator-char {
  transform: translateX(-.8em) skewX(-14deg) scale(.9);
  opacity: 0;
}
.rotator-word[data-anim="slide"].is-in .rotator-char {
  transform: translateX(.8em) skewX(14deg) scale(.9);
  opacity: 0;
}

/* 5 — rotation autour de l'axe vertical, façon carte qu'on retourne */
.rotator-word[data-anim="spin"].is-out .rotator-char {
  transform: rotateY(92deg) translateZ(40px);
  opacity: 0;
}
.rotator-word[data-anim="spin"].is-in .rotator-char {
  transform: rotateY(-92deg) translateZ(40px);
  opacity: 0;
}

/* 6 — chute : la lettre tombe et se retire, la suivante se laisse tomber */
.rotator-word[data-anim="drop"].is-out .rotator-char {
  transform: translateY(.9em) rotate(9deg) scale(.75);
  opacity: 0;
}
.rotator-word[data-anim="drop"].is-in .rotator-char {
  transform: translateY(-.9em) rotate(-9deg) scale(.75);
  opacity: 0;
}

/* Léger gonflement du bloc entier à chaque changement : le titre « respire »
   au lieu de rester figé pendant que seules les lettres bougent. */
.rotator.is-pulse { transform: scale(1.035); }

/* Champ de particules émis à chaque changement de mot. Débordement volontaire
   du cadre (le canvas est plus grand que le mot) pour que les éclats puissent
   s'échapper au-delà des lettres. */
.rotator-fx {
  position: absolute;
  z-index: -1;                       /* derrière les lettres, devant le fond */
  pointer-events: none;
}

/* .text-gradient pose le dégradé sur le conteneur, mais des enfants
   transformés en 3D sont peints dans leur propre couche et perdent le
   background-clip:text du parent. Le dégradé est donc reporté sur chaque
   lettre ; le JS recale background-position lettre par lettre pour
   reconstituer un dégradé continu sur toute la largeur du mot. */
.rotator.text-gradient { background: none; }
.rotator.text-gradient .rotator-char {
  background-image: var(--grad-brand);
  background-repeat: no-repeat;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Volontairement de la MÊME couleur que le reste du titre : ce mot ne se
   distingue pas par la couleur mais par son animation (il explose à l'arrivée,
   puis la phrase marque une pause sur lui). La classe reste indispensable —
   c'est elle que le JS cible pour déclencher l'explosion. */
.hero-accent { color: inherit; }

/* A nowrap rotator would otherwise blow out the grid track (min-width:auto)
   and squeeze the showcase column, so the copy column is allowed to shrink. */
.hero-copy { min-width: 0; }
.hero-title .rotator { display: block; max-width: 100%; }

/* Three deliberate lines ("L'agence #1" / "pour vos" / word), so the size is
   tuned to the longest rotating word rather than to a wrapping paragraph. */
.hero-title {
  /* Mesuré à chaque palier : aucun débordement de 390 px à 1920 px. Ne pas
     monter le plafond sans revérifier « sites e-commerce », qui ne peut pas
     revenir à la ligne. */
  font-size: clamp(2.1rem, 5.4vw, 4.8rem);
  perspective: 1000px;              /* profondeur des lettres pendant l'intro */
  position: relative;               /* repère du canvas d'éclats de l'intro */
}

/* Lettres découpées le temps de l'intro seulement : le JS remet les nœuds de
   texte d'origine une fois la séquence terminée, pour ne pas laisser un titre
   en confettis de <span> dans le DOM. */
.intro-char {
  display: inline-block;
  transform-origin: 50% 50% -.35em;
}
/* Below ~400px the 2.1rem floor makes the longest rotating word wider than
   the column, and body{overflow-x:hidden} would silently clip it — so small
   phones get their own, steeper curve. */
@media (max-width: 400px) {
  .hero-title { font-size: clamp(1.7rem, 8.4vw, 2.1rem); }
}

@media (prefers-reduced-motion: reduce) {
  .rotator { width: auto !important; }
}

/* Reduced motion ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}


/* =====================================================================
   Objet 3D de bandeau + repère de défilement
   ---------------------------------------------------------------------
   Les deux éléments sont injectés à l'exécution par assets/js/agency-2026.js
   (section « objet 3D de bandeau »), pour qu'aucune balise ne soit ajoutée
   aux 14 pages copiées-collées (racine + en/).
   ===================================================================== */

:root {
  /* Halo posé derrière le fil de fer — un dégradé radial en CSS coûte moins
     cher qu'un redessin par frame sur le canvas. */
  --object-halo: radial-gradient(circle, rgba(124,92,255,.26), rgba(255,77,109,.11) 46%, transparent 66%);
  /* Plus opaque que --glass-bg : le repère survole aussi bien du blanc que
     des vignettes sombres, et doit rester lisible sur les deux. */
  --cue-bg: rgba(20,20,28,.88);
  --band-veil: rgba(7,7,11,.72);
}
:root[data-theme="light"] {
  --object-halo: radial-gradient(circle, rgba(95,52,240,.17), rgba(227,15,76,.08) 46%, transparent 66%);
  --cue-bg: rgba(255,255,255,.92);
  --band-veil: rgba(255,255,255,.78);
}

/* Objet 3D ------------------------------------------------------------------ */
/* top et --object-room sont posés par le JS : le bloc de texte va d'un titre
   seul (mentions légales) à trois lignes plus un chapô, et l'objet doit s'y
   centrer sans jamais déborder du bandeau, qui rogne ce qui dépasse. */
.hero-object, .side-object {
  position: absolute;
  top: 0;
  right: calc(50% - min(var(--container), 100% - var(--gutter) * 2) / 2);
  transform: translateY(-50%);
  height: min(clamp(330px, 36vw, 520px), var(--object-room, 40vh));
  aspect-ratio: 1;
  pointer-events: none;
  z-index: 0;
}
.hero-object::before, .side-object::before {
  content: "";
  position: absolute;
  inset: -14%;
  border-radius: 50%;
  background: var(--object-halo);
  filter: blur(38px);
  animation: object-halo 14s ease-in-out infinite;
}
@keyframes object-halo {
  0%, 100% { transform: scale(1);    opacity: .88; }
  50%      { transform: scale(1.07); opacity: 1; }
}
.hero-object canvas, .side-object canvas {
  position: relative;
  width: 100%;
  height: 100%;
  opacity: 0;
  transform: scale(.92);
  transition: opacity 1.1s var(--ease-out), transform 1.1s var(--ease-out);
}
.hero-object.is-ready canvas, .side-object.is-ready canvas { opacity: 1; transform: none; }

/* Objet posé à côté d'un chapeau de section (« Nos expertises ») : un peu plus
   petit que celui d'un bandeau, et la section rogne ce qui dépasserait. */
.side-object { height: min(clamp(260px, 26vw, 400px), var(--object-room, 34vh)); }
.has-side-object { overflow: hidden; }
.has-side-object .container { position: relative; z-index: 1; }
@media (max-width: 1080px) { .side-object { display: none; } }

/* Le texte du bandeau se resserre pour ne pas croiser l'objet. */
.inner-banner .container { position: relative; z-index: 1; }
@media (min-width: 1081px) {
  .inner-banner.has-hero-object h1 { max-width: min(18ch, 56%); }
  .inner-banner.has-hero-object .lead { max-width: min(62ch, 52%); }
}
/* En dessous, la colonne de texte prend toute la largeur : l'objet ne serait
   plus qu'un fond parasite derrière le titre. */
@media (max-width: 1080px) { .hero-object { display: none; } }

/* Nappe pleine largeur derrière les compteurs ------------------------------- */
/* La bande de statistiques flottait au milieu d'une section très aérée : la
   nappe occupe ce vide sans rien disputer aux chiffres, qui restent au-dessus.
   Le masque efface les bords gauche/droit pour que la grille ne se coupe pas
   net contre la fenêtre. */
.object-band {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent);
}
.object-band canvas {
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 1.4s var(--ease-out);
}
.object-band.is-ready canvas { opacity: 1; }
/* Dans le bloc CTA, la nappe passe derrière un texte et deux boutons : elle
   s'efface pour rester un fond, et le masque se resserre sur les bords. */
.object-band--card {
  -webkit-mask-image: linear-gradient(90deg, transparent 30%, #000 55%, #000 88%, transparent);
  mask-image: linear-gradient(90deg, transparent 30%, #000 55%, #000 88%, transparent);
}
.object-band--card.is-ready canvas { opacity: .5; }
.cta.has-band > *:not(.object-band) { position: relative; z-index: 1; }
.cta .h-display { font-size: clamp(2rem, 3.4vw, 3.3rem); }
.has-object-band .container { position: relative; z-index: 1; }
/* Le fond de la bande est translucide : sans ce voile, la nappe passerait à
   travers les chiffres. */
.has-object-band .stats {
  background:
    linear-gradient(var(--band-veil), var(--band-veil)),
    var(--surface);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
@media (max-width: 768px) { .object-band { display: none; } }

/* Repère de défilement ------------------------------------------------------ */
/* Fixé au bas de la fenêtre, et non au bas de la section : les bandeaux
   intérieurs ne font que ~580 px de haut, le repère atterrissait donc au
   milieu de l'écran, là où il n'indique plus rien.
   Le fond vitré n'est pas décoratif : le repère survole ce qui se trouve
   sous le pli — souvent une vignette sombre — et un libellé nu y disparaît. */
.scroll-cue {
  position: fixed;
  left: 50%;
  bottom: clamp(16px, 3vh, 34px);
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 11px 16px 11px 20px;
  border-radius: var(--radius-pill);
  border: 1px solid var(--border-strong);
  background: var(--cue-bg);
  box-shadow: var(--shadow-2);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: var(--text);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateX(-50%) translateY(14px);
  transition: opacity .6s var(--ease), transform .6s var(--ease-out),
              border-color .25s var(--ease), background .25s var(--ease);
}
.scroll-cue.is-shown { opacity: 1; transform: translateX(-50%); }
.scroll-cue:hover {
  border-color: var(--border-hover);
  background: var(--bg-elev);
}
.scroll-cue.is-shown:hover { transform: translateX(-50%) translateY(-2px); }
.scroll-cue:focus-visible { outline: 2px solid var(--accent-3); outline-offset: 4px; }
/* Onde qui s'échappe de la pilule, calée sur le rebond de la flèche. */
.scroll-cue::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 1px solid var(--accent-3);
  opacity: 0;
  pointer-events: none;
  animation: cue-halo 2.2s var(--ease-out) infinite;
}
.scroll-cue .cue-arrow {
  width: 16px; height: 16px;
  flex: 0 0 auto;
  color: var(--accent-1);
  animation: cue-arrow 2.2s var(--ease) infinite;
}
@keyframes cue-arrow {
  0%, 100% { transform: translateY(-2px); opacity: .65; }
  35%      { transform: translateY(3px);  opacity: 1; }
  70%      { transform: translateY(-2px); opacity: .65; }
}
@keyframes cue-halo {
  0%        { opacity: .45; transform: scale(1); }
  60%, 100% { opacity: 0;  transform: scale(1.12); }
}
/* Retiré dès que le visiteur a défilé, et tant que le bandeau cookies
   occupe le bas de l'écran (voir le module JS). */
.scroll-cue.is-gone {
  opacity: 0;
  transform: translateX(-50%) translateY(14px);
  pointer-events: none;
}

/* ============================================================
   SEO 2026 — composants ajoutés pour les pages piliers,
   les pages locales et l'espace Ressources.
   ============================================================ */

/* --- Navigation : 6 entrées, on resserre entre 1024 et 1240px --- */
@media (min-width: 1025px) and (max-width: 1240px) {
  .nav-links a { padding: 10px 12px; font-size: 13.5px; }
  .nav-cta { gap: 8px; }
}

/* --- Footer : marque + 4 colonnes (Expertises, Agence, Contact, Bureaux).
       L'ancienne colonne « Nos villes » a été fusionnée dans « Bureaux » :
       les adresses sont elles-mêmes les liens vers les pages locales.
       Le nombre de colonnes est piloté par le contenu réel, pas par une
       valeur fixe, pour que le blog (3 colonnes) ne laisse pas de trou. --- */
.site-footer .footer-grid {
  grid-template-columns: 1.4fr repeat(auto-fit, minmax(148px, 1fr));
  gap: 40px;
}
@media (max-width: 1120px) { .site-footer .footer-grid { grid-template-columns: 1fr 1fr 1fr; } }
@media (max-width: 820px)  { .site-footer .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 540px)  { .site-footer .footer-grid { grid-template-columns: 1fr; } }
.site-footer .footer-grid ul a strong { transition: color .2s var(--ease); }
.site-footer .footer-grid ul a:hover strong { color: var(--accent-1) !important; }

/* --- Fil d'Ariane visible --- */
.breadcrumb { font-size: 13px; color: var(--text-muted); letter-spacing: .02em; }
.breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; list-style: none; margin: 0; padding: 0; }
.breadcrumb li { display: flex; align-items: center; gap: 8px; }
.breadcrumb li + li::before { content: "/"; opacity: .45; }
.breadcrumb a { color: var(--text-muted); transition: color .2s var(--ease); }
.breadcrumb a:hover { color: var(--text); }
.breadcrumb [aria-current="page"] { color: var(--text-soft); }

/* --- FAQ (contenu visible, adossé au schema FAQPage) --- */
.faq-list { display: grid; gap: 12px; margin-top: 36px; }
.faq-item {
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); overflow: hidden;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.faq-item[open] { border-color: var(--border-strong); background: var(--bg-elev); }
.faq-item summary {
  cursor: pointer; list-style: none; padding: 22px 26px;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; color: var(--text);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+"; flex: none; font-size: 1.35rem; line-height: 1; font-weight: 400;
  color: var(--text-muted); transition: transform .25s var(--ease), color .2s var(--ease);
}
.faq-item[open] summary::after { transform: rotate(45deg); color: var(--accent-1); }
.faq-item summary:hover::after { color: var(--text); }
.faq-answer { padding: 0 26px 24px; color: var(--text-soft); font-size: 15px; line-height: 1.72; }
.faq-answer > * + * { margin-top: 12px; }
.faq-answer ul { margin-left: 18px; list-style: disc; }
.faq-answer li { margin-bottom: 6px; }

/* --- Corps de texte long (pages piliers, mentions légales EN).
       Le blog a son propre .post-body dans blog-2026.css : ne pas
       reintroduire ici .post-card, .post-grid, .toc, .article-layout
       ni .article-meta, qui appartiennent a ce composant-la. --- */
.article-body { max-width: 760px; font-size: 16.5px; line-height: 1.78; color: var(--text-soft); }
.article-body > * + * { margin-top: 22px; }
.article-body h2 {
  font-family: var(--font-display); font-weight: 700; font-size: clamp(1.5rem, 2.6vw, 2rem);
  color: var(--text); margin-top: 56px; scroll-margin-top: 110px; line-height: 1.2;
}
.article-body h3 {
  font-family: var(--font-display); font-weight: 600; font-size: 1.18rem;
  color: var(--text); margin-top: 36px; scroll-margin-top: 110px;
}
.article-body ul, .article-body ol { margin-left: 22px; }
.article-body ul { list-style: disc; }
.article-body ol { list-style: decimal; }
.article-body li { margin-bottom: 10px; }
.article-body li::marker { color: var(--accent-1); }
.article-body strong { color: var(--text); font-weight: 600; }
.article-body a:not(.btn) {
  color: var(--text); text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--accent-1) 55%, transparent);
  text-underline-offset: 3px; transition: text-decoration-color .2s var(--ease);
}
.article-body a:not(.btn):hover { text-decoration-color: var(--accent-1); }
.article-body blockquote {
  border-left: 3px solid var(--accent-1); padding: 4px 0 4px 22px;
  color: var(--text); font-size: 1.06rem; font-style: italic;
}
.article-lead { font-size: 1.18rem; line-height: 1.65; color: var(--text); }

/* --- Tableau lisible dans un article --- */
.table-wrap { overflow-x: auto; border: 1px solid var(--border); border-radius: var(--radius-md); }
.article-body table { width: 100%; border-collapse: collapse; font-size: 14.5px; min-width: 560px; }
.article-body th, .article-body td { padding: 14px 18px; text-align: left; border-bottom: 1px solid var(--border); }
.article-body thead th {
  background: var(--bg-soft); color: var(--text); font-weight: 600;
  font-size: 12px; letter-spacing: .12em; text-transform: uppercase;
}
.article-body tbody tr:last-child td { border-bottom: none; }
.article-body td strong { color: var(--text); }

/* --- Pastilles technos --- */
.tech-pills { display: flex; flex-wrap: wrap; gap: 9px; }
.tech-pills span {
  font-size: 13px; padding: 8px 15px; border-radius: var(--radius-pill);
  border: 1px solid var(--border); background: var(--surface); color: var(--text-soft);
}

/* --- Bloc « en bref » / réponse directe (visé AI Overviews + extraits) --- */
.key-takeaway {
  border: 1px solid var(--border-strong); border-left: 3px solid var(--accent-1);
  border-radius: var(--radius-md); padding: 26px 30px; background: var(--bg-elev);
}
.key-takeaway h2, .key-takeaway h3 { font-size: 12px; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); margin: 0 0 12px; font-family: var(--font-sans); font-weight: 600; }
.key-takeaway p { font-size: 16.5px; line-height: 1.68; color: var(--text); margin: 0; }
.key-takeaway p + p { margin-top: 10px; }

/* --- Grille de villes / d'arguments locaux --- */
.local-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 900px) { .local-grid { grid-template-columns: 1fr; } }
.local-card {
  padding: 30px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); transition: border-color .3s var(--ease), transform .3s var(--ease);
}
.local-card:hover { border-color: var(--border-strong); transform: translateY(-3px); }
.local-card h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem; color: var(--text); margin-bottom: 10px; }
.local-card p { font-size: 14.5px; color: var(--text-soft); line-height: 1.62; }
.local-card address { font-style: normal; font-size: 13.5px; color: var(--text-muted); margin-top: 14px; line-height: 1.6; }

/* --- Liens contextuels de fin de page --- */
.related { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; }
@media (max-width: 900px) { .related { grid-template-columns: 1fr; } }
.related a {
  display: block; padding: 26px; border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface); transition: border-color .3s var(--ease), transform .3s var(--ease);
}
.related a:hover { border-color: var(--border-strong); transform: translateY(-3px); }
.related .r-kicker { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--text-muted); display: block; margin-bottom: 10px; }
.related .r-title { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; color: var(--text); line-height: 1.32; display: block; }

/* --- Impression : garder le contenu lisible --- */
@media print {
  .site-header, .mobile-menu, .site-footer, .cta, .theme-toggle, .toc { display: none !important; }
  .article-body { max-width: none; color: #000; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 11px; }
}

/* =====================================================================
   Bandeau d'annonce
   ---------------------------------------------------------------------
   L'en-tête est en position: fixed, top: 0. Le bandeau prend cette place
   et pousse tout le reste de --promo-h : l'en-tête via son top, la page
   via le padding du body. Une seule variable à remettre à zéro pour le
   faire disparaître, sans toucher aux marges des sections.
   ===================================================================== */

:root { --promo-h: 44px; }
:root.promo-off { --promo-h: 0px; }
:root.promo-off .promo-bar { display: none; }

body { padding-top: var(--promo-h); }
.site-header { top: var(--promo-h); }

.promo-bar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 101;              /* au-dessus de l'en-tête (100) et du menu (99) */
  height: var(--promo-h);
  display: flex;
  align-items: center;
  background: var(--grad-brand);
  color: #ffffff;
  font-size: 13.5px;
  overflow: hidden;
}
.promo-inner {
  display: flex;
  align-items: center;
  gap: 16px;
}
.promo-text {
  margin: 0;
  flex: 1;
  text-align: center;
  line-height: 1.3;
  /* Une ligne, toujours : le bandeau a une hauteur fixe dont dépendent le
     top de l'en-tête et le padding du body. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.promo-text strong { font-weight: 700; }
.promo-emoji { font-size: 15px; }
.promo-text a {
  color: #ffffff;
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
  text-decoration-color: rgba(255,255,255,.5);
  transition: text-decoration-color .2s var(--ease);
}
.promo-text a:hover { text-decoration-color: #ffffff; }
.promo-close {
  flex: 0 0 auto;
  width: 26px; height: 26px;
  display: grid; place-items: center;
  border-radius: 50%;
  color: rgba(255,255,255,.75);
  transition: color .2s var(--ease), background .2s var(--ease);
}
.promo-close:hover { color: #ffffff; background: rgba(255,255,255,.16); }
.promo-close:focus-visible { outline: 2px solid #ffffff; outline-offset: 2px; }
.promo-close svg { width: 14px; height: 14px; }

/* Le bouton de fermeture est hors flux à partir de la tablette : sans ça, le
   texte est centré sur l'espace restant et non sur le bandeau. */
@media (min-width: 701px) {
  .promo-inner { position: relative; }
  .promo-close { position: absolute; right: 0; top: 50%; transform: translateY(-50%); }
}
@media (max-width: 700px) {
  .promo-bar { font-size: 12.5px; }
  .promo-text { text-align: left; }
  /* Sur téléphone il ne reste que l'accroche et le numéro : le reste ne
     tiendrait pas sur une ligne. */
  .promo-more { display: none; }
}

/* Pied de page : cinquième colonne pour les adresses ------------------------
   La colonne « Contact » empilait téléphone, e-mail et trois bureaux : elle
   descendait deux fois plus bas que ses voisines. Les adresses ont désormais
   la leur, un peu plus large — « 48 rue des Charmettes · 69100 Villeurbanne »
   ne tient pas dans une colonne de liens. */
.footer-grid {
  grid-template-columns: 1.3fr repeat(3, .95fr) 1.2fr;
  gap: 40px;
}
@media (max-width: 1100px) { .footer-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 900px)  { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px)  { .footer-grid { grid-template-columns: 1fr; } }

/* === BLOG/CTA — bloc 55a-blog, ne pas dupliquer === */
/* Bouton « Contactez-nous » du header : variante rouge/rose du bouton dégradé.
   Contact ayant quitté la navigation au profit du Blog, ce bouton devient le
   seul point d'entrée contact du header — il doit donc se voir. */
:root { --grad-contact: linear-gradient(120deg, #ff4d6d 0%, #ff2e63 55%, #e0154a 100%); }
:root[data-theme="light"] { --grad-contact: linear-gradient(120deg, #e81f5c 0%, #d61048 55%, #bf0a3c 100%); }

.btn-contact {
  color: #ffffff;
  background: var(--grad-contact);
  box-shadow: 0 10px 30px -10px rgba(255, 46, 99, .55);
}
.btn-contact:hover { box-shadow: 0 20px 50px -16px rgba(255, 46, 99, .7); }
:root[data-theme="light"] .btn-contact { box-shadow: 0 10px 30px -12px rgba(191, 10, 60, .45); }
:root[data-theme="light"] .btn-contact:hover { box-shadow: 0 18px 44px -14px rgba(191, 10, 60, .55); }

/* Sous 1024px le bouton du header est masque (.nav-cta .btn), le menu mobile
   doit donc porter lui-meme le point d'entree contact. */
.mobile-menu a.mobile-contact {
  background: var(--grad-contact);
  color: #ffffff;
  border-radius: var(--radius-pill);
  padding-left: 22px;
  padding-right: 22px;
  margin-top: 8px;
  align-self: flex-start;
  box-shadow: 0 10px 30px -12px rgba(255, 46, 99, .55);
}
.mobile-menu a.mobile-contact:hover { color: #ffffff; }
/* === fin bloc 55a-blog === */
