/* ==========================================================================
   Testimonial hero 1.0 — two-column hero with a review card pinned to the photo
   --------------------------------------------------------------------------
   Plain CSS. No framework, no build step, no external request, no script.

   The left column carries the eyebrow, the headline, one paragraph, a call to
   action and a row of overlapping faces. The right column is a single photo
   whose bottom-left corner is bevelled — the bevel lives in the file's alpha
   channel, not in a clip-path — with a white review card pinned 0.5 em from
   its bottom-right corner.

   The only moving part is the call to action: on hover and on keyboard focus
   its label slides up out of a one-line window while a copy slides in from
   below, and its arrow slides out to the right while a copy arrives from the
   left. Both run 350 ms on cubic-bezier(.25,.46,.45,.94) — the values read
   from the original's animation store, not guessed (README, "Provenance").

   PROPORTIONS
   Every metric derives from --prh-font-size, the body copy size. Ratios were
   measured on the live original with getBoundingClientRect for the boxes and
   getComputedStyle for the type, at five widths:

     body copy          1                (the reference unit, 16 px)
     row max-width      81 em            (1296 px, padding included)
     side padding       1 em             (16 px)
     column gap         6.25 em          (100 px)
     padding top        5 em             (80 px)
     padding bottom     7.5 em           (120 px)
     columns            1fr 0.9fr        (612.63 px / 551.38 px at 1440)
     column stack gap   2.5 em           (40 px)
     intro gap          1.88 em          (30.08 px)
     eyebrow to head    1 em             (16 px)
     headline           4.75 em          (76 px, leading 1, tracking -0.19 em)
     paragraph width    30 em            (480 px)
     button padding     1.25 em 1.5 em   (20 px 24 px)
     button radius      0.75 em          (12 px)
     button gap         0.25 em          (4 px)
     arrow              1.125 em         (18 px)
     face               2.75 em          (44 px), 0.125 em white ring
     face overlap       1 em             (16 px)
     card width         19.5625 em       (313 px)
     card padding       1.5 em           (24 px)
     card gap           1.5 em           (24 px)
     card offset        0.5 em           (8 px from the photo's edges)
     stars              1 em             (16 px), 0.12 em apart
     quote              1.125 em         (18 px, leading 1.4)
     name               1.125 em         (18 px) / role 1 em (16 px)
     photo ratio        1539 / 1500      (the source file's own ratio)

   So changing --prh-font-size rescales the whole component. Metrics that feed
   a calculation are written calc(ratio * font-size) rather than in em: a
   custom property in em resolves against whoever consumes it, so a tracking
   of -0.19 em read from the 76 px headline would come out five times too big.
   As an absolute value it is -3.04 px everywhere.

   Narrow layouts use @container, not @media: this hero has to fold when the
   column it sits in is narrow, whatever the window does. It also means the
   preview page neutralises every breakpoint with one declaration —
   container-type: normal — instead of restating each ratio.

   Order of this file:
     1. Face declarations
     2. Design tokens
     3. Derived metrics and narrow steps
     4. Shell: section and grid
     5. Text: eyebrow, headline, paragraph
     6. Call to action with sliding label
     7. Social proof: faces and mention
     8. Media: photo and pinned review card
     9. Original mode: the defect this component fixes
    10. Fallbacks: reduced motion, forced colours

   Naming follows BEM: .testimonial-hero, .testimonial-hero__part, .testimonial-hero--variant.
   ========================================================================== */

/* ------------------------------------------------- 1. Face declarations ---
   Three families, all under the SIL Open Font License, all served from this
   folder. Prefixed names so they cannot collide with a host page's own. */

