/* ==========================================================================
   Triptych Hero 1.0 — three photographs that drift apart as the page scrolls
   --------------------------------------------------------------------------
   Plain CSS. No framework, no build step, no external request.

   Three panels sit on top of each other: a tall centre plate and two side
   plates tucked behind it. As the block travels through the viewport the side
   plates slide outward and tilt, the centre plate rises, the photographs zoom
   a little, and two painted botanical ornaments swing across the frame.

   The whole motion is driven by ONE inherited number, --th-p, which the script
   moves from 0 to 1. Every moving part reads it and computes its own transform,
   so there is no per-element JavaScript and no second source of truth. Without
   the script --th-p keeps its initial value of 0, which is a finished, framed
   composition rather than a broken one.

   PROPORTIONS
   Every metric derives from --th-font-size, the size of the running text. The
   ratios were measured on the reference page with getBoundingClientRect(), not
   estimated from a screenshot:

     running text     1                  (the reference, 18px)
     title            3.4445 em          62px
     eyebrow          0.7223 em          13px
     link             0.6667 em          12px
     rule             3 em tall, 1px wide
     plate            31.1112 em wide    560px, capped
     plate ratio      560 / 828          the centre photograph's own ratio
     side plate       67% of the plate, pulled 40% outside it
     top ornament     52% wide, -8% / -24% from the plate's corner
     bottom ornament  33% wide, -10% / -6% from the opposite corner

   Changing --th-font-size rescales type, spacing and the plate together.
   Percentages inside the plate keep the collage itself self-similar, so the
   arrangement is identical at 320px and at 1600px.

   Order of this file:
     1. Design tokens
     2. Section and layout
     3. Intro: rules, ornament, eyebrow, title, link
     4. Stage and plates
     5. Botanical ornaments
     6. Scroll-driven motion
     7. Responsive type
     8. Fallbacks: reduced motion, forced colours, print

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

/* The single number the whole composition hangs from. Registering it gives it
   a type, an initial value and inheritance — which is what lets one custom
   property on the stage drive a dozen transforms on its descendants. Its
   initial value of 0 is also the no-JavaScript state. */
@property --th-p {
  syntax: "<number>";
  initial-value: 0;
  inherits: true;
}

/* ==========================================================================
   1. Design tokens
   ========================================================================== */

.triptych-hero {
  /* The component declares its own box model and assumes no reset. */
  box-sizing: border-box;

  /* Scale. Every metric below is a multiple of this one value. */
  --th-font-size: 18px;

  /* Ink and ground. Measured off the reference page. */
  --th-ground: #f6f4ec; /* page behind the composition */
  --th-ink: #6d705e; /* running text */
  --th-ink-strong: #545748; /* title and link */
  --th-ink-soft: #a0a48e; /* eyebrow */
  --th-accent: #de967d; /* link underline, warm terracotta */
  --th-rule: rgba(160, 164, 142, 0.5); /* the two vertical hairlines */
  --th-plate-ground: #ede9db; /* shows while a photograph loads */
  /* A thin warm veil over the centre photograph, which is what ties the three
     plates to the cream ground instead of leaving them floating. */
  --th-veil: rgba(222, 150, 125, 0.15);

  /* Metrics, all relative to --th-font-size. Ratios are rounded UP: the engine
     truncates to 1/64px, and rounding down invents a one-pixel overflow. */
  --th-plate-width: calc(31.1112 * var(--th-font-size)); /* 560px */
  --th-title: calc(3.4445 * var(--th-font-size)); /* 62px */
  --th-title-max: calc(49.4445 * var(--th-font-size)); /* 890px */
  --th-eyebrow: calc(0.7223 * var(--th-font-size)); /* 13px */
  --th-link: calc(0.6667 * var(--th-font-size)); /* 12px */
  --th-tracking: calc(0.1112 * var(--th-font-size)); /* 2px */
  --th-rule-height: calc(3 * var(--th-font-size)); /* 54px */
  --th-ornament-width: calc(3.4445 * var(--th-font-size)); /* 62px */
  --th-pad-x: calc(1.1112 * var(--th-font-size)); /* 20px */
  --th-pad-bottom: calc(4.2223 * var(--th-font-size)); /* 76px */

  /* The plate's aspect ratio is the centre photograph's own, so the frame
     never crops differently from the reference. */
  --th-plate-ratio: 560 / 828;

  /* Travel of the vertical drift. The reference expresses it in vh, which ties
     the parallax to the window. Override it with a length of your own — a
     percentage of the plate, or an em — when the component lives inside a box
     that is not the window, as apercu.css does. */
  --th-course: 1vh;

  /* Type. Both families are embedded next to this file. */
  --th-family-title: "Marcellus", "Cormorant Garamond", Georgia, serif;
  --th-family-ui: "Montserrat", system-ui, -apple-system, sans-serif;

  /* Motion. --th-ease is the settle time of the scroll follower. The reference
     smooths heavily; solving its measured lag against elapsed time puts its
     time constant at 360ms, which is the value used here. */
  --th-ease: 360ms;
  --th-link-motion: 400ms;
}

