/* ==========================================================================
   Responsive — tablet and mobile.

   Loaded last, after pages.css, so every rule here wins its specificity tie
   against the desktop value it replaces. Keeping the breakpoints in one file
   rather than scattered through the others means the desktop cascade can be
   read without stepping over media queries.

   Both breakpoints are measured from their own artboards, not interpolated:

     iPad artboards    768 wide,  24px page margin
     Mobile artboards  375 wide,  20px page margin

   Two things change shape rather than size at both widths — the menu becomes a
   burger opening a fixed panel, and the process steps go to a single column.
   Below 768 the case cards stack too, with the photograph moving inside the
   green panel.
   ========================================================================== */


/* ==========================================================================
   Tablet — from the 768 artboards
   ========================================================================== */

@media (max-width: 1024px) {

  :root {
    --page-margin: 24px;

    /* The XD drops the display face by a third and pulls its leading in to
       match the size exactly — 55/55, not 55 on the desktop 75. */
    --t-display:    55px; --t-display-lh:    55px;
    --t-card-title: 30px; --t-card-title-lh: 34px;
    --t-h2:         30px; --t-h2-lh:         34px;
    --t-lead:       20px; --t-lead-lh:       19px;

    /* 768 board: the editorial body sets 20/22. It does not follow --t-lead-lh
       here — the lead paragraphs tighten to 19, these stay at 22. */
    --t-editorial-lh: 22px;
  }

  /* --- Header ------------------------------------------------------------
     Header row y27. The pill of menu items is replaced by a burger beside the
     contact square; both are 48px and 6px apart (642 and 696). */

  .site-header { padding-block-start: 27px; }

  .site-nav__list,
  .site-nav { margin-inline-start: 0; }

  .nav-toggle {
    display: block;
    order: 3;
    flex: 0 0 auto;
    width: 48px;
    height: 48px;
    margin-inline-start: 6px;
    border-radius: 10px;
    background: var(--c-off-white);
    color: var(--c-panel-deep);
  }

  .nav-toggle__bar {
    left: 50%;
    width: 25px;
    height: 1.5px;
    margin-inline-start: -12.5px;
  }

  /* 8px apart, centred on the 48px square. */
  .nav-toggle__bar:nth-child(1) { top: 20px; }
  .nav-toggle__bar:nth-child(2) { top: 28px; }

  /* Crossed, not collapsed — the open state in the artboard is an X. */
  .nav-toggle[aria-expanded='true'] .nav-toggle__bar:nth-child(1) { translate: 0 4px; rotate: 45deg; }
  .nav-toggle[aria-expanded='true'] .nav-toggle__bar:nth-child(2) { translate: 0 -4px; rotate: -45deg; }

  .lang-switcher { margin-inline: auto 15px; }
  .contact-toggle { order: 2; }

  /* --- Menu drawer -------------------------------------------------------
     332 x 567 panel at r10, its right edge on the burger's, 10px below the
     header row. Fixed rather than absolute so it stays put while the page
     behind it scrolls. */

  .site-nav {
    position: fixed;
    inset-block-start: 85px;              /* header row 27 + 48, then 10 */
    inset-inline-end: var(--page-margin);
    z-index: var(--z-header);

    display: flex;
    flex-direction: column;

    width: min(332px, calc(100vw - var(--page-margin) * 2));
    min-height: 567px;
    /* Anchored on the rule, which is a shape and so exact: both drawer boards
       put it 213 below the panel top (292 against a panel at 79 on the 375
       board, and the iPad board agrees). The links sit centred in that space:
       three 29px items and two 24px steps are 135, which leaves 39 above and
       39 below (the rule's margin). A head of 62 was read off y141, which is
       the first item's baseline and not its top, and left the list crowding
       the rule. */
    padding: 39px 30px 40px;

    border-radius: var(--radius-card);
    background: var(--c-off-white);
    color: var(--c-panel-deep);

    /* Parked rather than hidden: `visibility` in the same frame as a transform
       is what made the contact panel misfire, and this is the same problem. */
    opacity: 0;
    translate: 0 -12px;
    pointer-events: none;
    transition: opacity var(--dur-base) var(--ease-out),
                translate var(--dur-base) var(--ease-out);
  }

  .site-nav.is-open {
    opacity: 1;
    translate: 0 0;
    pointer-events: auto;
  }

  /* min-inline-size undoes the pill's 485 floor, which would push the list
     out of a 332 drawer. */
  .site-nav__list {
    display: block;
    min-inline-size: 0;
    height: auto;
    padding: 0;
    background: none;
    border-radius: 0;
  }

  /* Items step 53px apart in the design: 141, 194, 247 on the 375 board and
     147, 200, 253 on the iPad one. A 29px line box leaves 24 between them; the
     29 here made the step 58 and the third item sat 10px low. */
  .site-nav__item + .site-nav__item { margin-block-start: 24px; }

  .site-nav__link {
    display: block;
    font-size: 24px;
    line-height: 29px;
    color: var(--c-panel-deep);
    opacity: 1;
  }

  .site-nav__link:hover,
  .site-nav__link:focus-visible { color: var(--c-panel-deep); opacity: 0.55; }

  .site-nav__extra {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
  }

  .site-nav__rule {
    height: 1px;
    margin: 39px -30px 0;                 /* the rule runs the full panel width */
    border: 0;
    background: var(--c-mist-2);
  }

  /* The boards leave a deliberate void under the rule — the address block sits
     at 363 against a rule at 213 — and it is what gives the drawer its air. */
  .site-nav__address {
    margin-block-start: 144px;
    font-size: 18px;
    line-height: 27px;
  }

  .site-nav__contact {
    margin-block-start: 11px;
    font-size: 18px;
    line-height: 27px;
  }

  .site-nav__legal {
    margin-block-start: auto;
    padding-block-start: 40px;
    font-family: var(--font-mono);
    font-size: var(--t-tag);
    line-height: 23px;
  }

  /* --- Hero --------------------------------------------------------------
     Band 1117 tall, title y189 w536, lead in the right column at y711, rule
     y841, button right-aligned at y909. */

  .hero { min-height: 1034px; }           /* 1117 less the 75px header row */
  [data-sphere="section"]:not(.cta) { --sphere-ref: 1034px; }   /* the hero's height; see pages.css */
  .hero__inner { padding-block-start: 114px; }

  /* Both in row 1, as at desktop, so the right column's offsets are measured
     from the band top rather than from the bottom of the headline. Stacked in a
     second row they moved with every extra line the live headline took: three
     lines instead of the artboard's two put the lead at 782 against a rule at
     841, close enough to touch it, and pushed the button to 999. */
  .hero__main { grid-column: 1 / -1; grid-row: 1; }

  /* Bottom-anchored like the desktop column: content top y189, the artboard's
     lead ends at y764 over three 19px lines, so the column stops there and the
     lead is pushed onto its foot. */
  .hero__side { grid-column: 7 / -1; grid-row: 1; height: 575px; }

  /* Neither the iPad nor the mobile artboard carries the "[ SCROLL ↴ ]" hint —
     it is a desktop affordance, and leaving it in flow pushed the whole right
     column down a row's worth. */
  .hero__hint { display: none; }

  /* Artboard: lead x484 w260 at y707, button x411 w333 at y909 — both flush to
     the right margin at 744, not filling columns 7-12. */
  .hero__lead {
    width: 260px;
    margin-inline-start: auto;
    margin-block-start: auto;             /* sits on the column's foot, y764 */
  }

  /* The button hangs off the column's foot (see layout.css), so its gap is an
     inset rather than a margin — a margin here would add to the desktop inset
     instead of replacing it. */
  .hero__cta {
    display: flex;
    justify-content: flex-end;
    margin-block-start: 0;
    inset-block-start: calc(100% + 145px);   /* y909 */
  }

  .hero__rule { inset-block-start: 766px; }

  .page-home .hero__title { max-width: 536px; }

  /* The headline's line breaks are placed by hand for the 1440 artboard, where
     the display face is 80px. At 55 and 40 they land in the wrong places, so the
     text wraps to the column instead. */
  .hero__title br { display: none; }

  /* 862, not 780. The 780 is the second #181c18 rect's own height, but that
     rect starts at 5157 — 82 below the marquee at 5075 where this section
     actually begins, and the rect above it is the same colour so no boundary
     is visible there. Measured from the marquee's foot to where the dark
     finally gives way to the footer at 5937, the band is 862. At 780 the
     colour changed 82px early, under the button instead of clear of it. */
  .cta { min-height: 862px; }
  .cta__inner { padding-block-start: 166px; }
  .cta__main { grid-column: 1 / -1; }

  /* Content top 5237, the artboard's lead ends at 5581 — three lines again. */
  .cta__side { grid-column: 7 / -1; grid-row: 1; height: 344px; }

  /* Centred, as at desktop. 12.8% hit the artboard's x=116 only at 768 itself;
     by 1024 it had drifted 94px off the centre of the content box. */
  .cta__title { margin-inline: auto; max-width: 537px; }

  /* Same right column as the hero — 260 wide at x484, button 333 at x411, both
     against the right margin — and the same band-relative offsets, taken from
     a band top of 5071: heading 5237, lead 5524, rule 5655, button 5718. */
  .cta__lead {
    width: 260px;
    margin-inline-start: auto;
    margin-block-start: auto;             /* sits on the column's foot, 5581 */
  }

  .cta__action {
    display: flex;
    justify-content: flex-end;
    margin-block-start: 0;
    inset-block-start: calc(100% + 137px);   /* 5718 */
  }

  .cta__rule { inset-block-start: 584px; }

  /* --- Case cards --------------------------------------------------------
     Still side by side at this width: panel 24-376, photograph 392-742. */

  .case-card { grid-template-columns: 352fr 352fr; }
  .case-card__panel { grid-template-columns: 267fr 85fr; min-height: 404px; }
  .case-card__body { padding: 27px 21px 21px; }
  /* 226 of content cannot carry a pill column beside the rows -- "TEMPS ET
     PRÉSENCE" alone would leave them about 40px. The iPad artboard stacks the
     pills under the rows at x45, stepping 30, and that is what happens here. */
  .case-card__details { display: block; padding-block-start: 19px; }  /* Ligne 154 at 156, row 1 at 175 */

  .case-card__tags {
    align-items: flex-start;
    gap: 6px;                                          /* pills step 30: 24 tall + 6 */
    margin-block-start: 29px;                          /* last rule 259, first pill 288 */
  }

  /* The gloss anchors to the pill's leading edge from here down. At desktop the
     pills sit against the panel's right edge, so the bubble hangs off their
     right and opens inward; stacked, they sit against the left edge instead and
     that same anchoring sent the bubble off the panel — and, at 375, off the
     screen. Capped at 200 so it stays inside the body's 225 (768) and 215 (375)
     of content whichever pill it belongs to. */
  .case-card__tag[data-tip]::after {
    right: auto;
    left: 0;
    max-width: 200px;
  }

  .case-card__tag[data-tip]::before {
    right: auto;
    left: 14px;
  }
  /* 21, not 60. Same autoHeight trap as the 1440 rule in components.css: the
     title frame's y is its TOP and its two baselines are +30 and +64 inside it,
     so the last baseline is at 1448 and the figures' at 1489 — 41 between them,
     which is 21 of margin once the title's descent and the figures' ascent are
     taken off. Reading the frame y as a baseline put the figures ~39 too low,
     and a real title wrapping to three lines carried that error down the panel.
     The 12 below was measured the same way and is right: caption baseline 1504,
     Ligne 154 at 1519. */
  .case-card__stats { gap: 48px; margin-block-start: 21px; margin-block-end: 12px; }
  .case-card__media { aspect-ratio: 350 / 600; }

  /* #212121, not the #3a3e3d the 1440 board uses. Both the 768 and the 375
     boards set the case title in the same ink as the step title beside it —
     six nodes each, no exception — so the switch happens with the layout. */
  .case-card__title { max-width: 222px; color: var(--c-panel); }
  .case-card__stat-value { font-size: 16px; line-height: 15px; }
  .case-card__stat-label { font-size: 11px; line-height: 12px; }
  .case-card__value { font-size: 12px; line-height: 18px; }
  .case-card__label { flex: 0 0 60px; }

  /* Three per row is a fixed 24px column each in the design; stacked keeps them
     legible when a tag runs long. */
  .case-card__row { flex-wrap: wrap; }

  /* --- Editorial rules (À propos) ----------------------------------------
     The 96/46 below this breakpoint is the 1440 board's. Both small boards
     close it up and agree on the foot: 31 under the rule, and 74 (768) / 73
     (375) over it, measured from the foot of the paragraph above. The first
     rule on the page follows a picture rather than a text block and sits
     tighter still — 62 here, 34 at 375 — so it gets its own value instead of
     inheriting a gap sized for descender space that is not there. */
  /* Scoped to À propos rather than to .separator, which the case study page
     also uses with margins of its own — an unscoped rule here would outrank
     `.page-case .separator` on specificity and quietly reset that page too. */
  .page-about .shell > .separator:not(.separator--band) {
    margin-block: 74px 31px;
  }

  .page-about .shell > .separator:not(.separator--band):first-child {
    margin-block-start: 62px;
  }

  .section--results { padding-block: 91px 100px; }

  /* 56, not 89: the artboard runs this heading over two 55px lines from y1197
     and opens the first card at 1363. The larger figure came of measuring that
     gap against a one-line heading — which is what the live copy happens to
     take — so every line the real heading needs was being added to a gap that
     was already a line too deep. The same correction applies to the three
     headings below it. */
  .section--results .section__title { max-width: 626px; margin-block-end: 56px; }
  /* The anchor landing from pages.css, re-measured: card 257 below the
     section's top, heading 91, header 75. */
  .section--results { scroll-margin-top: clamp(-8px, calc(40svh - 265px), 83px); }

  /* --- Process steps -----------------------------------------------------
     One column, full width — 720 x 357 with a 78px foot. */

  .process-steps { grid-template-columns: minmax(0, 1fr); gap: 16px; }

  /* One column from here down, so there is nothing left to align the titles
     with and the reserved second line would only open a hole under each. */
  .process-steps .step-card__title { min-height: 0; }

  .step-card { min-height: 357px; padding: 30px 19px 19px; }
  .step-card__tags { margin-block-start: 33px; }

  /* No rule below the desktop breakpoint. The 1440 board draws one (Tracé 1599,
     284 down the card); neither small board has anything between the last pill
     and the description — on the 768 board the pills end at 3820 and the copy
     starts at 3836, and on the 375 board 3336 and 3352. Sixteen pixels is not a
     gap a rule lives in, and both boards leave their slack at the foot of the
     card instead.

     display:none rather than dropping the <hr>: the desktop layout still wants
     it, and the markup is one template part shared by all three widths. */
  .step-card__rule { display: none; }

  /* 15, not 37. The board puts the copy 16 under the pills, and the frame top
     it measures that to is the ascent line — the CSS line box starts 1.3 above
     it at 16/18, so the margin is 16 less that. The old 37 was the figure for
     the gap *under the rule*; with the rule gone it was the whole 70px stack
     that used to sit there. */
  .step-card__desc { margin-block-start: 15px; }
  .step__foot { height: 78px; padding-inline: 29px; }

  .section--process { padding-block: 111px 130px; }

  /* Nothing under the marquee on the home page. The closing band's own 166px
     head (.cta__inner below) already carries the whole 162 the artboard leaves
     between the bar at 5075 and the heading at 5237; the 130 was that gap
     counted a second time, and the two bands share a colour, so it read as a
     hole rather than as a boundary.
     Scoped to the home page: À propos runs the same band, but what follows it
     there is a plain .section whose 128px head is all that separates the two —
     the 130 is doing real work on that page. */
  .page-home .section--process { padding-block-end: 0; }
  .section--process .section__title { margin-block-end: 65px; }  /* heading foot 3560, card 3625 */
  .section--process .marquee { margin-block-start: 65px; }       /* step foot 4962, bar 5027 */
  .section--process .process-steps-wide + .marquee { margin-block-start: 110px; }
  .section__title--indent { margin-inline-start: 0; max-width: 626px; }

  /* --- Footer ------------------------------------------------------------
     Address and menu side by side, contact under them, then the wordmark
     right-aligned at 250px — below the text here, not level with it. */

  /* How far the closing heading sits under whatever ended the page is set by
     the band above, not by the footer, so the head is per page rather than one
     figure for all of them. The foot — heading to the contact bar — is the
     board's 72 everywhere.

     Home: the board leaves 239 between the button and the heading and gives
     159 of it to the dark band, so only 80 is the footer's. À propos ends on a
     step card instead, with no band to carry any of it, so the whole 121 the
     board leaves there belongs to the footer. The pages with no 768 board of
     their own keep the 160 they were built with. */
  .site-footer__intro { padding-block: 160px 72px; }
  body:has(.page-home)  .site-footer__intro { padding-block-start: 80px; }
  body:has(.page-about) .site-footer__intro { padding-block-start: 121px; }
  .site-footer__heading { grid-column: 1 / 8; max-width: 444px; }
  .site-footer__side { grid-column: 8 / -1; }

  .site-footer__main {
    padding-block: 44px 26px;
    margin-block-start: 132px;          /* marquee ends 6412, rule 6544 */
    row-gap: 68px;
  }

  /* The wordmark sets about 3.35px of ink per px of font-size, so the artboard
     sizes — 250 here, 117 at mobile — are wider than the content box they sit
     in: 837 against 720 at 768, 392 against 335 at 375. Pinned to the right
     edge, the overflow all came off the left, which put the leading "1" outside
     the viewport and left the lockup looking slipped rather than placed.

     Sized to the content box instead. It fills the width at every size below
     the desktop breakpoint, which is the full-bleed reading the artboards are
     after, and being exactly as wide as its box it is centred by construction.
     It also ramps continuously — 217 at 767 against 250 at 768 — where the two
     fixed sizes jumped from 117 to 250 across one pixel. */

  /* The query container the wordmark's font-size is cut from. It has to be the
     shell rather than the brand itself: an element cannot size its own text
     from its own width, and this is the box whose inline size IS the content
     width — the page margin is the shell's padding. Inline-size containment
     only, so the footer grid's block layout is untouched. */
  .site-footer__main { container-type: inline-size; }

  .site-footer__brand {
    /* Relative, not static: it is the containing block of the twinkle canvas.
       `inset: auto` is what keeps the layout the same as static. Without it
       the desktop rule's top: 61px and right: page-margin, which a static box
       ignores, become live offsets on a relative one and shove the wordmark
       61px down onto the legal links and a margin's width off centre. */
    position: relative;
    inset: auto;
    grid-column: 1 / -1;
    grid-row: 3;
    justify-self: stretch;
    text-align: center;
    /* -0.07em is the XD's own letterSpacing on this node, and leaving it out
       was what made the artboard sizes look too wide: the wordmark sets 2.93px
       of ink per px of font-size with it, not the 3.35 measured without. At
       117 that is 343 against a 335 box and at 250 it is 732 against 720 —
       the boards' sizes do fit, near enough to full bleed either way.
       34.8vw is those two sizes expressed against their own content box
       (117/335 and 250/720 agree to within a thousandth). */
    letter-spacing: -0.07em;

    /* 34.15, not 34.8. The old coefficient set the lockup wider than the box it
       sits in — measured, the advance is 2.928px per px of font-size, and 34.8
       asks for more than the content box has: 13.5px of overflow at 767, 7 at
       430, 6 at 375. And an overflowing line does not centre. `text-align`
       distributes slack, so with none to distribute the text starts at the
       content edge and every pixel of the excess goes off the right — which
       reads as a wordmark shoved sideways rather than one that is too big.
       Reported from a phone as "pas centré".

       The divisor is 2.998, not 2.928: the advance is 2.928 per px of
       font-size and the padding below adds another 0.07, and both have to fit
       inside the box. So (vw - margins - 4) / 2.998, the 4 being a hair of
       clearance so rounding cannot put it back over.

       cqw, not vw, and no 250px cap. Two faults, both of which made the lockup
       narrower than its row:

       vw counts the scrollbar and the content box does not — 15px here, which
       is 5px of font-size the fit was spending on a gutter that is not there.
       100cqw is the footer shell's own content box, so the fit is exact at any
       width and survives a platform whose scrollbar is a different width.

       The 250px cap held from about 802 up to 1024 while the row kept growing
       underneath it: at 1024 that is 750px of ink in a 961px box, 211 short,
       which is the "pas assez large". 250 is the 768 board's size, not a
       ceiling the design asks for — that board sets the wordmark to the full
       content width (ink 26..742 against margins of 26), and this now does
       that at every width in the band.

       Note the step at 1025: desktop is 210px right-aligned, deliberately not
       full bleed, so the wordmark drops when the breakpoint is crossed. That
       jump existed before at 250; it is bigger now. Cap this again if the
       tablet lockup is ever wanted smaller than its row. */
    font-size: calc(100cqw / 2.9981);

    /* Restores the space the negative tracking removes after the last glyph.
       Letter-spacing applies to every character including the final one, so the
       measured line is ~0.07em narrower than the ink it paints; centring that
       line leaves the ink sitting half that distance right of true centre. The
       padding takes it off the content box so the two centres agree. */
    padding-inline-end: 0.07em;

    /* The lockup is six glyphs with no descender between them, so a normal line
       box parks ~100px of empty space under the ink and pushed the legal line
       that far off the wordmark — 143 under the baseline against the board's 59.
       0.3 trims the box to about the band the artboard gives it (92 on 250);
       the margin then puts the baseline back where the board has it, 213 under
       the contact block. */
    line-height: 0.3;
    margin-block-start: 46px;
  }

  .site-footer__address { grid-column: 1 / 7; grid-row: 1; }
  .site-footer__nav     { grid-column: 8 / -1; grid-row: 1; }
  .site-footer__contact { grid-column: 1 / 7; grid-row: 2; }
  /* row-gap 0: the two links do not fit side by side in half a 768 row, so the
     flex wraps — and the 24px gap that separates them across the row then also
     separates the two lines, setting them 47 apart. The board has only the
     privacy link here; the consent link is ours, and it belongs directly under
     its neighbour at the 23px line height, not a block away from it. */
  .site-footer__legal   { grid-column: 7 / -1; grid-row: 4; justify-content: flex-end; row-gap: 0; }

  /* The 768 board swaps the two: the privacy link is the one anchored right,
     the credit runs from the page margin. Left in place, the desktop rule's
     text-align pushed the credit against the middle of the row instead. */
  .site-footer__credit  { grid-column: 1 / 7; grid-row: 4; justify-self: start; text-align: left; }

  .site-footer__address,
  .site-footer__contact { font-size: 20px; line-height: 23px; }
  .site-footer__menu { font-size: 20px; line-height: 29px; }

  /* --- Contact popup -----------------------------------------------------
     It has its own artboards at both widths, and at neither is it a side panel:
     the sheet fills the viewport and the form runs edge to edge inside the page
     margin, so the body loses the 34px inset it carries at desktop.

     iPad: head bar 720x58 at y22, title y216, fields from y379 two-up on a 76px
     pitch, preference row y531, message 720x286, send bar y933. */

  .popup {
    padding-inline: 0;
    --popup-w: 100vw;
  }

  /* The sheet itself is the green surface. Neither small board draws a body
     rectangle — the green is the screen — so the panel carries the fill and the
     bar sits on it as a chip in the deeper green, 22 down from the top and
     inset by the page margin, exactly as both boards draw it.

     That 22 is not decoration: the body's own head padding below is measured
     from it. With the panel flush at 0 the bar lost the offset and every row
     under it rode 22px high — the title landed on 194 at 768 against the
     artboard's 216, and on 92 at 375 against 114. */
  .popup__panel {
    width: 100%;

    /* Follows the layer rather than measuring the viewport a second time. It
       was `100svh`, the small viewport — the layer is the layout viewport, and
       on iOS those are two different boxes, which is how the panel ended up
       above the visible area. One measurement, published by popup.js, and this
       just fills it. See the note on .popup in components.css. */
    max-height: 100%;
    padding-block: 22px 0;
    border-radius: 0;
    background: var(--c-accent);
  }

  /* An earlier pass took the bar edge to edge because insetting it left a
     channel of dark scrim down either side and across the 22px above it, and
     the bar read as a detached chip on the wrong ground. That channel was the
     symptom of the panel having no fill of its own — now that it does, the
     inset is simply what the artboard draws. */
  .popup__head {
    margin-inline: var(--page-margin);
    padding-inline: 23px;
    border-radius: var(--radius-card);
  }

  /* The body no longer paints: two greens meeting on a seam is what made the
     step. It keeps its own measured head padding and the page margin. */
  .popup__body {
    padding: 136px var(--page-margin) 40px;
    border-radius: 0;
    background: none;
  }

  /* The sheet's title carries its own step — 46 / 40 / 25 across the three
     boards — rather than following the h2 token, which lands on 30 here. */
  .popup__title { font-size: 40px; line-height: 41px; }

  textarea.form__input { min-height: 286px; }

  /* --- Editorial / about --------------------------------------------------
     The iPad artboard keeps the label beside the body rather than above it:
     label x24 w184, body x300 w444, so a 92px channel between two columns that
     are not on the 12-column grid. Only the 375 board stacks them. */

  .editorial {
    grid-template-columns: minmax(0, 184fr) minmax(0, 444fr);
    column-gap: 92px;
    row-gap: var(--s-4);
  }

  .editorial__label { grid-column: 1; }
  .editorial__body  { grid-column: 2; }
  .editorial__aside { grid-column: 1 / -1; }

  /* The 768 board crops the hero photograph taller than the desktop one —
     720 x 364 against 1388 x 621. Without this it kept the desktop ratio and
     came out 42px short. */
  .about-hero__media { aspect-ratio: 720 / 364; }

  /* x299 on a 768 board — 38.2% into the content box, not the 8.43% the 1440
     board uses. Declared on the separator, not the mark: `--plus-x` resolves
     its own `var()`s where it is declared, so setting the ratio on the child
     would never reach it.

     The closing band's rule is excluded: its plus tracks the right-hand column,
     not the label column, and the 768 board keeps it at 573 like the others. */
  .separator:not(.separator--band):not(.separator--legal) { --plus-ratio: 0.382; }

  /* x573 on a 768 board. */
  .hero__rule,
  .cta__rule,
  .separator--band { --plus-ratio: 0.7625; }

  /* À propos Approche band: the section's own 128 of head is enough above the
     rule at this width and below — the 85 the rule adds on desktop left too
     much empty sphere over it. */
  .separator--band { margin-block-start: 0; }

  /* x560 on the 768 legal board, not the 573 the other rules use. */
  .separator--legal { --plus-ratio: 0.7444; }


  /* The numeral steps 300 → 210 → 150 across the three boards. Only the 375
     value was carried over, so the 768 page kept the desktop 300. */
  .page-404__numeral { font-size: 210px; }

  /* --- Case study detail --------------------------------------------------
     No artboard exists for this page below 1440, so it follows the rules the
     other pages set at this width rather than a measured layout. */

  .page-case .case-hero__inner { padding-block-start: 114px; }
  .case-hero__title { grid-column: 1 / -1; }
  .case-meta { grid-column: 1 / -1; margin-block-start: 40px; max-width: 332px; }

  /* Full width here rather than two columns of twelve, so the board's single
     line fits: 332 less the 65 label and its gutter leaves 251, which holds
     every service value but the longest. A grid, not the wrapping flex row it
     used to be — a value too long for the track grows its own cell instead of
     jumping under the label and leaving the other rows behind. */
  .case-meta__row {
    grid-template-columns: 65px minmax(0, 1fr);
    column-gap: var(--s-2);
    row-gap: 0;
    align-items: baseline;
    padding-block-end: 0;

    /* The row is 28px and its text is 18, and without this the whole 10px of
       slack fell below the line — measured 0 above, 10 below. The value sat
       against the rule of the row overhead and a gap opened before its own,
       which reads as three lines of text pushed up rather than three rows.
       Centring the track puts 5 on each side, so each value sits midway
       between the two rules that bracket it. */
    align-content: center;
  }
  .case-hero__media { margin-block-start: 60px; }
  .case-hero__badge { width: 150px; height: 62px; }

  .page-case .separator { margin-block: 120px 43px; }
  .case-defi { grid-template-columns: minmax(0, 1fr); gap: var(--s-5); margin-block-start: 140px; min-height: 0; }
  .case-defi__media { aspect-ratio: 420 / 500; }
  .case-defi__body { padding-block-start: 0; }
  .case-defi__lead { margin-block-start: var(--s-5); }
  .case-defi__text { margin-block-start: var(--s-4); }

  .section--solutions { padding-block: 120px 0; }
  .section--solutions .section__title { margin-block-end: 100px; }

  /* Row cards. From the iPad À propos board, which is the only place any
     artboard draws this component below 1440: body 626 and numeral 96 on a
     246-tall row, title inset 32 from the card edge and the copy stacked under
     it rather than beside it. */
  .row-card { grid-template-columns: minmax(0, 1fr) 96px; min-height: 246px; }
  .row-card__body { grid-template-columns: minmax(0, 1fr); gap: 0; padding: 34px 32px; }

  /* The wide step closes the Expertises group, stacked flush under the grey
     cards, so at this width its text has to start where theirs does. The 768
     board puts both at x43 — 19 in from a card that begins at the 24px page
     margin. The green rows in the Approche band keep their 32: their own board
     draws them on a narrower card (x26 w626), which lands their text at x56. */
  .process-steps-wide .row-card__body { padding-inline: 19px; }
  .row-card__text { max-width: none; margin-block-start: 18px; }
  .row-card__number { padding-block: 34px 25px; }

  /* The wide step stacks at this width: face on top, numeral bar under it —
     not the numeral column beside the body that every other width uses.

     The note in components.css reads the 768 board as "720+78" side by side,
     and that is the rotation trap in CLAUDE.md: Rectangle 2367 is stored
     rotated, so a walk reports it 78 wide and 720 tall when it is drawn 720
     wide and 78 tall, under the face. The rest of the board agrees — the face
     (Rectangle 2363) is 720x220 at x24,y2976, the numeral group opens at y3196
     where the face ends, and inside it S4/ sits at x85 while the 30px mark sits
     at x684. Those are the two ends of a horizontal bar; a 78px column at x744
     would be off a 768 artboard altogether.

     Which makes this exactly the grey step card's face-plus-foot, and it is
     given the same 78px bar and 29px insets so the two read as one family.

     Scoped to .process-steps-wide: the case study's solution rows are the same
     component and have no artboard below 1440, so they keep the column.

     This holds at 375 too, on purpose and against that board: the ≤767 block
     restores the column on `.row-card`, which this outranks, so the wide step
     stays stacked all the way down. The 375 artboard does draw it side by side
     — Rectangle 2382 at 252x286 with Rectangle 2383 at 80x286 beside it — and
     the stack is what was asked for instead. Delete these four rules' hold on
     ≤767 (scope them to `@media (min-width: 768px)`) to go back to the board. */
  .process-steps-wide .row-card {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }

  .process-steps-wide .row-card__body { min-height: 220px; }

  .process-steps-wide .row-card__number {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    min-height: 78px;
    padding: 0 29px;
  }

  /* `auto` on the block axis is what floats the mark to the foot of a column;
     in a row it does nothing and the mark would sit against the numeral. */
  .process-steps-wide .row-card__mark { margin-block-start: 0; }

  /* --- Politiques ---------------------------------------------------------
     iPad board: title 24,164 w536 at 55/55, rule 345, body 24,409 w444 and the
     contact block 560,409 w184 beside it. Both text columns open on the page
     margin here — the column-2 indent is a desktop move — and the head is 99,
     which is the artboard title at 174 less this width's 75px header row. */
  .page-legal { padding-block: 99px 100px; }
  .page-legal__title,
  .page-legal__body { grid-column: 1 / 9; }

  /* The sphere's floor, as at desktop (pages.css). */
  .case-results__panel { min-height: calc(var(--sphere-ref) * 0.82); padding-block-end: 40px; }
  .case-results__list { margin-block-start: 60px; }

  /* At 1440 this copy is held 116px off the panel's edge by the editorial
     grid's own columns — it starts at column 2. Below that breakpoint the grid
     collapses to one column and the inset went with it, so the heading, the
     numbered results and the closing paragraph all sat flush against the
     panel's rounded edge.

     On `.editorial` rather than on the content wrapper above it — the wrapper
     used to hold an edge-to-edge rule as well, since removed. */
  .case-results__panel .editorial { padding-inline: var(--page-margin); }

  /* The numbered list lives inside the label column, which is 184fr of the
     184/444 split this breakpoint sets — 166px at 768. Each result was folding
     into five to seven lines of three words beside a paragraph still holding
     399. The panel stacks here instead, a breakpoint earlier than the editorial
     blocks elsewhere, because it is the only one carrying a list in that
     column. The list keeps its 351 cap, so it does not run the full width
     either. */
  .case-results__panel .editorial {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
    row-gap: var(--s-4);
  }

  .case-results__panel .editorial__label,
  .case-results__panel .editorial__body { grid-column: 1 / -1; }


  /* --- Expertise ---------------------------------------------------------
     The page is other pages' components, so nearly all of its tablet
     behaviour arrives with them — the editorial split, the card that goes to
     one column, the rows, the panel that stacks just above. What is left is
     the rhythm between the sections, which follows the case study's: its
     gaps at this width, not the desktop ones scaled. */

  /* The 12-column lead column is 320px at 768 and the lead is prose. It keeps
     an indent so it still reads as held back from the title, but not one that
     sets it in a rail. */
  .expertise-hero__lead { grid-column: 4 / -1; }

  .page-expertise .separator { margin-block: 120px 43px; }

  .expertise-intro { padding-block: 80px 0; }

  .section--volets { padding-block: 120px 0; }
  .section--volets .section__title { margin-block-end: 100px; }

  .expertise-encart { padding-block: 140px 0; }

  .expertise-preuve__list { gap: var(--s-5); }

  .expertise-more__link { padding-block: var(--s-3); }
}