@font-face {
  font-family: "Testimonial hero Cambo";
  src: url("Cambo-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Testimonial hero Geist Mono";
  src: url("GeistMono-var.woff2") format("woff2");
  font-weight: 300 700;
  font-style: normal;
  font-display: swap;
}

/* The original declares Aspekta 450 before Aspekta 400 inside the same face,
   so the browser actually renders regular text with the 450 cut. That is the
   weight shipped here, so the reproduction matches what the original draws. */
@font-face {
  font-family: "Testimonial hero Aspekta";
  src: url("Aspekta-450.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Testimonial hero Aspekta";
  src: url("Aspekta-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ------------------------------------------------------ 2. Design tokens ---
   Everything a host page is expected to touch. Colours, type, timing and the
   one size that rescales the rest. */

.testimonial-hero {
  /* Scale */
  --prh-font-size: 1rem;

  /* Type */
  --prh-police-titre: "Testimonial hero Cambo", Georgia, "Times New Roman", serif;
  --prh-police-texte: "Testimonial hero Aspekta", system-ui, -apple-system, sans-serif;
  --prh-police-mono: "Testimonial hero Geist Mono", ui-monospace, "SFMono-Regular", monospace;

  /* Colour */
  --prh-fond: #f8f7f7;
  --prh-encre: #161515;
  --prh-encre-douce: #272626;
  --prh-encre-tertiaire: #555151;
  --prh-bouton-fond: #161515;
  --prh-bouton-encre: #fff;
  --prh-carte-fond: #fff;
  --prh-carte-ombre: rgb(39 38 38 / 5%);
  --prh-lisere: #fff;
  --prh-focus: #161515;

  /* Motion — read from the original's animation store */
  --prh-duree: 350ms;
  --prh-courbe: cubic-bezier(0.25, 0.46, 0.45, 0.94);

  /* The photo's own ratio. Change it with the photo. */
  --prh-photo-ratio: 1539 / 1500;

  /* The component declares its own box model and assumes no reset. */
  box-sizing: border-box;
  position: relative;
  z-index: 0;
  container-type: inline-size;
  container-name: testimonial-hero;
  background-color: var(--prh-fond);
  color: var(--prh-encre);
  font-family: var(--prh-police-texte);
  font-size: var(--prh-font-size);
  font-weight: 400;
  line-height: 140%;
  text-align: start;
}

.testimonial-hero *,
.testimonial-hero *::before,
.testimonial-hero *::after {
  box-sizing: border-box;
}

/* ------------------------------- 3. Derived metrics and narrow steps ---
   Held one level below the root so the @container rules below can restate
   them: a query container cannot match itself. */

.testimonial-hero__grille {
  --prh-largeur-max: calc(81 * var(--prh-font-size));
  --prh-marge-laterale: calc(1 * var(--prh-font-size));
  --prh-colonnes: minmax(0, 1fr) minmax(0, 0.9fr);
  --prh-ecart-colonnes: calc(6.25 * var(--prh-font-size));
  --prh-haut: calc(5 * var(--prh-font-size));
  --prh-bas: calc(7.5 * var(--prh-font-size));
  --prh-colonne-max: none;

  --prh-ecart-pile: calc(2.5 * var(--prh-font-size));
  --prh-ecart-intro: calc(1.88 * var(--prh-font-size));
  --prh-ecart-entete: calc(1 * var(--prh-font-size));

  --prh-surtitre-corps: calc(1 * var(--prh-font-size));
  --prh-titre-corps: calc(4.75 * var(--prh-font-size));
  --prh-titre-approche: calc(-0.19 * var(--prh-font-size));
  --prh-texte-max: calc(30 * var(--prh-font-size));

  --prh-retour-ligne: nowrap;
  --prh-ecart-rangee: calc(1.88 * var(--prh-font-size));
  --prh-bouton-corps: calc(1 * var(--prh-font-size));
  --prh-bouton-marge-h: calc(1.5 * var(--prh-font-size));
  --prh-bouton-marge-v: calc(1.25 * var(--prh-font-size));
  --prh-bouton-rayon: calc(0.75 * var(--prh-font-size));
  --prh-bouton-ecart: calc(0.25 * var(--prh-font-size));
  --prh-fleche: calc(1.125 * var(--prh-font-size));

  --prh-ecart-confiance: calc(1 * var(--prh-font-size));
  --prh-visage: calc(2.75 * var(--prh-font-size));
  --prh-visage-chevauchement: calc(-1 * var(--prh-font-size));
  --prh-visage-lisere: calc(0.125 * var(--prh-font-size));
  --prh-mention-corps: calc(1 * var(--prh-font-size));

  --prh-photo-hauteur: auto;
  --prh-carte-largeur: calc(19.5625 * var(--prh-font-size));
  --prh-carte-marge: calc(1.5 * var(--prh-font-size));
  --prh-carte-ecart: calc(1.5 * var(--prh-font-size));
  --prh-carte-rayon: calc(0.75 * var(--prh-font-size));
  --prh-carte-decalage: calc(0.5 * var(--prh-font-size));
  --prh-carte-ombre-y: calc(0.25 * var(--prh-font-size));
  --prh-carte-ombre-flou: calc(0.5 * var(--prh-font-size));
  --prh-ecart-note: calc(1.25 * var(--prh-font-size));
  --prh-etoile: calc(1 * var(--prh-font-size));
  --prh-ecart-etoiles: calc(0.12 * var(--prh-font-size));
  --prh-citation-corps: calc(1.125 * var(--prh-font-size));
  --prh-ecart-auteur: calc(0.12 * var(--prh-font-size));
  --prh-nom-corps: calc(1.125 * var(--prh-font-size));
  --prh-role-corps: calc(1 * var(--prh-font-size));
}

/* Below 992 px of container the two columns stack, the photo takes a fixed
   height and crops, and the type steps down. Same three thresholds as the
   original. */
@container testimonial-hero (max-width: 991px) {
  .testimonial-hero__grille {
    --prh-colonnes: minmax(0, 1fr);
    --prh-ecart-colonnes: calc(2.5 * var(--prh-font-size));
    --prh-haut: calc(3.75 * var(--prh-font-size));
    --prh-bas: calc(5 * var(--prh-font-size));
    --prh-colonne-max: calc(42 * var(--prh-font-size));
    --prh-ecart-pile: calc(2 * var(--prh-font-size));
    --prh-ecart-intro: calc(1.25 * var(--prh-font-size));
    --prh-titre-corps: calc(4 * var(--prh-font-size));
    --prh-texte-max: calc(36 * var(--prh-font-size));
    --prh-photo-hauteur: calc(32 * var(--prh-font-size));
  }
}

@container testimonial-hero (max-width: 767px) {
  .testimonial-hero__grille {
    --prh-ecart-colonnes: calc(2 * var(--prh-font-size));
    --prh-haut: calc(3 * var(--prh-font-size));
    --prh-bas: calc(4 * var(--prh-font-size));
    --prh-colonne-max: calc(36 * var(--prh-font-size));
    --prh-ecart-pile: calc(1.5 * var(--prh-font-size));
    --prh-surtitre-corps: calc(0.875 * var(--prh-font-size));
    --prh-titre-corps: calc(3 * var(--prh-font-size));
    --prh-titre-approche: calc(-0.1 * var(--prh-font-size));
    --prh-texte-max: calc(36 * var(--prh-font-size));
    --prh-ecart-rangee: calc(1.5 * var(--prh-font-size));
    --prh-bouton-corps: calc(0.875 * var(--prh-font-size));
    --prh-bouton-marge-h: calc(1.25 * var(--prh-font-size));
    --prh-bouton-marge-v: calc(1 * var(--prh-font-size));
    --prh-ecart-confiance: calc(0.5 * var(--prh-font-size));
    --prh-mention-corps: calc(0.875 * var(--prh-font-size));
    --prh-carte-largeur: calc(19 * var(--prh-font-size));
    --prh-carte-marge: calc(1.25 * var(--prh-font-size));
    --prh-carte-ecart: calc(1.25 * var(--prh-font-size));
    --prh-citation-corps: calc(1 * var(--prh-font-size));
    --prh-nom-corps: calc(1 * var(--prh-font-size));
  }
}

@container testimonial-hero (max-width: 479px) {
  .testimonial-hero__grille {
    --prh-retour-ligne: wrap;
    --prh-haut: calc(2.5 * var(--prh-font-size));
    --prh-colonne-max: none;
    --prh-titre-corps: calc(2.5 * var(--prh-font-size));
    --prh-texte-max: none;
    --prh-visage: calc(2.5 * var(--prh-font-size));
    --prh-photo-hauteur: auto;
    --prh-carte-largeur: calc(15 * var(--prh-font-size));
    --prh-carte-decalage: calc(0.1 * var(--prh-font-size));
    --prh-citation-corps: calc(0.875 * var(--prh-font-size));
  }
}

/* --------------------------------------------------- 4. Shell and grid --- */

.testimonial-hero__grille {
  display: grid;
  grid-template-columns: var(--prh-colonnes);
  align-items: center;
  gap: var(--prh-ecart-colonnes);
  width: 100%;
  max-width: var(--prh-largeur-max);
  margin-inline: auto;
  padding-block: var(--prh-haut) var(--prh-bas);
  padding-inline: var(--prh-marge-laterale);
}

.testimonial-hero__colonne {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--prh-ecart-pile);
  width: 100%;
  max-width: var(--prh-colonne-max);
}

/* -------------------------------------------------------------- 5. Text ---
   None of these blocks is stretched to 100 %: they are flex items of a column
   aligned to flex-start, so each is as wide as its content allows, capped by
   the column. That is what makes the action row 616.08 px wide at 810 px and
   612.63 px at 1440 px — one number, two behaviours. */

.testimonial-hero__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--prh-ecart-intro);
  max-width: 100%;
}

.testimonial-hero__entete {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--prh-ecart-entete);
  max-width: 100%;
}

