/*
Theme Name: Alex Tome — Cahier
Theme URI: https://alextome.com
Template: alextome
Author: 56k Studio
Author URI: https://56k.studio
Description: Second art direction — a Swiss contact sheet. Near-white ground, one grotesque, type kept deliberately small: the hierarchy is carried by position and empty space rather than by size, and the photographs are the only thing on the page allowed to be big. Satoshi is self-hosted, so no request ever leaves for a font CDN.
Version: 0.2.0
Requires at least: 6.5
Requires PHP: 8.1
License: Proprietary
Text Domain: alextome
*/

/* ═══════════════════════════════════════════════════════════
   TOKENS
   Nothing on this page competes with a photograph: the ground
   is near-white, the ink is small, and the only large object
   on screen is ever an image.
   ═══════════════════════════════════════════════════════════ */
:root {
  /* A touch lighter than the first pass: still warm, still not #fff, but the
     paper now reads as paper rather than as grey card. */
  --paper: #f7f6f3;
  --paper-2: #eeece7;
  --ink: #15140f;
  --ink-soft: #6d6a62;
  --ink-faint: #9c988f;
  --line: rgba(21, 20, 15, 0.15);
  --line-strong: rgba(21, 20, 15, 0.42);

  /* ONE family, everywhere. No serif, no second voice. */
  --sans: "Satoshi", "Helvetica Neue", Arial, sans-serif;
  --display: var(--sans);
  --body: var(--sans);
  --mono: var(--sans);

  /* Titles are set tight but at TEXT weight — the reference sets a name
     large without ever shouting. In-page labels stay sentence case.
     NAVIGATION is the exception since 18/08/2026: it follows the front door
     into small tracked capitals, so the site speaks with one voice from the
     first screen onwards. */
  --track-tight: -0.03em;
  --track-label: 0;

  /* THE WORDMARK. The name is not a piece of text, it is the signature —
     so it has ONE shape, set once here and never restated. Value taken from
     the front door, which the client validated: nothing else gets to decide
     what the name looks like. Only the COLOUR follows the ground. */
  --track-wordmark: 0.22em;
  --size-wordmark: 0.6875rem;   /* the name at small rank: masthead + colophon */

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --slow: 1.1s;

  --gutter: clamp(1.25rem, 5vw, 5rem);
  /* THE MEASURE. Content is capped here so the page reads the same at 1440,
     1920 or 2560 — the margins grow, the design does not. Declared as a token
     because the masthead, the colophon and the front door all have to know it
     to keep their text on the same line as the sections. */
  --shell-max: 90rem;
  /* DEUX GOUTTIERES, PARCE QUE CE SONT DEUX OBJETS DIFFERENTS.
     La mosaique d'un reportage est dense a dessein (reference Samm Blake,
     validee par Alex le 20/08) : les photos se serrent, rien ne s'intercale
     entre elles. La grille du portfolio porte une legende sous chaque
     vignette — il lui faut de l'air, et surtout le MEME air dans les deux
     sens. Jusqu'au 20/08 elles partageaient un seul token : les colonnes se
     touchaient (12,8 px mesures) pendant que les lignes s'ecartaient
     (44,8 px), un rapport de 3,5 qui cassait la lecture. */
  --mosaic-gap: clamp(0.5rem, 1vw, 1rem);   /* la mosaique d'un reportage */
  --plate-gap: clamp(1.25rem, 2.2vw, 2rem); /* la grille du portfolio */
  --story-gap: clamp(1.25rem, 2.2vw, 2rem); /* entre deux photos d'un reportage */
  --story-step: clamp(1rem, 2.5vw, 2.25rem); /* le pas des decalages verticaux */
  /* L'unite de ligne de la trame du portfolio. 0,6957 colonne : c'est ce
     rapport qui donne aux zones leur ratio 3:2, celui des photos d'Alex.
     En vw, donc la composition garde ses proportions a toute largeur. */
  --plate-row: 2.777vw;
  --measure: 34ch;          /* narrow columns, as in the references */
  --micro: 0.8125rem;       /* the working text size of the whole site */
}

/* ═══════════════════════════════════════════════════════════
   BASE
   ═══════════════════════════════════════════════════════════ */
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  font-size: var(--micro);
  line-height: 1.5;
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
}

body::after { display: none; }   /* no grain: this ground is paper, not a screen */

/* The composition is tuned at 1440. Past that the parent lets the page run
   edge to edge, so on a wide display the hairlines stretch across a metre of
   nothing while the columns stay put. Capping the measure keeps the same
   page at 1440, 1920 or 2560 — the margins grow, the design does not. */
/* `:not()` matters here: `.shell--narrow` carries the same specificity as
   `.shell`, so a plain `.shell { max-width }` declared later silently won
   and stretched the contact form's 46rem column across the whole page. */
.shell:not(.shell--narrow) { max-width: var(--shell-max); margin-inline: auto; }

/* ── ONE MEASURE, HEADER TO FOOTER ──────────────────────────
   The cap above applies to the CONTENT only. The masthead and the colophon
   are full-bleed and padded with the plain gutter, so the two agreed at
   exactly 1440 and nowhere else: at 1920 the content sat 312px from the edge
   while the name in the bar sat at 80 — a 232px step between the header and
   the section right under it (Mendar, 19/08/2026).

   Rather than capping the bars themselves — which would pull the colophon's
   hairline and the bar's background away from the edges — the padding grows
   to match the content's own margin once the page is wider than the measure.
   Below that it collapses back to the gutter. Bars stay full-bleed, TEXT
   lines up, at 1440, 1920 or 2560. */
.masthead,
.colophon {
  padding-inline: max(var(--gutter), calc((100% - var(--shell-max)) / 2 + var(--gutter)));
}

/* The parent clears the fixed masthead with a flat 3.5rem. That was measured
   against a desktop bar of 69px; on a phone the burger makes it 89px and the
   first line of the page slides underneath it. Cleared with room to spare at
   both ends rather than tuned to one viewport. */
/* Same selector as the parent's, not a shorter one: `:not(.has-portal)`
   counts as a class, so `body main` loses on specificity and the rule is
   silently ignored. Matching it wins on source order instead. */
body:not(.has-portal) main { padding-top: 6.5rem; }
@media (min-width: 46rem) { body:not(.has-portal) main { padding-top: 5.5rem; } }

::selection { background: var(--ink); color: var(--paper); }

a { color: inherit; text-decoration: none; }

:focus-visible { outline: 1px solid var(--ink); outline-offset: 3px; }

/* ═══════════════════════════════════════════════════════════
   TYPE
   ═══════════════════════════════════════════════════════════ */
.section__title,
.story__couple,
.about__title,
.year-block__mark {
  font-family: var(--sans);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  line-height: 1;
  text-transform: none;
}

/* ── WORDMARK ────────────────────────────────────────────────
   The name used to inherit from the rule above, alongside section titles
   and couple names — so it was set as a TITLE, and each place then argued
   with it: capitals and +0.22em on the front door, capitals and +0.16em in
   the masthead, lower case and NEGATIVE tracking in the colophon. Three
   drawings of one signature (Mendar, 19/08/2026).

   From here the name is drawn ONCE. Every place that prints it points at
   this block; nothing downstream restates family, weight, case or tracking.
   Size follows rank (front door large, masthead and colophon small) and
   colour follows the ground — those two are allowed to vary, nothing else. */
.wordmark,
.masthead__name,
.colophon__name,
.portal__name,
.portal--ecrin .ecrin-name {
  font-family: var(--sans);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: var(--track-wordmark);
  line-height: 1;
}

.label {
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
}

.prose { max-width: var(--measure); font-size: var(--micro); }
.prose p + p { margin-top: 1em; }

/* ═══════════════════════════════════════════════════════════
   MASTHEAD
   A line of small words across the top, evenly spread. No bar,
   no frosted panel, no border.
   ═══════════════════════════════════════════════════════════ */
.masthead {
  background: none;
  border-bottom-color: transparent !important;
  padding-block: 1.5rem;
}
/* A flat block of paper, not a fade. A gradient that dissolves into the
   page is the same crutch as a drop shadow — and there is nothing to
   dissolve into here, since the header never overlaps a photograph. */
.masthead::before {
  display: block;
  inset: 0;
  background: var(--paper);
  backdrop-filter: none;
}

/* ── ONE navigation, everywhere ────────────────────────────
   The front door sets the register: small capitals, widely tracked. Until
   18/08/2026 three menus coexisted on four pages — the hero's capitals at
   11px, the masthead's sentence case at 13px in grey with NEGATIVE tracking,
   and a third treatment at 20px inside the phone menu.

   The hero wins the arbitration (Mendar): it is the first thing anyone sees,
   and it is what the references do. Only the COLOUR follows the ground —
   paper over a photograph, ink on paper. The shape never changes. */
