@font-face {
  font-family: "Poppins";
  src: url("fonts/poppins-v19-latin-regular.woff2") format("woff2");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Poppins";
  src: url("fonts/poppins-v19-latin-500.woff2") format("woff2");
  font-style: normal;
  font-weight: 500;
  font-display: swap;
}

body {
  font-family: "Poppins", Arial, sans-serif;
}

h1,
h2,
h3,
.brand,
.button,
.main-nav {
  font-family: "Urbanist", Arial, sans-serif;
}

h1 em,
h2 em {
  color: var(--accent-warm);
  font-family: "Iowan Old Style", "Baskerville", "Times New Roman", serif;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.035em;
}

.button {
  justify-content: space-between;
  min-height: 50px;
  line-height: 1.2;
}

.button-label {
  display: block;
}

.button-arrow {
  display: block;
  flex: 0 0 16px;
  height: 16px;
  width: 16px;
}

.hero {
  isolation: isolate;
  overflow: hidden;
  position: relative;
}

.hero-pixel-wave {
  height: 100%;
  inset: 0;
  opacity: 1;
  pointer-events: none;
  position: absolute;
  width: 100%;
  z-index: 0;
}

.hero::after {
  background:
    radial-gradient(ellipse at 68% 42%, rgba(232, 112, 24, 0.10), transparent 42%),
    linear-gradient(90deg, rgba(10, 22, 27, 0.10), rgba(10, 22, 27, 0.01) 58%, rgba(10, 22, 27, 0.20));
  content: "";
  inset: 0;
  pointer-events: none;
  position: absolute;
  z-index: 0;
}

.hero > .shell {
  position: relative;
  z-index: 1;
}

.trust-bar {
  gap: 54px;
  overflow: hidden;
}