/* Native margins are reset here, not inherited from a host reset: a <p> keeps
   its bottom margin by default and a <h1> its own, which is how a block ends
   up 16 px too low. */
.testimonial-hero__surtitre {
  margin: 0;
  font-family: var(--prh-police-mono);
  font-size: var(--prh-surtitre-corps);
  font-weight: 500;
  line-height: 140%;
  text-transform: uppercase;
  color: var(--prh-encre);
}

.testimonial-hero__titre {
  margin: 0;
  font-family: var(--prh-police-titre);
  font-size: var(--prh-titre-corps);
  font-weight: 400;
  line-height: 100%;
  letter-spacing: var(--prh-titre-approche);
  color: var(--prh-encre);
}

.testimonial-hero__texte {
  width: 100%;
  max-width: var(--prh-texte-max);
  margin: 0;
  color: var(--prh-encre-douce);
}

/* ----------------------------------------------------- 6. Call to action --- */

/* wrap, but the social proof only moves to the next line once even its minimum
   size no longer fits: its basis is min-content, not its natural width. Without
   that it would drop down as early as 1440 px while it still has room to
   tighten, and the button — which is no longer squeezed — would overflow its
   column between 992 and 1107 px. */
.testimonial-hero__rangee {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--prh-ecart-rangee);
  max-width: 100%;
  margin: 0;
}