/* ==========================================================================
   Mobile — from the 375 artboards
   ========================================================================== */

@media (max-width: 767px) {

  :root {
    --page-margin: 20px;

    --t-display:    40px; --t-display-lh:    40px;
    --t-card-title: 25px; --t-card-title-lh: 27px;
    --t-h2:         25px; --t-h2-lh:         27px;
    --t-lead:       18px; --t-lead-lh:       20px;

    /* 375 board: 18/20, the one width where the two scales agree. */
    --t-editorial-lh: 20px;
  }

  /* --- Header ------------------------------------------------------------ */

  .site-header { padding-block-start: 21px; }
  .site-nav { inset-block-start: 79px; }        /* 21 + 48, then 10 */
  .site-header__logo img { height: 24px; }

  /* --- Hero --------------------------------------------------------------
     Band 722 tall, title y143, lead y388, rule y490, button y589. The lead and
     button move under the title rather than into a side column. */

  .hero { min-height: 653px; }                  /* 722 less the 69px header row */
  [data-sphere="section"]:not(.cta) { --sphere-ref: 653px; }   /* the hero's height; see pages.css */
  .hero__inner { padding-block-start: 74px; }

  /* Full width, but still both in row 1 like the wider breakpoints. Stacking
     them makes every offset below depend on how many lines the headline takes,
     and the rule underneath does not move with it — it is pinned to the band.
     In row 1 the lead and the button keep the artboard's own y whatever the
     headline does, which is the only way the rule stays between them. */
  .hero__main,
  .hero__side { grid-column: 1 / -1; grid-row: 1; }

  /* Content top y143, the artboard's lead ends at y444 — bottom-anchored here
     too, so a longer lead grows up into the gap under the headline rather than
     down onto the rule at y490. */
  .hero__side { height: 301px; }

  .page-home .hero__title { max-width: none; }

  /* The artboard puts the button at y589, well below the rule at y490. These
     offsets were short enough that with the live headline — three lines at 40px
     rather than the artboard's two — the button landed at 465 and the rule ran
     straight through the middle of it. Measured from the design's own gaps:
     169 from the title to the lead, 145 from the lead to the button, less the
     16px grid row gap between the two columns. */
  /* Full width again, and left — the 260px right-hand column is a tablet
     construction. Offsets run from the content top at 143: lead y388,
     button y589, both artboard values. */
  .hero__lead {
    width: auto;
    margin-inline-start: 0;
    margin-block-start: auto;             /* sits on the column's foot, y444 */
  }

  .hero__cta {
    justify-content: flex-start;
    margin-block-start: 0;
    inset-block-start: calc(100% + 145px);   /* y589 */
  }

  .hero__rule { inset-block-start: 421px; }

  /* Height comes from the content here, so without a floor under it the band
     closed exactly on the bottom edge of the button. The artboard leaves 160px
     between that edge and the footer heading, and the footer contributes 108 of
     its own, so 52 belongs to this band. */
  /* The button hangs off the column's foot rather than sitting in it, so it no
     longer adds its own height here and the band needs a floor that reaches
     past it: content top 120, the lead's foot at 414, the button 108 below that
     and 60 tall, then the 52 the artboard leaves before the footer heading. A
     longer heading still grows the band beyond this. */
  .cta {
    /* 812: marquee foot 4548, the 30 below it, then dark to 5390. At 754 the
       footer's lighter grey started 58px early. */
    min-height: 812px;
    padding-block-end: 52px;
  }

  .cta__inner { padding-block-start: 120px; }
  .cta__main,
  .cta__side { grid-column: 1 / -1; grid-row: 1; }

  /* Content top 4698, the artboard's lead ends at 5112, rule at 5190. */
  /* 430, not 414: the lead is four 19px lines from 5052, so its foot is 5128
     — 430 under the content top at 4698, not the 414 a three-line reading of
     it gave. The 16 it was short put the lead that much high and opened the
     same 16 under it, against the rule. */
  .cta__side { height: 430px; }

  .cta__title { margin-inline: 0; max-width: none; }

  /* Band top 4578, content top 4698: lead 5052, rule 5190, button 5220. */
  /* The one paragraph that does not follow --t-lead down to 18 at this width.
     Home holds its closing lead at 20/19 — while the hero lead above and the footer paragraph below are both
     18/20 on those same two boards. */
  .cta__lead { font-size: 20px; line-height: 19px; }

  .cta__lead {
    width: auto;
    margin-inline-start: 0;
    margin-block-start: auto;             /* sits on the column's foot, 5128 */
  }

  .cta__action {
    justify-content: flex-start;
    margin-block-start: 0;
    inset-block-start: calc(100% + 92px);    /* lead foot 5128, button 5220 */
  }

  /* The artboard does carry this rule at 375 — y5190, with the same split-plus
     on it — 30px above the button. It was switched off here. */
  .cta__rule { display: block; inset-block-start: 612px; }

  /* --- À propos: Approche band — the 375 board's own 29 under the rule,
     doubled like the wider boards' 55 → 110. */
  .separator--band { margin-block-end: 58px; }

  /* --- Arrow buttons -----------------------------------------------------
     Full width: a 60px icon then the label pill filling what is left. The
     collapse/expand travel is dropped — there is no hover on a touch screen,
     and a 275px pill that changes width would reflow the page. */

  /* The trailing icon stays in flow here, and the travel with it.

     It used to be `display: none`, which is what made the travel unusable at
     this width: with nothing taking the leading icon's place the button lost
     60px as it collapsed, and the label — `flex: 1 1 auto` — grew to fill the
     gap, so the pill visibly changed width mid-animation. Kept in flow, the two
     icons ease over the same curve in opposite directions, their widths sum to
     60 at every instant, and the label never moves. */
  .btn-arrow { width: 100%; }
  .btn-arrow__label { flex: 1 1 auto; width: auto; }

  /* The small button was the one case that already put its trailing icon back,
     to undo the `display: none` above. That rule is gone, so this no longer has
     anything to undo — and it was restoring it as `grid`, which quietly swapped
     the icon's own flex centring for grid's. */
  .btn-arrow--sm { width: auto; }
  .btn-arrow--sm .btn-arrow__label { flex: 0 0 auto; }

  /* --- Case cards --------------------------------------------------------
     Stacked: one 252-wide green panel with the photograph inside it, and the
     numeral column still running full height beside it. */

  /* `display: contents` dissolves the panel so its body and numeral column
     become items of the card's own grid. That is what lets the photograph sit
     between the copy and the foot of the green column while the numeral column
     still runs the full height beside all of it — the panel is a sibling of the
     media in the markup, so no nesting can express this. */
  .case-card {
    grid-template-columns: minmax(0, 1fr) 80px;
    grid-template-rows: auto auto;
    gap: 0;

    /* The desktop rule sets `start` so the sticky panel does not stretch to the
       photograph's height. Here the numeral column must run the full card. */
    align-items: stretch;

    /* DELIBERATE DIVERGENCE FROM THE ARTBOARD — do not "fix" this back.

       The 375 board draws this card the way every other board draws it: two
       abutting rectangles, 252 and 80 at x20 and x272, each r=[10,10,10,10],
       neither stroked. The dark band showing through where the two curves meet
       is the divider there, a notch at the head and foot of the seam.

       The site does not reproduce it at this width. One clipped slab, with the
       seam carried by the hairline on .case-card__number alone, is what we are
       keeping: the card is 640px tall at 375 against 427 at desktop, and on a
       seam that long two small bites out of the corners read as a gap in the
       card rather than as a join between two tiles. It was tried and it looked
       worse. The desktop and tablet widths keep the artboard's construction —
       see .case-card__body / .case-card__number in components.css — and the
       À propos rows keep it at every width, where the block is 293px and the
       notch still reads as a join.

       The fill has to live here rather than on .case-card__body because the
       green spans two grid rows at this width: the copy, then the photograph
       inset inside it. .case-card__panel is `display: contents` here, so no
       element wraps those two. */
    border-radius: var(--radius-card);
    overflow: hidden;
    background: var(--c-accent);
    color: var(--c-ink);
  }

  .case-card__panel {
    display: contents;
    position: static;                           /* nothing to pin against at this height */
  }

  .case-card--right .case-card__panel { order: 0; }

  /* Square: the card above carries the radius and clips, so the body's own
     corners would only cut into the middle of that shape. */
  .case-card__body {
    grid-column: 1;
    grid-row: 1;
    padding: 25px 20px 20px;
    border-radius: 0;
  }
  .case-card__title { max-width: none; }
  /* No floor needed here: .case-card__details below takes an explicit top
     margin at this width rather than auto, so the gap cannot collapse. */
  .case-card__stats { gap: 47px; margin-block-start: 52px; margin-block-end: 0; }

  /* At this width the artboard stops putting a pill at the end of its row and
     collects all three into a stack underneath — rows at 1155/1182/1209, then
     pills at 1245/1274/1303. That is not decoration: 212px of panel cannot hold
     a label, a value and a pill on one line, and leaving them in the row left
     long values ("Application mobile industrielle") wrapping under their own
     label with the label stranded on a line of its own.

     The pills are a column of their own in the markup, so the stack costs
     nothing here: the details block falls back to block flow and lays the rows
     out above the pills. What still needs saying is the rows grid below --
     `display: contents` dissolves each row so its label and value become items
     of it, which is what keeps the two columns aligned down the block. */
  .case-card__details {
    margin-block-start: 10px;                     /* Ligne 154 sits 13 under the caption baseline */
    padding-block-start: 16px;                    /* Ligne 154 at 147, row 1 at 163 */
  }

  .case-card__rows {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr);   /* label x40, value x96 */
  }

  .case-card__row { display: contents; }

  /* The row rule was the row's own border; with the row dissolved it has to be
     carried by the two cells that remain, which together span the same width. */
  .case-card__label,
  .case-card__value {
    display: flex;
    align-items: center;
    min-height: 28px;
    border-bottom: 1px solid var(--c-ink);
  }

  .case-card__label { flex: 0 0 auto; grid-column: 1; }
  /* Rows are dissolved into the grid above and each cell carries its own rule,
     so capping the value would cut its underline short. */
  .case-card__value { grid-column: 2; max-width: none; }

  .case-card__tags {
    gap: 5px;                                     /* pills step 29: 24 tall + 5 */
    margin-block-start: 24px;                     /* last rule 1221, first pill 1245 */
  }

  /* The gloss used to be switched off entirely here — there was no hover to
     open it with, so the pill was a bare acronym to everyone but a screen
     reader, which still gets it from the sr-only copy. It opens on a tap now
     (case-card.js), so the bubble comes back.

     It opens upward, as it does everywhere else: above a pill is the rows
     block, never the panel's edge. .case-card still clips at this width, so a
     very long gloss could be cut at the head of the card — the 200px cap above
     keeps the usual four or five lines well inside it. */

  /* Inside the green column now, inset 20 on three sides — x40 w212 against a
     252-wide panel in the design. */
  .case-card__media {
    grid-column: 1;
    grid-row: 2;
    margin: 0 20px 20px;
    aspect-ratio: 212 / 163;

    /* Same reset the panel above gets: the card is one column here and the two
       are stacked, so there is nothing to pin against — left alone the
       photograph would creep down its own row as the card scrolled past. */
    position: static;
  }

  /* Full height beside both rows. */
  .case-card__number {
    grid-column: 2;
    grid-row: 1 / -1;
    padding-block: 20px 20px;

    /* The other half of the divergence noted on .case-card above, and the one
       place on the site that draws a stroke the artboards do not.

       Squared off because the card is a single clipped slab at this width, so a
       rounded rail would cut a notch into the middle of it rather than meet a
       curve of its own — it keeps var(--radius-card) at every wider breakpoint.
       With no notch there is nothing left to divide the two greens, and
       #ade542 against #a4d93f is too small a step to carry the seam on its own,
       so the hairline stands in for it here only. #3a3e3d at 40%: the ink the
       rules and the body copy use, held back so it settles into the green
       rather than drawing as hard as the text.

       Inline start, not `border-left`: the numeral column is the second track
       of its grid at every width — the alternating layout swaps the panel and
       the photograph, never the two halves of the panel. */
    border-radius: 0;
    border-inline-start: 1px solid rgb(58 62 61 / 0.4);
  }

  /* Rules at 478 and 836 on the À propos board — see the tablet note. */
  .page-about .shell > .separator:not(.separator--band) {
    margin-block: 73px 31px;
  }

  .page-about .shell > .separator:not(.separator--band):first-child {
    margin-block-start: 34px;
  }

  .section--results { padding-block: 88px 76px; }
  /* Heading y802 over three 40px lines, first card y974. */
  .section--results .section__title { max-width: none; margin-block-end: 52px; }
  /* Anchor landing (pages.css): card 260 down, heading 88, header 69. */
  .section--results { scroll-margin-top: clamp(-11px, calc(40svh - 268px), 83px); }

  /* --- Process steps ----------------------------------------------------- */

  .step-card { min-height: 344px; padding: 26px 19px 19px; }
  .step-card__title { max-width: 272px; }
  .step-card__tags { margin-block-start: 44px; }
  /* Same 16 the tablet rule above explains — the 375 board has the pills ending
     at 3336 and the copy at 3352, and no rule between them either. */
  .step-card__desc { margin-block-start: 15px; }
  .step__foot { height: 78px; padding-inline: 29px; }

  /* 30 is what is left of the 150 the board leaves between the marquee at 4548
     and the closing heading at 4698 once .cta__inner's 120 is counted — which
     puts the band top every other offset in that band is measured from back on
     4578, where .cta__rule and .cta's min-height already assume it is. */
  .section--process { padding-block: 58px 30px; }
  /* Restated at this specificity so it outranks the tablet block's
     `.page-home .section--process` rather than inheriting its 0. */
  .page-home .section--process { padding-block-end: 30px; }
  /* Heading y2894 over five 40px lines, first card y3154. */
  .section--process .section__title { margin-block-end: 60px; }
  .section--process .marquee { margin-block-start: 60px; }
  .section--process .process-steps-wide + .marquee { margin-block-start: 90px; }
  .section__title--indent { max-width: none; }

  /* Cards at 3154, 3586 and 4018 over a 344 card and a 78 foot — a 10px step
     here, not the 16 the wider breakpoints keep. */
  .process-steps { gap: 10px; }

  /* --- Footer ------------------------------------------------------------
     Everything stacks to one column; the wordmark drops to 117px and sits
     between the menu and the legal lines, still right-aligned. */

  /* Same split as the tablet rule above, at this board's figures: home leaves
     160 between the button and the heading and the dark band takes 110 of it;
     À propos leaves 160 from the foot of its last step card with no band to
     share it. Other pages keep the 108 they were built with. */
  .site-footer__intro { padding-block: 108px 40px; }
  body:has(.page-home)  .site-footer__intro { padding-block-start: 50px; }
  body:has(.page-about) .site-footer__intro { padding-block-start: 160px; }
  .site-footer__heading,
  .site-footer__side { grid-column: 1 / -1; }
  .site-footer__heading { max-width: none; }
  /* 38 and not 54: the intro is a grid and the two blocks are in rows of their
     own here, so the 16px row gap is already under the heading. */
  .site-footer__side { margin-block-start: 38px; }   /* heading foot 5640, lead 5694 */

  .site-footer__main {
    padding-block: 37px 30px;
    margin-block-start: 120px;          /* marquee ends 6053, rule 6173 */
    row-gap: 53px;
  }

  .site-footer__address,
  .site-footer__nav,
  .site-footer__contact,
  .site-footer__legal,
  .site-footer__credit,
  .site-footer__brand { grid-column: 1 / -1; }

  .site-footer__address { grid-row: 1; }
  .site-footer__contact { grid-row: 2; }
  .site-footer__nav     { grid-row: 3; }
  /* Same fit as the tablet rule, against this breakpoint's 20px margins. No cap
     here: 117 would have held from 433px up and left the lockup stranded in the
     middle of a 727px box at 767. */
  /* Same trimmed box as the tablet rule above; 21 puts the baseline 120 under
     the menu's foot, which is the board's own gap. */
  /* Same correction as the tablet rule above, against this breakpoint's 20px
     margins: (vw - 40 - 4) / 2.998. The padding compensating the tracking is
     inherited from that rule and is not repeated here. */
  .site-footer__brand   { grid-row: 4; letter-spacing: -0.07em;
                          font-size: min(250px, calc(33.36vw - 14.7px));
                          line-height: 0.3; margin-block-start: 21px; }
  .site-footer__legal   { grid-row: 5; justify-content: flex-start; }

  /* The right-anchoring that keeps this on one line at 1440 has nothing left to
     do once it owns the full column, and it was setting the line ragged-left
     over two rows. The 375 board runs it from x20 across the whole width. */
  .site-footer__credit  { grid-row: 6; justify-self: start; text-align: left; }

  .site-footer__address,
  .site-footer__contact { font-size: 18px; line-height: 27px; }
  .site-footer__menu { font-size: 18px; line-height: 30px; }

  .site-footer__legal,
  .site-footer__credit { align-self: start; }

  /* --- About --------------------------------------------------------------
     Only here does the label stack above the body — the 768 board keeps them
     side by side. */

  /* The 375 board runs two display sizes on this page, and it is not an
     inconsistency: 30 for the page title and for Expertises, 40 for the two
     closing bands. Scoped to those two headings rather than to every
     .t-display, so the Approche title keeps the 40 it shares with the footer
     heading right under it — at 30 it read smaller than the band that follows
     it, which inverted the hierarchy.

     The footer heading is outside .page-about and was already untouched. */
  .page-about .about-hero__title,
  .page-about .section__title { font-size: 30px; line-height: 1; }

  .editorial {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
    gap: var(--s-4);
  }

  .editorial__label,
  .editorial__body,
  .editorial__aside { grid-column: 1 / -1; }

  /* x253 on a 375 board. */
  .separator:not(.separator--band):not(.separator--legal) { --plus-ratio: 0.696; }

  /* The 375 board is the one place the three rules disagree: the hero puts its
     plus at 277, both closing rules at 252. Two against one, so each keeps its
     own value rather than being averaged into a single wrong one. */
  .hero__rule { --plus-ratio: 0.767; }

  .cta__rule,
  .separator--band { --plus-ratio: 0.6925; }

  .about-hero { padding-block-start: 74px; }
  /* 332 x 190 on the 375 board. It had been set to 335/250, which is a much
     deeper crop than either the 375 or the 768 board draws. */
  /* 29, not 60: three 30px lines from y135 end on 225 and the picture opens at
     254. The 60 was the desktop figure left to ride down. */
  .about-hero__media { margin-block-start: 29px; aspect-ratio: 332 / 190; }
  .subvention__steps { grid-template-columns: minmax(0, 1fr); }

  /* The row closes the Expertises group — step feet end 2640, the row opens
     2649 — which is the same 10px step .row-cards keeps at this width. */
  .process-steps-wide { margin-block-start: 10px; }

  /* Where "Découvrez notre approche" lands — see the note in pages.css. The
     sentence that introduces the steps sits 341 above the first one here
     against 458 at desktop, and the header is 69 rather than 83, so the offset
     is its own measurement: 390 puts that line on y95, clear of the header and
     of an editor's admin bar, with the first step whole underneath. */
  .section--etapes { scroll-margin-top: 390px; }

  /* --- Politiques / 404 --------------------------------------------------- */

  /* Title 21,135 at 30/30 — box 140, less this width's 69px header row. */
  .page-legal { padding-block: 71px 80px; }
  .page-legal__title,
  .page-legal__body,
  .page-legal__aside { grid-column: 1 / -1; }
  .page-legal__aside { margin-block-start: var(--s-5); }

  /* The 375 board drops this title to 30/30 rather than letting it ride the
     display token down to 40 — it is the only page whose headline does not
     follow that scale. */
  .page-legal__title { font-size: 30px; line-height: 1; }

  /* x277 at 375 — the legal rule sides with the hero, not the closing bands. */
  .separator--legal { --plus-ratio: 0.7669; margin-block: 48px 40px; }

  .page-404 { padding-block: 160px 120px; }
  .page-404__numeral { font-size: 150px; }
  .page-404 .btn-arrow { margin-block-start: 60px; }

  /* --- Contact popup -----------------------------------------------------
     Same sheet as the tablet, with the two-up form collapsed to one column.
     Artboard: head bar y22, title y114 at 25/29, fields from y267 on a 73px
     pitch, preference row y559 (127 tall), message 332x183, send bar y921. */

  .popup__body { padding: 34px var(--page-margin) 40px; }

  /* One column, and a 13px gutter rather than the desktop 16: the board steps
     its fields 73 apart from 267, and each field is 60. */
  .form__grid { grid-template-columns: minmax(0, 1fr); row-gap: 13px; }

  textarea.form__input { min-height: 183px; }

  .popup__title { font-size: 25px; line-height: 29px; max-width: 249px; }

  /* The row stacks its legend above the two choices rather than pushing them to
     the right of it — 332px cannot hold both on one line. The explicit width is
     not redundant: this is a <fieldset>, whose anonymous content box keeps the
     shrink-to-fit sizing the flex row gave it, and the options collapsed to zero
     width at the right edge with the pills overflowing off-screen. */
  .form__toggle {
    display: block;
    height: auto;
    padding: 23px 20px 20px;
  }

  .form__toggle-options {
    width: 100%;
    margin: 16px 0 0;
    flex-wrap: wrap;
    justify-content: flex-start;
  }

  .form-success { min-height: 360px; }
  .form-success__title { font-size: 30px; line-height: 32px; }
  .form-success__text { font-size: 18px; }

  /* --- Consent banner ----------------------------------------------------
     No artboard covers this — it was added for Law 25 — and it had no narrow
     layout at all. The row stayed a row at 375: the copy was squeezed into a
     100px column fifteen lines deep, the banner grew to 457px, more than half
     the screen, and "Accepter" was pushed off the right edge. Stacked, with the
     two choices sharing the width. */

  .consent__inner {
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-3);
    padding-block: var(--s-3);
  }

  .consent__actions { margin-left: 0; }
  .consent__actions .btn { flex: 1 1 0; justify-content: center; }


  /* --- Case study detail -------------------------------------------------- */

  .case-hero__badge { width: 120px; height: 50px; padding: var(--s-1); }
  .page-case .separator { margin-block: 90px 32px; }
  .case-defi { margin-block-start: 90px; padding: 20px; }
  .case-defi__media { aspect-ratio: 4 / 3; }
  .section--solutions { padding-block: 80px 0; }
  .section--solutions .section__title { margin-block-end: 60px; }

  /* 375: body 252 and numeral 80 on a 293-tall row, inset 20, and the rows sit
     10 apart rather than 20. The 60px numeral column here was a guess made
     before the mobile board was read. */
  .row-cards > * + * { margin-top: 10px; }
  .row-card { grid-template-columns: minmax(0, 1fr) 80px; min-height: 293px; }
  .row-card__body { padding: 20px; }

  /* Cancels the 19 the tablet rule sets for this card: at 375 the board puts
     this row's text at x40, a plain 20 in from the page margin, and the
     tablet rule's higher specificity would otherwise carry 19 all the way
     down. */
  .process-steps-wide .row-card__body { padding-inline: 20px; }
  .row-card__text { margin-block-start: 18px; }
  .row-card__number { padding-block: 25px 20px; }
  .case-results__panel { min-height: calc(var(--sphere-ref) * 0.82); padding-block: 200px 32px; }
  .case-results__list { margin-block-start: 40px; }
  .case-results__index { flex: 0 0 26px; }
  .case-results__row { padding-block: 12px; }
  .case-results__row:first-child { padding-block-start: 0; }


  /* --- Expertise ---------------------------------------------------------- */

  .expertise-hero { padding-block-start: 74px; }   /* as .about-hero at this width */
  .expertise-hero__lead-row { margin-block-start: 29px; }
  .expertise-hero__lead { grid-column: 1 / -1; }

  .page-expertise .separator { margin-block: 90px 32px; }

  .expertise-intro { padding-block: 60px 0; }

  .section--volets { padding-block: 80px 0; }
  .section--volets .section__title { margin-block-end: 60px; }

  .expertise-encart { padding-block: 90px 0; }

  /* 200px of head is the Résultats panel's, where the short list sits low
     under the sphere. This panel carries paragraphs and a button, so it opens
     higher — enough sphere to read as one, not half a screen of it. */
  .expertise-preuve__panel { padding-block: 120px 32px; }
  .expertise-preuve__list { gap: var(--s-5); }
  .expertise-preuve__item { padding-inline-start: 34px; }

  .expertise-more__mark { width: 40px; height: 40px; }
}