.logo-carousel {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.logo-track {
  display: flex;
  width: max-content;
  animation: trust-logo-scroll 34s linear infinite;
}

.logo-carousel:hover .logo-track {
  animation-play-state: paused;
}

.logo-group {
  align-items: center;
  display: flex;
  flex-shrink: 0;
}

.trust-logo {
  align-items: center;
  display: flex;
  height: 76px;
  justify-content: center;
  margin-inline: 27px;
  width: 144px;
}

.trust-logo img {
  filter: grayscale(1) brightness(0) invert(1);
  height: auto;
  max-height: 44px;
  max-width: 132px;
  object-fit: contain;
  opacity: 0.76;
  width: auto;
}

.trust-logo--wide img {
  max-height: 38px;
  max-width: 144px;
}

.trust-logo--compact img {
  max-height: 58px;
  max-width: 108px;
}

@keyframes trust-logo-scroll {
  to { transform: translateX(-50%); }
}

.footer-brand {
  background: transparent;
  padding: 0;
}

.footer-brand img {
  height: auto;
  width: 138px;
}


.expertise-system {
  aspect-ratio: 1;
  margin-inline: auto;
  max-width: 430px;
  position: relative;
  width: 100%;
}

.system-orbit {
  border: 1px solid #334951;
  border-radius: 50%;
  inset: 10%;
  position: absolute;
}

.orbit-two {
  border-style: dashed;
  inset: 25%;
  transform: rotate(28deg);
}

.system-core {
  align-items: center;
  background: #182a31;
  border: 1px solid var(--accent);
  display: flex;
  flex-direction: column;
  inset: 37%;
  justify-content: center;
  position: absolute;
}

.system-core span {
  color: var(--accent-light);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.system-core strong {
  font-size: 12px;
  font-weight: 500;
  margin-top: 4px;
}

.system-label {
  background: var(--ink);
  border: 1px solid #3c525c;
  color: #bdc8cc;
  font-size: 10px;
  letter-spacing: 0.11em;
  padding: 7px 11px;
  position: absolute;
  text-transform: uppercase;
}

.label-one { left: 0; top: 48%; }
.label-two { left: 43%; top: 4%; }
.label-three { right: 1%; top: 48%; }
.label-four { bottom: 5%; left: 40%; }


.expertise-intro {
  background: var(--white);
}

.expertise-intro-grid {
  display: grid;
  gap: 10vw;
  grid-template-columns: 1fr 1fr;
}

.expertise-intro-grid h2,
.outcome-heading h2,
.ai-role h2,
.engagement-section h2,
.expertise-proof h2,
.expertise-cta h2 {
  font-size: clamp(40px, 4.8vw, 64px);
  font-weight: 500;
  letter-spacing: -0.045em;
  line-height: 1.06;
  margin: 0;
}

.expertise-intro-grid > p {
  color: var(--muted);
  font-size: 20px;
  margin: 6px 0 0;
}

.principle-grid {
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 90px;
}

.principle-grid article {
  border-right: 1px solid var(--line);
  padding: 28px 36px 6px 0;
}

.principle-grid article + article {
  padding-left: 36px;
}

.principle-grid article:last-child { border-right: 0; }
.principle-grid span,
.outcome-index { color: var(--accent); font-size: 11px; }
.principle-grid h3 { font-size: 21px; margin: 28px 0 10px; }
.principle-grid p { color: var(--muted); font-size: 14px; }

.outcome-section { background: var(--paper); }

.outcome-heading {
  align-items: end;
  display: grid;
  gap: 8vw;
  grid-template-columns: 1.4fr 0.6fr;
  margin-bottom: 80px;
}

.outcome-heading p { color: var(--muted); margin: 0; }
.outcome-list { border-top: 1px solid var(--line); }

.outcome-item {
  border-bottom: 1px solid var(--line);
  display: grid;
  gap: 45px;
  grid-template-columns: 1.25fr 0.75fr;
  padding-block: 58px;
}

.outcome-main h3 {
  font-size: clamp(30px, 3vw, 43px);
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
  margin: 0 0 18px;
}

.outcome-main > strong {
  display: block;
  font-family: "Iowan Old Style", "Baskerville", serif;
  font-size: 22px;
  font-style: italic;
  font-weight: 400;
  line-height: 1.35;
  margin-bottom: 20px;
}

.outcome-main > p { color: var(--muted); max-width: 680px; }

.deliverable-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 26px 0 0;
  padding: 0;
}

.deliverable-list li {
  border: 1px solid #c7c2b8;
  font-size: 10px;
  letter-spacing: 0.08em;
  padding: 7px 10px;
  text-transform: uppercase;
}

.outcome-item aside {
  border-left: 1px solid var(--line);
  padding-left: 34px;
}

.outcome-item aside > span {
  color: var(--accent);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.outcome-item aside ul { list-style: none; padding: 0; }
.outcome-item aside li { border-top: 1px solid var(--line); color: var(--muted); font-size: 13px; padding: 13px 0; }

.ai-role-grid {
  display: grid;
  gap: 9vw;
  grid-template-columns: 0.85fr 1.15fr;
}

.ai-role-grid > div:first-child p { color: #9daaaf; font-size: 17px; margin-top: 28px; }
.ai-use-grid { display: grid; grid-template-columns: 1fr 1fr; }
.ai-use-grid article { border-left: 1px solid #2d424b; border-top: 1px solid #2d424b; min-height: 210px; padding: 26px; }
.ai-use-grid span { color: var(--accent-light); font-size: 10px; }
.ai-use-grid h3 { font-size: 23px; margin: 32px 0 9px; }
.ai-use-grid p { color: #94a2a7; font-size: 13px; margin: 0; }

.engagement-section { background: #ded9ce; }
.engagement-section > .shell > h2 { max-width: 760px; }
.engagement-grid { border-top: 1px solid #bbb6ac; display: grid; grid-template-columns: repeat(3, 1fr); margin-top: 65px; }
.engagement-grid article { border-right: 1px solid #bbb6ac; min-height: 300px; padding: 28px 34px 10px 0; }
.engagement-grid article + article { padding-left: 34px; }
.engagement-grid article:last-child { border-right: 0; }
.engagement-grid article > div { display: flex; justify-content: space-between; }
.engagement-grid span { color: var(--accent); font-size: 11px; }
.engagement-grid small { color: #77776f; font-size: 10px; text-transform: uppercase; }
.engagement-grid h3 { font-size: 30px; margin: 48px 0 12px; }
.engagement-grid p { color: var(--muted); font-size: 14px; }

.expertise-proof { background: var(--white); padding-block: 110px; }
.expertise-proof-grid { align-items: center; display: grid; gap: 10vw; grid-template-columns: 1fr 1fr; }
.expertise-proof p { color: var(--muted); margin: 25px 0; }
.proof-names { display: grid; grid-template-columns: repeat(2, 1fr); }
.proof-names span { border-bottom: 1px solid var(--line); color: #77776f; font-family: "Urbanist", sans-serif; font-size: 24px; padding: 20px 8px; }

.expertise-cta { text-align: center; }
.expertise-cta .shell { align-items: center; display: flex; flex-direction: column; }
.expertise-cta h2 { max-width: 900px; }
.expertise-cta p { color: var(--muted); font-size: 18px; max-width: 650px; }
.expertise-cta .button { margin-top: 18px; }

.page-thesis { background: var(--white); }
.page-thesis .shell { display: grid; gap: 10vw; grid-template-columns: 1fr 1fr; }
.page-thesis h2, .sector-story-head h2, .beyond-section h2, .decision-gates h2, .collaboration h2, .origin-story h2, .founder-section > .shell > h2, .combination-section > .shell > h2, .values-section h2, .team-model h2, .page-final-cta h2 { font-size: clamp(40px, 4.8vw, 66px); font-weight: 500; letter-spacing: -.045em; line-height: 1.06; margin: 0; }
.page-thesis p { color: var(--muted); font-size: 20px; margin: 4px 0 0; }
.sector-story { background: var(--paper); scroll-margin-top: 30px; }
.sector-story-alt { background: #e4dfd5; }
.sector-story-head { align-items: start; display: grid; gap: 35px; grid-template-columns: 1fr .85fr; }
.sector-story-head > span { color: var(--accent); font-size: 11px; }
.sector-story-head > p { font-family: "Iowan Old Style", Baskerville, serif; font-size: 23px; font-style: italic; line-height: 1.4; margin: 5px 0 0; }
.sector-story-grid { border-top: 1px solid #c6c1b7; display: grid; gap: 0; grid-template-columns: 1.2fr .9fr .9fr; margin-top: 65px; }
.sector-story-grid > div { border-right: 1px solid #c6c1b7; padding: 30px 32px 12px 0; }
.sector-story-grid > div + div { padding-left: 32px; }
.sector-story-grid > div:last-child { border-right: 0; }
.sector-story-grid h3, .sector-reality > span { color: #77776f; font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.sector-reality p { font-size: 16px; }
.sector-story-grid ul { list-style: none; margin: 22px 0 0; padding: 0; }
.sector-story-grid li { border-top: 1px solid #c6c1b7; color: var(--muted); font-size: 13px; padding: 11px 0; }
.sector-proof { align-items: center; border: 1px solid #bbb6ac; display: grid; gap: 25px; grid-template-columns: 110px 100px 1fr 20px; margin-top: 50px; padding-block: 18px; transition: background .2s; }
.sector-proof:hover { background: var(--white); }
.sector-proof > span { color: #77776f; font-size: 9px; letter-spacing: .12em; text-transform: uppercase; }
.sector-proof strong { font-size: 20px; }
.sector-proof p { color: var(--muted); font-size: 13px; margin: 0; }
.sector-proof i { color: var(--accent); font-style: normal; }
.beyond-grid { display: grid; gap: 9vw; grid-template-columns: .9fr 1.1fr; }
.beyond-grid > div:first-child p { color: #9ca9ae; margin-top: 25px; }
.beyond-grid > div:last-child { border-top: 1px solid #2f444d; }
.beyond-grid article { border-bottom: 1px solid #2f444d; padding: 24px 0; }
.beyond-grid article h3 { font-size: 21px; margin: 0 0 7px; }
.beyond-grid article p { color: #8f9ea4; font-size: 13px; margin: 0; }
.page-final-cta { text-align: center; }
.page-final-cta .shell { align-items: center; display: flex; flex-direction: column; }
.page-final-cta h2 { max-width: 950px; }
.page-final-cta p { color: #526068; margin: 22px auto 0; max-width: 720px; }
.page-final-cta .button { margin-top: 35px; }

.industries .section-action { margin-top: 38px; text-align: right; }

.process-section { background: var(--paper); padding-bottom: 130px; }
.process-list { border-top: 1px solid var(--line); }
.process-stage { border-bottom: 1px solid var(--line); display: grid; gap: 40px; grid-template-columns: 78px 1fr .75fr; padding-block: 55px; }
.process-verb { color: var(--accent-ink); font-size: 10px; letter-spacing: .1em; text-transform: uppercase; }
.process-copy h2 { font-size: clamp(31px, 3.2vw, 45px); font-weight: 500; letter-spacing: -.04em; line-height: 1.08; margin: 12px 0 18px; }
.process-copy p { color: var(--muted); max-width: 650px; }
.process-output { border-left: 1px solid var(--line); padding-left: 35px; }
.process-output small { color: #77776f; letter-spacing: .12em; text-transform: uppercase; }
.process-output p { font-size: 14px; }
.decision-gates > .shell > h2 { max-width: 700px; }
.gate-grid { border-top: 1px solid #2f444d; display: grid; grid-template-columns: repeat(3, 1fr); margin-top: 65px; }
.gate-grid article { border-right: 1px solid #2f444d; min-height: 245px; padding: 26px 34px 10px 0; }
.gate-grid article + article { padding-left: 34px; }
.gate-grid article:last-child { border-right: 0; }
.gate-grid span { color: var(--accent-light); font-size: 10px; }
.gate-grid h3 { font-size: 28px; margin: 55px 0 10px; }
.gate-grid p { color: #8f9ea4; font-size: 13px; }
.collaboration { background: #ded9ce; }
.collaboration-grid { align-items: center; display: grid; gap: 10vw; grid-template-columns: 1fr 1fr; }
.collaboration-grid > div:first-child p { color: var(--muted); margin-top: 25px; }
.role-map { display: flex; flex-direction: column; }
.role-map span { background: rgba(255,255,255,.22); border: 1px solid #bcb7ad; font-size: 13px; margin-top: -1px; padding: 14px 18px; transform: translateX(calc(var(--i) * 12px)); width: calc(100% - 48px); }

.origin-story { background: var(--white); }
.origin-grid { display: grid; gap: 10vw; grid-template-columns: .9fr 1.1fr; }
.origin-grid p { color: var(--muted); }
.origin-grid .lead { color: var(--ink); font-family: "Iowan Old Style", Baskerville, serif; font-size: 25px; line-height: 1.45; margin-top: 0; }
.origin-grid > div > div + div { display: block; margin-top: 28px !important; }
.about-page .origin-grid a { color: #b4400f !important; font-weight: 600; text-decoration: underline; text-decoration-color: #b4400f; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.founder-section > .shell > h2 { max-width: 800px; }
.founder-grid { display: grid; gap: 1px; grid-template-columns: 1fr 1fr; margin-top: 70px; background: #31464f; }
.founder-grid article { background: var(--ink); padding: 40px; }
.founder-id { align-items: center; display: flex; gap: 20px; }
.founder-id > span { border: 1px solid var(--accent); color: var(--accent-light); display: grid; font-family: "Iowan Old Style", serif; font-size: 20px; height: 58px; place-items: center; width: 58px; }
.founder-id h3 { font-size: 25px; margin: 0; }
.founder-id small, .founder-education { color: #86959b; font-size: 10px; letter-spacing: .09em; text-transform: uppercase; }
.founder-education { border-bottom: 1px solid #2f444d; border-top: 1px solid #2f444d; margin: 30px 0; padding: 13px 0; }
.founder-grid article > p { color: #9eacb2; font-size: 14px; }
.founder-grid blockquote { border-left: 1px solid var(--accent); font-family: "Iowan Old Style", serif; font-size: 19px; font-style: italic; margin: 30px 0 0; padding-left: 20px; }
.combination-section { background: var(--paper); }
.combination-section > .shell > h2 { max-width: 820px; }
.combination-grid { border-top: 1px solid var(--line); display: grid; grid-template-columns: repeat(3,1fr); margin-top: 65px; }
.combination-grid article { border-right: 1px solid var(--line); padding: 27px 35px 8px 0; }
.combination-grid article + article { padding-left: 35px; }
.combination-grid article:last-child { border-right: 0; }
.combination-grid span, .values-layout article > span { color: var(--accent); font-size: 10px; }
.combination-grid h3 { font-size: 22px; margin: 42px 0 12px; }
.combination-grid p { color: var(--muted); font-size: 14px; }
.values-section { background: #ded9ce; }
.values-layout { display: grid; gap: 9vw; grid-template-columns: .85fr 1.15fr; }
.values-layout > div { border-top: 1px solid #bbb6ac; }
.values-layout article { align-items: baseline; border-bottom: 1px solid #bbb6ac; display: grid; gap: 22px; grid-template-columns: .7fr 1fr; padding: 23px 0; }
.values-layout h3 { font-size: 20px; margin: 0; }
.values-layout p { color: var(--muted); font-size: 13px; margin: 0; }
.team-model-grid { display: grid; gap: 10vw; grid-template-columns: 1fr 1fr; }
.team-model-grid > div > p { color: #96a4a9; margin-top: 25px; }
.team-model ul { border-top: 1px solid #2f444d; list-style: none; margin: 0; padding: 0; }
.team-model li { border-bottom: 1px solid #2f444d; color: #c4ced2; font-size: 14px; padding: 17px 0 17px 25px; position: relative; }
.team-model li::before { color: var(--accent-light); content: "→"; left: 0; position: absolute; }

@media (max-width: 900px) {
  .main-nav {
    background: var(--paper);
    border-top-color: var(--line);
  }

  .main-nav a {
    color: var(--ink);
  }

  .main-nav .language-switch {
    border-left: 0;
    padding-left: 0;
  }

  .trust-bar {
    display: flex;
    padding-block: 24px;
  }

  .trust-bar > span {
    display: none;
  }

  .trust-logo {
    margin-inline: 19px;
  }

  .expertise-intro-grid,
  .outcome-heading,
  .ai-use-grid { grid-template-columns: 1fr; }
  .ai-role-grid,
  .expertise-proof-grid {
    grid-template-columns: 1fr;
  }

  .expertise-system { max-width: 360px; }
  .outcome-item { grid-template-columns: 1fr; }
  .outcome-item aside { border-left: 0; grid-column: 1; padding-left: 0; }
  .principle-grid,
  .engagement-grid { grid-template-columns: 1fr; }
  .principle-grid article,
  .principle-grid article + article,
  .engagement-grid article,
  .engagement-grid article + article { border-bottom: 1px solid var(--line); border-right: 0; min-height: 0; padding: 28px 0; }
  /* Recovered: these were trapped inside the reduced-motion query below by a
     stray brace, so every interior page stayed multi-column on phones. */
  .page-thesis .shell, .sector-story-head, .beyond-grid, .collaboration-grid, .origin-grid, .values-layout, .team-model-grid { grid-template-columns: 1fr; }
  .sector-story-grid { grid-template-columns: 1fr; }
  .sector-story-grid > div, .sector-story-grid > div + div { border-bottom: 1px solid #c6c1b7; border-right: 0; padding: 25px 0; }
  .sector-proof { grid-template-columns: 90px 80px 1fr; }
  .sector-proof i { display: none; }
  .process-stage { grid-template-columns: 1fr; }
  .process-copy { grid-column: 1; }
  .process-output { border-left: 0; grid-column: 1; padding-left: 0; }
  .gate-grid, .founder-grid, .combination-grid { grid-template-columns: 1fr; }
  .gate-grid article, .gate-grid article + article, .combination-grid article, .combination-grid article + article { border-bottom: 1px solid var(--line); border-right: 0; min-height: 0; padding: 28px 0; }
  .values-layout article { grid-template-columns: 1fr; }
  .values-layout article p { grid-column: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .logo-track {
    animation-play-state: paused;
    transform: none;
  }
}

/* ==========================================================================
   ITERATION 02 — palette discipline, brand light, motion variety
   ========================================================================== */

/* --- Accent discipline --------------------------------------------------- */
/* The bright orange is a fill colour, not a text colour: #e87018 only clears
   2.8:1 on paper. Small orange text switches to the deep end of the logo
   gradient (#b4400f = 5.0:1) so the marks stay legible and the family reads as
   the fox's range of oranges rather than one flat salmon. */
.three-steps span,
.service-row > span,
.service-row i,
.industry > span,
.industry b,
.method-list span,
.listing-card span,
.listing-card b,
.main-nav .language-switch,
.contact-details a,
.prose a,
.eyebrow-dark span { color: var(--accent-ink); }

.eyebrow-dark span { background: var(--accent-ink); }

/* Brand gradient as structure: the header rule is the logo's own ramp. */
.site-header { position: relative; border-bottom-color: transparent; }
.site-header::after {
  content: "";
  position: absolute; inset: auto 0 0 0; height: 1px;
  background: linear-gradient(90deg, var(--flame), var(--accent) 34%, var(--amber) 62%, var(--line) 100%);
  opacity: .5;
}

/* --- Hero: lit from the brand, not flat black --------------------------- */
/* Two soft sources (ember low-left under the headline, amber high-right) plus a
   top vignette that softens the seam where the light header meets the dark
   hero. Replaces the neutral grey wash. */
.hero::after {
  background:
    radial-gradient(122% 92% at 6% 90%, rgba(222, 70, 26, .17), transparent 58%),
    radial-gradient(74% 62% at 90% 10%, rgba(244, 178, 19, .085), transparent 62%),
    linear-gradient(180deg, rgba(10, 22, 27, .38), transparent 30%);
}

/* The status dot was status-page green; amber reads as signal, and it is ours. */
.live { color: #e9c77a; }
.live i { background: var(--amber); box-shadow: 0 0 0 3px rgba(244, 178, 19, .14); }

/* --- Trust bar ---------------------------------------------------------- */
/* Stepping the track one slot at a time made the logos jump. Back to a
   continuous glide, slowed a little, with the edge mask widened so a logo fades
   out rather than being clipped mid-glyph. */
.logo-track { animation: trust-logo-scroll 46s linear infinite; }
.logo-carousel {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent);
}
.trust-logo img { opacity: .84; transition: opacity .3s ease; }
.trust-logo:hover img { opacity: 1; }

/* --- Sourced figures --------------------------------------------------- */
/* A ruled register, not a row of stat cards: numeral in the serif, unit small,
   and every figure carries the client it came from and links to the case that
   documents it. No number appears here without a source. */
/* The section heading already draws a rule; a second one 50px below it read as
   a mistake. The figures now hang off that single rule.
   Each figure is its own three-row grid — numeral / text / source — so the
   client attributions sit on one baseline however long the descriptions run,
   and the hover surface is inset on all four sides instead of bleeding flush
   to the left edge. */
.proof-figures {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 1px;
  background: #1f2e35;
  margin-bottom: 78px;
}
.proof-figure {
  background: var(--ink);
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: 32px 30px 28px;
  transition: background .32s ease;
}
.proof-figure:hover { background: #16262e; }
.proof-figure b {
  display: block;
  font-family: "Iowan Old Style", Baskerville, Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(46px, 5.4vw, 74px);
  line-height: .92;
  letter-spacing: -.03em;
  color: var(--accent-light);
  font-variant-numeric: tabular-nums lining-nums;
}
.proof-figure b i { font-size: .42em; font-style: italic; letter-spacing: 0; margin-left: .1em; }
.proof-figure p {
  margin: 20px 0 0;
  font-size: 15px;
  line-height: 1.45;
  color: #c4ced2;
  max-width: 21em;
}
.proof-figure small {
  display: block;
  margin-top: 14px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .13em;
  color: #7f8f96;
}
.proof-figure:hover small { color: var(--accent-light); }

@media (max-width: 900px) {
  .proof-figures { grid-template-columns: 1fr; row-gap: 1px; margin-bottom: 48px; }
  .proof-figure { padding: 24px 22px; }
}

/* ==========================================================================
   MOTION
   Five behaviours instead of one, chosen by what the element is:
     rise    prose and blocks              opacity + short lift
     words   the hero headline             a wave across the words, left to right
     rule    ruled lists and tables        clip left→right along the rule
     stagger grid children                 sequenced, 1 child at a time
     hold    the hero panel                settle in from slightly small
   Nothing is hidden unless JS is running, so first paint always has text.
   ========================================================================== */
:root {
  --ease-settle: cubic-bezier(.22, .61, .16, 1);
  --ease-draw: cubic-bezier(.16, 1, .3, 1);
}

/* Neutralise the old unconditional hide. Without html.motion, everything is on. */
.reveal { opacity: 1; transform: none; transition: none; }

html.motion .reveal,
html.motion [data-anim="rise"] {
  opacity: 0; transform: translateY(14px);
  transition: opacity .62s var(--ease-settle), transform .62s var(--ease-settle);
}
html.motion .reveal.visible,
html.motion [data-anim="rise"].visible { opacity: 1; transform: none; }

/* Ruled lists are drawn along their rule rather than faded, so they need a
   mask, not clip-path: a clipped element reports a 0x0 intersection rect, which
   means the IntersectionObserver watching it can never fire and it stays hidden
   forever. The mask is dropped once the transition ends (see anim-done) so it
   cannot clip hover states or overflowing pseudo-elements afterwards. Masking
   is only safe on these because they are boxes with padding: a mask is bounded
   by the border box, so it crops any ink painting outside one. That is what
   ruled it out for the hero headline, whose line-height is .99em on a 1em font,
   putting its ascenders and descenders outside the box. */
html.motion [data-anim="rule"]:not(.anim-done) {
  -webkit-mask-image: linear-gradient(#000, #000);
  mask-image: linear-gradient(#000, #000);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

html.motion [data-anim="rule"]:not(.anim-done) {
  -webkit-mask-size: 0% 100%;
  mask-size: 0% 100%;
  transition: -webkit-mask-size 1.05s var(--ease-draw), mask-size 1.05s var(--ease-draw);
}
html.motion [data-anim="rule"].visible:not(.anim-done) {
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
}

html.motion [data-anim="stagger"] > * {
  opacity: 0; transform: translateY(16px);
  transition: opacity .58s var(--ease-settle), transform .58s var(--ease-settle);
  transition-delay: calc(var(--i, 0) * 85ms);
}
html.motion [data-anim="stagger"].visible > * { opacity: 1; transform: none; }

html.motion [data-anim="hold"] {
  opacity: 0; transform: scale(.986) translateY(8px);
  transition: opacity .9s var(--ease-settle), transform .9s var(--ease-settle);
}
html.motion [data-anim="hold"].visible { opacity: 1; transform: none; }

/* --- The hero headline -------------------------------------------------- */
/* This was a mask uncovering the line from the top down, with the italic
   clause fading in separately, in white, and warming to the accent half a
   second later. Three things were wrong with it. The mask clipped the bottoms
   of the letters for the whole sweep, because a mask is bounded by the border
   box and this headline's ink is not. The staged colour read as a rendering
   fault rather than as a reveal. And a vertical wipe is an effect laid over the
   text; it says nothing about the text.
   The line now arrives as a wave across its own words, left to right, in the
   direction it is read, and settles. There is no clip edge, so nothing can
   crop, and the italic clause lands last because it is last in the sentence
   rather than because it was singled out. Words are split at build time (see
   partials/headline.html) so they are hidden from first paint; fasfox.js is
   deferred, so splitting in the browser would paint the line and then hide it.
   The stagger is deliberately tight: 34ms across seven words reads as one
   gesture with a direction, not as seven separate animations. */
/* Unconditional, so the line wraps identically whether or not JS runs. */
.hero h1 .hw { display: inline-block; }
html.motion .hero h1 .hw {
  opacity: 0;
  transform: translateY(.17em);
  transition: opacity .5s var(--ease-settle), transform .66s var(--ease-settle);
  transition-delay: calc(var(--hw, 0) * 34ms + 60ms);
}
html.motion .hero h1.visible .hw { opacity: 1; transform: none; }
html.motion .hero .hero-intro { transition-delay: .3s; }
html.motion .hero .actions { transition-delay: .42s; }
html.motion .hero .operations-visual { transition-delay: .5s; }
html.motion .hero .trust-bar { transition-delay: .72s; }

/* Interaction, tuned: the service rows already shift on hover. Give the rule a
   direction so the row feels like it is being selected rather than nudged. */
.service-row { position: relative; }
.service-row::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--accent-ink); transform: scaleX(0); transform-origin: left;
  transition: transform .42s var(--ease-draw);
}
.service-row:hover::after { transform: scaleX(1); }

.case { transition: border-color .3s ease, transform .3s var(--ease-settle), background .3s ease; }
.case:hover { background: rgba(232, 112, 24, .03); }

@media (prefers-reduced-motion: reduce) {
  html.motion .reveal,
  html.motion [data-anim] {
    opacity: 1 !important; transform: none !important;
    clip-path: none !important; transition: none !important;
    -webkit-mask-image: none !important; mask-image: none !important; }
  html.motion [data-anim="stagger"] > * { opacity: 1 !important; transform: none !important; transition: none !important; }
  html.motion .hero h1 .hw { opacity: 1 !important; transform: none !important; transition: none !important; }
  .logo-track { animation: none; }
}

/* --- Hero proportions --------------------------------------------------- */
/* The client roster is the strongest asset on the page; at 1440x900 it was
   falling below the fold. Tightening the grid brings the logos back above it
   and makes the hero read less like a template's default 100vh block. */
.hero-grid { min-height: 596px; padding-top: 52px; padding-bottom: 44px; }
.trust-bar { min-height: 104px; }
@media (max-width: 900px) { .hero-grid { min-height: 0; } }

/* Same accent discipline on the interior pages: small orange marks sitting on
   paper take the deep end of the gradient so they clear 4.5:1. */
.principle-grid span,
.outcome-index,
.outcome-item aside > span,
.engagement-grid span,
.sector-story-head > span,
.sector-proof i,
.process-verb,
.combination-grid span,
.values-layout article > span { color: var(--accent-ink); }

/* --- Client logos on dark ---------------------------------------------- */
/* grayscale + brightness(2) leaves a dark logo dark: on the blue ground the
   marks were effectively invisible. Knock them out to white the way the trust
   bar already does, and give them enough room to be recognised. */
.case-logo img,
.case-page-logo {
  filter: grayscale(1) brightness(0) invert(1);
  opacity: .82;
}
.case-logo img { max-height: 46px; max-width: 168px; }
.case-logo.small img { max-height: 38px; max-width: 132px; }
.case:hover .case-logo img { opacity: 1; }
.case-page-logo { max-height: 58px; }

/* --- Client listing logos ---------------------------------------------- */
/* Nine marks at nine different colours read as a directory listing. Muted to a
   single value they read as one roster; colour returns on hover. */
.listing-logo img {
  filter: grayscale(1);
  opacity: .72;
  max-height: 46px;
  transition: filter .3s ease, opacity .3s ease;
}
.listing-card:hover .listing-logo img { filter: none; opacity: 1; }

/* The italic serif takes its colour from the ground it sits on: the pale tint
   reads well knocked out on petrol blue and lands at 1.7:1 on paper. Selectors
   are matched to `.split-heading h2 em` in fasfox.css, which outranks a bare
   `h2 em`. */
h1 em,
h2 em,
.split-heading h2 em { color: var(--accent-warm); }

.hero h1 em,
.page-hero h1 em,
.section-dark h1 em,
.section-dark h2 em,
.section-dark .split-heading h2 em { color: var(--accent-light); }

/* ==========================================================================
   ITERATION 03 — page headers, sector page, article layout
   ========================================================================== */

/* --- Engagement note and the ownership answer --------------------------- */
/* The engagement ladder implied the right client size; the note states the
   boundary out loud. The ownership block answers who keeps the code, the data
   and the ability to change it, which nothing on the site addressed. */
.engagement-note {
  color: var(--muted);
  font-size: 18px;
  margin: 22px 0 0;
  max-width: 68ch;
}
.ownership-section { background: var(--white); }
.ownership-grid {
  display: grid;
  gap: 6vw;
  grid-template-columns: 1fr 1.35fr;
}
.ownership-grid h2 {
  font-size: clamp(32px, 3.4vw, 46px);
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1.08;
  margin: 0;
}
.ownership-grid p {
  color: var(--muted);
  font-size: 18px;
  margin: 0;
  max-width: 66ch;
}
@media (max-width: 900px) {
  .ownership-grid { grid-template-columns: 1fr; gap: 26px; }
}

/* --- One header for every section page --------------------------------- */
/* Expertises, Secteurs, Usages, Notre approche, Réalisations and À propos used
   to run three different treatments between them: three wrappers, three grids,
   three h1 scales, three greys and four unrelated right-hand columns. Measured
   at 1440x900 the hero was 849px tall on Expertises, 708px on the editorial
   three and 455px on Réalisations, and the h1 landed at 265 / 279 / 351 / 442 —
   the title moved as you navigated.
   The h1 was moving because the old grid used `align-items: end`, which pins the
   lede to the bottom of a row sized by whichever column is taller: a page with
   a short right-hand column pushed its own title down. Aligning to the start
   fixes the kicker and the title to the same pixel on every page.
   The right-hand column carried a list through several revisions — sector links,
   capability bands, method promises, department counts. Unifying them made the
   set consistent without making it better: they competed with the title at the
   top of every page and said nothing the page underneath did not say more fully.
   The column now holds one line of lede and stops. */
.page-header {
  --hero-muted: #a7b5ba;
  --hero-label: #8b9aa1;
  padding-top: 88px;              /* clears the fixed site header */
}

.page-header-grid {
  align-items: start;
  display: grid;
  gap: clamp(46px, 7vw, 100px);
  grid-template-columns: 1.12fr .88fr;
  /* No min-height on purpose. What has to match between pages is where the
     title starts and how much air surrounds the block — the padding above plus
     align-items:start pin the kicker and the title to the same pixel on every
     page, and with no floor every page also gets exactly the same padding
     below its content. Height then follows the title's line count, which is
     copy, not layout. Pinning the block to the tallest page instead left the
     one-line titles above 450px of nothing, and a floor only moved that
     emptiness around. */
  padding-block: clamp(86px, 9vw, 122px) clamp(66px, 7vw, 94px);
}

.page-header-kicker {
  color: var(--hero-label);
  display: block;
  font-size: 10px;
  letter-spacing: .18em;
  line-height: 1;
  margin-bottom: 28px;
  text-transform: uppercase;
}

.page-header h1 {
  font-size: clamp(52px, 6.2vw, 88px);
  font-weight: 500;
  letter-spacing: -.055em;
  line-height: 1;
  margin: 0;
}

.page-header-cta { margin-top: clamp(34px, 3.4vw, 46px); }

.page-header-aside { padding-top: 38px; }
.page-header-intro {
  color: var(--hero-muted);
  font-size: 19px;
  line-height: 1.55;
  margin: 0;
  max-width: 46ch;
}

@media (max-width: 900px) {
  .page-header-grid {
    gap: 44px;
    grid-template-columns: 1fr;
    min-height: 0;
    padding-block: clamp(74px, 12vw, 96px) clamp(52px, 8vw, 72px);
  }
  .page-header-aside { padding-top: 0; }
}

/* --- Subpage headers share the homepage field, not its gradient ---------- */
/* The homepage keeps the warm ember wash; section pages get the same pixel
   field in a cooler, flatter tuning plus a single cool vignette. Related, not
   identical, and the header seam is softened the same way. */
.page-header,
.page-hero {
  isolation: isolate;
  overflow: hidden;
  position: relative;
}

.page-pixel-wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}

.page-header::after,
.page-hero::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(88% 70% at 78% 8%, rgba(146, 172, 184, .085), transparent 60%),
    linear-gradient(180deg, rgba(10, 22, 27, .42), transparent 26%);
}

.page-header > .shell,
.page-hero > .shell {
  position: relative;
  z-index: 1;
}

/* --- Sector story: three treatments, no micro-headlines ----------------- */
/* The labels ("Réalité du terrain", "Frictions fréquentes", "Réponses
   possibles") added weight and no information, so they are kept in the markup
   as .sr-only headings for structure and screen readers, and the distinction is
   carried visually instead: the reality is set as a lede, the frictions as a
   ruled list of what goes wrong, the responses as chips of what we build. That
   chip treatment already means "things we deliver" on the expertise page. */
.sector-story-grid {
  border-top: 1px solid #c6c1b7;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  column-gap: 7vw;
  row-gap: 0;
  margin-top: 58px;
}
.sector-story-grid > div { border-right: 0; padding: 34px 0 0; }
.sector-story-grid > div + div { padding-left: 0; }

.sector-reality p {
  font-size: 19px;
  line-height: 1.5;
  color: #33352f;
  margin: 0;
  max-width: 30em;
}

.sector-frictions ul { list-style: none; margin: 0; padding: 0; }
.sector-frictions li {
  border-bottom: 1px solid #cfcabf;
  color: #3c3e37;
  font-size: 15px;
  padding: 13px 0;
}
/* the grid rule above already opens the block */

.sector-responses {
  grid-column: 1 / -1;
  padding-top: 34px;
}
.sector-responses ul {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.sector-responses ul { gap: 10px 34px; }
.sector-responses li {
  color: var(--accent-ink);
  font-size: 11.5px;
  letter-spacing: .09em;
  padding-left: 20px;
  position: relative;
  text-transform: uppercase;
}
.sector-responses li::before {
  content: "→";
  position: absolute;
  left: 0;
  opacity: .65;
}

/* --- Related project row ------------------------------------------------ */
/* Was a four-column grid with vertical padding only, so the tag touched the
   border and the arrow sat pinned 20px off the right edge. Now a padded row
   with the arrow attached to its own label, and a hover that moves rather than
   flashing to white. */
.sector-proof {
  align-items: baseline;
  border: 0;
  border-top: 1px solid #c2bdb2;
  display: grid;
  grid-template-columns: minmax(120px, 150px) 1fr auto;
  gap: 8px 32px;
  margin-top: 46px;
  padding: 26px 0 4px 20px;
  position: relative;
  transition: background .3s ease;
}
.sector-proof::before {
  content: "";
  position: absolute;
  inset: 0 auto 4px 0;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform .38s var(--ease-draw);
}
.sector-proof:hover { background: rgba(232, 112, 24, .04); }
.sector-proof:hover::before { transform: scaleY(1); }

.sector-proof-tag {
  color: #6f6f67;
  font-size: 9px;
  grid-row: 1;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.sector-proof strong { font-size: 21px; font-weight: 500; grid-row: 2; grid-column: 1; }
.sector-proof p {
  color: var(--muted);
  font-size: 14.5px;
  grid-column: 2;
  grid-row: 2;
  margin: 0;
  max-width: 46em;
}
.sector-proof-go {
  color: var(--accent-ink);
  font-size: 11px;
  grid-column: 3;
  grid-row: 2;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.sector-proof-go i {
  display: inline-block;
  font-style: normal;
  transition: transform .3s var(--ease-settle);
}
.sector-proof:hover .sector-proof-go i { transform: translate(3px, -3px); }

@media (max-width: 900px) {
  .sector-story-grid { grid-template-columns: 1fr; }
  .sector-story-grid > div,
  .sector-story-grid > div + div { border-bottom: 0; border-right: 0; padding: 28px 0 0; }
  .sector-proof {
    grid-template-columns: 1fr;
    gap: 6px;
    padding: 20px 22px;
  }
  .sector-proof strong,
  .sector-proof p,
  .sector-proof-go { grid-column: 1; grid-row: auto; }
  .sector-proof-go { margin-top: 10px; }
}

/* --- AI use-case catalogue ---------------------------------------------- */
/* 52 use cases used to render as one 15,000px wall of identical cards. Grouped
   by the department that owns the pain, four visible per group, the rest behind
   a native <details>. Our judgment comes before the list, not after it. */
.usecase-thesis { background: var(--white); }
.usecase-thesis-head { max-width: 900px; }
.usecase-thesis-head h2 {
  font-size: clamp(34px, 4vw, 56px);
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1.08;
  margin: 0;
}
.usecase-thesis-head p { color: var(--muted); font-size: 19px; margin: 26px 0 0; max-width: 44em; }

.usecase-criteria {
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: 74px;
}
.usecase-criteria article { border-right: 1px solid var(--line); padding: 28px 34px 8px 0; }
.usecase-criteria article + article { padding-left: 34px; }
.usecase-criteria article:last-child { border-right: 0; }
.usecase-criteria span { color: var(--accent-ink); font-size: 11px; }
.usecase-criteria h3 { font-size: 20px; margin: 26px 0 12px; }
.usecase-criteria p { color: var(--muted); font-size: 14.5px; margin: 0; }

.usecase-groups-head { margin-bottom: 66px; max-width: 760px; }
.usecase-groups-head h2 {
  font-size: clamp(30px, 3.4vw, 44px);
  font-weight: 500;
  letter-spacing: -.04em;
  margin: 0;
}
.usecase-groups-head p { color: var(--muted); font-size: 16px; margin: 16px 0 0; }

.usecase-group { margin-bottom: 78px; }
.usecase-group-head {
  align-items: baseline;
  border-bottom: 1px solid var(--ink);
  display: grid;
  gap: 4px 22px;
  grid-template-columns: auto 1fr;
  padding-bottom: 16px;
}
.usecase-group-head h3 {
  font-size: clamp(24px, 2.6vw, 33px);
  font-weight: 500;
  letter-spacing: -.035em;
  margin: 0;
}
.usecase-count {
  color: var(--accent-ink);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  letter-spacing: .1em;
  align-self: center;
}
.usecase-group-head p {
  color: var(--muted);
  font-size: 15px;
  grid-column: 1 / -1;
  margin: 10px 0 0;
  max-width: 52em;
}

.usecase-list { list-style: none; margin: 0; padding: 0; }
.usecase-list li { border-bottom: 1px solid var(--line); }
.usecase-list a {
  align-items: baseline;
  display: grid;
  gap: 30px;
  grid-template-columns: minmax(220px, .8fr) 1.2fr 18px;
  padding: 19px 8px 19px 0;
  position: relative;
  transition: padding-left .28s var(--ease-settle), background .28s ease;
}
.usecase-list a:hover { background: #f8f5ee; padding-left: 14px; }
.usecase-list strong { font-size: 17px; font-weight: 500; }
.usecase-list span { color: var(--muted); font-size: 14.5px; }
.usecase-list i {
  color: var(--accent-ink);
  font-style: normal;
  opacity: 0;
  transition: opacity .25s ease, transform .25s var(--ease-settle);
}
.usecase-list a:hover i { opacity: 1; transform: translate(2px, -2px); }

.usecase-more { margin-top: 4px; }
.usecase-more summary {
  color: var(--accent-ink);
  cursor: pointer;
  font-size: 11px;
  letter-spacing: .12em;
  list-style: none;
  padding: 18px 0;
  text-transform: uppercase;
  transition: color .2s ease;
}
.usecase-more summary::-webkit-details-marker { display: none; }
.usecase-more summary::after { content: "↓"; display: inline-block; margin-left: 9px; transition: transform .25s ease; }
.usecase-more[open] summary::after { content: "↑"; }
.usecase-more summary:hover { color: var(--ink); }

.usecase-sector-note {
  align-items: baseline;
  border-top: 1px solid var(--line);
  display: flex;
  gap: 40px;
  justify-content: space-between;
  padding-top: 26px;
}
.usecase-sector-note p { color: var(--muted); font-size: 15px; margin: 0; max-width: 46em; }

@media (max-width: 900px) {
  .usecase-criteria { grid-template-columns: 1fr; }
  .usecase-criteria article,
  .usecase-criteria article + article {
    border-bottom: 1px solid var(--line); border-right: 0; padding: 24px 0; }
  .usecase-criteria article:last-child { border-bottom: 0; }
  .usecase-list a { grid-template-columns: 1fr; gap: 6px; }
  .usecase-list i { display: none; }
  .usecase-sector-note { flex-direction: column; gap: 18px; }
}

/* --- Sector page framing ------------------------------------------------ */
.page-thesis .text-link { margin-top: 30px; display: inline-block; }
.sector-stories-note {
  border-top: 1px solid var(--line);
  padding-top: 18px;
  margin-bottom: -30px;
}
.sector-stories-note span {
  color: #6f6f67;
  font-size: 10px;
  letter-spacing: .15em;
  text-transform: uppercase;
}
.beyond-cta { margin-top: 34px; }

/* ==========================================================================
   ITERATION 04 — text face and the standard article layout
   ========================================================================== */

/* --- Body text face ----------------------------------------------------- */
/* Poppins is a geometric display face; at 17px over several thousand words of
   French it is tiring and characterless. IBM Plex Sans is a text face: better
   rhythm, real italics, proper diacritics, and its slightly technical drawing
   suits industrial and telecom readers. Headings stay in Urbanist, so the brand
   voice is unchanged. Two variable files, latin subset, self-hosted. */
@font-face {
  font-family: "Plex";
  src: url("fonts/ibm-plex-sans-var.woff2") format("woff2-variations"),
       url("fonts/ibm-plex-sans-var.woff2") format("woff2");
  font-weight: 100 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Plex";
  src: url("fonts/ibm-plex-sans-var-italic.woff2") format("woff2-variations"),
       url("fonts/ibm-plex-sans-var-italic.woff2") format("woff2");
  font-weight: 100 700;
  font-style: italic;
  font-display: swap;
}

body {
  font-family: "Plex", "Poppins", system-ui, sans-serif;
  font-size: 16.5px;
  line-height: 1.62;
  letter-spacing: -0.002em;
}

/* --- Standard article layout -------------------------------------------- */
/* One centred measure instead of a sidebar. The old aside held an unstyled
   .TableOfContents that duplicated the headings and gave nowhere useful to go;
   a single 68ch column is what a long read wants. */
.article-layout {
  display: block;
  padding-top: 78px;
  padding-bottom: 120px;
  max-width: 100%;
}
.article-layout > .prose {
  margin-inline: auto;
  max-width: 68ch;
}

.prose {
  font-size: 17.5px;
  line-height: 1.68;
  color: #33352f;
}
.prose > :first-child { margin-top: 0; }
.prose p { margin: 0 0 1.3em; }
.prose p,
.prose li { color: #383a33; }
.prose strong { font-weight: 600; color: var(--ink); }

.prose h2 {
  font-size: clamp(27px, 2.9vw, 34px);
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1.16;
  margin: 2.5em 0 .7em;
  padding-top: .9em;
  border-top: 1px solid var(--line);
}
.prose h2:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.prose h3 {
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.015em;
  margin: 2.1em 0 .5em;
}
.prose h4 { font-size: 17px; font-weight: 600; margin: 1.8em 0 .4em; }

.prose a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
.prose a:hover { color: var(--ink); }

.prose ul,
.prose ol { margin: 0 0 1.4em; padding-left: 1.15em; }
.prose li { margin-bottom: .5em; }
.prose li::marker { color: #9a958a; }

.prose blockquote {
  border-left: 2px solid var(--accent);
  margin: 2em 0;
  padding: 2px 0 2px 24px;
  font-size: 19px;
  color: var(--ink);
}
.prose blockquote p:last-child { margin-bottom: 0; }

.prose img {
  border: 1px solid var(--line);
  display: block;
  margin: 2.4em 0;
  width: 100%;
}

/* Tables carry the specifications in these case studies; they should read like
   specifications and not like leftover markdown. */
.prose table {
  border-collapse: collapse;
  font-size: 15px;
  margin: 2.2em 0;
  width: 100%;
}
.prose thead th {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--ink);
  color: #55574f;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .12em;
  padding: 0 14px 11px 0;
  text-align: left;
  text-transform: uppercase;
}
.prose tbody td {
  border: 0;
  border-bottom: 1px solid var(--line);
  padding: 14px 14px 14px 0;
  vertical-align: top;
}
.prose tbody tr:last-child td { border-bottom: 1px solid var(--ink); }
.prose tbody td:first-child { color: var(--ink); font-weight: 500; width: 32%; }
.prose td:last-child,
.prose th:last-child { padding-right: 0; }

.prose hr { border: 0; border-top: 1px solid var(--line); margin: 3em 0; }
.prose code {
  background: #e9e5db;
  font-size: .88em;
  padding: 2px 5px;
}

/* --- Reading progress --------------------------------------------------- */
/* Replaces the sidebar's only real function: knowing how much is left. */
.read-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: linear-gradient(90deg, var(--flame), var(--accent) 60%, var(--amber));
  z-index: 60;
  pointer-events: none;
}

@media (max-width: 900px) {
  .article-layout { padding-top: 54px; padding-bottom: 84px; }
  .prose { font-size: 16.5px; }
  .prose table { display: block; overflow-x: auto; }
}

/* --- Case study dossier strip ------------------------------------------- */
/* The facts a reader wants before committing to 3,000 words, in the header
   rather than buried in the prose. */
.dossier-strip {
  border-top: 1px solid #2c4048;
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  margin: 52px 0 0;
  padding: 0;
}
.dossier-strip > div {
  border-right: 1px solid #24363d;
  padding: 20px 34px 0 0;
  margin-right: 34px;
}
.dossier-strip > div:last-child { border-right: 0; margin-right: 0; padding-right: 0; }
.dossier-strip dt {
  color: #7f8f96;
  font-size: 9px;
  letter-spacing: .15em;
  text-transform: uppercase;
}
.dossier-strip dd {
  color: var(--white);
  font-size: 17px;
  font-weight: 500;
  margin: 8px 0 0;
}

/* Client work reads as a project dossier rather than a generic article. */
.case-page .case-hero {
  background: var(--ink);
  border-bottom: 1px solid #263a43;
  color: var(--white);
  padding: 172px 0 96px;
}
.case-hero-grid {
  align-items: end;
  display: grid;
  gap: clamp(55px, 8vw, 120px);
  grid-template-columns: minmax(0, 1.35fr) minmax(240px, .65fr);
}
.case-hero-main .article-kicker {
  color: #8b9aa1;
  display: block;
  font-size: 10px;
  letter-spacing: .18em;
  margin-bottom: 38px;
  text-transform: uppercase;
}
.case-hero-main .case-page-logo {
  filter: grayscale(1) brightness(0) invert(1);
  margin: 0 0 42px;
  max-height: 64px;
  max-width: 210px;
  opacity: .8;
}
.case-page .case-hero h1 {
  font-size: clamp(34px, 4.3vw, 60px);
  font-weight: 500;
  letter-spacing: -.04em;
  line-height: 1.08;
  margin: 0;
  max-width: 18ch;
}
.case-hero .dossier-strip {
  border-top-color: #35505b;
  display: grid;
  grid-template-columns: 1fr;
  margin: 0;
}
.case-hero .dossier-strip > div {
  border-bottom: 1px solid #2c4048;
  border-right: 0;
  margin: 0;
  padding: 16px 0;
}
.case-hero .dossier-strip > div:first-child { border-top: 1px solid #2c4048; }
.case-hero .dossier-strip dt { color: #7f8f96; }
.case-hero .dossier-strip dd { color: var(--white); }
.case-reading-layout {
  display: block;
  padding-bottom: 140px;
  padding-top: 92px;
}
.case-reading-layout > .case-prose { margin-inline: auto; max-width: 760px; }
.case-prose > p:first-child {
  color: var(--ink);
  font-family: "Iowan Old Style", Baskerville, Georgia, serif;
  font-size: 23px;
  line-height: 1.5;
}
.case-prose h2 { scroll-margin-top: 120px; }
.case-prose strong { color: inherit; font-weight: 400; }
.case-prose figure { margin: 2.8em auto; max-width: 560px; }
.case-prose figure img,
.case-prose img {
  height: auto !important;
  margin: 2.8em auto;
  max-width: min(100%, 560px);
  width: auto !important;
}
.case-prose figure img { margin: 0 auto; }

@media (max-width: 900px) {
  .case-hero-grid { align-items: start; grid-template-columns: 1fr; }
  .case-hero .dossier-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .case-hero .dossier-strip > div { border-top: 1px solid #2c4048; }
  .case-reading-layout { padding-bottom: 90px; padding-top: 62px; }
}

@media (max-width: 580px) {
  .case-page .case-hero { padding: 142px 0 70px; }
  .case-hero .dossier-strip { grid-template-columns: 1fr; }
}

/* --- Use-case single ---------------------------------------------------- */
.usecase-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  list-style: none;
  margin: 38px 0 0;
  padding: 0;
}
.usecase-tags li {
  border: 1px solid #35505b;
  color: #b6c2c7;
  font-size: 10px;
  letter-spacing: .1em;
  padding: 7px 11px;
  text-transform: uppercase;
}
.usecase-intro {
  font-size: 19.5px;
  line-height: 1.55;
  margin-bottom: 0;
  color: #2f3129;
}
/* The intro used to draw its own bottom rule, and the first h2 drew a top rule
   90px below it: two hairlines with nothing between them. One rule now. */
.usecase-intro + h2 { margin-top: 2.1em; }
.usecase-intro p:last-child { margin-bottom: 0; }

/* --- Read next ---------------------------------------------------------- */
/* padding-top:0 pushed the heading flush against the article above it */
.article-next { background: var(--white); padding-top: clamp(64px, 7vw, 104px); padding-bottom: clamp(64px, 7vw, 104px); }
.article-next-head {
  align-items: baseline;
  border-bottom: 1px solid var(--ink);
  display: flex;
  gap: 30px;
  justify-content: space-between;
  padding-bottom: 14px;
}
.article-next-head h2 {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 500;
  letter-spacing: -.035em;
  margin: 0;
}
.article-next-list { list-style: none; margin: 0; padding: 0; }
.article-next-list li { border-bottom: 1px solid var(--line); }
.article-next-list a {
  align-items: baseline;
  display: grid;
  gap: 30px;
  grid-template-columns: minmax(200px, .8fr) 1.2fr 18px;
  padding: 20px 8px 20px 0;
  transition: padding-left .28s var(--ease-settle), background .28s ease;
}
.article-next-list a:hover { background: #f8f5ee; padding-left: 14px; }
.article-next-list strong { font-size: 17px; font-weight: 500; }
.article-next-list span { color: var(--muted); font-size: 14.5px; }
.article-next-list i { color: var(--accent-ink); font-style: normal; opacity: 0; transition: opacity .25s ease; }
.article-next-list a:hover i { opacity: 1; }

@media (max-width: 900px) {
  .dossier-strip > div { border-right: 0; margin-right: 0; padding: 16px 0 0; width: 50%; }
  .article-next-list a { grid-template-columns: 1fr; gap: 6px; }
  .article-next-list i { display: none; }
}

/* --- Article header scale ----------------------------------------------- */
/* On case studies and use cases the H1 is a full summary sentence, not a
   three-word headline. At the homepage's 88px it filled more than a viewport
   before the reader saw a single fact. Scaled to a lede and given a measure. */
.page .page-hero,
.case-page .page-hero,
.usecase-single .page-hero { padding: 172px 0 88px; }

/* One header language for the three article types: case studies, use-case pages
   and analyses. They keep a smaller title than the section pages, because an 88px
   headline above two thousand words reads as front-loaded, but the kicker, the
   scale and the tracking are now shared rather than three separate treatments. */
.page-hero .article-kicker {
  color: #8b9aa1;
  display: block;
  font-size: 10px;
  letter-spacing: .18em;
  margin-bottom: 24px;
  text-transform: uppercase;
}
.page .page-hero h1,
.case-page .page-hero h1,
.usecase-single .page-hero h1 {
  font-size: clamp(31px, 3.7vw, 52px);
  letter-spacing: -.032em;
  line-height: 1.14;
  max-width: 21ch;
  max-width: min(880px, 21em);
}
.usecase-single .page-hero > div > p:last-of-type,
.case-page .page-hero > div > p { font-size: 18.5px; max-width: 62ch; }

.case-page .case-page-logo { margin-bottom: 30px; }

@media (max-width: 900px) {
  .page .page-hero,
  .case-page .page-hero,
  .usecase-single .page-hero { padding: 132px 0 60px; }
}

/* ==========================================================================
   ITERATION 05 — indicators, hero motion, cases grid, sector page
   ========================================================================== */

/* --- Step rail ----------------------------------------------------------- */
/* Replaces 01/02/03. Non-sequential groups lost their numerals entirely; where
   order genuinely matters, this reads as progress and stays out of the way. */
.step-rail { display: inline-flex; gap: 3px; align-items: center; }
.step-rail i {
  background: #c3beb3;
  display: block;
  height: 2px;
  width: 9px;
  transition: background .3s ease;
}
.step-rail i.on { background: var(--accent-ink); }
.section-dark .step-rail i { background: #3c525c; }
.section-dark .step-rail i.on { background: var(--accent); }

/* the numerals are gone, so the space they held collapses */
.three-steps h3 { margin-top: 0; }
.principle-grid h3,
.usecase-criteria h3 { margin-top: 0; }
.outcome-index { min-height: 1px; }
.service-row { grid-template-columns: 1.1fr 1fr 30px; }
.method-list li { grid-template-columns: 56px 1fr 1.2fr; }
.industry > .industry-pattern:first-child { margin-top: 0; }
.ai-use-grid article > h3:first-child,
.engagement-grid article h3 { margin-top: 0; }
.combination-grid h3,
.gate-grid h3 { margin-top: 0; }

/* --- Hero panel carousel ------------------------------------------------- */
/* The stage labels lost their numbers; the dots below carry the position. */











@media (prefers-reduced-motion: reduce) {
  
}

/* --- Cases section rhythm ----------------------------------------------- */
/* One rule under the heading, and the figures register hangs directly off it. */
.cases-section .section-heading { border-bottom: 1px solid #2c4048; padding-bottom: 40px; margin-bottom: 0; }
.proof-figure small { align-self: end; }
.proof-figure p { margin: 18px 0 22px; }

/* --- Featured case card -------------------------------------------------- */
/* The card was a 610px box with everything pinned to the bottom and a 46px logo
   lost in the corner. The logo now fills its column, and the empty upper half
   carries the same pixel field as the hero in a lighter blue, so the card reads
   as deliberate rather than under-filled. */
.case-featured {
  background: #142832;
  isolation: isolate;
  overflow: hidden;
  position: relative;
}
.case-pixel-wave {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}
.case-featured > * { position: relative; z-index: 1; }
.case-featured::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(20, 40, 50, 0) 22%, rgba(20, 40, 50, .72) 58%, #142832 82%);
}
.case-featured:hover { background: #16303c; }

.case-featured .case-body {
  align-items: end;
  grid-template-columns: 0.62fr 1.38fr;
  gap: 40px;
}
.case-featured .case-logo {
  align-items: center;
  display: flex;
  min-height: 0;
}
.case-featured .case-logo img {
  max-height: 128px;
  max-width: 100%;
  opacity: .92;
  width: auto;
}
.case-featured:hover .case-logo img { opacity: 1; }

@media (max-width: 900px) {
  .case-featured .case-body { grid-template-columns: 1fr; }
  .case-featured .case-logo img { max-height: 76px; }
}

/* --- Expertise proof names ---------------------------------------------- */
/* The rule has to hug the name. On the anchor it stretched across the whole
   grid cell, arrow and gap included, and ran off to the right of the column. */
.proof-names a {
  align-items: baseline;
  display: inline-flex;
  gap: 5px;
  transition: color .25s ease;
  width: fit-content;
}
/* the original rule styled bare spans as full-width rows; now that each name is
   an anchor, the row rule belongs to the anchor and the hover rule to the text */
/* No row rules: six short ragged underlines read worse than none, and this page
   already carries too many lines. The names are a plain two-column list; the
   underline appears only under the name you are pointing at. */
.proof-names a {
  color: var(--ink);
  font-family: "Urbanist", sans-serif;
  font-size: 25px;
  padding: 11px 0;
}
/* the legacy `.proof-names span` rule still reached the inner span, greying the
   names out and adding a second helping of padding inside the anchor */
.proof-names a > span {
  border-bottom: 1px solid transparent;
  color: inherit;
  font-size: inherit;
  padding: 0 0 2px;
  transition: border-color .25s ease;
}
.proof-names a:hover > span { border-bottom-color: var(--accent-ink); }
.proof-names a i {
  color: var(--accent-ink);
  font-size: .7em;
  font-style: normal;
  opacity: 0;
  transition: opacity .25s ease, transform .25s var(--ease-settle);
}
.proof-names a:hover { color: var(--accent-ink); }
.proof-names a:hover i { opacity: 1; transform: translate(2px, -2px); }


/* --- Sector story: fewer rules -------------------------------------------- */
/* The grid drew a rule, then the friction list drew its own 34px below it, and
   the responses row added a third. Three parallel lines in 120px. One rule now
   opens the block; the friction rows separate with a lighter hairline and the
   last row carries none, so nothing stacks against the chips below. */
/* The base rule `.sector-story-grid li { border-top }` was still firing on both
   lists, so every friction row carried a border-top AND my border-bottom — two
   hairlines a pixel apart, which is exactly the doubled, thickened look. One
   rule per row now, and the response items carry none at all. */
.sector-story-grid li { border-top: 0; }
.sector-frictions li { border-bottom: 1px solid #d6d1c6; padding: 13px 0; }
.sector-frictions li:last-child { border-bottom: 0; }
.sector-responses { border-top: 1px solid #cfcabf; margin-top: 26px; padding-top: 26px; }
.sector-responses li { border: 0; padding: 2px 0 2px 20px; }
.sector-story-grid { border-top: 1px solid #b9b3a7; }

/* balanced two columns instead of a ragged 3 + 1 wrap */
.sector-responses ul {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px clamp(30px, 5vw, 64px);
}

/* --- Other sectors ------------------------------------------------------- */
.beyond-grid > div:last-child { border-top: 0; }
.beyond-grid > div:last-child > article {
  border-top: 1px solid #2f444d;
  padding: 22px 0 24px;
}
.beyond-grid article h3 { font-size: 19px; margin: 0 0 8px; }
.beyond-grid article p { color: #9ca9ae; font-size: 14.5px; margin: 0; max-width: 44em; }
.beyond-proof {
  color: var(--accent-light);
  display: inline-flex;
  gap: 5px;
  align-items: baseline;
  font-size: 10.5px;
  letter-spacing: .12em;
  margin-top: 12px;
  text-transform: uppercase;
  transition: color .25s ease;
}
.beyond-proof i { font-style: normal; transition: transform .25s var(--ease-settle); }
.beyond-proof:hover { color: var(--amber); }
.beyond-proof:hover i { transform: translate(2px, -2px); }

/* --- Branch navigation --------------------------------------------------- */
/* Secteurs and Usages are one destination in the main nav; this is how a
   visitor sees both halves of it and which one they are on. */
/* At 12.5px muted grey on paper this was easy to miss entirely. It now lives in
   the dark band, continuous with the hero above it, and stays pinned over the
   light content below — where a dark bar is impossible to overlook. */
.branch-nav {
  background: var(--ink);
  position: sticky;
  top: 0;
  z-index: 25;
}
.branch-nav .shell { align-items: center; display: flex; gap: 0; }
.branch-nav-label {
  color: #6e8088;
  font-size: 9.5px;
  letter-spacing: .18em;
  margin-right: 26px;
  text-transform: uppercase;
}
.branch-nav a {
  border-bottom: 2px solid transparent;
  color: #b6c2c7;
  font-size: 14px;
  letter-spacing: .01em;
  margin-right: 30px;
  padding: 19px 2px 17px;
  transition: color .25s ease, border-color .25s ease;
}
.branch-nav a:hover { color: var(--white); }
.branch-nav a[aria-current="page"] { color: var(--white); border-bottom-color: var(--accent); }
.branch-anchor { display: block; scroll-margin-top: 58px; }

/* --- Expertise proof block ---------------------------------------------- */
.expertise-proof-grid { align-items: start; }
.proof-names {
  grid-template-columns: repeat(2, max-content);
  column-gap: clamp(40px, 6vw, 96px);
}


/* Stale min-heights: they were reserving room for numerals that no longer
   exist, leaving bordered columns standing empty below the text. */
.three-steps article,
.engagement-grid article,
.industry { min-height: 0; }


/* --- Section rhythm ------------------------------------------------------ */
/* Every boundary was 156px + 156px = 312px of nothing, and the three-steps
   articles added another 111px of stale min-height on top. Between "Trouver le
   point de friction" and the next heading that came to 423px. Tightened to a
   scale that still breathes but reads deliberate rather than unfinished. */
.section { padding-block: clamp(78px, 8.4vw, 118px); }
.three-steps { margin-top: clamp(52px, 6vw, 78px); }
.three-steps article { padding-bottom: 0; }
.services-section .section-heading { margin-bottom: clamp(44px, 5vw, 62px); }

/* --- Featured card meta -------------------------------------------------- */
/* "Santé · Intelligence artificielle" was flush to the card's left edge, sitting
   above the logo instead of above the headline it labels. It now shares the
   body grid so it lines up with the title in column two. */
.case-featured .case-meta {
  display: grid;
  grid-template-columns: 0.62fr 1.38fr;
  gap: 40px;
}
.case-featured .case-meta > span { grid-column: 2; }

@media (max-width: 900px) {
  .case-featured .case-meta { grid-template-columns: 1fr; gap: 0; }
  .case-featured .case-meta > span { grid-column: 1; }
}

/* --- Sector page thesis -------------------------------------------------- */
/* The CTA used to land in the left column two hundred pixels below the heading.
   It now follows the paragraph it belongs to. */
.page-thesis-body { display: block; }
.page-thesis .text-link { margin-top: 0; }
.page-thesis-body .text-link { display: inline-block; margin-top: 28px; }

/* --- Expertise proof: clients and the technology partner ----------------- */
/* The partner line was a `.shell` paragraph whose own `margin: 30px 0 0` beat
   `.shell`'s `margin-inline: auto`, so it escaped the gutter and sat flush to
   the viewport edge. A footnote was the wrong home for it anyway: Mistral is a
   credential, so it now sits in the right column under the client roster, with
   its own label so nobody reads it as a client. */
.proof-right { display: block; }
.proof-partner {
  border-top: 1px solid var(--line);
  margin-top: 38px;
  padding-top: 22px;
}
.proof-partner-label {
  color: #6f6f67;
  display: block;
  font-size: 9.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.proof-partner strong {
  color: var(--ink);
  display: block;
  font-family: "Urbanist", sans-serif;
  font-size: 25px;
  font-weight: 500;
  letter-spacing: -.02em;
  margin-top: 10px;
}
.proof-partner p {
  color: var(--muted);
  font-size: 14.5px;
  line-height: 1.5;
  margin: 10px 0 0;
  max-width: 34em;
}

/* --- Anchor landing under the sticky branch nav -------------------------- */
/* The sector sections are jump targets from the homepage cards and from the
   in-page anchor nav. The branch bar is 61px and pinned, so without a matching
   scroll-margin the heading lands underneath it. */
.sector-story { scroll-margin-top: 76px; }

/* --- Approach stages: rail above the title ------------------------------- */
/* Only the rail moves. The stage keeps its original three-column geometry, so
   the copy stays indented exactly where it was and the deliverable column is
   untouched; the first column is now simply empty. The rail sits on its own
   line above the verb label, sharing the heading's left edge. */
/* With the number div removed, .process-copy became the first grid child and
   collapsed into the 78px gutter. The children are placed explicitly so the
   gutter stays empty and the copy keeps its original column and width. */
.process-copy { grid-column: 2; }
.process-output { grid-column: 3; }

.process-copy > .process-meta { display: block; margin-bottom: 10px; }
.process-copy > .process-meta .step-rail { display: inline-flex; }
.process-verb { display: block; margin-top: 8px; }
.process-copy h2 { margin-top: 10px; }

/* The mobile overrides for these live at the 900px block far earlier in this
   file, so the desktop placements above were winning the source-order tie even
   inside the media query. Restated here, after them. */
@media (max-width: 900px) {
  .process-stage { grid-template-columns: 1fr; }
  .process-copy,
  .process-output { grid-column: 1; }
}

/* ==========================================================================
   HERO — document extraction illustration
   Replaces the three-stage carousel. It shows the transformation Fasfox
   actually sells: a raw cost breakdown read line by line into structured
   fields. Built in DOM rather than canvas or GIF so the text is real text,
   crisp at any DPI, translatable, and ~2KB instead of 1.3MB.
   ========================================================================== */
.operations-visual {
  background: var(--white);
  border: 0;
  box-shadow: 0 28px 60px -34px rgba(4, 14, 18, .5);
  border-radius: 16px;
  padding: 0;
  color: var(--ink);
  overflow: hidden;
}

.extract { display: flex; flex-direction: column; font-size: 13px; }

/* --- header --- */
.extract-head {
  align-items: center;
  border-bottom: 1px solid #e7e2d8;
  display: grid;
  gap: 13px;
  grid-template-columns: auto 1fr auto;
  padding: 17px 20px;
}
.extract-icon {
  background: var(--accent);
  border-radius: 9px;
  display: block;
  height: 34px;
  position: relative;
  width: 34px;
}
.extract-icon::before,
.extract-icon::after {
  background: #fff;
  content: "";
  height: 2px;
  left: 9px;
  position: absolute;
  right: 9px;
  border-radius: 2px;
}
.extract-icon::before { top: 12px; box-shadow: 0 5px 0 #fff; }
.extract-icon::after { bottom: 11px; right: 14px; }
.extract-titles strong { display: block; font-size: 15.5px; font-weight: 600; letter-spacing: -.015em; }
.extract-titles small { color: #7d7a71; display: block; font-size: 11.5px; margin-top: 1px; }

.extract-status {
  align-items: center;
  background: #fbeade;
  border-radius: 999px;
  color: var(--accent-ink);
  display: inline-flex;
  font-size: 11.5px;
  font-weight: 500;
  gap: 7px;
  padding: 7px 13px;
  transition: background .45s ease, color .45s ease;
  white-space: nowrap;
}
.extract-dot { background: var(--accent); border-radius: 50%; height: 6px; width: 6px; flex: none; }
.extract.is-done .extract-status { background: var(--accent); color: #fff; }
.extract.is-done .extract-dot {
  background: none;
  border-bottom: 2px solid #fff;
  border-left: 2px solid #fff;
  border-radius: 0;
  height: 5px;
  transform: rotate(-45deg) translate(1px, -1px);
  width: 9px;
}

/* --- body: source | arrow | output --- */
.extract-body {
  align-items: stretch;
  display: grid;
  gap: 12px;
  grid-template-columns: minmax(0, .78fr) 22px minmax(0, 1fr);
  padding: 18px 20px;
}
.extract-panel {
  border: 1px solid #e7e2d8;
  border-radius: 11px;
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.extract-source { background: #faf7f1; }
.extract-panel-head {
  align-items: center;
  border-bottom: 1px solid #ece7dd;
  display: flex;
  gap: 10px;
  justify-content: space-between;
  padding: 11px 13px;
}
.extract-file {
  color: #4a4740;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.extract-file::before {
  border: 1.5px solid var(--accent);
  border-radius: 3px;
  content: "";
  display: inline-block;
  height: 9px;
  margin-right: 7px;
  vertical-align: -1px;
  width: 9px;
}
.extract-tag { color: #a09b90; font-size: 10px; letter-spacing: .06em; flex: none; }
.extract-out-title { font-size: 13.5px; font-weight: 600; }
.extract-panel-foot { color: #a09b90; font-size: 10.5px; margin-top: auto; padding: 9px 13px 11px; }

/* raw rows: each becomes a highlighted band with an orange bar as it is read */
.extract-rows { display: flex; flex: 1; flex-direction: column; gap: 5px; justify-content: space-evenly; padding: 11px 9px 6px; }
.extract-raw {
  border-radius: 4px;
  display: block;
  height: 15px;
  position: relative;
}
.extract-raw::before {
  background: #ded9cf;
  border-radius: 3px;
  content: "";
  height: 4px;
  left: 4px;
  position: absolute;
  top: 6px;
  transition: background .3s ease, width .3s ease;
  width: var(--w);
}
.extract-raw.is-read { background: #fbeade; }
.extract-raw.is-read::before { background: var(--accent); }
/* the row currently being read flashes brighter, so the scan reads as movement */
.extract-raw.is-active { background: #f7d3b4; }
.extract-raw.is-active::before { background: var(--flame); box-shadow: 0 0 0 1px rgba(222, 70, 26, .25); }
.extract-raw--rest { opacity: .55; }

.extract-arrow { align-self: center; display: block; height: 12px; position: relative; }
.extract-arrow::before {
  border-top: 2px dotted var(--accent);
  content: "";
  left: 1px;
  position: absolute;
  right: 5px;
  top: 5px;
}
.extract-arrow::after {
  border-left: 6px solid var(--accent);
  border-bottom: 4px solid transparent;
  border-top: 4px solid transparent;
  content: "";
  position: absolute;
  right: 0;
  top: 2px;
}
.extract.is-pulsing .extract-arrow { animation: extract-pulse 1s ease-in-out infinite; }
@keyframes extract-pulse { 0%,100% { opacity: .35 } 50% { opacity: 1 } }

/* output rows */
.extract-fields { list-style: none; margin: 0; padding: 4px 0; }
/* Rows must ARRIVE, not merely darken. At .32 opacity every value was already
   legible, so a field landing read as static text getting slightly bolder —
   which is why the whole thing looked fixed. Unrevealed rows are now invisible
   and slide in; exactly one "next" row shows faintly to hint at what is coming,
   the way the reference does. Rows keep their box in the layout, so the panel
   height never shifts. */
.extract-fields li {
  align-items: center;
  border-bottom: 1px solid transparent;
  display: grid;
  gap: 10px;
  grid-template-columns: 1fr auto 18px;
  opacity: 0;
  padding: 8.5px 13px;
  transform: translateY(7px);
  transition: opacity .42s ease, transform .5s var(--ease-settle),
              background .4s ease, border-color .4s ease;
}
.extract-fields li:last-child { border-bottom: 0; }
.extract-fields li.is-next { opacity: .28; transform: none; }
.extract-fields li.is-in {
  border-bottom-color: #f0ece3;
  opacity: 1;
  transform: none;
}
.extract-label { color: #6f6c64; font-size: 12px; }
.extract-value {
  color: var(--ink);
  font-size: 12.5px;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  white-space: nowrap;
}
.extract-check {
  background: #e3ded4;
  border-radius: 50%;
  display: block;
  height: 15px;
  position: relative;
  transition: background .35s ease;
  width: 15px;
}
.extract-fields li.is-in .extract-check { background: var(--accent); }
.extract-fields li.is-in .extract-check::after {
  border-bottom: 1.5px solid #fff;
  border-left: 1.5px solid #fff;
  content: "";
  height: 3px;
  left: 4px;
  position: absolute;
  top: 5px;
  transform: rotate(-45deg);
  width: 6px;
}
.extract-fields li.is-total.is-in { background: #fbeade; }
.extract-fields li.is-total.is-in .extract-label { color: var(--accent-ink); font-weight: 600; }
.extract-fields li.is-total.is-in .extract-value { font-weight: 600; }

/* --- footer: progress, swapped for results on completion --- */
.extract-foot {
  border-top: 1px solid #e7e2d8;
  display: grid;
  min-height: 66px;
  padding: 0 20px;
  position: relative;
}
.extract-progress,
.extract-results {
  align-items: center;
  grid-area: 1 / 1;
  transition: opacity .5s ease;
}
.extract-progress {
  display: grid;
  gap: 12px;
  grid-template-columns: auto minmax(70px, 1fr) auto auto;
}
.extract-progress-label,
.extract-count { color: #7d7a71; font-size: 11px; white-space: nowrap; }
.extract-count b { color: var(--ink); font-variant-numeric: tabular-nums; font-weight: 600; }
.extract-track { background: #ece7dd; border-radius: 999px; display: block; height: 5px; overflow: hidden; }
.extract-track i { background: var(--accent); border-radius: 999px; display: block; height: 100%; width: 0; transition: width .45s var(--ease-settle); }
.extract-pct { color: var(--ink); font-size: 11.5px; font-variant-numeric: tabular-nums; font-weight: 600; }

.extract-results {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  opacity: 0;
  pointer-events: none;
  text-align: center;
}
.extract-results > div + div { border-left: 1px solid #ece7dd; }
.extract-results b {
  color: var(--accent-ink);
  display: block;
  font-family: "Urbanist", sans-serif;
  font-size: 21px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: -.02em;
}
.extract-results span { color: #86827a; display: block; font-size: 10px; margin-top: 3px; }
.extract.is-done .extract-progress { opacity: 0; pointer-events: none; }
.extract.is-done .extract-results { opacity: 1; pointer-events: auto; }

@media (max-width: 1080px) {
  .extract-body { grid-template-columns: minmax(0, .7fr) 18px minmax(0, 1fr); gap: 9px; padding: 14px; }
  .extract-results b { font-size: 18px; }
}
@media (max-width: 620px) {
  .extract-body { grid-template-columns: 1fr; }
  .extract-arrow { display: none; }
  .extract-source .extract-rows { padding-bottom: 8px; }
  .extract-progress { grid-template-columns: auto 1fr auto; }
  .extract-count { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .extract.is-pulsing .extract-arrow { animation: none; opacity: 1; }
  .extract-track i,
  .extract-fields li,
  .extract-raw::before,
  .extract-progress,
  .extract-results { transition: none; }
}

/* Narrow cards: the title and the status pill cannot share a row at 375px. */
@media (max-width: 520px) {
  .extract-head {
    grid-template-columns: auto 1fr;
    row-gap: 12px;
  }
  .extract-status { grid-column: 1 / -1; justify-self: start; }
  .extract-titles strong { font-size: 15px; }
  .extract-results b { font-size: 17px; }
  .extract-results span { font-size: 9.5px; }
}

/* ==========================================================================
   SCROLL ACT — pinned statement, moving background
   Performance rules this obeys:
     · pinning is position:sticky, so it costs nothing and works everywhere
     · every animated property is transform or opacity, never layout
     · progress comes from a native view-timeline, so it runs on the compositor
       with no scroll listener and no per-frame main-thread work
     · no 3D, no filters, no canvas, no library
   ========================================================================== */
.act {
  background: transparent;
  padding: 0;
  position: relative;
  z-index: 1;
}

.act--a .act-track {
  height: 240vh;
  position: relative;
  view-timeline-name: --actA;
  view-timeline-axis: block;
}

.act-stage {
  align-items: center;
  display: flex;
  height: 100vh;
  position: sticky;
  top: 0;
  overflow: hidden;
}

.act-grid {
  align-items: start;
  display: grid;
  gap: 7vw;
  grid-template-columns: 1fr 1fr;
  width: min(var(--max), calc(100% - var(--pad) * 2));
}

.act-lede h2 {
  font-size: clamp(34px, 4.4vw, 62px);
  font-weight: 500;
  letter-spacing: -.045em;
  line-height: 1.04;
  margin: 0;
  max-width: 15em;
}

/* --- background: two layers moving at different rates --------------------- */





/* --- beats --------------------------------------------------------------- */
.act { --item: 270px; --win: 430px; --count: 4; }
.act-beats { list-style: none; margin: 0; padding: 0; position: relative; }
.act-beat { max-width: 34em; }
.act-tag {
  color: var(--accent);
  display: block;
  font-size: 10px;
  letter-spacing: .17em;
  margin-bottom: 16px;
  text-transform: uppercase;
}
.act-beat h3 {
  font-size: clamp(23px, 2.5vw, 33px);
  font-weight: 500;
  letter-spacing: -.03em;
  line-height: 1.14;
  margin: 0 0 16px;
}
.act-beat p { color: #a9b7bc; font-size: 17px; line-height: 1.55; margin: 0; }

.act-rail { display: flex; gap: 5px; margin-top: 40px; }
.act-rail-mark {
  background: #35505b;
  display: block;
  height: 2px;
  transform-origin: left;
  width: 34px;
}
.act-rail-mark::after {
  background: var(--accent);
  content: "";
  display: block;
  height: 100%;
  transform: scaleX(0);
  transform-origin: left;
  width: 100%;
}

/* --- the scroll-driven part ---------------------------------------------- */
/* Stepped movement — hold, jump, hold — made the column read as fixed and
   then suddenly jumping, so it was unclear whether scrolling was doing
   anything. It now translates continuously at roughly 0.4x the scroll rate:
   the left column is pinned at 0x, the right moves steadily, and the
   difference between the two IS the parallax. Continuous motion also means
   the page always confirms that scrolling is working.
   Items still live in a real list inside a soft-edged window, so two of them
   can never be printed over each other. */
html.sda .act-reel {
  height: var(--win);
  overflow: hidden;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 16%, #000 84%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 16%, #000 84%, transparent);
}
html.sda .act-beats {
  animation: act-reel-slide linear both;
  animation-range: contain 0% contain 100%;
  animation-timeline: --actA;
  will-change: transform;
}
html.sda .act-beat {
  align-content: center;
  display: grid;
  height: var(--item);
}

@keyframes act-reel-slide {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, calc(-1 * (var(--item) * var(--count) - var(--win))), 0); }
}

html.sda .act-rail-mark::after { animation: act-fill linear both; animation-timeline: --actA; }
html.sda .act-rail-mark--1::after { animation-range: contain 0%  contain 25%; }
html.sda .act-rail-mark--2::after { animation-range: contain 25% contain 50%; }
html.sda .act-rail-mark--3::after { animation-range: contain 50% contain 75%; }
html.sda .act-rail-mark--4::after { animation-range: contain 75% contain 100%; }
@keyframes act-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* --- fallback: no scroll timelines -------------------------------------- */
/* The pinning is dropped and the beats read as a plain list. Same argument,
   no motion, nothing broken. */
html:not(.sda) .act-reel { height: auto; overflow: visible; }
html:not(.sda) .act-track { height: auto; }
html:not(.sda) .act-stage { height: auto; padding-block: clamp(78px, 8.4vw, 118px); position: static; }
html:not(.sda) .act-grid { align-items: start; }
html:not(.sda) .act-beats { display: flex; flex-direction: column; gap: 46px; }
html:not(.sda) .act-beat { grid-area: auto; }
html:not(.sda) .act-rail { display: none; }

@media (max-width: 900px) {
  html.sda .act-reel { height: auto; overflow: visible; -webkit-mask-image: none; mask-image: none; }
  html.sda .act-beats { animation: none !important; transform: none !important; }
  html.sda .act-beat { height: auto; opacity: 1 !important; }
  html.sda .act-track { height: auto; }
  html.sda .act-stage { height: auto; padding-block: 74px; position: static; }
  html.sda .act-grid { grid-template-columns: 1fr; gap: 44px; }
  html.sda .act-beats { display: flex; flex-direction: column; gap: 40px; }
  html.sda .act-beat { animation: none !important; grid-area: auto; opacity: 1 !important; transform: none !important; }
  html.sda .act-rail { display: none; }
  .opening-layer { animation: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  html.sda .act-reel { height: auto; overflow: visible; -webkit-mask-image: none; mask-image: none; }
  html.sda .act-beats { animation: none !important; transform: none !important; }
  html.sda .act-beat { height: auto; opacity: 1 !important; }
  html.sda .act-track { height: auto; }
  html.sda .act-stage { height: auto; padding-block: clamp(78px, 8.4vw, 118px); position: static; }
  html.sda .act-beats { display: flex; flex-direction: column; gap: 46px; }
  html.sda .act-beat { animation: none !important; grid-area: auto; opacity: 1 !important; transform: none !important; }
  html.sda .act-rail { display: none; }
  .opening-layer { animation: none !important; }
}

/* --- the act's closing proof register ------------------------------------ */
.act-proof { display: grid; gap: 26px 30px; grid-template-columns: repeat(3, 1fr); margin-top: 6px; }
.act-proof a { display: block; transition: transform .3s var(--ease-settle); }
.act-proof a:hover { transform: translateY(-2px); }
.act-proof b {
  color: var(--accent-light);
  display: block;
  font-family: "Iowan Old Style", Baskerville, Georgia, serif;
  font-size: clamp(34px, 3.6vw, 50px);
  font-style: italic;
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 400;
  letter-spacing: -.03em;
  line-height: .96;
}
.act-proof b i { font-size: .42em; font-style: italic; margin-left: .1em; }
.act-proof span { color: #a9b7bc; display: block; font-size: 13.5px; line-height: 1.4; margin-top: 12px; }
.act-proof small {
  color: #7f8f96;
  display: block;
  font-size: 9.5px;
  letter-spacing: .13em;
  margin-top: 9px;
  text-transform: uppercase;
}
.act-proof a:hover small { color: var(--accent-light); }
@media (max-width: 900px) {
  .act-proof { grid-template-columns: 1fr; gap: 22px; }
}

/* ==========================================================================
   OPENING — hero and scroll act share one continuous background
   The seam between them came from two separate canvases and two separate
   gradient systems trying to match. There is now one field: a single sticky,
   viewport-sized layer that spans both sections. Continuity is structural, not
   a matter of keeping two treatments in sync.
   Sticky also keeps the canvas viewport-sized, so the per-frame draw cost stays
   flat no matter how tall the opening gets.
   ========================================================================== */
.opening {
  background: var(--ink);
  color: var(--white);
  isolation: isolate;
  position: relative;
  timeline-scope: --actA;
}

.opening-bg {
  height: 100vh;
  margin-bottom: -100vh;   /* takes no space in the flow */
  overflow: hidden;
  pointer-events: none;
  position: sticky;
  top: 0;
  z-index: 0;
}

.opening-wave {
  height: 100%;
  inset: 0;
  position: absolute;
  width: 100%;
}

.opening-layer { display: block; inset: -22% -12%; position: absolute; will-change: transform; }
.opening-layer--grid {
  background-image:
    linear-gradient(to right, rgba(146, 172, 184, .085) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(146, 172, 184, .065) 1px, transparent 1px);
  background-size: 96px 96px;
}
.opening-layer--glow {
  background:
    radial-gradient(52% 44% at 12% 78%, rgba(222, 70, 26, .26), transparent 70%),
    radial-gradient(44% 38% at 88% 16%, rgba(244, 178, 19, .13), transparent 72%);
}

/* the hero keeps its own soft wash but stops painting a ground of its own */
.hero { background: transparent; position: relative; z-index: 1; }
.hero::after { background: linear-gradient(180deg, rgba(10, 22, 27, .34), transparent 26%); }

html.sda .opening-layer--grid {
  animation: opening-grid linear both;
  animation-timeline: --actA;
  animation-range: cover;
}
@keyframes opening-grid {
  from { transform: translate3d(0, 5%, 0) scale(1.05); }
  to   { transform: translate3d(0, -13%, 0) scale(1); }
}
html.sda .opening-layer--glow {
  animation: opening-glow linear both;
  animation-timeline: --actA;
  animation-range: cover;
}
@keyframes opening-glow {
  from { opacity: .55; transform: translate3d(0, -10%, 0); }
  50%  { opacity: 1; }
  to   { opacity: .6; transform: translate3d(0, 16%, 0); }
}

/* ==========================================================================
   ACT B — the same machinery on paper, over the use cases
   Timeline names cannot be parameterised per instance in CSS, so the second act
   declares its own scope and name. Everything else is shared.
   ========================================================================== */
.act--b {
  background: var(--white);
  color: var(--ink);
  position: relative;
  timeline-scope: --actB;
}
.act--b .act-track {
  height: 240vh;
  position: relative;
  view-timeline-name: --actB;
  view-timeline-axis: block;
}
.act--b .act-lede h2 { color: var(--ink); }
.act--b .act-tag { color: var(--accent-ink); }
.act--b .act-beat h3 { color: var(--ink); }
.act--b .act-beat p { color: var(--muted); }
.act--b .act-rail-mark { background: #d8d3c8; }

.act-beat h3 a {
  align-items: baseline;
  display: inline-flex;
  gap: 8px;
  transition: color .25s ease;
}
.act-beat h3 a i {
  color: var(--accent-ink);
  font-size: .55em;
  font-style: normal;
  opacity: 0;
  transition: opacity .25s ease, transform .25s var(--ease-settle);
}
.act-beat h3 a:hover { color: var(--accent-ink); }
.act-beat h3 a:hover i { opacity: 1; transform: translate(2px, -2px); }
.act--a .act-beat h3 a i { color: var(--accent-light); }
.act--a .act-beat h3 a:hover { color: var(--accent-light); }

.act-link { display: inline-block; margin-top: 34px; }

html.sda .act--b .act-beats { animation-timeline: --actB; }
html.sda .act--b .act-rail-mark::after { animation-timeline: --actB; }
html.sda .act--b .act-layer--grid {
  animation: actb-grid linear both;
  animation-range: cover;
  animation-timeline: --actB;
}
@keyframes actb-grid {
  from { transform: translate3d(0, 4%, 0) scale(1.04); }
  to   { transform: translate3d(0, -10%, 0) scale(1); }
}

/* four items, no proof register: even quarters */
.act--b .act-beat--2 { animation-name: act-beat-dim;       animation-range: contain 22% contain 53%; }
.act--b .act-beat--3 { animation-name: act-beat-dim;       animation-range: contain 49% contain 80%; }
.act--b .act-beat--4 { animation-name: act-beat-dim-last;  animation-range: contain 76% contain 100%; }

@media (max-width: 900px) {
  html.sda .act--b .act-track { height: auto; }
  html.sda .act--b .act-beats { animation: none !important; transform: none !important; }
  html.sda .act--b .act-beat { animation: none !important; height: auto; opacity: 1 !important; }
}
@media (prefers-reduced-motion: reduce) {
  html.sda .act--b .act-track { height: auto; }
  html.sda .act--b .act-beats { animation: none !important; transform: none !important; }
  html.sda .act--b .act-beat { animation: none !important; height: auto; opacity: 1 !important; }
}
html:not(.sda) .act--b .act-track { height: auto; }

/* --- Light act: the grid belongs here ------------------------------------ */
/* No overflow:hidden here. It would make the section a scroll container, which
   makes the track fully contained within it and collapses the view-timeline's
   `contain` range to a constant. The grid layer is clipped by .act-bg instead. */
.act--b { isolation: isolate; }
.act--b .act-bg { inset: 0; pointer-events: none; position: absolute; z-index: 0; overflow: hidden; }
.act--b .act-layer { display: block; inset: -18% -10%; position: absolute; will-change: transform; }
.act--b .act-layer--grid {
  background-image:
    linear-gradient(to right, rgba(20, 30, 36, .055) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(20, 30, 36, .045) 1px, transparent 1px);
  background-size: 96px 96px;
}
.act--b .act-track { position: relative; z-index: 1; }

/* --- Dark opening: the wave carries it, plus a gradient that moves ------- */
/* The wave alone does not tell you that you are scrolling — it drifts on its
   own clock. A gradient tied to scroll position does, so the two together read
   as "the page is moving" rather than "something is animating". */
.opening-layer--glow {
  background:
    radial-gradient(58% 48% at 14% 80%, rgba(222, 70, 26, .34), transparent 68%),
    radial-gradient(48% 40% at 86% 14%, rgba(244, 178, 19, .17), transparent 70%),
    radial-gradient(70% 55% at 50% 50%, rgba(20, 52, 66, .40), transparent 76%);
}
html.sda .opening-layer--glow {
  animation: opening-glow linear both;
  animation-range: cover;
  animation-timeline: --actA;
}
@keyframes opening-glow {
  from { opacity: .5;  transform: translate3d(0, -16%, 0) scale(1.06); }
  50%  { opacity: 1; }
  to   { opacity: .62; transform: translate3d(0, 22%, 0) scale(1); }
}

@media (max-width: 900px) {
  .act--b .act-layer { animation: none !important; }
  html.sda .act-reel { height: auto !important; overflow: visible !important; }
  html.sda .act-beat { height: auto !important; }
}
@media (prefers-reduced-motion: reduce) {
  .act--b .act-layer { animation: none !important; }
  html.sda .act-reel { height: auto !important; overflow: visible !important; }
  html.sda .act-beat { height: auto !important; }
}

/* ==========================================================================
   FOOTER EASTER EGG
   A travelling ribbon of dots (the hero's vocabulary, a different figure), a
   glint that crosses the heading once when the footer arrives, and a small
   recurring sparkle for anyone who lingers. All of it opacity/transform only,
   all of it paused off-screen, none of it under prefers-reduced-motion.
   ========================================================================== */
.site-footer {
  isolation: isolate;
  overflow: hidden;
  position: relative;
  view-timeline-name: --footer;
  view-timeline-axis: block;
}
.site-footer > .shell { position: relative; z-index: 1; }

/* The footer carries the mark, so it is given room to breathe: the two hairline
   rules the base stylesheet draws under the lead and over the baseline are
   dropped and replaced by space. Nothing separates the blocks but distance,
   which is also what lets the fold read against an uninterrupted ground. */
.site-footer { padding-top: clamp(118px, 12vw, 168px); }
.footer-lead {
  border-bottom: 0;
  padding-bottom: clamp(132px, 13.5vw, 196px);
}
.footer-grid { padding: 0 0 clamp(58px, 6vw, 92px); }
.footer-base {
  border-top: 0;
  padding: 0 0 clamp(38px, 4vw, 58px);
}
@media (max-width: 760px) {
  .site-footer { padding-top: clamp(96px, 18vw, 130px); }
  .footer-lead { padding-bottom: clamp(90px, 20vw, 150px); }
}


/* --- recurring sparkle --------------------------------------------------- */
.footer-sparks { inset: 0 0 auto 0; height: 340px; pointer-events: none; position: absolute; z-index: 0; }
.footer-sparks i {
  background: var(--amber);
  border-radius: 50%;
  height: 3px;
  left: var(--x);
  opacity: 0;
  position: absolute;
  top: var(--y);
  width: 3px;
}
.site-footer.is-sparkling .footer-sparks i {
  animation: footer-spark 2.4s var(--ease-settle) var(--d) 1;
}
@keyframes footer-spark {
  0%, 100% { opacity: 0; transform: scale(.4); }
  8%       { opacity: .95; transform: scale(1); box-shadow: 0 0 7px 1px rgba(244, 178, 19, .55); }
  30%      { opacity: 0; transform: scale(.5); }
}

/* --- the glint over the heading ----------------------------------------- */
/* Drawn as a pseudo-element clone sitting exactly on the real heading, so the
   heading itself keeps its colour, stays selectable and is untouched if the
   effect is unsupported. */
.footer-title { position: relative; }
.footer-title::after {
  color: #fff8ec;
  content: attr(data-glint);
  clip-path: inset(0 100% 0 0);
  inset: 0;
  opacity: 0;
  pointer-events: none;
  position: absolute;
  text-shadow: 0 0 9px rgba(244, 178, 19, .5);
}
.site-footer.is-glinting .footer-title::after {
  animation: footer-glint 1.6s cubic-bezier(.35, .02, .2, 1) 1;
}
@keyframes footer-glint {
  0%   { clip-path: inset(0 100% 0 0);      opacity: 0; }
  10%  { opacity: 1; }
  50%  { clip-path: inset(0 40% 0 44%);     opacity: 1; }
  90%  { opacity: 1; }
  100% { clip-path: inset(0 -4% 0 100%);    opacity: 0; }
}

@media (max-width: 620px) {
  .footer-sparks { height: 240px; }
}

@media (prefers-reduced-motion: reduce) {
  .footer-sparks { display: none; }
  .footer-title::after { animation: none !important; opacity: 0 !important; }
}




/* --- The mark, folding into place ---------------------------------------- */
/* The logo cut by hand into squares and triangles (assets/images/logo/
   fasfox-mark-split.svg — 21 pieces, reassembling to the original mark at
   IoU 0.995). Each piece is a window onto that file, so assembled they are the
   artwork itself, not a redrawing of it.
   Every piece hinges on the edge it will share with its neighbours and starts a
   quarter turn out of the page — edge-on to the viewer, so invisible — then
   swings back down onto the picture plane as you scroll.
   It is still only transforms and opacity on composited layers: no WebGL, no
   library, nothing per-frame on the main thread. Progress comes from the
   footer's view-timeline `entry` phase, which for the last element on the page
   completes exactly at the bottom of the scroll. */
.footer-mark {
  --size: clamp(230px, 26vw, 392px);
  height: var(--size);
  /* Opacity and the screen blend live out here, on a wrapper. Both are grouping
     properties, and a grouping property flattens transform-style — putting them
     on the element that carries the perspective would collapse the 3D context
     and make the pieces stack in document order instead of by depth. Blending
     the group rather than each piece also avoids the hairline seams that
     per-piece blending draws where neighbours meet. */
  isolation: isolate;
  mix-blend-mode: screen;
  opacity: .46;
  pointer-events: none;
  position: absolute;
  right: 2%;
  top: 14.5%;
  width: var(--size);
  z-index: 0;
}
.footer-mark-3d {
  height: 100%;
  perspective: 560px;
  perspective-origin: 58% 42%;
  position: relative;
  transform-style: preserve-3d;
  width: 100%;
}
.fp {
  backface-visibility: hidden;
  background-image: var(--mark);
  background-position: var(--bp);
  background-repeat: no-repeat;
  background-size: var(--bs);
  display: block;
  opacity: 0;
  position: absolute;
  will-change: transform, opacity;
}
/* A piece turned edge-on catches no light. The shade rides the same range as
   the fold and lifts as the piece comes to rest, which is what separates a
   panel folding from a card sliding. */
.fp::after {
  background: #05090b;
  content: "";
  inset: 0;
  opacity: 0;
  position: absolute;
}

html.sda .fp, html.sda .fp::after {
  animation-fill-mode: both;
  animation-timeline: --footer;
  animation-timing-function: linear;
}
html.sda .fp::after { animation-name: fp-shade; }
@keyframes fp-shade {
  from { opacity: .82; }
  55%  { opacity: .46; }
  85%  { opacity: .08; }
  to   { opacity: 0; }
}

/* No timelines, or reduced motion: the mark is simply assembled and flat. */
html:not(.sda) .fp { opacity: 1; transform: scale(1.006); }
html:not(.sda) .fp::after { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .fp { animation: none !important; opacity: 1 !important; transform: scale(1.006) !important; }
  .fp::after { animation: none !important; opacity: 0 !important; }
}
@media (max-width: 760px) {
  /* Narrow viewports: the heading takes the full column, so the mark bleeds off
     the right edge as a texture behind it rather than a shape beside it. */
  .footer-mark { --size: 190px; right: -22%; top: 2%; opacity: .24; }
}
/* GENERATED by tools/gen-footer-mark.py — do not edit by hand. */
html.sda .fp0 { animation-name: fp0-k; animation-range: entry 0.00% entry 55.00%; transform-origin: 100% 50%; }
html.sda .fp0::after { animation-range: entry 0.00% entry 55.00%; }
html.sda .fp1 { animation-name: fp1-k; animation-range: entry 2.25% entry 57.25%; transform-origin: 100% 50%; }
html.sda .fp1::after { animation-range: entry 2.25% entry 57.25%; }
html.sda .fp2 { animation-name: fp2-k; animation-range: entry 4.50% entry 59.50%; transform-origin: 100% 50%; }
html.sda .fp2::after { animation-range: entry 4.50% entry 59.50%; }
html.sda .fp3 { animation-name: fp3-k; animation-range: entry 6.75% entry 61.75%; transform-origin: 50% 100%; }
html.sda .fp3::after { animation-range: entry 6.75% entry 61.75%; }
html.sda .fp4 { animation-name: fp4-k; animation-range: entry 9.00% entry 64.00%; transform-origin: 100% 50%; }
html.sda .fp4::after { animation-range: entry 9.00% entry 64.00%; }
html.sda .fp5 { animation-name: fp5-k; animation-range: entry 11.25% entry 66.25%; transform-origin: 0% 50%; }
html.sda .fp5::after { animation-range: entry 11.25% entry 66.25%; }
html.sda .fp6 { animation-name: fp6-k; animation-range: entry 13.50% entry 68.50%; transform-origin: 50% 100%; }
html.sda .fp6::after { animation-range: entry 13.50% entry 68.50%; }
html.sda .fp7 { animation-name: fp7-k; animation-range: entry 15.75% entry 70.75%; transform-origin: 100% 50%; }
html.sda .fp7::after { animation-range: entry 15.75% entry 70.75%; }
html.sda .fp8 { animation-name: fp8-k; animation-range: entry 18.00% entry 73.00%; transform-origin: 50% 100%; }
html.sda .fp8::after { animation-range: entry 18.00% entry 73.00%; }
html.sda .fp9 { animation-name: fp9-k; animation-range: entry 20.25% entry 75.25%; transform-origin: 0% 50%; }
html.sda .fp9::after { animation-range: entry 20.25% entry 75.25%; }
html.sda .fp10 { animation-name: fp10-k; animation-range: entry 22.50% entry 77.50%; transform-origin: 100% 50%; }
html.sda .fp10::after { animation-range: entry 22.50% entry 77.50%; }
html.sda .fp11 { animation-name: fp11-k; animation-range: entry 24.75% entry 79.75%; transform-origin: 0% 50%; }
html.sda .fp11::after { animation-range: entry 24.75% entry 79.75%; }
html.sda .fp12 { animation-name: fp12-k; animation-range: entry 27.00% entry 82.00%; transform-origin: 0% 50%; }
html.sda .fp12::after { animation-range: entry 27.00% entry 82.00%; }
html.sda .fp13 { animation-name: fp13-k; animation-range: entry 29.25% entry 84.25%; transform-origin: 100% 50%; }
html.sda .fp13::after { animation-range: entry 29.25% entry 84.25%; }
html.sda .fp14 { animation-name: fp14-k; animation-range: entry 31.50% entry 86.50%; transform-origin: 0% 50%; }
html.sda .fp14::after { animation-range: entry 31.50% entry 86.50%; }
html.sda .fp15 { animation-name: fp15-k; animation-range: entry 33.75% entry 88.75%; transform-origin: 50% 0%; }
html.sda .fp15::after { animation-range: entry 33.75% entry 88.75%; }
html.sda .fp16 { animation-name: fp16-k; animation-range: entry 36.00% entry 91.00%; transform-origin: 0% 50%; }
html.sda .fp16::after { animation-range: entry 36.00% entry 91.00%; }
html.sda .fp17 { animation-name: fp17-k; animation-range: entry 38.25% entry 93.25%; transform-origin: 50% 0%; }
html.sda .fp17::after { animation-range: entry 38.25% entry 93.25%; }
html.sda .fp18 { animation-name: fp18-k; animation-range: entry 40.50% entry 95.50%; transform-origin: 0% 50%; }
html.sda .fp18::after { animation-range: entry 40.50% entry 95.50%; }
html.sda .fp19 { animation-name: fp19-k; animation-range: entry 42.75% entry 97.75%; transform-origin: 50% 0%; }
html.sda .fp19::after { animation-range: entry 42.75% entry 97.75%; }
html.sda .fp20 { animation-name: fp20-k; animation-range: entry 45.00% entry 100.00%; transform-origin: 50% 0%; }
html.sda .fp20::after { animation-range: entry 45.00% entry 100.00%; }
@keyframes fp0-k {
  from { opacity: 0; transform: translate3d(-33.13vw, -87.3%, 399px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-4.64vw, -12.2%, 56px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp1-k {
  from { opacity: 0; transform: translate3d(-28.32vw, -65.5%, 339px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-3.96vw, -9.2%, 47px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp2-k {
  from { opacity: 0; transform: translate3d(-29.14vw, -32.0%, 349px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-4.08vw, -4.5%, 49px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp3-k {
  from { opacity: 0; transform: translate3d(-21.26vw, -76.2%, 252px) rotateX(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-2.98vw, -10.7%, 35px) rotateX(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}
@keyframes fp4-k {
  from { opacity: 0; transform: translate3d(-22.50vw, -42.0%, 267px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-3.15vw, -5.9%, 37px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp5-k {
  from { opacity: 0; transform: translate3d(31.15vw, -81.1%, 374px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(4.36vw, -11.3%, 52px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp6-k {
  from { opacity: 0; transform: translate3d(21.27vw, -76.3%, 252px) rotateX(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(2.98vw, -10.7%, 35px) rotateX(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}
@keyframes fp7-k {
  from { opacity: 0; transform: translate3d(-25.75vw, -0.0%, 308px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-3.61vw, -0.0%, 43px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp8-k {
  from { opacity: 0; transform: translate3d(17.26vw, -72.5%, 203px) rotateX(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(2.42vw, -10.2%, 28px) rotateX(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}
@keyframes fp9-k {
  from { opacity: 0; transform: translate3d(27.59vw, -56.0%, 330px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(3.86vw, -7.8%, 46px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp10-k {
  from { opacity: 0; transform: translate3d(-17.25vw, -0.1%, 202px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-2.41vw, -0.0%, 28px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp11-k {
  from { opacity: 0; transform: translate3d(22.51vw, -42.2%, 267px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(3.15vw, -5.9%, 37px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp12-k {
  from { opacity: 0; transform: translate3d(29.15vw, -32.0%, 350px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(4.08vw, -4.5%, 49px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp13-k {
  from { opacity: 0; transform: translate3d(-22.50vw, 42.0%, 267px) rotateY(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-3.15vw, 5.9%, 37px) rotateY(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp14-k {
  from { opacity: 0; transform: translate3d(17.25vw, -0.2%, 202px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(2.41vw, -0.0%, 28px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp15-k {
  from { opacity: 0; transform: translate3d(17.24vw, 72.5%, 202px) rotateX(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(2.41vw, 10.1%, 28px) rotateX(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}
@keyframes fp16-k {
  from { opacity: 0; transform: translate3d(25.75vw, -0.1%, 308px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(3.61vw, -0.0%, 43px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp17-k {
  from { opacity: 0; transform: translate3d(-22.49vw, 84.1%, 267px) rotateX(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(-3.15vw, 11.8%, 37px) rotateX(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}
@keyframes fp18-k {
  from { opacity: 0; transform: translate3d(22.50vw, 42.0%, 267px) rotateY(-90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(3.15vw, 5.9%, 37px) rotateY(-12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateY(0deg) scale(1.006); }
}
@keyframes fp19-k {
  from { opacity: 0; transform: translate3d(22.50vw, 84.1%, 267px) rotateX(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(3.15vw, 11.8%, 37px) rotateX(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}
@keyframes fp20-k {
  from { opacity: 0; transform: translate3d(25.58vw, 106.8%, 305px) rotateX(90deg) scale(1);
         animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  12%   { opacity: 1; animation-timing-function: cubic-bezier(.5, .02, .72, .72); }
  80%  { transform: translate3d(3.58vw, 14.9%, 43px) rotateX(12.6deg) scale(1.006);
         animation-timing-function: cubic-bezier(.13, .2, .45, 1); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) rotateX(0deg) scale(1.006); }
}

/* ==========================================================================
   Correctifs QA preprod (octobre 2026)
   ========================================================================== */

/* Formulaire : 16 px minimum pour éviter le zoom automatique de Safari iOS */
.contact-form input,
.contact-form select,
.contact-form textarea {
  font-size: 16px;
  text-transform: none;
  letter-spacing: normal;
}
.contact-form .required-mark { color: #ad502c; }
.contact-form .form-required-note {
  margin: 0;
  font-size: 12px;
  color: #66665f;
}
.contact-form .cf-turnstile { min-height: 65px; }

/* Lisibilité : plus aucun texte courant sous 12 px */
.deliverable-list li { font-size: 12px; }
.trust-bar > span {
  font-size: 11px;
  color: #9a9b93; /* contraste 6,2:1 sur le fond sombre */
}

/* Contraste : texte gris sur le fond beige du bloc approche (5,2:1) */
.approach-teaser { --muted: #56564f; }

/* Menu mobile : l'icône devient une croix quand le menu est ouvert */
.menu-toggle span:not(.sr-only) { transition: transform 0.2s ease; }
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(4px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { transform: translateY(-4px) rotate(-45deg); }

/* Pied de page : zones de clic d'au moins 24 px de haut */
.footer-grid a:not(.brand) { padding-block: 2px; }

/* ==========================================================================
   Retours QA du 6 octobre 2026
   ========================================================================== */

/* Tailles de police : tous les petits textes (surtitres, boutons, menus,
   libellés, légendes) sont remontés de 1 à 2 px. Les titres ne changent pas. */
.eyebrow,
.trust-bar > span,
.industry > span,
.industry b,
.method-list span,
.footer-grid strong,
.main-nav .language-switch,
.contact-form label,
.principle-grid span, .outcome-index,
.engagement-grid span,
.sector-story-head > span,
.sector-proof-go,
.usecase-criteria span,
.usecase-count,
.usecase-more summary { font-size: 13px; }
.main-nav a,
.button,
.footer-grid p,
.outcome-item aside li,
.ai-use-grid p,
.sector-story-grid li,
.sector-proof p,
.beyond-grid article p,
.gate-grid p,
.role-map span,
.values-layout p,
.act-proof span { font-size: 14.5px; }
.text-link,
.case p,
.prose table,
.listing-card p,
.principle-grid p,
.engagement-grid p,
.process-output p,
.founder-grid article > p,
.combination-grid p,
.team-model li,
.branch-nav a { font-size: 15px; }
.three-steps span, .service-row > span,
.case-link,
.article-layout aside,
.deliverable-list li,
.sector-responses li,
.contact-form .form-required-note { font-size: 13.5px; }
.case-meta,
.footer-base,
.listing-card span, .listing-card b,
.outcome-item aside > span,
.ai-use-grid span,
.engagement-grid small,
.sector-story-grid h3, .sector-reality > span,
.process-verb,
.gate-grid span,
.founder-id small, .founder-education,
.combination-grid span, .values-layout article > span,
.proof-figure small,
.page-header-kicker,
.sector-stories-note span,
.prose thead th,
.case-hero-main .article-kicker,
.usecase-tags li,
.page-hero .article-kicker,
.act-tag { font-size: 12px; }
.sector-proof > span,
.sector-proof-tag,
.dossier-strip dt { font-size: 11px; }
.beyond-proof { font-size: 12.5px; }
.branch-nav-label,
.proof-partner-label,
.act-proof small { font-size: 11.5px; }
.footer-grid a:not(.brand) { font-size: 14.5px; }
.process-output p { font-size: 16px; }
.approach-teaser small { font-size: 16px; }

/* Menu : la page en cours est identifiable */
.main-nav a[aria-current="page"]:not(.nav-cta) {
  text-decoration: underline;
  text-decoration-color: #e87018;
  text-decoration-thickness: 2px;
  text-underline-offset: 8px;
}

/* Usages : une fois la liste dépliée, le bouton du haut disparaît et un
   bouton « Masquer » apparaît en bas de la liste. */
.usecase-more[open] > summary { display: none; }
.usecase-less {
  appearance: none;
  background: none;
  border: 0;
  color: var(--accent-ink);
  cursor: pointer;
  font: inherit;
  font-size: 13px;
  letter-spacing: .12em;
  padding: 18px 0;
  text-transform: uppercase;
  transition: color .2s ease;
}
.usecase-less::after { content: "↑"; display: inline-block; margin-left: 9px; }
.usecase-less:hover { color: var(--ink); }

/* Corps des articles (cas clients, usages) : plus de trait entre les
   paragraphes ni de bordure autour des illustrations. */
.prose h2 { border-top: 0; }
.prose hr { display: none; }
.prose img { border: 0; }

/* Formulaire : message d'erreur d'envoi */
.contact-form .form-status {
  margin: 0;
  padding: 12px 14px;
  border-left: 2px solid #ad502c;
  background: #f6ece6;
  color: #7a3519;
  font-size: 14px;
}
.contact-form button[disabled] { opacity: .6; cursor: progress; }

/* Expertises, mobile : en une colonne, la bordure gauche seule n'a plus de sens */
@media (max-width: 900px) {
  .ai-use-grid article {
    border-left: 0;
    min-height: 0;
    padding-left: 0;
    padding-right: 0;
  }
}

/* Accueil, blocs animes au defilement : le fondu en haut et en bas de la fenetre
   rendait illisibles les surtitres et les liens sous les chiffres.
   Le fondu est reduit a quelques pixels et les liens eclaircis. */
/* Uniquement la ou la fenetre defile : sous 900px et en mouvement reduit la liste
   est statique, et le fondu effacait sa derniere ligne. */
@media (min-width: 901px) and (prefers-reduced-motion: no-preference) {
  html.sda .act-reel {
    -webkit-mask-image: linear-gradient(transparent, #000 6px, #000 calc(100% - 22px), transparent);
    mask-image: linear-gradient(transparent, #000 6px, #000 calc(100% - 22px), transparent);
  }
}
.act-proof small { color: #b4c0c5; }

/* ==========================================================================
   QA visuelle, 2e passe (6 octobre)
   ========================================================================== */

/* Contraste : gris et orange de texte sur les fonds beiges (AA 4,5:1) */
:root { --muted: #585850; --accent-ink: #a3380b; }
.prose a { color: var(--accent-ink); }
.about-page .origin-grid a { color: var(--accent-ink) !important; }
.article-layout nav a,
.engagement-grid small,
.proof-names span,
.sector-story-grid h3,
.sector-reality > span,
.sector-proof > span,
.process-output small { color: #5c5c54; }
.footer-base,
.branch-nav-label { color: #8c9ba2; }

/* Plus aucun libelle sous 12px */
.act-proof small,
.proof-partner-label,
.branch-nav-label,
.sector-proof > span,
.case-hero dt,
.case-facts dt { font-size: 12px; }

/* Notre approche, mobile : le texte de droite restait dans une colonne de 114px */
@media (max-width: 580px) {
  .method-list li { grid-template-columns: 44px 1fr; }
  .method-list small { grid-column: 2; }
}

/* Realisations : logos trop pales ou sur aplat une fois passes en gris */
.listing-logo img[src*="chronolife"] { filter: grayscale(1) brightness(.5); opacity: .85; }
.listing-logo.is-inverted img,
.listing-card:hover .listing-logo.is-inverted img { filter: invert(1); opacity: .72; }

/* Boutons places dans un contenu redige (message envoye, 404) */
.prose a.button { color: var(--white); text-decoration: none; margin-top: 12px; }
.prose .status-icon { display: block; margin: 0 0 22px; }

/* ==========================================================================
   Retours QA du 7 octobre
   ========================================================================== */

/* Entre 901 et 1100px le menu passait sur deux lignes et touchait le logo :
   le menu mobile prend le relais plus tot. */
@media (min-width: 901px) and (max-width: 1100px) {
  .menu-toggle { display: block; }
  .main-nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 88px;
    background: var(--paper);
    padding: 25px var(--pad);
    flex-direction: column;
    align-items: start;
    border-top: 1px solid var(--line);
  }
  .main-nav.open { display: flex; }
  .main-nav a { color: var(--ink); }
  .main-nav .language-switch { border-left: 0; padding-left: 0; }
}

/* Contact : sans le bloc "Vous avez un projet ?", le motif du pied de page
   se superposait aux liens de la derniere colonne. */
.site-footer--plain .footer-mark { display: none; }