.masthead__nav a {
  font-family: var(--sans);
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* The name sat inside the rule above and was drawn exactly like a menu item.
   It is not one: the links are where you go, the name is who you are. It keeps
   the rank (same size as the menu) and takes the wordmark's own tracking. */
.masthead__name { font-size: var(--size-wordmark); color: var(--ink); }

.masthead__items { gap: 1.75rem; }

.masthead__nav a {
  color: var(--ink-soft);
  transition: color 0.35s var(--ease);
}
.masthead__nav a:hover,
.masthead__nav .current-menu-item > a { color: var(--ink); }
.masthead__nav a::after { background: var(--ink); }

.nav-toggle span { background: var(--ink); }

@media (max-width: 46rem) {
  .masthead__nav { background: var(--paper); }
  /* The panel menu keeps the same capitals — enlarged, because a tap target
     of 11px is one a thumb misses, not a design decision. The padding does
     the same job vertically: measured at 27px tall, the link was smaller than
     the finger aiming at it. The gap shrinks by as much as the padding grows,
     so the menu looks unchanged and simply becomes easier to hit. */
  /* inline-block, not inline: on an inline link vertical padding inflates the
     box without pushing the line, so the three tap zones ended up OVERLAPPING
     (34px tall for 29px between centres) — the finger aiming at Folio could
     land on Meet Alex. inline-block keeps the underline the width of the word
     while making the padding count in the flow. */
  .masthead__nav a { font-size: 0.875rem; letter-spacing: 0.18em; display: inline-block; padding-block: 0.55rem; }
  .masthead__items { gap: 0.5rem; }
}

.skip-link { background: var(--ink); color: var(--paper); }

/* ═══════════════════════════════════════════════════════════
   NO SHADOWS, NO VEILS, NO GRAIN
   The parent theme lays type over the photograph and then fights
   for legibility with drop shadows, a darkening veil and a grain
   overlay. That is the look of a 2015 template. Here the type
   never sits on an image in the first place — it sits on paper,
   beside it — so none of those crutches are needed.
   ═══════════════════════════════════════════════════════════ */
.portal__veil,
.grain { display: none !important; }

.portal__name,
.portal__tagline,
.portal__enter,
.story__couple,
.story__facts span { text-shadow: none !important; }

/* ═══════════════════════════════════════════════════════════
   PORTAL — a photograph, then the name underneath it
   ═══════════════════════════════════════════════════════════ */
.portal {
  height: auto;
  min-height: 0;
  background: var(--paper);
  overflow: visible;
}

.portal__media,
.portal__media img { position: static; }

.portal__media img {
  width: 100%;
  height: min(72svh, 44rem);
  object-fit: cover;
  display: block;
  /* No slow zoom either: a photograph that creeps is a photograph
     nobody trusts to hold the frame on its own. */
  animation: none;
  transform: none;
}

/* The parent centres this block in a grid; the references set the name flush
   left, at the top of the page. `justify-items` has to go with the display
   change, or the grid keeps shrinking the children to their content width. */
.portal__inner {
  position: static;
  height: auto;
  display: block;
  justify-items: start;
  place-items: start;
  padding: 1.1rem var(--gutter) clamp(3rem, 8vw, 7rem);
  color: var(--ink);
  text-align: left;
}
.portal__inner > * { width: 100%; margin-inline: 0; }

.portal__name {
  font-size: clamp(1.5rem, 3.2vw, 2.5rem);
  color: var(--ink);
  opacity: 1;
  animation: none;
}

.portal__tagline,
.portal__enter {
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  color: var(--ink-soft);
  margin-top: 0.3rem;
  opacity: 1;
  animation: none;
}

/* The scroll cue was a line fading into nothing, pulsing on a loop. With the
   name now printed under the photograph there is nothing left to hint at,
   and a blinking arrow is the most dated gesture on the web. */
.portal__enter .bar { display: none; }
/* The parent pins this to the bottom of the full-screen portal. That anchor
   is gone now the photograph no longer fills the viewport, and an absolute
   child would escape the gutter and stick to the page edge. */
.portal__enter {
  position: static;
  justify-content: flex-start;
  align-items: flex-start;
  text-align: left;
  margin-top: 1.75rem;
  transform: none;
}

/* Front-page thumbnails: the caption is printed UNDER the photograph and
   always visible, instead of being revealed on hover from behind a black
   wash. Nothing is hidden and nothing is overlaid. */
.tile { background: var(--paper-2); }
.tile__meta {
  position: static;
  inset: auto;
  background: none;
  color: var(--ink);
  padding: 0.5rem 0 0;
  opacity: 1;
  transform: none;
  display: block;
}
.tile__couple {
  display: block;
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}
.tile__place {
  display: block;
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
}
.tile img { transition: opacity 0.5s var(--ease); }
.tile:hover img { opacity: 0.82; }

/* ═══════════════════════════════════════════════════════════
   SECTION HEADS
   A hairline, a small label, and a name set large but quiet.
   ═══════════════════════════════════════════════════════════ */
.section { padding-block: clamp(2.5rem, 6vw, 5rem); }

.section__head {
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.85rem;
  align-items: baseline;
}

.section__title {
  font-size: clamp(2rem, 5.5vw, 4rem);
  font-weight: 500;
}

/* ═══════════════════════════════════════════════════════════
   HOME — label left, content right, hairlines between
   The structure of the second reference: a rule and a line of
   facts, the name flush left, then every block introduced by a
   small label in its own column.
   ═══════════════════════════════════════════════════════════ */
.meta {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 0.8rem;
  color: var(--ink-soft);
}

/* The hero: words on the left, a photograph standing on the right. The two
   are aligned on their baseline so the name sits at the foot of the picture
   rather than floating beside its middle. */
.hero {
  display: grid;
  grid-template-columns: 1fr minmax(16rem, 34%);
  gap: clamp(1.5rem, 4vw, 4rem);
  /* Top-aligned, as in the reference. Hanging the name off the foot of the
     photograph left a quarter of the screen empty above it, which reads as
     an accident rather than as space given on purpose. */
  align-items: start;
  padding: clamp(1.5rem, 4vw, 3rem) 0 clamp(3rem, 7vw, 6rem);
}

.lede {
  font-family: var(--sans);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  line-height: 0.98;
  font-size: clamp(2.25rem, 7vw, 5.5rem);
  margin: 0;
}

/* Wide enough to fall on two lines, not to crumble into four short ones
   beside a title of this size. */
.hero__line {
  max-width: 38ch;
  margin-top: clamp(1rem, 2vw, 1.75rem);
  color: var(--ink-soft);
}

.hero__frame { margin: 0; background: var(--paper-2); }
.hero__frame img {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 46rem) {
  .hero { grid-template-columns: 1fr; align-items: start; gap: 1.75rem; }
}

/* The portrait belongs to the About block, not to the top of the page: on
   its own up there it read as one more project plate. */
.row__body--about {
  display: grid;
  grid-template-columns: minmax(7rem, 12rem) 1fr;
  gap: clamp(1.25rem, 3vw, 3rem);
  align-items: start;
}
.row__cols { columns: 2; column-gap: clamp(1.5rem, 3vw, 3rem); max-width: 40rem; }
.row__cols p { break-inside: avoid; margin-top: 0; }
.row__cols p + p { margin-top: 0.9em; }

.portrait { margin: 0; background: var(--paper-2); }
.portrait img { display: block; width: 100%; height: auto; }

.row--last { border-bottom: 0; }
.row__more { margin-top: 1.25rem; }

@media (max-width: 46rem) {
  .row__body--about { grid-template-columns: 1fr; }
  .row__cols { columns: 1; }
  .portrait { width: clamp(8rem, 44vw, 13rem); }
}

/* Wherever the name is already set large in the hero, the bar does not
   repeat it. It stays on every other page, where nothing collides. */
body.home .masthead__name,
body.page-template-page-about .masthead__name { visibility: hidden; }

.row {
  display: grid;
  grid-template-columns: minmax(6rem, 11rem) 1fr;
  gap: 0.75rem clamp(1.5rem, 4vw, 4rem);
  border-top: 1px solid var(--line);
  padding: 0.9rem 0 clamp(2.25rem, 6vw, 5rem);
  align-items: start;
}
.row__label { color: var(--ink-soft); }
.row__body p + p { margin-top: 0.9em; }

.row__body--cols {
  columns: 2;
  column-gap: clamp(1.5rem, 3vw, 3rem);
  max-width: 42rem;
}
.row__body--cols p { break-inside: avoid; margin-top: 0; }
.row__body--cols p + p { margin-top: 0.9em; }

.row__body--split {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(1rem, 3vw, 3rem);
  align-items: start;
}

/* L'ancre du « Enter » : une cible de defilement, rien de visible. */
.anchor { display: block; height: 0; scroll-margin-top: 6rem; }

.headline {
  font-family: var(--sans);
  font-weight: 500;
  letter-spacing: var(--track-tight);
  line-height: 1.03;
  font-size: clamp(1.625rem, 4vw, 3rem);
}
.headline { max-width: 16ch; }

.underlined { text-decoration: underline; text-underline-offset: 0.22em; text-decoration-thickness: 1px; }
.underlined:hover { text-decoration-color: var(--ink-faint); }
.dim { color: var(--ink-faint); }

.row--end { border-top: 1px solid var(--line); display: block; padding-bottom: 0; }

/* Below the fold of a laptop the two columns of the label/content pair are
   worth keeping; below a tablet they stack, exactly as the reference's own
   mobile screen does — label above, content under it, type unchanged. */
@media (max-width: 46rem) {
  .row,
  .row__body--split { grid-template-columns: 1fr; }
  .row__body--cols { columns: 1; }
  .meta { flex-wrap: wrap; gap: 0.2rem 1rem; }
  .portrait { margin-left: 0; width: clamp(8rem, 44vw, 13rem); }
}

/* ═══════════════════════════════════════════════════════════
   THE FOLIO AS A CONTACT SHEET
   Prints of different sizes laid out on a light table: each one
   takes its own width and its own place across the page, and the
   caption sits small underneath. The empty space between them is
   the composition, not a gap left over.
   ═══════════════════════════════════════════════════════════ */
/* LA BARRE DES ANNEES SUIT LA LECTURE — 07/09.
   Le folio fait 45 ecrans : la barre etait posee a 263 px du haut et
   disparaissait au premier defilement. Elle etait donc la seule navigation de
   la page, et elle n'existait que sur le premier ecran.

   `top` se cale sous l'en-tete, qui est FIXE : 69 px de barre au bureau,
   89 px sur telephone ou le menu deplie la rend plus haute. Le z-index passe
   devant les plaques (elles n'en portent pas) mais reste sous l'en-tete (90).
   Le fond opaque est indispensable : sans lui les photos defilent au travers. */
.years {
  gap: 0.9rem 1.75rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1rem;

  position: sticky;
  top: 88px;
  z-index: 60;
  background: var(--paper);
  /* Le fond deborde jusqu'aux bords de l'ecran, sinon les photos passent dans
     la marge laissee libre par la coque. */
  margin-inline: calc(50% - 50vw);
  padding-inline: max(1.75vw, calc((100vw - 1680px) / 2));
  padding-top: 0.7rem;
}
@media (min-width: 46rem) { .years { top: 68px; } }
.years a {
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
  transition: color 0.35s var(--ease);
}
.years a:hover { color: var(--ink); }

.chapter {
  display: block;
  padding-block: clamp(2rem, 5vw, 4rem) 0;
  border: 0;
}

.chapter__rail {
  position: static;
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  padding-bottom: clamp(1.5rem, 4vw, 3rem);
}

.chapter__year {
  font-family: var(--sans);
  font-weight: 500;
  font-size: var(--micro);
  letter-spacing: 0;
  line-height: 1;
  color: var(--ink);
}

.chapter__count {
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
}

/* ── LES PROJETS ────────────────────────────────────────────
   Une grille reguliere : toutes les vignettes ont la meme largeur.
   Le jeu de dimensions variables (38% / 22% / 31% / 26% / 44% / 20%,
   avec decalages) a ete retire a la demande d'Alex le 20/08 — le
   contraste entre une grande image et un petit format horizontal
   genait la lecture. */
/* ── LES DEUX COMPOSITIONS — 31/08 ───────────────────────────────────────
   Il n'y en a pas une, il y en a DEUX, et elles n'obeissent pas a la meme
   regle. La passe precedente les avait confondues, et donnait le meme dessin
   aux deux endroits.

     A · LA GALERIE (accueil et folio) — une SEQUENCE d'images SEULES. Jamais
         deux cote a cote. Un cycle a trois temps — centree, collee a droite,
         collee a gauche — qui se deforme apres deux tours.

     B · LE REPORTAGE — des PALIERS. Une grande et une petite dans la meme
         zone, en opposition diagonale, le cote s'inversant a chaque paire ;
         un solo moyen centre respire tous les deux ou trois paliers.

   LA TRAME COMMUNE. Les deux releves tombent sur la meme grille : sur 1440
   avec 25 px de marge et 25 px de gouttiere, 24 demi-colonnes (pas de 58,95)
   expliquent toutes les valeurs — 329/447/683 valent 6/8/12 demi-colonnes, et
   les bords 25/202/379/497/733/909/1086 valent 0/3/6/8/12/15/18.

   TOUT EN POURCENTAGE, JAMAIS EN PIXELS. Un `margin-top` en % se calcule sur
   la LARGEUR du parent : le rythme vertical grandit donc avec le rail et tient
   a n'importe quelle taille d'ecran sans une seule requete media. */

/* Le rail, commun aux deux : 1390 px sur 1440. Il sort de la coque du theme —
   centre dans `.shell`, il demarrait a x=72 et debordait de 22 px a droite. */
.sequence,
.tiers {
  width: auto;
  margin-inline: calc(50% - 50vw);
  padding-inline: max(1.75vw, calc((100vw - 1680px) / 2));
  margin-block-start: var(--plate-gap);
}

/* ── A · LA SEQUENCE ──────────────────────────────────────────────────────
   Pas de grille ici, et c'est voulu : une grille alignerait, or le propre de
   cette suite est que chaque image se pose ou elle veut. Un simple flux, ou
   chacune porte sa largeur, son bord gauche et son ecart au precedent.

   L'ECART PEUT ETRE NEGATIF — c'est la que se joue la liberte du dessin. Trois
   fois dans le cycle, une image remonte SUR la precedente (−190, −222, −242 px
   au releve). Ca ne se produit qu'entre deux images de cotes opposes : elles se
   chevauchent verticalement sans jamais se croiser. */
.sequence { display: block; }

.plate {
  display: flex;
  flex-direction: column;
  width: var(--width);
  margin: 0;
  margin-inline-start: var(--left, 0);
  margin-block-start: var(--gap, 0);
  padding: 0;
  min-width: 0;
}

/* LA POSE AU PREMIER NIVEAU LIBRE — 07/09.
   Le motif enchainait les plaques a la queue leu leu, meme quand deux d'entre
   elles occupaient des cotes opposes du rail et pouvaient cohabiter : a partir
   du 24e reportage, le folio passait a 823 px par fiche, une photo par ecran.

   `--pack` est calcule en PHP, hauteur des fichiers comprise, et vaut la meme
   chose que `--gap` : un ecart de flux en % du rail. Rien d'autre ne bouge —
   ni la largeur, ni le bord, ni le cadrage.

   AU-DESSUS DE 736 px SEULEMENT. En dessous, la reduction mobile ramene tout a
   une colonne (58/74/92 % de large, bords alternes) : il n'y a plus de cote
   oppose, donc plus rien a resserrer — mesure du 07/09, la pose y rallongeait
   meme la page de 1 %. `--gap` y garde la main. La borne est a 46.01rem pour
   ne pas se superposer a la requete mobile, qui va jusqu'a 46rem incluses. */
@media (min-width: 46.01rem) {
  .sequence .plate { margin-block-start: var(--pack, var(--gap, 0)); }
}

/* ── B · LES PALIERS ──────────────────────────────────────────────────────
   Ici une grille, parce que deux images doivent tenir cote a cote a des places
   precises. La trame de 24 demi-colonnes est celle du releve ; la gouttiere de
   1,8 % rend exactement les 25 px mesures a 1440. */
.tier {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  gap: 1.8%;
  align-items: start;
  margin-block-start: var(--lead, 0);
}

.shot {
  grid-column: calc(var(--start) + 1) / span var(--span);
  /* TOUTES SUR LA MEME LIGNE. Sans cette ligne explicite, la grille place les
     items « en avancant » : quand la petite d'une paire commence AVANT la fin
     de la grande qui la precede dans le code (petite a gauche, grande a
     droite), le curseur refuse de revenir en arriere et la renvoie a la ligne
     suivante. Mesure du 31/08 : la paire tombait a 1145 px d'ecart au lieu de
     236, la diagonale devenait un empilement. */
  grid-row: 1;
  margin: 0;
  /* Le decalage de la petite vers le bas : ce qui met la paire en diagonale
     plutot que de la ranger en ligne. */
  margin-block-start: var(--shift, 0);
  padding: 0;
  min-width: 0;
}

.plate__frame,
.shot {
  aspect-ratio: var(--ratio, 3 / 4);
}

/* ── LA REDUCTION MOBILE ─────────────────────────────────────────────────
   A 390 px, ni l'un ni l'autre systeme ne se transpose. Trois largeurs de la
   trame y deviendraient trois timbres, une paire cote a cote deux vignettes
   illisibles, et les chevauchements de la sequence — qui ne fonctionnent que
   parce que les images sont de cotes opposes — deviennent de vraies collisions
   des que chaque image occupe plus de la moitie de la largeur. Mesure du
   31/08 : deux collisions reelles sur l'accueil et le folio.

   ON GARDE CE QUI FAIT CHAQUE SYSTEME, pas ses valeurs. La sequence conserve
   son alternance de largeurs et de bords, mais ses ecarts redeviennent tous
   positifs. Les paliers se deplient : la paire passe l'une sous l'autre en
   gardant son opposition — la grande d'un cote, la petite de l'autre. */
@media (max-width: 46rem) {
  .sequence,
  .tiers { padding-inline: 5vw; }

  /* A · trois largeurs remontees (une petite a 23 % serait un timbre), et un
     ecart TOUJOURS positif : `max()` neutralise les valeurs negatives du
     releve sans avoir a les retirer du motif. */
  .plate {
    margin-inline-start: 0;
    margin-block-start: max(2.75rem, calc(var(--gap, 0) * 0.5));
  }

  .plate--l { width: 92%; }
  .plate--m { width: 74%; }
  .plate--s { width: 58%; }

  /* L'alternance des bords, posee sur ce qui RESTE de place a droite : une
     image sur deux se cale a droite, jamais au-dela du rail. */
  .sequence .plate:nth-child(3n+2) { margin-inline-start: auto; }
  .sequence .plate:nth-child(3n)   { margin-inline-start: 42%; }
  .sequence .plate--l:nth-child(3n) { margin-inline-start: 8%; }
  .sequence .plate--m:nth-child(3n) { margin-inline-start: 26%; }

  /* B · le palier se deplie ; le decalage vertical de la trame n'a plus de
     sens en colonne, l'ecart entre les deux photos le remplace. */
  .tier {
    display: block;
    margin-block-start: max(2.5rem, calc(var(--lead, 0) * 0.6));
  }

  .shot {
    margin-block-start: 0;
    width: 92%;
  }

  .tier > * + * { margin-block-start: 2.75rem; }

  .shot--m { width: 74%; }
  .shot--s { width: 58%; }

  /* L'opposition de la paire survit a la mise en colonne. */
  .tier:nth-child(odd)  .shot--s { margin-inline-start: auto; }
  .tier:nth-child(even) .shot--l { margin-inline-start: auto; }
  .tier .shot--m { margin-inline: auto; }
}

.plate__frame {
  position: relative;
  overflow: hidden;
  background: var(--paper-2);
  display: block;
  /* Le format n'est plus fixe ici : chaque emplacement porte le sien
     (`--ratio`, pose par le motif). 3:4 domine, 2:3 sert les respirations. */
}
.plate__frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: opacity 0.6s var(--ease);
}