.testimonial-hero__bouton {
  display: flex;
  position: relative;
  flex-shrink: 0; /* see section 9: the original lets it shrink, and clips */
  align-items: center;
  justify-content: center;
  gap: var(--prh-bouton-ecart);
  max-width: 100%;
  padding: var(--prh-bouton-marge-v) var(--prh-bouton-marge-h);
  border-radius: var(--prh-bouton-rayon);
  background-color: var(--prh-bouton-fond);
  color: var(--prh-bouton-encre);
  font-family: var(--prh-police-mono);
  font-size: var(--prh-bouton-corps);
  font-weight: 500;
  line-height: 100%;
  text-transform: uppercase;
  text-decoration: none;
}

.testimonial-hero__bouton:focus-visible {
  outline: calc(0.125 * var(--prh-font-size)) solid var(--prh-focus);
  outline-offset: calc(0.1875 * var(--prh-font-size));
}

/* The window is exactly one line tall; the two labels stack inside it. */
.testimonial-hero__libelles {
  display: block;
  position: relative;
  height: 1em;
  overflow: clip;
}

.testimonial-hero__libelle {
  display: block;
  white-space: nowrap;
  transition: transform var(--prh-duree) var(--prh-courbe);
}

.testimonial-hero__fleches {
  display: block;
  position: relative;
  flex: none;
  width: var(--prh-fleche);
  height: var(--prh-fleche);
  overflow: clip;
}

.testimonial-hero__fleche {
  display: block;
  width: var(--prh-fleche);
  height: var(--prh-fleche);
  transition: transform var(--prh-duree) var(--prh-courbe);
}

/* The second arrow waits one window to the left, so it lands where the first
   one leaves. */
.testimonial-hero__fleche--relais {
  position: absolute;
  inset: 0 auto 0 -100%;
}

.testimonial-hero__bouton:hover .testimonial-hero__libelle,
.testimonial-hero__bouton:focus-visible .testimonial-hero__libelle {
  transform: translateY(-100%);
}

.testimonial-hero__bouton:hover .testimonial-hero__fleche,
.testimonial-hero__bouton:focus-visible .testimonial-hero__fleche {
  transform: translateX(100%);
}

/* ------------------------------------------------------ 7. Social proof --- */

.testimonial-hero__confiance {
  display: flex;
  flex: 1 1 min-content;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--prh-ecart-confiance);
  max-width: max-content;
  margin: 0;
}

/* flex: none, so the faces keep their 100 px whatever happens. The original
   lets this box shrink, which pulls the mention onto the last face — see
   section 9. */
.testimonial-hero__visages {
  display: flex;
  flex: none;
  align-items: center;
}

.testimonial-hero__visage {
  display: block;
  flex: none;
  width: var(--prh-visage);
  height: var(--prh-visage);
  border: var(--prh-visage-lisere) solid var(--prh-lisere);
  border-radius: 50%;
  object-fit: cover;
}

.testimonial-hero__visage + .testimonial-hero__visage {
  margin-left: var(--prh-visage-chevauchement);
}

.testimonial-hero__mention {
  font-family: var(--prh-police-mono);
  font-size: var(--prh-mention-corps);
  font-weight: 500;
  line-height: 140%;
  text-transform: uppercase;
  color: var(--prh-encre);
}

/* ------------------------------------------------------------- 8. Media --- */

.testimonial-hero__media {
  display: flex;
  position: relative;
  align-items: flex-end;
  justify-content: flex-end;
  width: 100%;
}

