/* Méridien · slide grid v1 — the Figma layout guide style «grid v1» (Branding → section Grid, 819:71).
   1920 × 1080 · 24 columns × 16 rows · gutter 16 on both axes · margin 56 on all sides.
   Column 60 (pitch 76) · row 45.5 (pitch 61.5) · field 1808 × 968. Guide: references/layout-grid.md

   <section class="slide">
     <div class="g24">
       <p class="lbl" style="--gc:1 / span 8; --gr:1">Mobility</p>
       <h2 class="trim" style="--gc:1 / span 18; --gr:2 / span 5">Where people move</h2>
       <img class="bleed-t bleed-r bleed-b" style="--gc:13 / span 12; --gr:1 / span 16" src="…">
     </div>
   </section>

   Guide notation "c1–18 · r2–6" (columns 1…18, rows 2…6, inclusive)
   → --gc: 1 / span 18; --gr: 2 / span 5   (start / span = b − a + 1). */

:root { --g-margin: 56px; --g-gap: 16px; --g-col: 60px; --g-row: 45.5px; }

.g24 {
  position: absolute; inset: 0; box-sizing: border-box; padding: var(--g-margin);
  display: grid; gap: var(--g-gap);
  grid-template-columns: repeat(24, var(--g-col));
  grid-template-rows: repeat(16, var(--g-row));
}
.g24 > * { grid-column: var(--gc, auto); grid-row: var(--gr, auto); min-width: 0; min-height: 0; margin: 0; box-sizing: border-box; }

/* Anchoring. A block sits on the top line of its area by default.
   .to-bottom — the block hangs from the area's bottom line (with .trim: the baseline is on that line).
   .to-right  — right edge on the area's right line (page number, right-hand captions). */
.g24 > .to-bottom { align-self: end; }
.g24 > .to-right { justify-self: end; text-align: right; }

/* Display roles: the box runs from cap height to baseline, so caps and baseline land exactly on row lines.
   Chrome 133+, Safari 18.2+; older engines simply ignore it (the box is then ~0.13em taller on top). */
.trim { text-box: trim-both cap alphabetic; }

/* Bleed: the block runs through the margin to the slide edge. Any edge is either a grid line or the slide edge. */
.g24 > .bleed-l { margin-left: calc(-1 * var(--g-margin)); }
.g24 > .bleed-r { margin-right: calc(-1 * var(--g-margin)); }
.g24 > .bleed-t { margin-top: calc(-1 * var(--g-margin)); }
.g24 > .bleed-b { margin-bottom: calc(-1 * var(--g-margin)); }
.g24 > .bleed { margin: calc(-1 * var(--g-margin)); }
/* Replaced elements (img, video, canvas) don't stretch in a grid area by default: the negative margins above only
   shifted them, leaving a 56 px strip at the far edges. Stretch them explicitly and crop with object-fit. */
.g24 > :is(.bleed, .bleed-l, .bleed-r, .bleed-t, .bleed-b) { justify-self: stretch; align-self: stretch; }
.g24 > :is(img, video, canvas):is(.bleed, .bleed-l, .bleed-r, .bleed-t, .bleed-b) { width: auto; height: auto; object-fit: cover; }

/* Media fill their area and are cropped by it. */
.g24 > img, .g24 > video, .g24 .fill { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Overlay for checking: add class "show-grid" to <html>, e.g.
   if (new URLSearchParams(location.search).has('grid')) document.documentElement.classList.add('show-grid'); */
.show-grid .g24::after {
  content: ""; position: absolute; inset: var(--g-margin); pointer-events: none; z-index: 50;
  background:
    repeating-linear-gradient(90deg, rgba(255, 0, 0, .1) 0 60px, transparent 60px 76px),
    repeating-linear-gradient(180deg, rgba(255, 0, 0, .1) 0 45.5px, transparent 45.5px 61.5px);
}