/* Plus de zone verticale d'exception : la grille de la reference n'en a
   aucune, ses 22 couvertures sont au meme format. La classe `.plate--tall` et
   la lecture d'orientation qui la posait ont ete retirees du gabarit le
   31/08 — il ne reste donc rien a neutraliser ici. */
.plate:hover .plate__frame img { opacity: 0.82; }

/* ── LA LEGENDE DE LA REFERENCE — 31/08 ──────────────────────────────────
   Chez gregfinck, sous chaque couverture : le LIEU en surtitre minuscule et
   capitales (Anton, 12 px, interlettrage +1,2), puis les PRENOMS en grand
   (32 px, capitales, +0,8), le tout CENTRE sous la photo.
   Ici les deux lignes avaient le meme corps — 13 px chacune, alignees a
   gauche : rien ne disait laquelle on lisait. On reprend donc la hierarchie
   et le centrage de la reference, dans la typographie du site (Satoshi).
   Le corps est a 24 px et non 32 : Satoshi est une grotesque, bien plus
   large qu'une serif condensee, et « Caroline & Guillaume » en capitales
   doit tenir sur les 504 px de la colonne. */
.plate__caption {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  margin-top: 1.15rem;
  border: 0;
  padding: 0;
}

.plate__num { display: none; }

.plate__name {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: 0.6px;
  line-height: 1.15;
  text-transform: uppercase;
  color: var(--ink);
}