.testimonial-hero__photo {
  display: block;
  width: 100%;
  height: var(--prh-photo-hauteur);
  aspect-ratio: var(--prh-photo-ratio);
  object-fit: cover;
  object-position: 50% 50%;
}

/* Pinned to the photo's bottom-right corner. Three corners are rounded and
   the fourth is square — that is the original's shape, not an oversight. */
.testimonial-hero__avis {
  display: flex;
  position: absolute;
  right: var(--prh-carte-decalage);
  bottom: var(--prh-carte-decalage);
  flex-direction: column;
  gap: var(--prh-carte-ecart);
  width: 100%;
  max-width: var(--prh-carte-largeur);
  margin: 0;
  padding: var(--prh-carte-marge);
  border-radius: var(--prh-carte-rayon) var(--prh-carte-rayon) 0 var(--prh-carte-rayon);
  background-color: var(--prh-carte-fond);
  box-shadow: 0 var(--prh-carte-ombre-y) var(--prh-carte-ombre-flou) var(--prh-carte-ombre);
}

.testimonial-hero__jugement {
  display: flex;
  flex-direction: column;
  gap: var(--prh-ecart-note);
}

.testimonial-hero__note {
  display: flex;
  align-items: center;
  gap: var(--prh-ecart-etoiles);
}

.testimonial-hero__etoile {
  display: block;
  flex: none;
  width: var(--prh-etoile);
  height: auto;
}

.testimonial-hero__citation {
  margin: 0;
  font-size: var(--prh-citation-corps);
  font-weight: 500;
  line-height: 140%;
  color: var(--prh-encre);
}

.testimonial-hero__citation p {
  margin: 0;
}

.testimonial-hero__auteur {
  display: flex;
  flex-direction: column;
  gap: var(--prh-ecart-auteur);
}

.testimonial-hero__nom {
  font-size: var(--prh-nom-corps);
  font-weight: 500;
  line-height: 140%;
  color: var(--prh-encre);
}

.testimonial-hero__role {
  font-size: var(--prh-role-corps);
  font-weight: 400;
  line-height: 140%;
  color: var(--prh-encre-tertiaire);
}

/* ----------------------------------------------------- 9. Original mode ---
   The original's action row is saturated at 1440 px: button and mention add
   up to 625.68 px inside a 612.63 px column, so both shrink. The button's
   label then wraps to a second line and the one-line window clips it, which
   is why the original reads "START A FREE" instead of "START A FREE MEETING".
   The wrapped label is also twice the window tall, so its slide travels two
   windows while the arrow travels one — that mismatch is the same defect.

   Shipped fixed: the button no longer shrinks and its label never wraps, so
   the mention absorbs the overflow and wraps to two lines exactly as it does
   in the original. Add data-prh-original to the root to get the defect back,
   which is what the bench compares against. */

.testimonial-hero[data-prh-original] .testimonial-hero__bouton {
  flex-shrink: 1;
}

.testimonial-hero[data-prh-original] .testimonial-hero__libelle {
  white-space: normal;
}

/* The original keeps the row on a single line — except below 480 px — and lets
   the social proof be squeezed rather than drop down. */
.testimonial-hero[data-prh-original] .testimonial-hero__rangee {
  flex-wrap: var(--prh-retour-ligne);
}

.testimonial-hero[data-prh-original] .testimonial-hero__confiance {
  flex: 0 1 auto;
  flex-wrap: var(--prh-retour-ligne);
  max-width: none;
}

/* Same saturation, one row down: the original lets the row of faces shrink
   past its own min-content, so at 1200 px the box is 89.44 px wide for 100 px
   of faces — they spill out of it and the mention lands on the last one.
   min-width: 0 is what allows a flex item to go below min-content. */
.testimonial-hero[data-prh-original] .testimonial-hero__visages {
  flex: 0 1 auto;
  min-width: 0;
}

/* --------------------------------------------------------- 10. Fallbacks --- */

/* A delay is movement spread over time, so it goes too. What is a picture and
   not a movement — the photo, the bevel, the shadow — stays. */
@media (prefers-reduced-motion: reduce) {
  .testimonial-hero__libelle,
  .testimonial-hero__fleche {
    transition-duration: 1ms;
    transition-delay: 0s;
  }
}

@media (forced-colors: active) {
  .testimonial-hero__bouton {
    border: 1px solid currentColor;
  }

  .testimonial-hero__avis {
    border: 1px solid currentColor;
    box-shadow: none;
  }

  .testimonial-hero__visage {
    border-color: currentColor;
  }
}