/* --------------------------------------------------------------------------
   Coarse pointers

   Hover states that reveal content are unreachable on a touch screen, and the
   marquee pauses on hover — which on touch means it never pauses at all. Both
   are handled where they matter rather than by breakpoint, since a touch laptop
   is wide and still cannot hover.

   The case card photographs used to be un-greyed here, on the reasoning that a
   reveal nobody can reach should show its revealed state. That is not what the
   cards want: grey is the resting state, the colour is the reward for hovering,
   and a touch device simply does not get the reward. Un-greying them made the
   cards read as a different design at the same breakpoint the rest of the page
   kept. They stay grey everywhere now — the base rule in components.css is all
   it takes, and the hover rule beside it cannot fire here anyway.
   -------------------------------------------------------------------------- */

@media (hover: none) {

  /* On a hover device the travel has all the time it wants — the pointer rests
     on the button. A tap does not: the press, the lift and the page swap are all
     over inside a few hundred milliseconds, and half an animation reads as a
     glitch rather than as motion. 340ms is what fits in that window, and it is
     the figure animations.js holds the navigation against. Keep the two in step
     if either changes. */
  .btn-arrow__icon { transition-duration: 0.34s; }
}


/* --- Small desktop: the process card title -------------------------------
   "Développement" sets 305px at 46px and cannot break, so below about 1194 it
   runs out of its card.

   The card is one of three in a fixed row, so its text column is
   (content - 32) / 3 - 60, which is 249 at 1026 and only reaches 305 — the
   width of that one word — at 1194. Above that nothing here applies.

   Fitted rather than hyphenated. `hyphens: auto` works (the document is fr-CA)
   but it spends a line: "Dévelop-pement sur mesure" is three, and the row
   reserves two — see the note on .process-steps .step-card__title, where a card
   that takes a third line drops its own pills below its neighbours'.

   The coefficient is the word's own aspect: it needs 6.63px of width per px of
   font-size, so the largest size that fits is (vw/3 - 93) / 6.63, which is
   5.03vw - 14. The 93 is the page margins, the two gutters and the card padding
   over three columns, plus the 15px scrollbar that vw counts and the content box
   does not. min() holds it at the design's 46 where the fit allows it.

   The line height is a unitless ratio, so it follows the size down on its own,
   and the two-line floor is set from --t-h2-lh, which does not move — the slot
   stays 92 and simply holds a little more air. */

@media (min-width: 1025px) and (max-width: 1194px) {
  .step-card__title { font-size: min(var(--t-h2), calc(5.03vw - 14px)); }
}


/* --- Small desktop: the footer heading ------------------------------------
   The heading takes 9 of 12 columns and is capped at 819. Those two agree only
   at the design width: at 1440 the track is 1037 and the cap stops the text 223
   short of the paragraph's column, but the track shrinks with the page and the
   cap does not, so from about 1164 down the cap stops biting and the heading
   runs the full track — 715 at 1026, ending 16px from the paragraph, which is
   the grid's gutter and nothing more.

   The inset is expressed as the distance from the width where the two meet, so
   it opens as the page narrows and is exactly 0 at 1164 rather than switching on
   with a step: 139px at 1025, which leaves the text about 155 clear of the
   column, and nothing at all at the top of the range. 100vw counts the scrollbar
   and so does the 1164, so the two cancel.

   Padding rather than max-width because the heading is a grid item: a percentage
   max-width would resolve against its own 9-column track, not against the
   content box the 819 was measured from, and would need a query container to
   mean what it says. */

@media (min-width: 1025px) and (max-width: 1164px) {
  .site-footer__heading { padding-inline-end: calc(1164px - 100vw); }
}