/* Le lieu passe AU-DESSUS du nom sans toucher au gabarit : l'ordre visuel
   se regle ici, l'ordre du document reste celui qui a du sens a la lecture
   d'ecran (le nom d'abord). */
.plate__facts {
  order: -1;
  margin: 0 0 0.45rem;
  font-size: 0.625rem;
  font-weight: 400;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  color: var(--ink-faint);
}


/* ═══════════════════════════════════════════════════════════
   ONE STORY
   ═══════════════════════════════════════════════════════════ */
/* Same principle as the portal: the cover is a photograph, and the couple's
   name is a caption printed under it — not a title floating on a dark wash. */
.story__cover {
  height: auto;
  background: var(--paper);
  overflow: visible;
  /* LA COUVERTURE RENTRE DANS L'EMPRISE DE LA GRILLE — 31/08.
     Elle s'affichait sur toute la fenetre : 1440 px pour un fichier de
     1001 px, soit 44 % d'etirement, et un reportage qui s'ouvrait sur une
     pleine page la ou la reference commence a 682 px. Bornee aux 80 % de la
     grille, elle retrouve une definition acceptable (1001 pour 1152) et le
     reportage s'ouvre dans le meme cadre que ses photos. */
  width: 80vw;
  margin-inline: auto;
}
.story__cover img {
  position: static;
  display: block;
  filter: none;
  /* ── LA COUVERTURE TIENT DANS LA FENETRE — 01/09 ──────────────────────
     RETOUR DE MENDAR : « quand on ouvre un projet, la premiere photo quand
     elle est en portrait depasse grandement sur la hauteur de l'ecran ».
     Mesure sur les 25 reportages a 1440x900 : la largeur etait fixee (80vw
     = 1152 px) et la hauteur laissee libre, donc une couverture verticale
     2:3 s'affichait a 1728 px — 192 % de la hauteur de fenetre, sur 14
     reportages sur 25. Le visiteur ouvrait un reportage sur un fragment
     d'image, sans titre ni repere visible.

     On BORNE LA HAUTEUR, on ne recadre pas : le format libre vient d'etre
     retabli, on ne le reprend pas d'une main apres l'avoir donne de l'autre.
     La largeur derive de la hauteur (`width: auto`), donc la photographie
     reste ENTIERE ; sous sa largeur de bloc elle se centre.

     85vh, et pas moins : c'est exactement la part d'ecran qu'occupait deja
     une couverture HORIZONTALE (768 px sur 900). Les deux orientations
     finissent donc a la meme hauteur — c'est la seule facon qu'elles se
     comportent pareil pour le lecteur. Au passage, ca corrige aussi les
     horizontales sur les ecrans courts, ou 768 px valaient 102 % de 750. */
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 85vh;
  margin-inline: auto;
}

.story__head {
  position: static;
  background: none;
  color: var(--ink);
  padding: 1.1rem var(--gutter) 0;
}

.story__couple {
  font-size: clamp(1.5rem, 3.4vw, 2.5rem);
  font-weight: 500;
  color: var(--ink);
  letter-spacing: var(--track-tight);
}

.story__facts {
  margin-top: 0.3rem;
  display: flex;
  gap: 0 0.75rem;
}
.story__facts span {
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
}

.story__intro {
  font-family: var(--sans);
  font-weight: 400;
  font-size: var(--micro);
  line-height: 1.5;
  letter-spacing: 0;
  max-width: var(--measure);
  margin-inline: 0 auto;
  text-align: left;
  color: var(--ink);
  padding-block: clamp(2.5rem, 6vw, 5rem);
}

/* Ce qui n'appartient qu'aux photographies d'un reportage : le fond du cadre
   pendant le chargement, et le recadrage. */
.shot {
  background: var(--paper-2);
  overflow: hidden;
}