.triptych-hero *,
.triptych-hero *::before,
.triptych-hero *::after {
  box-sizing: inherit;
}

/* ==========================================================================
   2. Section and layout
   ========================================================================== */

.triptych-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 var(--th-pad-x) var(--th-pad-bottom);
  background-color: var(--th-ground);
  color: var(--th-ink);
  font-family: var(--th-family-title);
  font-size: var(--th-font-size);
  line-height: 1.8;

  /* The ornaments are meant to hang outside the plate, and near 390px the top
     one reaches past the left edge of the screen. The reference leaves that
     overflow to a global `overflow-x: hidden` on <body>; a component cannot
     assume such a thing exists, so it clips its own bleed here. `clip` rather
     than `hidden`: it creates no scroll container, so nothing inside can be
     scrolled into view by accident. */
  overflow-x: clip;
}

.triptych-hero__contenu {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: calc(66.6667 * var(--th-font-size)); /* 1200px */
}

/* ==========================================================================
   3. Intro: rules, ornament, eyebrow, title, link
   ========================================================================== */

.triptych-hero__intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  padding: 0 5%;
  text-align: center;
}

/* The two hairlines that open and close the wordmark. They are decorative, so
   they are empty elements the accessibility tree never sees. */
.triptych-hero__filet {
  width: 1px;
  height: var(--th-rule-height);
  background-color: var(--th-rule);
}

.triptych-hero__filet--haut {
  margin: calc(0.8334 * var(--th-font-size)) 0 calc(2.2223 * var(--th-font-size));
}

.triptych-hero__filet--bas {
  margin: calc(2.7778 * var(--th-font-size)) 0;
}

.triptych-hero__ornement {
  width: var(--th-ornament-width);
  height: auto;
  margin-bottom: calc(0.7778 * var(--th-font-size));
  object-fit: contain;
}

.triptych-hero__surtitre {
  margin: 0 0 calc(0.4445 * var(--th-font-size));
  color: var(--th-ink-soft);
  font-family: var(--th-family-ui);
  font-size: var(--th-eyebrow);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--th-tracking);
  text-transform: uppercase;
}

.triptych-hero__titre {
  /* Margins are set explicitly: a bare <h1> carries a browser margin that
     would push the whole block down by more than a line. */
  margin: 0 0 calc(1.5556 * var(--th-font-size));
  max-width: var(--th-title-max);
  color: var(--th-ink-strong);
  font-family: var(--th-family-title);
  font-size: var(--th-title);
  font-weight: 400;
  line-height: 1.1;
}

.triptych-hero__lien {
  padding: calc(0.3334 * var(--th-font-size)) 0;
  border-bottom: 1px solid var(--th-accent);
  color: var(--th-ink-strong);
  font-family: var(--th-family-ui);
  font-size: var(--th-link);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--th-tracking);
  text-transform: uppercase;
  text-decoration: none;
  transition:
    box-shadow var(--th-link-motion) cubic-bezier(0.25, 0.46, 0.45, 0.94),
    color var(--th-link-motion) cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.triptych-hero__lien:hover {
  box-shadow: 0 10px 20px -12px var(--th-accent);
}

.triptych-hero__lien:focus-visible {
  outline: 2px solid var(--th-ink-strong);
  outline-offset: 4px;
}

/* ==========================================================================
   4. Stage and plates
   ========================================================================== */

.triptych-hero__scene {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  padding: 0 10%;
}

/* The plate is the unit of the collage: everything inside is a percentage of
   it, which is what keeps the arrangement identical at every width. */
.triptych-hero__pile {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: var(--th-plate-width);
  aspect-ratio: var(--th-plate-ratio);
}

.triptych-hero__volet {
  background-color: var(--th-plate-ground);
  overflow: hidden;
}

.triptych-hero__volet--centre {
  position: relative;
  z-index: 15;
  width: 100%;
  height: 100%;
  /* The warm veil sits on the ground colour, under the photograph's own
     background, exactly as the reference layers it. */
  background-image: linear-gradient(var(--th-veil), var(--th-veil));
}

/* The side plates are two thirds of the centre and hang 40% outside it. They
   carry no top/bottom offset on purpose: as absolute children of a centred
   flex container, their static position is already the vertical middle. */
.triptych-hero__volet--gauche,
.triptych-hero__volet--droite {
  position: absolute;
  z-index: 5;
  width: 67%;
  height: 67%;
}

.triptych-hero__volet--gauche {
  left: -40%;
}

.triptych-hero__volet--droite {
  right: -40%;
}

.triptych-hero__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ==========================================================================
   5. Botanical ornaments
   ========================================================================== */

.triptych-hero__fleur {
  position: absolute;
  width: 52%;
  height: auto;
  max-width: none;
  object-fit: contain;
  /* Painted decoration: it says nothing a screen reader needs, and it must not
     intercept a click meant for the link behind it. */
  pointer-events: none;
}

.triptych-hero__fleur--haut {
  z-index: 10;
  top: -8%;
  left: -24%;
}

.triptych-hero__fleur--bas {
  z-index: 20;
  right: -6%;
  bottom: -10%;
  width: 33%;
}