.shot img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* ── LA PHOTOGRAPHIE D'OUVERTURE TIENT DANS LA FENETRE — 01/09 ───────────
   RETOUR DE MENDAR : « quand on ouvre un projet, la premiere photo quand
   elle est en portrait depasse grandement sur la hauteur de l'ecran ».
   Mesure : a 1440x900 une verticale s'affichait a 1023 px, soit 114 % de la
   hauteur de fenetre — et 136 % sur un ecran de 750 px. Une horizontale, au
   meme endroit, n'en prenait que 35 a 51 %. Le lecteur qui ouvre un reportage
   ne voyait donc qu'un fragment d'image sans repere, et le comportement
   dependait de l'orientation du fichier.

   On BORNE LA HAUTEUR, on ne recadre pas : le format libre vient d'etre
   retabli, il n'est pas question de le reprendre d'une main apres l'avoir
   donne de l'autre. Le cadre lache son `aspect-ratio` et epouse l'image ;
   l'image se borne a 78vh et derive sa largeur, donc elle reste ENTIERE. En
   dessous de sa largeur de zone elle se centre.

   Meme valeur que la couverture (85vh) : une seule regle de hauteur sur la
   page, sinon les deux premieres images se repondent mal.

   Uniquement au-dessus de 46rem : sur telephone une verticale pleine largeur
   fait ~69 % de la hauteur, elle ne deborde pas — la borner l'amoindrirait. */
@media (min-width: 46rem) {
  .tiers .tier:first-child .shot:first-child {
    aspect-ratio: auto;
    display: flex;
    justify-content: center;
  }

  .tiers .tier:first-child .shot:first-child img {
    width: auto;
    height: auto;
    max-width: 100%;
    max-height: 85vh;
    object-fit: contain;
    margin-inline: auto;
  }
}

/* LE THEME PARENT DEBORDAIT DE LA GRILLE. Il pose
   `.gallery__figure:nth-child(3n+1) { grid-column: 1 / -1 }` — une photo sur
   trois en pleine largeur, heritage de l'ancienne mosaique. La classe
   `.gallery__figure` n'est plus emise par le gabarit : la regle du parent ne
   trouve plus personne, il n'y a donc plus rien a neutraliser. */

/* La galerie complete du couple, quand Alex a renseigne le lien Pixieset.
   Meme voix que le reste du reportage : sans-serif discret, encre douce, et
   rien qui crie. Le bloc est absent quand le champ est vide. */
.story__gallery-link {
  margin-top: clamp(2rem, 5vw, 4rem);
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ink-soft);
}
.story__gallery-link a {
  color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.15em;
  transition: color 0.25s ease, border-color 0.25s ease;
}
.story__gallery-link a:hover,
.story__gallery-link a:focus-visible {
  color: var(--ink);
  border-bottom-color: currentColor;
}

.story__nav {
  border-top: 1px solid var(--line);
  margin-top: clamp(2rem, 5vw, 4rem);
  padding-top: 1rem;
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
}
.story__nav a:hover { color: var(--ink); }

/* ═══════════════════════════════════════════════════════════
   MEET ALEX
   Label left, text in narrow columns on the right — the column
   structure of the second reference.
   ═══════════════════════════════════════════════════════════ */
.about__title { font-size: clamp(2rem, 5.5vw, 4rem); font-weight: 500; }
.about__figure { background: var(--paper-2); }
.about__figure img { filter: none; }

.about__text .prose {
  columns: 2;
  column-gap: 2.5rem;
  max-width: 46rem;
}
@media (max-width: 46rem) { .about__text .prose { columns: 1; } }

.press { border-top-color: var(--line); }
.press__items {
  font-family: var(--sans);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  font-size: var(--micro);
  gap: 0.5rem 2rem;
}
.press__items a { color: var(--ink-soft); }
.press__items a:hover { color: var(--ink); }

/* ═══════════════════════════════════════════════════════════
   FORM — rules, not boxes
   ═══════════════════════════════════════════════════════════ */
.enquiry__progress { border-bottom-color: var(--line); }
.enquiry__progress li { color: var(--ink-faint); font-size: var(--micro); text-transform: none; letter-spacing: 0; }
.enquiry__progress li.is-current { color: var(--ink); }
.enquiry__num { font-family: var(--sans); font-weight: 500; }

.field__label { font-family: var(--sans); font-size: var(--micro); font-weight: 400; color: var(--ink); }
.field__optional { color: var(--ink-faint); text-transform: none; letter-spacing: 0; }

/* Note sous un champ — la precision qui evite un malentendu, pas un avertissement.
   Elle se lit apres avoir choisi, donc elle reste discrete : meme gris que les
   legendes, pas de capitales, pas de cadre. */
.field__note {
  margin: 0.85rem 0 0;
  max-width: 34rem;
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.55;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
}

.enquiry input[type="text"],
.enquiry input[type="email"],
.enquiry input[type="date"],
.enquiry textarea {
  background: transparent;
  color: var(--ink);
  border: 0;
  border-bottom: 1px solid var(--line-strong);
  font-family: var(--sans);
  font-size: var(--micro);
  padding: 0.55rem 0;
  width: 100%;
  transition: border-color 0.35s var(--ease);
}
.enquiry input:focus,
.enquiry textarea:focus { border-bottom-color: var(--ink); outline: none; }
.enquiry input[type="date"]::-webkit-calendar-picker-indicator { filter: none; opacity: 0.45; }

.choice span {
  border: 1px solid var(--line);
  color: var(--ink-soft);
  font-size: var(--micro);
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease), background 0.3s var(--ease);
}
.choice:hover span { border-color: var(--line-strong); color: var(--ink); }
.choice input:checked + span { border-color: var(--ink); background: var(--ink); color: var(--paper); }

/* The parent sizes this for a 10px tracked label. At 13px untracked it
   became a slab twice the height of anything else on the page. */
.btn {
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  padding: 0.6rem 1.4rem;
  border: 1px solid var(--ink);
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}
.btn:hover { background: transparent; color: var(--ink); }
.btn--ghost { background: transparent; color: var(--ink-soft); border-color: var(--line); }
.btn--ghost:hover { color: var(--ink); border-color: var(--ink); }

.enquiry__legal {
  color: var(--ink-faint);
  font-size: var(--micro);
  letter-spacing: 0;   /* the parent tracks this line; nothing else here is tracked */
  max-width: 46ch;
}

/* The form column sat centred while every other page on the site hangs from
   the left gutter. Same rail, same starting line. */
.shell--narrow { margin-inline: 0; }

.notice { border: 1px solid var(--line); background: transparent; }
.notice--good .notice__title { font-family: var(--sans); font-weight: 500; letter-spacing: var(--track-tight); }
.has-error input,
.has-error textarea { border-bottom-color: #a9432f; }

/* ═══════════════════════════════════════════════════════════
   COLOPHON
   ═══════════════════════════════════════════════════════════ */
.colophon {
  border-top: 1px solid var(--line);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-faint);
}
/* Was the loudest of the three drawings: lower case, weight 500 and tracking
   pulled NEGATIVE — the exact opposite of the front door. Shape now comes from
   the wordmark block; only size and colour are stated here. */
.colophon__name { font-size: var(--size-wordmark); color: var(--ink); }
.colophon a:hover { color: var(--ink); }

/* The legal menu printed bare <li> straight into a <nav>: invalid markup,
   and it rendered with bullets. Third time the parent's `items_wrap` has
   done this — masthead, press strip, and now the footer. */
.colophon__items {
  display: flex;
  gap: 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.colophon__links { display: flex; gap: 1.5rem; align-items: baseline; }

/* STUDIO SIGNATURE — a row of its own, not a fourth item in the strip.
   `flex-basis: 100%` makes the existing flex container break the line for it,
   so the credit inherits the colophon's padding and lands on exactly the same
   left and right edges as the name and the copyright. No second padding
   formula to keep in sync when --gutter or --shell-max move.

   Right-aligned on desktop: the studio signs in the corner, and the left edge
   stays the client's. On a phone the colophon already stacks everything on the
   left margin, so the signature follows it there rather than floating alone. */
.colophon__credit {
  flex-basis: 100%;
  text-align: left;
  /* The strip's own gap is 1.25rem; a signature sits closer to what it signs
     than the columns sit to each other. */
  margin-top: -0.25rem;
}
@media (min-width: 46rem) {
  .colophon__credit { text-align: right; }
}
.colophon__credit a {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  color: var(--ink-faint);
  transition: color 0.35s var(--ease);
}
/* Words and mark lift together — the mark inherits `currentColor`, so the
   credit reads as one object rather than a label next to a logo. */
.colophon__credit a:hover { color: var(--ink); }
.colophon__mark {
  /* Sized against the x-height of the line it sits on, not an arbitrary px
     value: at --micro (13px) this puts the mark at cap height. */
  height: 0.7em;
  width: auto;
  display: block;
}

.empty { color: var(--ink-faint); }

/* ═══════════════════════════════════════════════════════════
   LEGAL PAGES
   Each h2 becomes the left-hand label of its block, so a legal
   document reads with the same structure as the rest of the
   site instead of as a wall of pasted text.
   ═══════════════════════════════════════════════════════════ */
.hero--plain { grid-template-columns: 1fr; padding-bottom: clamp(1.5rem, 4vw, 3rem); }

.legal > h2 {
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-soft);
  border-top: 1px solid var(--line);
  padding-top: 0.9rem;
  margin-top: clamp(2.25rem, 6vw, 5rem);
}

.legal > *:not(h2) {
  max-width: 46ch;
  margin-left: clamp(0rem, 12vw, 11rem);
  margin-top: 0.9em;
}
.legal > h2 + * { margin-top: -1.5em; }

.legal ul { padding-left: 1.1rem; }
.legal li { margin-top: 0.35em; }
.legal a { text-decoration: underline; text-underline-offset: 0.22em; text-decoration-thickness: 1px; }
.legal strong { font-weight: 500; }

/* What is still missing from a page, marked in the copy itself so it can
   never be published by accident. */
.legal .todo {
  background: #f3e7c9;
  padding: 0.05em 0.3em;
  font-weight: 500;
}

@media (max-width: 46rem) {
  .legal > *:not(h2) { margin-left: 0; }
  .legal > h2 + * { margin-top: 0.9em; }
}

/* ═══════════════════════════════════════════════════════════
   VIEWER — enlarge a photograph
   The layout prints some frames small on purpose. This is the
   way to actually look at one. The backdrop is a flat sheet of
   paper, not a dark wash, and nothing is lifted off it with a
   shadow.
   ═══════════════════════════════════════════════════════════ */
.is-zoomable { cursor: zoom-in; }

.viewer {
  width: 100vw;
  max-width: 100vw;
  height: 100svh;
  max-height: 100svh;
  padding: clamp(2.5rem, 5vw, 4rem) clamp(1rem, 4vw, 4rem);
  border: 0;
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  overflow: hidden;
}
.viewer::backdrop { background: var(--paper); }

.viewer__stage {
  margin: 0;
  height: 100%;
  display: grid;
  place-items: center;
}
.viewer__stage img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  display: block;
}

.viewer__close,
.viewer__step {
  position: absolute;
  background: none;
  border: 0;
  padding: 0.5rem;
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  color: var(--ink-soft);
  cursor: pointer;
  transition: color 0.3s var(--ease);
}
.viewer__close:hover,
.viewer__step:hover { color: var(--ink); }

.viewer__close { top: clamp(0.75rem, 2vw, 1.5rem); right: clamp(0.75rem, 3vw, 3rem); }
.viewer__step { top: 50%; transform: translateY(-50%); font-size: 1.25rem; line-height: 1; }
.viewer__step[data-step="-1"] { left: clamp(0.5rem, 2vw, 1.75rem); }
.viewer__step[data-step="1"]  { right: clamp(0.5rem, 2vw, 1.75rem); }

.viewer__count {
  position: absolute;
  bottom: clamp(0.75rem, 2vw, 1.5rem);
  left: clamp(0.75rem, 3vw, 3rem);
  font-size: var(--micro);
  color: var(--ink-faint);
}

/* ═══════════════════════════════════════════════════════════
   REVEALS
   ═══════════════════════════════════════════════════════════ */