/* ==========================================================================
   6. Scroll-driven motion
   --------------------------------------------------------------------------
   Each part interpolates its own transform between the two keyframes of the
   reference, reading the same --th-p. Multiplying a bare number by 1% / 1deg /
   a length is what lets a single unitless progress drive mixed units.

   Keyframes, measured from the source page's interaction data rather than
   guessed from a video:

     part            property     p=0      p=1
     photographs     scale        1        1.15
     centre plate    translateY   -1       +3      (× --th-course)
     left plate      translate    +10%     -30%
                     translateY   -2       +6
                     rotate       -3deg    -12deg
     right plate     mirrored
     top ornament    translate    +18%     -18%
                     translateY   -3       +6
                     rotate       -15deg   +17deg
     bottom ornament translateY   -1       +6
                     rotate       +20deg   +52deg
   ========================================================================== */

.triptych-hero__photo {
  transform: scale(calc(1 + 0.15 * var(--th-p)));
  transform-origin: center;
}

.triptych-hero__volet--centre {
  transform: translateY(calc((-1 + 4 * var(--th-p)) * var(--th-course)));
}

.triptych-hero__volet--gauche {
  transform: translate(
      calc((10 - 40 * var(--th-p)) * 1%),
      calc((-2 + 8 * var(--th-p)) * var(--th-course))
    )
    rotate(calc((-3 - 9 * var(--th-p)) * 1deg));
}

.triptych-hero__volet--droite {
  transform: translate(
      calc((-10 + 40 * var(--th-p)) * 1%),
      calc((-2 + 8 * var(--th-p)) * var(--th-course))
    )
    rotate(calc((3 + 9 * var(--th-p)) * 1deg));
}

.triptych-hero__fleur--haut {
  transform: translate(
      calc((18 - 36 * var(--th-p)) * 1%),
      calc((-3 + 9 * var(--th-p)) * var(--th-course))
    )
    rotate(calc((-15 + 32 * var(--th-p)) * 1deg));
}

.triptych-hero__fleur--bas {
  transform: translateY(calc((-1 + 7 * var(--th-p)) * var(--th-course)))
    rotate(calc((20 + 32 * var(--th-p)) * 1deg));
}

/* The script writes --th-p on the stage every frame while the block is in
   view, and does its own easing, so there is deliberately no transition here:
   two smoothings stacked on top of each other would drag twice.

   The script still needs to know how long that easing lasts, and
   getComputedStyle().getPropertyValue('--th-ease') would hand back the
   unresolved token rather than a duration. So the value is carried by a probe:
   an element with no ink and no size but a real box — `visibility: hidden`,
   never `display: none`, which would resolve nothing — whose
   transition-duration and width are always computed. */
.triptych-hero__sonde {
  position: absolute;
  visibility: hidden;
  width: 1px;
  height: 1px;
  transition-duration: var(--th-ease);
  transition-property: opacity;
  pointer-events: none;
}

/* ==========================================================================
   7. Responsive type
   --------------------------------------------------------------------------
   Only the title changes size: the reference keeps the eyebrow and the link at
   a fixed size, and the collage is already fluid because it is built out of
   percentages of the plate.
   ========================================================================== */

@media (max-width: 991px) {
  .triptych-hero {
    --th-title: calc(3 * var(--th-font-size)); /* 54px */
    --th-pad-bottom: calc(3.6667 * var(--th-font-size)); /* 66px */
  }
}

@media (max-width: 767px) {
  .triptych-hero {
    --th-title: calc(2.6667 * var(--th-font-size)); /* 48px */
    --th-pad-bottom: calc(3.2223 * var(--th-font-size)); /* 58px */
  }
}

@media (max-width: 479px) {
  .triptych-hero {
    --th-title: calc(2.3334 * var(--th-font-size)); /* 42px */
    --th-pad-bottom: calc(3 * var(--th-font-size)); /* 54px */
    --th-pad-x: calc(0.5556 * var(--th-font-size)); /* 10px */
  }
}

/* ==========================================================================
   8. Fallbacks
   ========================================================================== */

/* A drift tied to the wheel is motion, and a delay is motion spread over time.
   The arrangement itself — the tilt, the overlap, the veil — is a picture, so
   it stays: --th-p is pinned mid-travel, where the collage reads best, and the
   script sees the same query and stops writing to it. */
@media (prefers-reduced-motion: reduce) {
  .triptych-hero__pile {
    --th-p: 0.35;
  }

  .triptych-hero__lien {
    transition: none;
  }
}

/* In forced-colours mode the veil and the hairlines disappear into the system
   palette; the photographs stay, and the link keeps a visible border. */
@media (forced-colors: active) {
  .triptych-hero__volet--centre {
    background-image: none;
  }

  .triptych-hero__filet {
    background-color: CanvasText;
  }

  .triptych-hero__lien {
    border-bottom-color: LinkText;
  }
}

@media print {
  .triptych-hero__pile {
    --th-p: 0.35;
  }

  .triptych-hero {
    overflow-x: visible;
  }
}