.reveal { opacity: 0; transform: translateY(1rem); transition: opacity var(--slow) var(--ease), transform var(--slow) var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

/* ─── LA PAGE DE PRESTATION (page-wedding.php) ────────────────────────────
   Les destinations sont LUES sur les reportages publies, jamais saisies a la
   main : la ligne ne peut donc pas mentir, et elle se complete d elle-meme
   quand Alex renseigne les lieux manquants. C est la seule affirmation de la
   page qui soit prouvee par le folio — elle est donc posee au rang du titre,
   vue avant d etre lue, pendant que tout le reste de la page reste en prose. */
.service__countries{
  margin: .5rem 0 1.75rem;
  font-size: clamp(1.5rem, 4.2vw, 2.75rem);
  font-weight: 300;
  letter-spacing: var(--track-tight);
  line-height: 1.12;
  /* Pas de max-width etroite : a 44px, « France · Portugal · Greece · Corsica »
     tient sur une ligne, et un 20ch laissait « Corsica » orpheline en dessous.
     text-wrap:balance repartit proprement le jour ou la liste s allongera. */
  text-wrap: balance;
}

.service__close .about__cta{ margin-top: 1.5rem; }

/* Le chapeau est cale a margin:0 par le theme (il est concu pour vivre seul
   dans un hero). Sur la page de prestation il est suivi de prose : sans cet
   espace, la descendante du « y » de « quietly » vient toucher le premier
   paragraphe. */
.service .lede + .prose{ margin-top: 2.25rem; }
.service .section__head + .lede{ margin-top: 1.25rem; }

/* ═══════════════════════════════════════════════════════════
   L OUVERTURE DE LA PAGE PRESTATION
   Les mots a gauche, UNE photographie debout a droite.

   Mesure du 21/08/2026 en 1440x900 : la premiere version de cette page posait
   sa premiere photo a y=1553px, soit 653px SOUS la ligne de flottaison. Un
   couple devait derouler pres de deux ecrans de texte avant de voir une seule
   image, sur la page qui doit lui donner envie d ecrire.

   Rien de nouveau n est invente ici : la page reprend la grammaire deja posee
   sur la home (`.hero` — « words on the left, a photograph standing on the
   right »). Une seule composition a apprendre pour tout le site.
   ═══════════════════════════════════════════════════════════ */

/* `.hero` porte le rythme de la page d accueil, ou il vit seul en haut de
   page. Ici il suit un `.section__head` et sa filante : la section donne deja
   l air, le hero ne doit pas le redonner. */
.service__opening{
  padding: 0;
  margin-top: clamp(1.25rem, 2.5vw, 2rem);
}

/* 88px avait ete regle pour une colonne large comme la page. A cote de la
   photo il reste ~787px au chapeau, ou 88px se briserait en quatre lignes
   courtes. Descendu a 68px : toujours au-dessus des 64px du titre de page,
   donc l affirmation garde l accent et le titre reste l etiquette qu il est. */
.service__opening .lede{ font-size: clamp(2rem, 4.8vw, 4.25rem); }

/* La legende est une preuve, pas un ornement : elle dit que c est un vrai
   mariage et elle l ouvre. Meme rang de note de bas de page que les vignettes
   du folio, pour que le lecteur n apprenne la grammaire qu une fois. */
.service__credit{ margin-top: .5rem; }
.service__credit a{ display: block; text-decoration: none; border: 0; }
.service__credit a:hover .plate__name{
  text-decoration: underline;
  text-underline-offset: .2em;
  text-decoration-thickness: 1px;
}

@media (max-width: 46rem){
  /* Empilee, la photo ne doit surtout pas passer SOUS les trois paragraphes :
     sur un telephone cela recreerait trait pour trait le defaut corrige ici.
     `display:contents` fait remonter le chapeau et la prose au rang d elements
     de la grille, ce qui permet de glisser la photo entre les deux. */
  .service__opening .hero__text{ display: contents; }
  .service__opening .lede{ order: 1; }
  .service__standing{ order: 2; }
  .service__opening .prose{ order: 3; margin-top: 0; }
}

/* ═══════════════════════════════════════════════════════════
   LE RYTHME VERTICAL, DECLARE UNE SEULE FOIS
   Mesure du 21/08/2026 en 1440 : une bande `.row` donne 14px sous sa filante
   et 80px avant la filante suivante. La grille de la home RECEVAIT ces 80px
   (padding-bas du .row d ouverture) mais ne les RENDAIT pas : la filante de
   cloture arrivait a 0px sous la derniere legende, contre 80px a l ouverture.
   Asymetrie 80/0 sur la meme page.

   Le token remplace le nombre magique : le jour ou le rythme change, il
   change au meme endroit pour les deux cotes de la bande.
   ═══════════════════════════════════════════════════════════ */
:root{ --band: clamp(2.25rem, 6vw, 5rem); }

.row{ padding-bottom: var(--band); }

/* Une bande posee entre deux filantes rend l air qu elle a recu. */
.shell > .sequence + .row,
.shell > .tiers + .row,
.shell > .chapter + .row,
.shell > .sequence + .section,
.shell > .tiers + .section,
.shell > .chapter + .section{ margin-top: var(--band); }

/* L OUVERTURE D UNE PAGE NE DEPEND PAS DE CE QUI VIENT EN PREMIER
   Mesure du 22/08/2026 en 1440. Deux pages jumelles, meme gabarit :
   « Legal notice » ouvrait a 80px sous son titre, « Privacy » a 11px. Sept
   fois moins, pour une seule raison : la premiere ouvre sur un h2 (qui porte
   l air entre deux sections du document) et la seconde sur un paragraphe de
   chapeau (qui ne porte que son interligne). L air d ouverture etait donc
   decide par le hasard de la redaction, pas par la mise en page.
   Meme constat au portfolio : le premier reportage etait pousse a 128px quand
   tous les suivants tiennent a 64px — la barre des annees rend son air, et le
   chapitre ajoutait le sien par-dessus.
   Dans les deux cas la valeur est reprise a la page, pas au contenu. */
.legal > :first-child{ margin-top: var(--band); }
.years + .chapter{ padding-top: 0; }

/* ═══════════════════════════════════════════════════════════
   CONTACT — la page reprend la mesure du site, pas le formulaire
   Mesure du 21/08/2026 en 1440 : la page tenait dans 736px cales a gauche et
   laissait 704px de vide a droite, soit 49% de l ecran. La filante du titre
   s arretait au milieu de nulle part.
   Le formulaire, lui, avait raison d etre etroit — une colonne unique se
   remplit mieux qu une grille. Sa mesure est donc conservee a l identique
   (592px a 1440, exactement comme avant) ; c est la PAGE qui s elargit, et le
   vide ainsi borne recoit la photographie debout du reste du site.
   ═══════════════════════════════════════════════════════════ */
.contact__opening{
  padding: 0;
  margin-top: clamp(1.25rem, 2.5vw, 2rem);
}

/* 37rem = 592px : la largeur exacte qu avaient les champs dans l ancienne
   colonne etroite. Rien n a bouge pour celui qui remplit. */
.contact__opening .enquiry,
.contact__opening .notice{ max-width: 37rem; }

.contact__standing{ align-self: start; }

/* Les choix non selectionnes etaient en `--ink-soft` sur filet `--line` : a
   l ecran ils se lisaient comme DESACTIVES alors qu ils sont la pour etre
   cliques. L encre pleine les rend disponibles ; l etat choisi reste marque
   par le pave noir, qui suffit largement a les distinguer. */
.choice span{ color: var(--ink); }

@media (max-width: 46rem){
  /* Empilee, la photographie passe APRES le formulaire : le couple vient
     ecrire, rien ne doit repousser les champs vers le bas. */
  .contact__standing{ margin-top: clamp(2rem, 6vw, 3rem); }
}

/* ═══════════════════════════════════════════════════════════
   LA PRESSE, DANS LA LEGENDE — option A, arretee le 10/09/2026
   ═══════════════════════════════════════════════════════════
   L'option B — une rangee « In print » posee en tete du folio,
   entre le titre et la barre des annees — a ete ECARTEE, et ses
   regles (.inprint, .inprint__lede, __list, __item, __name,
   __note) retirees d'ici le meme jour. Ne pas les remettre :
   la parution appartient au mariage qui l'a obtenue, pas a un
   bandeau de palmares en haut de page.

   La marque se pose sous le nom du couple, dans la legende de sa
   vignette. Elle se lit a l'encre pleine quand le lieu et
   l'annee restent en gris : la publication est une distinction,
   pas une donnee de plus. */
.plate__press {
  margin-top: 0.5rem;
  font-family: var(--sans);
  font-size: var(--micro);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}


/* ═══════════════════════════════════════════════════════════
   « RECENT STORIES » — TROIS COMPOSITIONS À L'ESSAI, 08/09/2026
   ═══════════════════════════════════════════════════════════

   RELEVÉ AVANT (staging, /wedding-photography/) : le bloc mesurait
   5 060 px en 1440 — 5,6 écrans empilés, 72 % de la hauteur totale de la
   page — et 1 587 px en 390. Cause : `.chapter__plates` n'avait aucune
   règle sur cette page. Chaque vignette prenait les 1 296 px du rail et le
   format natif de sa couverture, d'où deux portraits à 2 000 px de haut.

   Ce que la section doit faire : montrer trois reportages d'un seul regard
   et dire qu'il y a une suite au folio. Elle n'a pas à rejouer le folio.

   Les trois variantes ne s'activent que par `?recent=a|b|c` — la page
   servie normalement n'est pas touchée. Rien ici ne déborde de
   `.chapter__plates` : ni le héros, ni le reste de la page ne bougent. */

.recent .plate {
  width: auto;
  margin: 0;
  min-width: 0;
}

/* Le format vient de la composition, plus du fichier : c'est la condition
   pour qu'une rangée se lise comme une rangée. */
.recent .plate__frame { aspect-ratio: var(--recent-ratio, 4 / 5); }

.recent .plate__caption { margin-top: 0.85rem; }
.recent .plate__name { font-size: 1rem; letter-spacing: 0.4px; }
.recent .plate__facts { margin-bottom: 0.3rem; }

/* ── A · LA RANGÉE ────────────────────────────────────────────────────────
   Trois vignettes de même hauteur, alignées sur la même ligne de sol. La
   lecture est horizontale : on compare, on choisit, on descend. Le portrait
   4/5 est le format qui tient le plus de sujet dans le moins de hauteur
   sans recadrer les couvertures à la serpe. */
.recent--a {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem;
  align-items: start;
}

/* ── B · LA BANDE ─────────────────────────────────────────────────────────
   Une bande qui défile, où la quatrième vignette est amorcée au bord droit :
   c'est elle qui dit « il y en a d'autres », sans l'écrire. Hauteur fixe,
   quel que soit le nombre de reportages — la section ne grandit plus jamais. */
.recent--b {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 0.75rem;
  scrollbar-width: thin;
}
.recent--b .plate { scroll-snap-align: start; }
.recent--b .plate__frame { aspect-ratio: 3 / 2; }
.recent--b .plate__caption { align-items: flex-start; text-align: left; }

/* ── C · L'ÉDITORIAL RESSERRÉ ─────────────────────────────────────────────
   Une image tient le regard, deux l'accompagnent — la composition dit
   laquelle est la plus récente au lieu de les mettre à égalité. C'est le
   dessin le plus proche du folio, en une seule hauteur d'écran. */
.recent--c {
  display: grid;
  grid-template-columns: 1.62fr 1fr;
  grid-template-rows: auto auto;
  gap: 1.5rem 1.75rem;
  align-items: start;
}
/* Le carré, et pas le 4/5 : sur ce rail, la grande image en 4/5 dépassait de
   190 px les deux petites de la colonne voisine et ouvrait un creux sous
   elles. En 1/1 les deux colonnes finissent à la même ligne. */
.recent--c .plate:first-child {
  grid-row: span 2;
  --recent-ratio: 1 / 1;
}
.recent--c .plate:not(:first-child) { --recent-ratio: 3 / 2; }
.recent--c .plate:not(:first-child) .plate__caption {
  align-items: flex-start;
  text-align: left;
}

/* ── LA RÉDUCTION MOBILE ──────────────────────────────────────────────────
   En dessous de 46rem il n'y a plus de rangée possible : trois portraits en
   colonne rallongeraient de nouveau la page. A et C passent donc en deux
   colonnes de paysages — trois vignettes visibles ensemble sur un écran de
   390. B garde son défilement, c'est là qu'il est le plus juste. */
@media (max-width: 46rem) {
  .recent--a,
  .recent--c {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: auto auto;
    gap: 1.25rem 0.9rem;
    align-items: start;
  }
  .recent--a .plate:first-child,
  .recent--c .plate:first-child {
    grid-column: 1 / -1;
    --recent-ratio: 3 / 2;
  }
  .recent--a .plate:not(:first-child),
  .recent--c .plate:not(:first-child) { --recent-ratio: 4 / 5; }
  .recent--c .plate:first-child { grid-row: auto; }

  .recent--b { grid-auto-columns: 15.5rem; gap: 1rem; }

  .recent .plate__name { font-size: 0.9375rem; }
  .recent .plate__facts { font-size: 0.5625rem; letter-spacing: 1.4px; }
}

/* ── Le filtre par pays du folio ────────────────────────────────────────────
   Demande d'Alex, visio du 16/07. Il reprend le dessin de la navigation par
   annee, a une difference pres : il ne colle PAS au defilement. Deux bandes
   collantes l'une sous l'autre se recouvriraient ; et le pays se choisit une
   fois, en haut de page, alors que l'annee sert de repere pendant la lecture.
   L'annee garde donc le sticky, le pays le laisse. */
.years--places {
  position: static;
  z-index: auto;
  border-bottom: none;
  padding-bottom: 0.35rem;
}

/* L'etat courant : le seul repere visuel du filtre actif. */
.years a[aria-current] {
  color: var(--ink);
}

/* ───────────────────────────────────────────────────────────
   /meet-alex/ — la liste des pays est une NAVIGATION, pas le
   sujet de la page. A 44px elle criait plus fort que les mots
   d Alex (13px) et que tout le reste de la page. Sur
   /wedding-photography/ elle reste grande : la-bas c est bien
   elle qu on vient chercher. 10/09.
   ─────────────────────────────────────────────────────────── */
.page-template-page-about .service__countries{
  font-size: clamp(1.0625rem, 2.2vw, 1.375rem);
  margin-bottom: 1.1rem;
}

/* ───────────────────────────────────────────────────────────
   /meet-alex/ — les quatre images du Wedding Guide 2027.
   Elles plafonnent a 648px de large (guide fait sous Canva) :
   la bande est bornee a 54rem pour qu aucune ne soit agrandie
   — 165px par vue, 330px en double densite : la plus petite source
   fait 336px, donc aucune agrandie. Ratio 2/3 impose, recadrage
   centre : les sources vont de 0,65 a 0,79. 10/09.
   ─────────────────────────────────────────────────────────── */
.frames{
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: .55rem;
  max-width: 43rem;
  margin: 0 0 1.15rem;
}
.frames__item{ margin: 0; }
.frames__item img{
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  object-position: center;
}
@media (max-width: 46rem){
  .frames{ grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: none; }
}

/* ───────────────────────────────────────────────────────────
   Le hero est ancre EN BAS, pas au centre. 10/09.
   La photo demandee par Dylan (celle de son site actuel) fait
   1280x853, soit un rapport 1,50 ; le cadre du portail est a
   1,60 : cover retranche ~62 px en hauteur. Centre, la coupe
   tombait EN PLEIN MILIEU du bandeau VOGUE incruste en bas a
   gauche — un credit coupe en deux se lit comme un defaut.
   Ancre en bas, le bandeau reste entier et la coupe se fait
   dans le ciel, ou il n y a rien a perdre.
   ─────────────────────────────────────────────────────────── */
.portal__media img{ object-position: center bottom; }

/* En portrait, le cadre ne garde qu une bande verticale de la photo :
   centre, elle tombait sur le dos de la mariee et les visages sortaient
   du cadre. Decale a 70 %, le baiser revient dans le champ. Le bandeau
   VOGUE, lui, est hors de cette bande — il n y a pas de position qui
   garde les deux. 10/09. */
@media (max-width: 46rem){
  .portal__media img{ object-position: 70% bottom; }
}
/* Wedding photography — Recent stories, desktop only. Mendar 10/09/2026. */
@media (min-width:64rem) {
  body.page-template-page-wedding .chapter__plates {
    display:grid;
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:2.5rem;
    align-items:start;
  }
  body.page-template-page-wedding .chapter__plates > .plate {
    width:100%;
    margin:0;
    min-width:0;
  }
  body.page-template-page-wedding .chapter__plates .plate__name {
    font-size:clamp(1rem,1.5vw,1.35rem);
  }
}

@media (min-width:64rem) {
  body.page-template-page-wedding .chapter__plates { padding-bottom:3rem; }
}
/* Recent stories: equal desktop frames after visual review, 10/09/2026. */
@media (min-width:64rem) {
  body.page-template-page-wedding .chapter__plates .plate__frame {
    aspect-ratio:3 / 4;
  }
  body.page-template-page-wedding .chapter__plates .plate__frame img {
    position:absolute;
    inset:0;
    width:100%;
    height:100%;
    object-fit:cover;
  }
}
/* Shared components — final consistency pass, Mendar 10/09/2026. */
/* ─── Option A, tranchee par Mendar le 10/09 a 13:00 ──────────────
   Deux declarations de cette passe sont RETIREES ici, pas surchargees.

   1) « body.has-portal .masthead { transform:none; opacity:1 } »
      forcait l en-tete visible sur la page a portail. Or le masthead
      porte un ::before opaque en var(--paper) : le thème l assume et
      dit pourquoi — « there is nothing to dissolve into here, since
      the header never overlaps a photograph ». Cette passe cassait
      exactement cette premisse : une barre creme de 72 px (93 px en
      390) se posait sur la photographie du hero.

   2) « body.home .ecrin-nav { display:none } » supprimait la
      navigation d origine, celle qui vit DANS l image en blanc.

   Le reste de la passe — cibles tactiles a 2,75 rem, :focus-visible,
   min-height — est CONSERVE : c est du travail d accessibilite, et il
   ne depend pas de la visibilite du masthead sur le portail. La nav
   du hero est une vraie <nav> du DOM, navigable au clavier.
   ────────────────────────────────────────────────────────────────── */
body.home .masthead__name,
body.page-template-page-about .masthead__name { visibility:visible; }
.masthead { min-height:4.5rem; }
.masthead__name { position:relative; z-index:2; }
.btn { min-height:2.75rem; }
:where(a,button,input,select,textarea):focus-visible {
  outline:2px solid var(--ink);
  outline-offset:4px;
}
@media (max-width:46rem) {
  .masthead { min-height:5.5rem; }
  .nav-toggle { width:2.75rem; height:2.75rem; }
  .masthead__nav { visibility:hidden; }
  body.nav-open .masthead__nav { visibility:visible; }
  .masthead__nav a { min-height:2.75rem; }
}
.service__credit { margin-top:1.15rem; background:transparent; }
.service__credit a {
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
}
.service__credit .plate__name { font-size:clamp(1rem,1.5vw,1.35rem); }
body.single-wedding .masthead__nav a[href$="/weddings/"] { color:var(--ink); }
body.single-wedding .masthead__nav a[href$="/weddings/"]::after { transform:scaleX(1); }

/* ═══════════════════════════════════════════════════════════════════════════
   /weddings/ — COMPOSITION TROIS COLONNES SUR DESKTOP
   Tranchée par Mendar le 10/09/2026. Reposée le 10/09 après un retrait par erreur.

   ⛔ NE PAS RETIRER CE BLOC.
   Il a déjà été supprimé une fois, le 10/09 à 12:25, sur un contresens : on avait
   lu « la bonne cible est Recent stories sur /wedding-photography/ » comme un
   REMPLACEMENT, alors que c'était un sujet EN PLUS. Mendar a redemandé la
   correction dans la foulée — mot pour mot : « il y a TOUJOURS la galerie qui
   s'affiche de manière étrange sur la version desktop ».

   POURQUOI : sans ce bloc, .sequence est en display:block et chaque plaque occupe
   sa propre rangée — 329 / 447 / 682 px sur 1440 disponibles, les deux tiers de
   l'écran vides en permanence. Mesuré : 41 042 px de hauteur, ≈ 45 écrans pour
   60 reportages. Le rythme « une image, du blanc, une image » est juste pour
   RACONTER un mariage ; il est faux pour une page de LISTE qui en présente
   soixante. C'est une erreur d'échelle, pas un choix de charte.

   PÉRIMÈTRE : tout est préfixé body.post-type-archive-wedding et enfermé sous
   min-width:64rem. L'accueil, les fiches reportage et le mobile (une colonne,
   31 551 px) ne sont pas touchés — c'est vérifié, pas supposé.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 64rem) {
  body.post-type-archive-wedding .sequence {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 4rem 2.5rem;
    align-items: start;
    max-width: 87rem;
    margin-inline: auto;
    padding-inline: 2rem;
  }
  body.post-type-archive-wedding .sequence > .plate {
    width: 100%;
    margin: 0;
    min-width: 0;
  }
  body.post-type-archive-wedding .sequence > .plate .plate__name {
    font-size: clamp(1rem, 1.5vw, 1.35rem);
  }
  /* --ratio est posé par plaque : les paysages restent en 3/2, les portraits en
     2/3. La grille cale les colonnes, elle n'uniformise pas les photographies. */
  body.post-type-archive-wedding .sequence > .plate .plate__frame {
    aspect-ratio: var(--ratio, 2/3);
  }
  /* Les intertitres d'année (« Weddings from 2026 » …) gardent la pleine largeur. */
  body.post-type-archive-wedding .sequence > :not(.plate) {
    grid-column: 1 / -1;
  }
}
