* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Display voice: Sekuya, self-hosted. It is SIL OFL 1.1 (see
   assets/fonts/Sekuya-OFL.txt), so the file ships with the site instead of
   being fetched from fonts.gstatic.com on every visit — same Law 25 reasoning
   that already applies to the body and machine faces. Subset to latin +
   latin-ext, so the French edition is covered by the same file. */
@font-face {
  font-family: "Sekuya";
  src: url("assets/fonts/Sekuya-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

/* Body voice: Instrument Sans, self-hosted variable file (400–700, latin
   subset — full French incl. « » and Œ). Helvetica stays as fallback only. */
@font-face {
  font-family: "Instrument Sans";
  src: url("assets/fonts/InstrumentSans-var.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}

/* Machine layer: Fragment Mono — a monospaced Helvetica. Labels, captions,
   index numerals and prices only; never running prose. */
@font-face {
  font-family: "Fragment Mono";
  src: url("assets/fonts/FragmentMono-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

:root {
  --accent: #2b4bf2;
  /* the accent as small text on the dark ground (the "recommended" tag):
     a lighter tint of it, 5.6:1 there, where the accent itself is 3.1:1 */
  --accent-ink: #6b81f6;
  --body-gray: #a6a9ae;
  --serif: "Sekuya", Didot, Georgia, serif;
  --sans: "Instrument Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono: "Fragment Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* Fluid scale: 1rem = 16px at the 1920px design width, everything sized in
   rem scales proportionally on other screens (laptop, LG monitor alike).
   Clamped so tiny/huge screens don't get absurd type. */
html {
  font-size: clamp(12.5px, 0.8333vw, 22px);
  background: #000;
}

body {
  background: #000;
  overscroll-behavior: none;
  font-family: var(--sans);
}

/* ---------- layers ---------- */

#seq {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100dvh;
  display: block;
  z-index: 0;
}

.dim {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(0, 0, 0, 0.55) 0%,
    rgba(0, 0, 0, 0.32) 30%,
    rgba(0, 0, 0, 0.08) 48%,
    transparent 60%);
}

/* shader fog (#fogfx, drawn by fog.js): domain-warped fBm noise rendered at
   low internal resolution — upscale + slight blur melt it into the footage.
   Screen blend: shader's black = invisible, fog brightness adds over film. */
.fog {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100dvh;
  z-index: 2;
  pointer-events: none;
  mix-blend-mode: screen;
  filter: blur(0.375rem);
  opacity: 0.48; /* 0.7 − 5% − 10% − 20% */
}

#spacer {
  position: relative;
  width: 100%;
  pointer-events: none;
}

/* ---------- nav ---------- */

.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  /* height matches the logo block (top 1.25 + 8.75 + 1.25) so the menu centers on it */
  height: 11.25rem;
  padding: 0 3.375rem;
}

/* animated logo: a white mark on a transparent ground (assets/mark/,
   baked 2026-09-28 from the old black-on-white GIF with the same invert and
   contrast that used to be applied here, alpha taken from the result). It
   needs no filter and no blend: the screen blend it replaces was not
   applied over the canvas by iOS Safari, which showed a black square. */
.brand-anim {
  position: fixed;
  top: 1.25rem;
  left: 3.375rem;
  width: 8.75rem;
  height: auto;
  z-index: 6;
  pointer-events: none;
}

/* keeps nav legible when the statue's head rises into it */
.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  height: 150%;
  background: linear-gradient(rgba(0, 0, 0, 0.55), transparent);
  pointer-events: none;
  z-index: -1;
}

.links {
  display: flex;
  gap: 3.625rem;
}

/* phone-only furniture — styled in the max-width:760px block */
.menu-btn,
.menu {
  display: none;
}

.links a {
  font-size: max(12px, 0.9375rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.85);
  font-weight: 700;
  position: relative;
  /* real hit area without moving the baseline */
  padding: 0.875rem 0;
}

.links a.active::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -0.6875rem;
  width: 100%;
  height: 0.125rem;
  background: var(--accent);
}

/* ---------- left rail ---------- */

.rail {
  position: fixed;
  left: 3.375rem;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.25rem;
}

/* scene ticker: each segment is a dot; the active one morphs into the accent line */
.rail i {
  width: 0.3125rem;
  height: 0.3125rem;
  border-radius: 0.1875rem;
  background: rgba(255, 255, 255, 0.55);
  margin-left: 0.0625rem;
  transition:
    width 0.3s cubic-bezier(0.25, 1, 0.5, 1),
    height 0.3s cubic-bezier(0.25, 1, 0.5, 1),
    background-color 0.3s cubic-bezier(0.25, 1, 0.5, 1),
    box-shadow 0.3s cubic-bezier(0.25, 1, 0.5, 1);
}

.rail i.active {
  width: 2.75rem;
  height: 0.1875rem;
  background: var(--accent);
  box-shadow: 0 0 0.75rem rgba(43, 75, 242, 0.8);
}

/* ---------- scenes ---------- */

.scene {
  position: fixed;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
}

.scene > * {
  pointer-events: auto;
}

/* scene 1 — hero (statue center-right, ring halo) */

.hero-title {
  position: absolute;
  left: 8.5%;
  top: 33.8%;
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 7.25rem;
  letter-spacing: 0.015em;
  line-height: 1.04;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-shadow: 0 0.125rem 1.875rem rgba(0, 0, 0, 0.55);
}

.hero-copy {
  position: absolute;
  left: 8.5%;
  top: 60.5%;
  max-width: 40rem;
  width: 44%;
  font-size: max(16px, 1.125rem);
  line-height: 1.6;
  color: #d9dee8;
  font-weight: 700;
  text-shadow: 0 0.0625rem 0.875rem rgba(0, 0, 0, 0.85);
}

.scroll-cue {
  position: absolute;
  left: 8.5%;
  bottom: 7%;
  font-family: var(--mono);
  /* 11px is the floor for functional text; at 10px this failed on high-DPI
     and on small viewports, and it is the one line telling the reader the
     price is further down. */
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}

.scroll-cue::after {
  content: "";
  display: block;
  margin-top: 0.75rem;
  width: 1px;
  height: 2.125rem;
  background: linear-gradient(rgba(255, 255, 255, 0.5), transparent);
}

/* attention dot: rides down the line every few seconds asking for a scroll */
.scroll-cue::before {
  content: "";
  position: absolute;
  left: -1px;
  top: 1.5rem;
  width: 0.1875rem;
  height: 0.1875rem;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0.375rem rgba(255, 255, 255, 0.8);
  opacity: 0;
  animation: cue-drop 4.2s cubic-bezier(0.5, 0, 0.65, 1) infinite;
}

@keyframes cue-drop {
  0%   { transform: translateY(0); opacity: 0; }
  12%  { opacity: 1; }
  70%  { opacity: 0.9; }
  100% { transform: translateY(2.0625rem); opacity: 0; }
}

/* scene 2 — profile, services on the empty left */

#s2 .info-block {
  position: absolute;
  left: 11%;
  width: 36rem;
}

#s2 .info-block:nth-child(1) { top: 21%; }
#s2 .info-block:nth-child(2) { top: 44.5%; }
#s2 .info-block:nth-child(3) { top: 68%; width: 30rem; }

#s2 h2 {
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 4.25rem;
  line-height: 1;
  margin-bottom: 1rem;
}

#s2 p {
  font-size: max(15px, 1.05rem);
  line-height: 1.62;
  color: #c7ccd6;
  font-weight: 700;
  max-width: 32rem;
  text-shadow: 0 0.0625rem 0.75rem rgba(0, 0, 0, 0.7);
}

/* scene 3 — close-up, statement + CTA inside the intact ring */

.statement {
  position: absolute;
  left: 8.5%;
  top: 30%;
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 3.375rem;
  line-height: 1.25;
  display: flex;
  flex-direction: column;
  text-shadow: 0 0.125rem 1.625rem rgba(0, 0, 0, 0.6);
}

.cta {
  position: absolute;
  left: 8%;
  top: 62%;
  display: inline-block;
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-decoration: none;
  color: #000;
  background: #fff;
  padding: 1rem 1.875rem;
  border-radius: 999px;
  font-weight: 700;
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.cta:hover {
  transform: translateY(-0.125rem);
  box-shadow: 0 0 2.125rem rgba(255, 255, 255, 0.35);
}

.cta:active {
  transform: translateY(0);
  box-shadow: 0 0 1.125rem rgba(255, 255, 255, 0.25);
}

.links a:focus-visible,
.cta:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 2px;
}

/* ---------- chrome ---------- */

#progress {
  position: fixed;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 2px;
  background: rgba(255, 255, 255, 0.08);
  z-index: 10;
  transition: opacity 0.6s ease;
}

#progress-fill {
  height: 100%;
  width: 0%;
  background: var(--accent);
  transition: width 0.15s linear;
}

#progress.done {
  opacity: 0;
}

#hud {
  position: fixed;
  top: 12px;
  right: 14px;
  z-index: 20;
  font: 11px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace;
  color: rgba(255, 255, 255, 0.55);
  background: rgba(0, 0, 0, 0.5);
  padding: 6px 10px;
  border-radius: 6px;
  letter-spacing: 0.04em;
}

/* ---------- phones ----------
   Phones run the portrait render (frames_v3_mobile): the same take, 9:19.5,
   with a synthetic sky-pad above the statue. That pad plus the empty upper
   third of the footage is the type area; the statue holds the right edge and
   the bottom, exactly like the desktop composition turned on its side.

   Percentages below are read straight off the footage: in the services beat
   the statue's silhouette never crosses x=49% above y=73%, so the copy column
   stops at 50% and the blocks sit above that line. */
@media (max-width: 760px) {
  html { font-size: 16px; }
  .links, .fog { display: none; }

  /* portrait needs readability at top and bottom, where the type sits — but
     keep a softer version of the landscape wipe so the copy column stays on a
     settled ground where it runs alongside the statue */
  .dim {
    background: linear-gradient(96deg,
      rgba(0, 0, 0, 0.42) 0%,
      rgba(0, 0, 0, 0.2) 34%,
      transparent 62%);
  }

  .dim::before,
  .dim::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    pointer-events: none;
  }

  /* the sky-pad is already near-black — this only has to carry the type, so
     keep it light or the top half crushes into a flat slab */
  .dim::before {
    top: 0;
    height: 52%;
    background: linear-gradient(rgba(0, 0, 0, 0.42), rgba(0, 0, 0, 0.14) 48%, transparent);
  }

  .dim::after {
    bottom: 0;
    height: 38%;
    background: linear-gradient(transparent, rgba(0, 0, 0, 0.34) 46%, rgba(0, 0, 0, 0.66));
  }

  /* ---- nav ---- */

  .nav {
    height: calc(64px + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) 18px 0;
    justify-content: flex-end;
  }

  .nav::before { height: 220%; }

  .brand-anim {
    top: calc(env(safe-area-inset-top) + 16px);
    left: 20px;
    width: 88px;
  }

  .menu-btn {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6px;
    width: 44px;
    height: 44px;
    margin-right: -10px;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    z-index: 10;
  }

  .menu-btn i {
    display: block;
    width: 24px;
    height: 1.5px;
    margin-left: auto;
    background: rgba(255, 255, 255, 0.9);
    transition: transform 0.32s cubic-bezier(0.25, 1, 0.5, 1),
      opacity 0.2s ease;
  }

  .menu-btn i:last-child { width: 16px; }

  .menu-open .menu-btn i:first-child { transform: translateY(3.75px) rotate(45deg); }
  .menu-open .menu-btn i:last-child { width: 24px; transform: translateY(-3.75px) rotate(-45deg); }

  .menu {
    position: fixed;
    inset: 0;
    z-index: 8;
    display: flex;
    flex-direction: column;
    gap: 22px;
    /* the items sit in the space under the mark (it ends 104px below the
       safe area), centred there by the auto margins below while they fit,
       so none of them ever slides under it (at 320x460 the first link did) */
    padding: calc(env(safe-area-inset-top) + 112px) 34px calc(env(safe-area-inset-bottom) + 24px);
    background: rgba(4, 6, 10, 0.86);
    backdrop-filter: blur(22px);
    -webkit-backdrop-filter: blur(22px);
    /* a touch on the panel must not scrub the sequence behind it */
    touch-action: none;
    overscroll-behavior: contain;
  }

  .menu[hidden] { display: none; }

  .menu > :first-child { margin-top: auto; }
  .menu > :last-child { margin-bottom: auto; }

  /* the page's sections, one under the other (2026-10-06) */
  .menu-links {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 11px;
  }

  .menu a {
    font-family: var(--serif);
    font-weight: 400;
    /* an index, not a poster: the display face small enough that the
       widest entry ("Questions and answers", "Deux façons de commencer")
       stays on one line and the six entries, the pill, the language and
       the two boxes all fit above the foot of a 659px screen */
    font-size: clamp(15px, 4.3vw, 17.5px);
    line-height: 1.25;
    letter-spacing: 0.02em;
    color: #fff;
    text-decoration: none;
  }


  .menu a.active { color: var(--accent); }

  .menu .menu-cta {
    margin-top: 14px;
    align-self: flex-start;
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: #000;
    background: #fff;
    padding: 15px 28px;
    border-radius: 999px;
  }

  /* a menu that opens on the pill (the one-pager, 2026-09-30) keeps the
     first item's auto margin, so its items stay centred under the mark;
     the 14px above is the room under the links when there are some */
  .menu-cta:first-child { margin-top: auto; }

  /* keep the mark and the close button above the open panel — .nav is its own
     stacking context, so the button can only clear the panel if the header does */
  .menu-open .brand-anim { z-index: 9; }
  .menu-open .nav { z-index: 10; }
  .menu-open .nav::before { opacity: 0; }

  /* ---- scene ticker: a row under the thumb instead of a left rail ---- */

  .rail {
    left: 50%;
    top: auto;
    bottom: calc(env(safe-area-inset-bottom) + 16px);
    transform: translateX(-50%);
    flex-direction: row;
    align-items: center;
    gap: 10px;
  }

  .rail i { margin-left: 0; }
  .rail i.active { width: 30px; height: 2px; }
  .menu-open .rail { opacity: 0; }

  /* ---- scene 1 — hero over the sky-pad, copy on the bottom scrim ---- */

  /* Sekuya is a wide display face — "Intelligence," is the widest line on the
     page and sets the ceiling for every phone type size below */
  .hero-title {
    left: 6%;
    /* the mark is a fixed 88px block — on short phones a percentage top slides
       under it, so every scene's first line clears it in absolute terms */
    top: max(12.5%, 118px);
    right: 6%;
    font-size: clamp(25px, 8.5vw, 35px);
    line-height: 1.06;
  }

  /* the French title is two characters longer: at the English size
     "L’intelligence," ran to x=401 on a 390px phone and the whole page
     scrolled sideways (measured 2026-09-26). Same ceiling logic, French word. */
  html[lang="fr-CA"] .hero-title { font-size: clamp(22px, 7.5vw, 30px); }

  .hero-copy {
    left: 7%;
    top: auto;
    bottom: 21%;
    width: 78%;
    max-width: none;
    font-size: clamp(13px, 3.6vw, 14.5px);
    line-height: 1.62;
    font-weight: 400;
    color: #cdd3de;
  }

  .scroll-cue {
    left: 7%;
    bottom: calc(env(safe-area-inset-bottom) + 46px);
    font-size: 9px;
  }

  .scroll-cue::after { height: 26px; }
  @keyframes cue-drop {
    0%   { transform: translateY(0); opacity: 0; }
    12%  { opacity: 1; }
    70%  { opacity: 0.9; }
    100% { transform: translateY(26px); opacity: 0; }
  }

  /* ---- scene 2 — statue holds the right edge, copy runs down the left ---- */

  /* the column tapers with the silhouette: the statue's edge sits near x=64%
     beside the head and walks in to x=40% by the forearm, so each block gets
     the measure its own band allows */
  #s2 .info-block { left: 7%; }

  #s2 .info-block:nth-child(1) { top: max(14%, 118px); width: 45%; }
  #s2 .info-block:nth-child(2) { top: 38%; width: 43%; }
  #s2 .info-block:nth-child(3) { top: 61%; width: 39%; }

  /* headings may run past the copy column — sized so the longest one still
     clears the statue at the height its block sits at */
  #s2 h2 {
    font-size: clamp(19px, 5.6vw, 23px);
    margin-bottom: 8px;
    line-height: 1;
    white-space: nowrap;
  }

  #s2 p {
    font-size: clamp(12.5px, 3.4vw, 14px);
    line-height: 1.6;
    font-weight: 400;
    max-width: 100%;
    color: #c3c9d4;
  }

  /* ---- scene 3 — statement in the clear band above the ring ---- */

  /* both clauses wrap at this measure; the gap keeps them reading as two
     statements rather than one four-line block */
  .statement {
    left: 6%;
    right: 6%;
    top: max(13%, 118px);
    font-size: clamp(22px, 7.2vw, 30px);
    line-height: 1.1;
    /* the last line crosses the statue's gilded hair — needs more than the
       desktop's single soft shadow to hold its edge */
    text-shadow: 0 2px 26px rgba(0, 0, 0, 0.75), 0 1px 5px rgba(0, 0, 0, 0.6);
  }

  .statement span + span { margin-top: 0.34em; }

  .cta {
    left: 7%;
    top: auto;
    bottom: 15%;
    font-size: 11px;
    padding: 16px 30px;
  }

  /* narrow phones: give the column back some measure and lean on the scrim */
  @media (max-width: 360px) {
    #s2 .info-block:nth-child(1) { width: 48%; }
    #s2 .info-block:nth-child(2) { width: 45%; }
    #s2 .info-block:nth-child(3) { width: 41%; }
    .hero-copy { width: 86%; }
  }
}

@media (prefers-reduced-motion: reduce) {
  .rail i,
  .cta {
    transition: none;
  }
  .scroll-cue::before {
    animation: none;
  }
}

/* ================= V4 COPY PREVIEW — new scenes + the base ================= */

/* scenes 1b / 2b — display + short body on the clear left */

#s1b .block-display,
#s2b .block-display {
  position: absolute;
  left: 8.5%;
  top: 34%;
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 3.75rem;
  line-height: 1.12;
  display: flex;
  flex-direction: column;
  text-shadow: 0 0.125rem 1.625rem rgba(0, 0, 0, 0.6);
}

#s1b .block-copy,
#s2b .block-copy {
  position: absolute;
  left: 8.5%;
  top: 52%;
  width: 36rem;
  font-size: max(15px, 1.05rem);
  line-height: 1.62;
  color: #c7ccd6;
  font-weight: 700;
  text-shadow: 0 0.0625rem 0.75rem rgba(0, 0, 0, 0.7);
}

#s2b .block-display { left: 11%; top: 32%; font-size: 3.375rem; }
#s2b .block-copy { left: 11%; top: 45%; width: 36rem; }

/* scene 3 — the ask block, bottom-left, clear of the ring's landing arc */

.ask {
  position: absolute;
  left: 8.5%;
  bottom: 8%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.ask-display {
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 2.625rem;
  line-height: 1.18;
  display: flex;
  flex-direction: column;
  text-shadow: 0 0.125rem 1.625rem rgba(0, 0, 0, 0.6);
  margin-bottom: 1.5rem;
  /* 2026-09-28 copy: "Ninety minutes to see yours." (and the French "Une
     heure et demie pour voir la vôtre.") ran one line across the statue's
     chest; held to the empty left, it breaks into two even lines */
  max-width: 17em;
  text-wrap: balance;
}

/* in the ask's column, where it falls, but positioned (no offset) so its
   44px overlay (hit areas, below) is measured from the button: measured
   from the whole ask it covered the fine print, and a click on "the
   diagnostic" there opened the call (desktop, 2026-09-30; touch screens
   already had this in m-home.css) */
.ask .cta {
  position: relative;
  left: 0;
  top: 0;
}

.ask-micro {
  margin-top: 0.875rem;
  font-family: var(--mono);
  font-size: max(11px, 0.75rem);
  letter-spacing: 0.03em;
  color: rgba(255, 255, 255, 0.72);
  font-weight: 400;
}

/* mid-settle the ask is dissolving — it must not keep taking clicks */
.settling #s3 .cta {
  pointer-events: none;
}

/* nav pill — pinned from pixel zero at every width */

.nav-pill {
  margin-left: 3.25rem;
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-decoration: none;
  color: #000;
  background: #fff;
  padding: 0.8125rem 1.625rem;
  border-radius: 999px;
  font-weight: 700;
}

/* the settle — fixed scrim that turns the held frame into the ground */

.settle {
  position: fixed;
  inset: 0;
  z-index: 3;
  background: #0b0d12;
  opacity: 0;
  pointer-events: none;
}

/* keep in sync with SETTLE_RUNWAY in v3-main.js */
.settle-runway {
  height: 115dvh;
  pointer-events: none;
}

/* The home page (body.home) sizes the canvas, the fog and the runway to the
   large viewport, the height with a phone browser's toolbars away (vh where
   lvh is unknown). In dvh they changed with every slide of the toolbar:
   the footage re-cropped and Act II, below the runway, jumped (Safari does
   no scroll anchoring). On touch screens v3-main.js lays the take out on
   the same height, re-measured only when the width changes, and pins it as
   --lv (html.lv-pin) for the runway and the phone plaque. Services and Work
   run their own engines and keep the rules above. (2026-09-28) */
.home #seq,
.home .fog {
  height: 100vh;
  height: 100lvh;
}

.home .settle-runway {
  height: 115vh;
  height: 115lvh;
}

.lv-pin .home .settle-runway { height: calc(115 * var(--lv)); }

.past-take .scene,
.past-take .rail {
  visibility: hidden !important;
}

/* ---------- the base (Act II) ---------- */

.socle {
  position: relative;
  z-index: 4;
  padding: 0 7% 6rem 10%;
  font-family: var(--sans);
}

.socle .plaque {
  padding: 24vh 0 11rem;
  max-width: 44rem;
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 2.875rem;
  line-height: 1.28;
  text-shadow: 0 0.125rem 1.625rem rgba(0, 0, 0, 0.6);
}

.socle .block {
  max-width: 56rem;
  padding: 5rem 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  /* anchor jumps must clear the fixed nav */
  scroll-margin-top: 8rem;
}

.socle h2 {
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 2.75rem;
  line-height: 1.12;
  margin-bottom: 2.25rem;
}

.socle h3 {
  font-family: var(--serif);
  font-weight: 400;
  color: #fff;
  font-size: 1.625rem;
  line-height: 1.25;
  margin: 3.25rem 0 1rem;
}

.socle p,
.socle dd,
.socle li {
  font-size: clamp(15px, 1.05vw, 19px);
  line-height: 1.7;
  color: #b7bcc6;
  font-weight: 400;
  letter-spacing: 0.012em;
  max-width: 62ch;
}

.socle p + p { margin-top: 1.125rem; }

.socle .kicker {
  margin-top: 1.75rem;
  color: #e8ebf1;
  font-weight: 700;
}

.socle .caption {
  margin: 2.5rem 0 0;
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  font-weight: 400;
}

.socle .fine {
  margin-top: 1.5rem;
  font-size: max(12px, 0.8125rem);
  color: rgba(255, 255, 255, 0.55);
}

/* the one accent moment in the base — price also gets the largest interval
   above it, so the section the page promised arrives with air around it */
#price {
  padding-top: 6.5rem;
}

#price h2::before {
  content: "";
  display: block;
  width: 2.5rem;
  height: 1px;
  background: var(--accent);
  margin-bottom: 1.75rem;
}

/* terms — definition rows, tight inside, generous between */
.socle .terms {
  margin-top: 2.5rem;
}

.socle .terms dt {
  margin-top: 1.75rem;
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  font-weight: 400;
}

.socle .terms dt:first-child {
  margin-top: 0;
}

.socle .terms dd {
  margin-top: 0.5rem;
}

/* price menu — three hairline rows, a menu not a pricing table.
   Name and price share the first baseline; the description sits under the
   name at reading width. Prices are the loudest thing in each row.
   The price column takes what its setup needs, up to 20rem: every English
   setup fits on one line inside it; the French one ("4 999 $ à
   l’implantation", 34rem on one line) breaks after its amount, so the
   name, the description and the examples keep their room at every desktop
   width. */
.menu-rows {
  margin-top: 2rem;
}

.menu-rows .row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) fit-content(20rem);
  column-gap: 3rem;
  row-gap: 0.625rem;
  align-items: baseline;
  padding: 1.875rem 0;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.menu-rows .row:last-child {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.menu-rows .row-name {
  font-family: var(--serif);
  color: #fff;
  font-size: 1.5rem;
  line-height: 1.2;
}

.menu-rows .row-name i {
  font-style: normal;
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.4);
  margin-right: 0.75rem;
}

.menu-rows .row-name em {
  display: inline-block;
  font-style: normal;
  font-family: var(--sans);
  font-weight: 700;
  font-size: max(9.5px, 0.625rem);
  line-height: 1;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #fff;
  background: var(--accent);
  padding: 0.42em 0.8em 0.36em;
  border-radius: 999px;
  margin-left: 0.85rem;
  vertical-align: middle;
  transform: translateY(-0.2em);
  white-space: nowrap;
}

/* under the name: what the package's build or builds usually are */
.menu-rows .row-sub {
  display: block;
  margin-top: 0.4rem;
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(13px, 0.875rem);
  line-height: 1.45;
  letter-spacing: 0.01em;
  color: var(--body-gray);
  max-width: 44ch;
}

.menu-rows .row-desc {
  grid-column: 1;
  grid-row: 2;
  max-width: 44ch;
  font-size: max(13.5px, 0.9375rem);
  color: #a6a9ae;
  line-height: 1.6;
}

.menu-rows .row-price {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--mono);
  color: #fff;
  font-weight: 400;
  font-size: max(14.5px, 1rem);
  white-space: nowrap;
}

/* who-for list */
.socle .reads {
  margin: 1.25rem 0 0 1.125rem;
}

.socle .reads li + li { margin-top: 0.75rem; }

/* answers — quiet rows, a typographic +/− affordance instead of the
   browser's disclosure triangle */
.socle details {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* the following block's border-top already draws the closing hairline */
.socle details:last-of-type {
  border-bottom: 0;
}

.socle summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
  padding: 1.5rem 0;
  font-size: max(15px, 1.0625rem);
  color: #e8ebf1;
  font-weight: 700;
}

.socle summary::-webkit-details-marker { display: none; }

.socle summary::after {
  content: "+";
  font-family: var(--sans);
  font-weight: 400;
  font-size: 1.25rem;
  line-height: 1;
  color: rgba(255, 255, 255, 0.4);
}

.socle details[open] summary::after {
  content: "−";
  color: rgba(255, 255, 255, 0.7);
}

.socle details p {
  margin: 0;
  padding: 0 0 1.75rem;
  max-width: 62ch;
}

/* diagnostic close */
.socle-cta {
  position: static;
  display: inline-block;
  margin-top: 2.5rem;
}

.cold {
  margin-top: 4.5rem;
  padding-top: 2.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

.cold h3 {
  margin-top: 0;
  max-width: 34ch;
}

/* The old .cold form rules lived here. They styled a three-input row that no
   longer exists, and one of them actively broke the replacement: `flex: 1 1
   14rem` on an input that now sits inside a flex COLUMN resolved as a 14rem
   *height*, making every field 175px tall. The enquiry form is styled in full
   at the end of this file. */

.footer {
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  padding-bottom: 2rem;
}

.footer p {
  font-size: max(13px, 0.875rem);
  color: #a6a9ae;
}
.footer p + p { margin-top: 0.75rem; }
.footer strong { color: #e8ebf1; }
.footer p a { color: inherit; text-underline-offset: 0.18em; }
.footer .tel { white-space: nowrap; }

/* ---------- phones ---------- */

@media (max-width: 760px) {
  .nav-pill {
    margin-left: 0;
    margin-right: 0.5rem;
    font-size: 10px;
    padding: 13px 18px;
  }

  #s1b .block-display,
  #s2b .block-display {
    left: 7%;
    right: 6%;
    top: max(14%, 118px);
    font-size: clamp(22px, 7.2vw, 30px);
  }

  #s1b .block-copy,
  #s2b .block-copy {
    left: 7%;
    top: auto;
    bottom: 21%;
    width: 80%;
    font-size: clamp(12px, 3.4vw, 14px);
    font-weight: 400;
    color: #c3c9d4;
  }

  .ask {
    left: 7%;
    right: 7%;
    bottom: calc(env(safe-area-inset-bottom) + 64px);
  }

  .ask-display { font-size: clamp(19px, 6vw, 26px); }

  .socle { padding: 0 6% 4rem; }
  /* 2026-10-06: at 30px the plaque ran eight lines on a 393px phone */
  .socle .plaque { padding: 18vh 0 4.5rem; font-size: clamp(21px, 5.6vw, 30px); line-height: 1.26; max-width: none; }
  /* home: the large viewport, like .home .settle-runway (2026-09-28) */
  .home .socle .plaque { padding-top: 18lvh; }
  .lv-pin .home .socle .plaque { padding-top: calc(18 * var(--lv)); }
  .socle h2 { font-size: 27px; }
  .socle p, .socle dd, .socle li { font-size: 16px; }

  #price { padding-top: 5rem; }

  .menu-rows .row {
    grid-template-columns: 1fr;
    column-gap: 0;
    row-gap: 0.625rem;
  }

  .menu-rows .row-name em {
    margin-left: 0.75rem;
  }

  .menu-rows .row-desc,
  .menu-rows .row-price {
    grid-column: 1;
    grid-row: auto;
  }

  .menu-rows .row-price { white-space: normal; }
}

/* narrow phones: the French label is the longest, and the pill keeps the
   Act I offset (left: 7%), so at 360px it ran past the screen's edge. A
   tighter tracking keeps it on one line, on screen, down to 320px. */
@media (max-width: 374px) {
  .home .socle .socle-cta {
    padding-inline: 18px;
    letter-spacing: 0.16em;
    text-align: center;
  }
}


/* ===========================================================================
   ACT II — the type ladder (a lead paragraph per block, body weight 500),
   the section rhythm and the price menu.
   ======================================================================== */

.socle { --t-lead: clamp(18px, 1.35vw, 23px); }

/* the third type role the base was missing: one lead paragraph per block,
   so a section doesn't open at 46px and drop straight to caption scale */
.socle .block > p:first-of-type {
  font-size: var(--t-lead);
  line-height: 1.52;
  color: #e4e7ec;
  letter-spacing: 0;
  font-weight: 500;
  max-width: 54ch;
}

/* long-form is 500, not 700 — tracking cannot fix a weight */
.socle p,
.socle dd,
.socle li,
.socle details p {
  font-weight: 500;
  letter-spacing: 0.012em;
}

/* heading → its paragraph tight; block → block loose */
.socle h2 { margin-bottom: 0.5em; }
.socle h3 { margin-bottom: 0.42em; }

.socle .block { padding-block: clamp(4.5rem, 9vh, 8rem); }
.socle #price { padding-top: clamp(7rem, 14vh, 12rem); }
.socle #answers { padding-top: clamp(5rem, 10vh, 9rem); }
.socle .footer { padding-top: 3rem; opacity: .78; }

.socle .terms dt { margin-top: 1.6rem; }
.socle .terms dt:first-of-type { margin-top: 0; }
.socle .terms dd { margin-top: 0.35rem; }

/* ---- the price menu ---- */

.menu-rows { margin-top: 2.6rem; border-top: 1px solid rgba(255,255,255,.14); }

.menu-rows .row {
  padding: 2.4rem 0;
  column-gap: 4rem;
  border-top: none;
  border-bottom: 1px solid rgba(255,255,255,.08);
}
.menu-rows .row:last-child { border-bottom: 1px solid rgba(255,255,255,.14); }

.menu-rows .row-name { font-size: 1.75rem; }

/* the setup sits at the SAME weight as the tier it prices. Smaller reads as
   apology; bigger reads as defending. Equal reads as settled. */
.menu-rows .row-price {
  font-family: var(--serif);
  font-size: 1.75rem;
  line-height: 1.2;
  color: #fff;
  font-variant-numeric: tabular-nums;
  text-align: right;
  /* where the column (at most 20rem, above) cannot hold the setup on one
     line, it breaks after its amount, and only there (.keep holds "à
     l’implantation" together): the French setups, at every desktop width.
     Phones set it free again (below). */
  white-space: normal;
  text-wrap: balance;
  letter-spacing: -0.01em;
}
.menu-rows .row-price .keep { white-space: nowrap; }
/* setup and monthly are one cell, so no reflow can separate them —
   drip-pricing law survives down to 390px by construction */
.menu-rows .row-price .then {
  display: block;
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(13px, 0.875rem);
  letter-spacing: 0.01em;
  color: var(--body-gray);
  margin-top: 0.45rem;
}

/* the one display figure on the page — the licence is the thesis, the setups
   are a menu. Boldness spent once. */
.licence-figure { margin: 3.4rem 0 2.4rem; }
.licence-figure .lb {
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--body-gray);
  margin: 0 0 1rem;
}
.licence-figure .fig {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(52px, 6.2vw, 104px);
  line-height: 0.94;
  letter-spacing: -0.02em;
  color: #fff;
  font-variant-numeric: tabular-nums;
  margin: 0;
  white-space: nowrap;
}
.licence-figure .per {
  display: block;
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(15px, 1.05rem);
  letter-spacing: 0.01em;
  color: var(--body-gray);
  margin-top: 0.9rem;
  white-space: normal;
  max-width: 30ch;
}

/* the FAQ rows are the only interactive thing in Act II */
.socle details summary { transition: color .18s ease; }
.socle details summary:hover,
.socle details[open] summary { color: #fff; }

.socle .cold input:focus-visible,
.socle .cold button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (max-width: 760px) {
  .menu-rows .row { padding: 1.9rem 0; grid-template-columns: 1fr; row-gap: .55rem; }
  /* white-space: normal — the desktop nowrap above made the French
     "19 999 $ à l’implantation" a 463px cell that pushed every price row off a
     390px phone (measured 2026-09-26). Setup and monthly still share the cell:
     .then is its own block, so nothing can separate them. */
  .menu-rows .row-price { grid-column: 1; grid-row: 3; text-align: left; font-size: 1.5rem; white-space: normal; }
  /* a 320px phone has no room for "à l’implantation" on one line */
  .menu-rows .row-price .keep { white-space: normal; }
  .menu-rows .row-desc { grid-row: 2; }
  .licence-figure .fig { font-size: clamp(44px, 13vw, 62px); }
}

/* ===========================================================================
   ACT I — the head/body gap. Display and body used to be two independent
   absolutes, so the gap was whatever their two percentages happened to
   leave (400px on a 390px phone). The body flows from the display at a
   fixed interval, and the pair moves as one object at every viewport
   height.
   ======================================================================== */

#s1b .block-display { top: 34%; margin: 0; }
#s1b .block-copy    { top: calc(34% + 9.5rem); }

#s2b .block-display { top: 36%; left: 8.5%; margin: 0; }
#s2b .block-copy    { top: calc(36% + 5.6rem); left: 8.5%; }

#s1b .block-copy,
#s2b .block-copy {
  width: 34rem;
  max-width: 46vw;
  /* the quiet half of a pair, not a caption: 700 at 15px over moving footage
     reads as a warning label */
  font-size: max(16px, 1.15rem);
  font-weight: 500;
  line-height: 1.58;
  letter-spacing: 0.008em;
  color: #cfd4dd;
}

@media (max-width: 760px) {
  #s1b .block-display,
  #s2b .block-display { top: max(15%, 118px); }
  #s1b .block-copy,
  #s2b .block-copy {
    top: calc(max(15%, 118px) + 6.2rem);
    /* stay inside the clear band — the statue's edge is at ~64% by the head */
    width: auto; max-width: 80%;
    font-size: 15px; line-height: 1.55;
  }
}

/* ============================================================
   Accessibility + enquiry form
   Everything here either adds a hit area without moving a pixel,
   or styles the form and the controls around it.
   ============================================================ */

/* ---------- skip link ---------- */
/* The take is ~3,100px of scroll before the offer is reachable. A reader who
   scrolls chooses that; a reader who tabs is trapped in it. */
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  transform: translateY(-160%);
  padding: 0.9rem 1.4rem;
  background: #fff;
  color: #000;
  font-family: var(--sans);
  font-size: max(13px, 0.8125rem);
  font-weight: 700;
  letter-spacing: 0.01em;
  /* a sentence, not a label — uppercase would cost the word shapes that make
     it scannable in the half-second it is on screen */
  text-decoration: none;
  border-radius: 999px;
  transition: transform 0.18s cubic-bezier(0.25, 1, 0.5, 1);
}

.skip-link:focus-visible {
  transform: translateY(0);
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .skip-link { transition: none; }
}

/* ---------- no-JS ---------- */
/* Without JS the canvas never paints and the scenes never get their inline
   opacity, so the page is black. The offer does not depend on any of that. */
.noscript-fallback {
  position: relative;
  z-index: 30;
  max-width: 62ch;
  margin: 0 auto;
  /* clear the fixed nav (11.25rem): the Work title ran into its links */
  padding: 12.5rem 2rem 3rem;
  font-family: var(--sans);
  color: #fff;
}

.noscript-fallback h1 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(38px, 7vw, 76px);
  line-height: 1.06;
  margin-bottom: 1.5rem;
}

.noscript-fallback p {
  color: var(--body-gray);
  font-size: max(14px, 0.9375rem);
  line-height: 1.62;
  margin-bottom: 1rem;
}

.noscript-fallback strong { color: #fff; }

/* ---------- hit areas ---------- */
/* 44px minimum, bought with padding where nothing is painted and with a
   transparent overlay where a pill is. Neither moves the design. */
.links a { padding: 1.15rem 0; }

.nav-pill { position: relative; font-size: max(11px, 0.6875rem); }

.nav-pill::after,
.cta::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: max(44px, 100%);
}

.cta { position: relative; }

/* the phone menu's links (and its language link, 12px of type) reach 44px
   through the same kind of overlay; Services had this on its own, and Home
   and Work fell short (27-39px at 320-393 wide) */
.menu a { position: relative; }

.menu a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: max(44px, 100%);
}

/* ---------- enquiry form ---------- */
.enquiry-form {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 1.25rem;
  margin-top: 1.75rem;
  align-items: flex-end;
}

.field {
  flex: 1 1 15rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  min-width: 0;
}

/* A placeholder is not a label: it vanishes the moment typing starts, and it
   is the first thing lost to autofill, translation and zoom. */
.field > label:not(.consent) {
  font-family: var(--mono);
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.enquiry-form input[type="text"],
.enquiry-form input[type="email"] {
  flex: 0 0 auto; /* the field column sizes it; it must not grow to fill */
  width: 100%;
  min-height: 44px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 0;
  color: #fff;
  font-family: var(--sans);
  font-size: max(16px, 0.9375rem); /* 16px stops iOS zooming the page on focus */
  padding: 0.6rem 0.125rem;
  outline: none;
}

.enquiry-form input[type="text"]:focus,
.enquiry-form input[type="email"]:focus {
  border-bottom-color: #fff;
}

.enquiry-form input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.field.invalid > label { color: #ff9d9d; }
.field.invalid input { border-bottom-color: #ff9d9d; }

/* The error names the problem and the recovery, and sits where the eye
   already is — under the field it belongs to, not in a summary at the top. */
.field-err {
  font-family: var(--sans);
  font-size: max(12px, 0.75rem);
  line-height: 1.45;
  color: #ff9d9d;
}

.field-consent { flex: 1 1 100%; }

.field-consent .consent {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.6rem 0; /* carries the row past 44px without a visible box */
  cursor: pointer;
}

.field-consent .consent span {
  font-family: var(--sans);
  font-size: max(13px, 0.8125rem);
  line-height: 1.5;
  color: var(--body-gray);
  max-width: 52ch;
}

.field-consent input[type="checkbox"] {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 0.1rem;
  accent-color: var(--accent);
  cursor: pointer;
}

.field-consent input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.enquiry-send {
  flex: none;
  min-height: 44px;
  padding: 0 1.75rem;
  font-family: var(--sans);
  font-size: max(11px, 0.6875rem);
  font-weight: 700;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #000;
  background: #fff;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), opacity 0.2s ease;
}

.enquiry-send:hover { transform: translateY(-0.125rem); }
.enquiry-send:active { transform: translateY(0); }

.enquiry-send:disabled {
  opacity: 0.55;
  cursor: progress;
  transform: none;
}

.enquiry-send:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

@media (prefers-reduced-motion: reduce) {
  .enquiry-send { transition: none; }
}

/* One live region for the form. Empty until there is something to say, so a
   screen reader is not handed a blank announcement on load. */
.form-status {
  flex: 1 1 100%;
  font-family: var(--sans);
  font-size: max(12px, 0.75rem);
  line-height: 1.5;
  color: var(--body-gray);
  max-width: 56ch;
}

.form-status:empty { display: none; }
.form-status[data-kind="ok"] { color: #fff; }
.form-status[data-kind="error"] { color: #ff9d9d; }

/* Honeypot. Off-screen rather than display:none — a bot that skips hidden
   fields is not the one this catches. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

@media (max-width: 760px) {
  .skip-link { font-size: 12px; }
  /* the send button goes full width rather than orphaning itself on a line */
  .enquiry-send { flex: 1 1 100%; }
  .noscript-fallback { padding: 7rem 1.5rem 3rem; }
}

/* ===========================================================================
   2026-09-26 — the enquiry panel, the footer, the book lightbox, the
   language switch. Type, colour and spacing follow the tokens above; the
   accent stays an indicator.
   ======================================================================== */

/* ---- fog: rendered at half resolution now, so less blur is needed ---- */
.fog { filter: blur(0.25rem); opacity: 0.42; }

/* ---- language switch in the nav ---- */
.lang {
  position: relative;
  margin-left: 3.625rem;
  padding: 1.15rem 0;
  font-family: var(--mono);
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  text-decoration: none;
  color: rgba(255, 255, 255, 0.72);
  transition: color 0.18s ease;
}
.lang:hover { color: #fff; }
.lang:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 2px; }
.menu .menu-lang {
  margin-top: 0.5rem;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.62);
}

/* ---- the enquiry panel ---- */
.cold { border-top: 0; padding-top: 0; }

.enquiry-panel {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
  gap: 3rem 4rem;
  max-width: 72rem;
  padding: 3.25rem 3.5rem 3.5rem;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.012));
}

.enquiry-kicker {
  margin: 0 0 1.25rem;
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  font-weight: 400;
}

.socle .enquiry-lead h3 {
  margin: 0 0 1.25rem;
  font-size: 1.9rem;
  line-height: 1.16;
  max-width: none;
}

.socle .enquiry-note {
  font-size: max(14px, 0.95rem);
  color: var(--body-gray);
  max-width: 38ch;
}

/* the field errors: the long-form rule (.socle p) outranked .field-err and
   set them as grey body copy; restated here as the lightbox shows them
   (2026-09-28) */
.enquiry-panel .field-err {
  font-family: var(--sans);
  font-size: max(12px, 0.75rem);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: normal;
  color: #ff9d9d;
  max-width: none;
}

.enquiry-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.75rem 1.5rem;
  align-items: start;
  margin: 0;
}
.enquiry-form[hidden] { display: none; }
.enquiry-form .field { flex: none; }
.enquiry-form .field-wide,
.enquiry-form .field-consent,
.enquiry-form .enquiry-actions { grid-column: 1 / -1; }

.enquiry-form input[type="text"],
.enquiry-form input[type="email"],
.enquiry-form textarea {
  width: 100%;
  min-height: 3.25rem;
  padding: 0.85rem 1rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 2px;
  color: #fff;
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(16px, 0.9375rem);
  line-height: 1.5;
  outline: none;
  transition: border-color 0.18s ease, background-color 0.18s ease;
}
.enquiry-form textarea { resize: vertical; min-height: 7rem; }
.enquiry-form input[type="text"]:focus,
.enquiry-form input[type="email"]:focus,
.enquiry-form textarea:focus {
  border-color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.06);
}
.enquiry-form textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.field.invalid input,
.field.invalid textarea { border-color: #ff9d9d; }

.field-consent .consent input {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 0.1rem;
  accent-color: var(--accent);
}

.enquiry-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1.25rem 1.5rem;
  margin-top: 0.25rem;
}

.enquiry-send {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  padding: 1rem 1.75rem;
  border: 0;
  border-radius: 999px;
  background: #fff;
  color: #000;
  font-family: var(--sans);
  font-weight: 700;
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.25s ease, box-shadow 0.25s ease, opacity 0.18s ease;
}
.enquiry-send::after { content: "\2192"; font-size: 1.1em; letter-spacing: 0; }
.enquiry-send:hover { transform: translateY(-0.125rem); box-shadow: 0 0 2.125rem rgba(255, 255, 255, 0.3); }
.enquiry-send:disabled { opacity: 0.6; cursor: default; transform: none; box-shadow: none; }

.socle .form-status,
.book .form-status {
  margin: 0;
  font-size: max(13px, 0.8125rem);
  line-height: 1.5;
  color: var(--body-gray);
  max-width: 40ch;
}
.form-status[data-kind="error"] { color: #ff9d9d; }
.form-status[data-kind="ok"] { color: #e8ebf1; }

.enquiry-done { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.5rem 0; outline: none; }
.enquiry-done[hidden] { display: none; }
.tick { width: 3rem; height: 3rem; margin-bottom: 0.75rem; fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.tick circle { stroke: rgba(255, 255, 255, 0.32); }
.tick path { stroke-dasharray: 40; stroke-dashoffset: 40; animation: tick-draw 0.6s cubic-bezier(0.25, 1, 0.5, 1) 0.15s forwards; }
@keyframes tick-draw { to { stroke-dashoffset: 0; } }
.socle .enquiry-done-h,
.book .enquiry-done-h { font-family: var(--serif); font-size: 2rem; line-height: 1.1; color: #fff; margin: 0; }

/* ---- the footer ----
   Outside main since 2026-09-29 (its own contentinfo landmark), in a
   wrapper that is .socle too, so every rule below and the page's measure
   still apply; main gives its bottom padding to that wrapper, so nothing
   moves by a pixel. */
main.socle { padding-bottom: 0; }

.socle .footer {
  max-width: 72rem;
  padding: 5rem 0 2.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
  opacity: 1;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 3rem 2.5rem;
}
.footer-mark { display: block; width: 3.5rem; height: auto; margin-bottom: 1.5rem; }
.socle .footer-line {
  margin: 0 0 0.75rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.375rem;
  line-height: 1.25;
  color: #fff;
  max-width: 18ch;
}
.socle .footer-where,
.socle .footer-h {
  margin: 0;
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}
.socle .footer-h { margin-bottom: 0.5rem; }
.footer-col { display: flex; flex-direction: column; align-items: flex-start; gap: 0.7rem; }
.footer-col a {
  color: #c3c9d4;
  text-decoration: none;
  font-size: max(14px, 0.9375rem);
  font-weight: 500;
  line-height: 1.4;
  border-bottom: 1px solid transparent;
  transition: color 0.18s ease, border-color 0.18s ease;
}
.footer-col a:hover { color: #fff; border-bottom-color: rgba(255, 255, 255, 0.4); }
.footer-col a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }
.socle .footer-small { margin: 0.25rem 0 0; font-size: max(12.5px, 0.8125rem); color: rgba(255, 255, 255, 0.5); max-width: 24ch; }
.footer-base {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  margin-top: 4rem;
  padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.socle .footer-base p {
  margin: 0;
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  max-width: none;
}
.footer-lang a { color: rgba(255, 255, 255, 0.75); text-decoration: none; transition: color 0.18s ease; }
.footer-lang a:hover { color: #fff; }
.footer-lang [aria-current] { color: #fff; }

/* ---- the book lightbox ---- */
.book {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100dvh;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: #fff;
  display: grid;
  place-items: center;
}
.book:not([open]) { display: none; }
.book::backdrop {
  background: rgba(4, 6, 10, 0.72);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
}
.book-panel {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 8fr);
  width: min(74rem, calc(100vw - 4rem));
  max-height: calc(100dvh - 4rem);
  overflow: auto;
  background: #0b0d12;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 2rem 6rem rgba(0, 0, 0, 0.6);
  animation: book-rise 0.32s cubic-bezier(0.25, 1, 0.5, 1);
}
@keyframes book-rise {
  from { opacity: 0; transform: translateY(1.25rem); }
  to { opacity: 1; transform: none; }
}
/* touch screens: a drag that reaches the panel's end stops there instead of
   carrying on into the page behind (2026-09-28) */
@media (pointer: coarse) {
  .book-panel { overscroll-behavior: contain; }
}
.book-side {
  position: relative;
  min-height: 100%;
  /* the hero frame: the whole figure with the halo fits the tall column
     uncut (frame 190 is a close-up the frame itself crops, 2026-09-26) */
  background: #000 url("/frames_v3_webp/frame_0000.webp") 50% 50% / cover no-repeat;
}
.book-side::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(11, 13, 18, 0) 72%, #0b0d12 100%),
    linear-gradient(180deg, rgba(11, 13, 18, 0.15), rgba(11, 13, 18, 0.6));
}
/* --kb: the height an on-screen keyboard covers, set by the page's script
   while the dialog is open on a touch screen (0 otherwise), so the send
   button can be scrolled above the keyboard */
.book-main { padding: 3.25rem 3.5rem calc(3.5rem + var(--kb, 0px)); min-width: 0; }
/* the heading takes focus on touch screens: a place to land, not a control */
.book-main h2:focus { outline: none; }
.book-main h2 {
  margin: 0 0 2rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 2.125rem;
  line-height: 1.16;
  color: #fff;
  max-width: 20ch;
}
.book-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  background: rgba(11, 13, 18, 0.7);
  color: #fff;
  font: 400 24px/1 var(--sans);
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease;
}
.book-close:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.4); }
.book input:focus-visible,
.book textarea:focus-visible,
.book button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.book .field > label:not(.consent) {
  font-family: var(--mono);
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.book .field { display: flex; flex-direction: column; gap: 0.4rem; min-width: 0; }
.book .field-consent .consent { display: flex; gap: 0.75rem; align-items: flex-start; padding: 0.6rem 0; cursor: pointer; }
.book .field-consent .consent span { font-family: var(--sans); font-size: max(13px, 0.8125rem); line-height: 1.5; color: var(--body-gray); max-width: 52ch; }
.book .field-err { font-family: var(--sans); font-size: max(12px, 0.75rem); line-height: 1.45; color: #ff9d9d; }
.book .field.invalid > label { color: #ff9d9d; }
.book .hp { position: absolute; left: -9999px; }
.book .enquiry-done p { font-size: max(15px, 1rem); color: #b7bcc6; }
html.book-open { overflow: hidden; }

@media (max-width: 760px) {
  .lang { margin-left: 0; margin-right: 14px; padding: 12px 0; font-size: 10px; }
  .enquiry-panel { grid-template-columns: 1fr; gap: 1.75rem; padding: 1.75rem 1.25rem 2rem; }
  .socle .enquiry-lead h3 { font-size: 24px; }
  .enquiry-form { grid-template-columns: 1fr; gap: 1.25rem; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 2.25rem 1.5rem; }
  .footer-brand { grid-column: 1 / -1; }
  .footer-base { flex-direction: column; }
  /* full screen, one column. The panel is a plain block here so the close
     button can stick to its top right through the whole scroll; the still
     is a 22svh band; the notch and the home indicator are kept clear
     (viewport-fit=cover). (2026-09-28: was a 30vh band, and the close
     button scrolled away with the form.) */
  .book-panel { display: block; width: 100vw; height: 100dvh; max-height: none; border: 0; }
  .book-close {
    position: sticky;
    top: calc(env(safe-area-inset-top) + 1rem);
    right: auto;
    margin: 0 calc(env(safe-area-inset-right) + 1rem) -44px auto;
  }
  /* the band shows the head and the ring, not the torso (2026-10-06) */
  .book-side { min-height: 26vh; min-height: 26svh; background-position: 50% 19%; }
  .book-main {
    padding: 1.5rem max(1.25rem, env(safe-area-inset-right))
      calc(3rem + env(safe-area-inset-bottom) + var(--kb, 0px))
      max(1.25rem, env(safe-area-inset-left));
  }
  .book-main h2 { font-size: 21px; margin-bottom: 1rem; }
  .book .enquiry-form { grid-template-columns: 1fr; gap: 1.25rem; }
}

@media (prefers-reduced-motion: reduce) {
  .book-panel { animation: none; }
  .tick path { animation: none; stroke-dashoffset: 0; }
  .enquiry-send, .lang, .footer-col a { transition: none; }
}

/* ---- back to top (2026-09-26) ---- */
/* a transparent hit area over the mark (the mark itself is an img that
   takes no pointer events) */
.brand-hit {
  position: fixed;
  top: 1.25rem;
  left: 3.375rem;
  width: 8.75rem;
  height: 8.75rem;
  z-index: 7;
  border-radius: 4px;
}
.brand-hit:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.menu-open .brand-hit { z-index: 9; }

.to-top {
  position: fixed;
  right: 3.375rem;
  bottom: 3rem;
  z-index: 5;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px;
  background: rgba(11, 13, 18, 0.55);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: rgba(255, 255, 255, 0.85);
  font: 400 18px/1 var(--mono);
  cursor: pointer;
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity 0.32s cubic-bezier(0.25, 1, 0.5, 1), transform 0.32s cubic-bezier(0.25, 1, 0.5, 1),
    background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.to-top[hidden] { display: none; }
.to-top.on { opacity: 1; transform: none; }
.to-top:hover { background: rgba(255, 255, 255, 0.1); border-color: rgba(255, 255, 255, 0.5); color: #fff; }
.to-top:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

@media (max-width: 760px) {
  .brand-hit { top: calc(env(safe-area-inset-top) + 16px); left: 20px; width: 88px; height: 88px; }
  .to-top { right: 18px; bottom: calc(env(safe-area-inset-bottom) + 16px); }
}
@media (prefers-reduced-motion: reduce) {
  .to-top { transition: none; transform: none; }
}

/* ===========================================================================
   2026-09-29 — four pages, two doors. The Work switch, the price rows'
   examples and the proof line, the door cards, the door choice in the
   enquiry form. New classes only; nothing above changes.
   ======================================================================== */

/* ---------- the Work switch ----------
   Every link to the Work page (the nav, the phone menu and the footer, on
   every page, EN and FR) carries data-work. The rule below, uncommented,
   hides them all; commented out, as it is, Work shows. */
/* [data-work] { display: none !important; } */

/* ---------- the price rows: what it is, then a few examples ----------
   The description keeps its place under the name; a mono "For example" and
   a short list follow in the same column, so the name and the price still
   share the first baseline and the price column still lines up. */
.menu-rows .row-ex {
  grid-column: 1;
  grid-row: 3;
  margin-top: 0.85rem;
}

.socle .menu-rows .row-ex-h {
  margin: 0 0 0.6rem;
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10px, 0.625rem);
  line-height: 1.4;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  max-width: none;
}

.menu-rows .row-ex ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.socle .menu-rows .row-ex li {
  position: relative;
  max-width: 58ch;
  padding-left: 1.2em;
  font-size: max(13px, 0.875rem);
  line-height: 1.5;
  color: #9ea2a9;
}

.socle .menu-rows .row-ex li + li { margin-top: 0.3rem; }

/* a short hairline, the page's own mark, instead of a bullet */
.menu-rows .row-ex li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.75em;
  width: 0.55em;
  height: 1px;
  background: rgba(255, 255, 255, 0.35);
}

/* the proof: one plain sentence after the menu, before the licence */
.socle .proof {
  margin-top: 2.6rem;
  max-width: 60ch;
  color: #e4e7ec;
}

/* ---------- the doors ----------
   Two framed cards on the enquiry panel's 3% lift: the price and the length
   in mono, the name in the serif, what you get, and the button, which sits
   on the card's floor so the two line up. */
.doors {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.5rem;
  margin-top: 2.5rem;
}

.door {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
  padding: 2.25rem 2.25rem 2.5rem;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.012));
  scroll-margin-top: 10.5rem;
}

/* the meta follows the name in the document, so a screen reader that jumps
   to the heading hears the price and the length next; it is drawn above */
.socle .door-meta {
  order: -1;
  margin: 0 0 1rem;
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10.5px, 0.6875rem);
  line-height: 1.5;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  max-width: none;
}

.socle .door-h {
  margin: 0 0 0.9rem;
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.9rem;
  line-height: 1.16;
  color: #fff;
}

.socle .door-text {
  margin: 0 0 2rem;
  max-width: 44ch;
  font-size: max(14px, 0.95rem);
  line-height: 1.6;
  color: var(--body-gray);
}

.socle .door-text + .door-text { margin-top: -1.25rem; }

/* .cta is relative with Act I's offsets (left 8%, top 62%): cleared here,
   so the pill sits on the card's floor */
.door .door-cta {
  left: 0;
  top: 0;
  bottom: auto;
  margin-top: auto;
}

/* the jump from a door's button lands the form under the nav and the mark */
.home .socle .cold { scroll-margin-top: 10.5rem; }

/* ---------- the door choice in the form ----------
   A fieldset of three native radios, each a tile the size of an input: the
   name over its price, the whole tile a label. The chosen one takes the
   focus border; the accent marks the radio itself, as on the consent box. */
.enquiry-form .field-door {
  grid-column: 1 / -1;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.field-door legend {
  margin: 0 0 0.6rem;
  padding: 0;
  font-family: var(--mono);
  font-size: max(11px, 0.6875rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.door-opts {
  display: grid;
  gap: 0.5rem;
}

.door-opt {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 0.85rem;
  row-gap: 0.1rem;
  min-height: max(44px, 3.25rem);
  padding: 0.65rem 1rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 2px;
  cursor: pointer;
  transition: border-color 0.18s ease, background-color 0.18s ease;
}

.door-opt:hover { border-color: rgba(255, 255, 255, 0.34); }

.door-opt:has(input:checked) {
  border-color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.07);
}

.door-opt input {
  grid-row: 1 / span 2;
  width: 18px;
  height: 18px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.door-opt input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.door-opt-name {
  grid-column: 2;
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(14px, 0.9375rem);
  line-height: 1.3;
  color: #fff;
}

.door-opt-note {
  grid-column: 2;
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

@media (max-width: 760px) {
  .menu-rows .row-ex { grid-row: 3; margin-top: 0.4rem; }
  .menu-rows .row-price { grid-row: 4; margin-top: 0.5rem; }
  .socle .menu-rows .row-ex li { font-size: 14px; }

  .doors { grid-template-columns: minmax(0, 1fr); gap: 1rem; margin-top: 2rem; }
  .door { padding: 1.75rem 1.25rem 2rem; }
  .socle .door-h { font-size: 24px; }
  .socle .door-text { max-width: none; font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .door-opt { transition: none; }
}

/* ===========================================================================
   Reach us directly: the email and the phone as two small boxes, each one
   link with its value written out, as on the Contact page: in the book
   lightbox (beside the form on a wide screen, under it on a phone) and in
   the phone menu, under the links. The door tiles' hairline and lift, a
   mono label over the value.
   ======================================================================== */
.reach-boxes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.reach-box {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.15rem;
  min-height: 44px;
  padding: 0.55rem 0.9rem 0.6rem;
  background: rgba(255, 255, 255, 0.035);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 2px;
  color: #fff;
  text-decoration: none;
  transition: border-color 0.18s ease, background-color 0.18s ease;
}

.reach-box:hover {
  border-color: rgba(255, 255, 255, 0.34);
  background: rgba(255, 255, 255, 0.06);
}

.reach-box:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.reach-lb {
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10.5px, 0.625rem);
  line-height: 1.3;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.reach-v {
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(14px, 0.875rem);
  line-height: 1.35;
  letter-spacing: 0.005em;
  color: #fff;
  white-space: nowrap;
}

/* the lightbox, on a wide screen: at the foot of the still, beside the
   form, so the form keeps its column to itself and nothing needs a scroll.
   It follows the form in the document (the keyboard reaches it last); the
   grid draws it in the still's cell, over a deeper shade at the foot. */
.book-side,
.book-reach { grid-column: 1; grid-row: 1; }
.book-main { grid-column: 2; grid-row: 1; }

.book-reach {
  position: relative;
  z-index: 1;
  align-self: end;
  margin: 0 2.25rem 2.5rem;
}

.book-reach .enquiry-kicker {
  margin-bottom: 0.85rem;
  color: rgba(255, 255, 255, 0.7);
}

.book-reach .reach-box { background: rgba(11, 13, 18, 0.72); }
.book-reach .reach-box:hover { background: rgba(24, 27, 34, 0.82); }

@media (min-width: 761px) {
  .book-side::after {
    background:
      linear-gradient(90deg, rgba(11, 13, 18, 0) 72%, #0b0d12 100%),
      linear-gradient(180deg, rgba(11, 13, 18, 0.15), rgba(11, 13, 18, 0.6) 58%, rgba(11, 13, 18, 0.9));
  }
}

@media (max-width: 760px) {
  /* the menu: one box over the other, under the language link. The menu's
     own link rules (the serif, the size, Contact's padding) stop here. */
  .menu .menu-reach {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }

  .menu .reach-box {
    padding: 8px 13px 9px;
    font-size: 15px;
    line-height: 1.3;
  }

  .menu .reach-v { font-size: 15px; }

  /* the lightbox on a phone is one column: the boxes follow the form,
     past a hairline, and carry the panel's foot (the safe area, and the
     room an open keyboard covers) that the form's column had */
  .book-main { padding-bottom: 0; }

  .book-reach {
    margin: 2rem max(1.25rem, env(safe-area-inset-right)) 0 max(1.25rem, env(safe-area-inset-left));
    padding: 1.4rem 0 calc(3rem + env(safe-area-inset-bottom) + var(--kb, 0px));
    border-top: 1px solid rgba(255, 255, 255, 0.08);
  }

  .book-reach .reach-box { background: rgba(255, 255, 255, 0.035); }
}

/* short phones (an iPhone SE with Safari's bars, 320x460): the language
   moves up beside the pill, so the links, the pill, the language and the
   two boxes all fit under the mark with every hit area still 44px (the
   links' 18px gaps keep their overlays from overlapping) */
@media (max-width: 760px) and (orientation: portrait) and (max-height: 620px) {
  .menu {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    align-content: center;
    align-content: safe center;
    column-gap: 24px;
    row-gap: 18px;
  }

  .menu > :first-child,
  .menu > :last-child { margin: 0; }

  .menu > a:not(.menu-cta):not(.menu-lang),
  .menu .menu-links,
  .menu .menu-reach { grid-column: 1 / -1; }

  /* the six section links, a step smaller and tighter (2026-10-06) */
  .menu .menu-links { gap: 7px; }
  .menu .menu-links a { font-size: 15px; }

  .menu .menu-cta { margin-top: 2px; }
  .menu .menu-lang { margin-top: 2px; align-self: center; justify-self: start; }
  .menu .menu-reach { gap: 6px; }
}

/* a small phone turned (667x375 and less): no room under the mark, so the
   menu starts under the nav bar, right of the mark, in two columns: the
   links and the pill, then the language over the two boxes. A row every
   45px or more, so no two 44px hit areas overlap (at 10px apart the links'
   overlapped by 9px; 2026-09-30, as main's turned menu does) */
@media (max-width: 760px) and (orientation: landscape) and (max-height: 500px) {
  .menu {
    display: grid;
    grid-template-columns: max-content minmax(0, max-content);
    grid-auto-rows: min-content;
    align-content: center;
    column-gap: 36px;
    row-gap: 19px;
    padding: calc(env(safe-area-inset-top) + 60px) max(24px, env(safe-area-inset-right))
      max(14px, env(safe-area-inset-bottom)) calc(max(20px, env(safe-area-inset-left)) + 108px);
    overflow-y: auto;
    touch-action: pan-y;
  }

  .menu > :first-child,
  .menu > :last-child { margin: 0; }

  .menu > a,
  .menu .menu-links { grid-column: 1; }
  .menu a { font-size: 22px; }
  /* the six section links (2026-10-06): one grid row, the index size */
  .menu .menu-links { gap: 8px; }
  .menu .menu-links a { font-size: 17px; }
  .menu .menu-cta { margin-top: 4px; justify-self: start; }
  .menu .menu-lang { grid-column: 2; grid-row: 1; margin-top: 0; align-self: center; justify-self: start; }

  .menu .menu-reach {
    grid-column: 2;
    grid-row: 2 / span 4;
    align-self: start;
  }

  /* 568 wide: the address breaks after its @ rather than leave the screen */
  .menu .reach-v { white-space: normal; }
}

@media (prefers-reduced-motion: reduce) {
  .reach-box { transition: none; }
}

/* the answer's count under the textarea: "0 / 5,000", quiet until the
   answer nears the limit (enquiry.js writes it; the word "characters" is
   there for a screen reader only) */
.enquiry-form .field-count {
  align-self: flex-end;
  margin: 0;
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  line-height: 1.4;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.55);
}

/* in the lightbox on a wide screen it sits on the label's line, so it adds
   no height and the panel still needs no scroll (the page's own panels are
   narrower: there "5,000 / 5,000" would meet the label, so it stays below) */
@media (min-width: 1000px) {
  .book .enquiry-form .field-wide { position: relative; }

  .book .enquiry-form .field-wide .field-count {
    position: absolute;
    top: 0;
    right: 0;
    line-height: normal;
  }
}

.enquiry-form .field-count[data-near="near"] { color: rgba(255, 255, 255, 0.85); }
.enquiry-form .field-count[data-near="full"] { color: #fff; }

.enquiry-form .field-count .sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ---- phones: a deeper shade under the mark and the controls where the
   page's text scrolls under them (2026-09-29) ----
   Home and Services: a second shade on the nav, in the ground's own colour,
   that fades in only while Act II or the footer covers the top of the
   screen (site.js sets html.over-text), so it never lies over the take.
   Work's phone page is text from the top: its nav's own shade deepens.
   Contact's nav already carries a near-opaque one. */
@media (max-width: 760px) {
  .nav::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    z-index: -1;
    height: calc(env(safe-area-inset-top) + 150px);
    background: linear-gradient(
      rgba(11, 13, 18, 0.8) 0,
      rgba(11, 13, 18, 0.64) calc(env(safe-area-inset-top) + 64px),
      rgba(11, 13, 18, 0.3) calc(env(safe-area-inset-top) + 104px),
      rgba(11, 13, 18, 0) 100%);
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
  }

  html.over-text body:not(.contact):not(.work):not(.menu-open) .nav::after { opacity: 1; }

  .work .nav::before {
    height: calc(env(safe-area-inset-top) + 150px);
    background: linear-gradient(
      rgba(11, 13, 18, 0.9) 0,
      rgba(11, 13, 18, 0.76) calc(env(safe-area-inset-top) + 64px),
      rgba(11, 13, 18, 0.36) calc(env(safe-area-inset-top) + 104px),
      rgba(11, 13, 18, 0) 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav::after { transition: none; }
}

/* ---------- line breaks (2026-09-29) ----------
   Headings and short display lines balance their lines; paragraphs avoid
   ending on a lone word. A browser without text-wrap keeps its own breaks.
   Act II, the footer, the lightbox and the no-JavaScript text: the takes'
   copy keeps the breaks its films and stills are set with
   (:where keeps these at one class, so a rule of a page's own wins.) */
.socle :where(p, li, dd),
.book .enquiry-done p,
.noscript-fallback p { text-wrap: pretty; }

/* (not the door cards' names: balanced, "The 20-minute call" broke at its
   hyphen) */
.socle :where(h1, h2, h3, summary, .plaque, .kicker):not(:where(.door-h)),
.book-main h2,
.noscript-fallback h1 { text-wrap: balance; }

/* ===========================================================================
   Copy v1.1 (2026-09-29): the few pieces of layout the new copy added.
   Nothing above moves.
   ======================================================================== */

/* ---------- the header with the longer pill ----------
   "Request a call" (« Demander un appel ») is two to three times the width
   of "Book", and the language link stays in the header at every size
   (Xavier, 2026-09-29). Measured against the mark's painted edge (its glyph
   fills 20–80% of its box), every item keeps 12px or more of it from 320px
   up (qa/copy-v11-2026-09-29/, sweep_nav.mjs):
   - narrow desktop windows and upright tablets (761–1099px), where the
     three links, the language and the pill ran into the mark in French
     (they touched it at 761–819px before this pass too): tighter gaps and
     tracking;
   - phones (760px and under): the pill's tracking and padding tighten;
   - the narrowest phones (under 360px): a step smaller again. */
@media (min-width: 761px) and (max-width: 1099px) {
  .links { gap: 2rem; }
  .links a { letter-spacing: 0.16em; }
  .lang { margin-left: 2rem; }
  .nav-pill { margin-left: 1.5rem; letter-spacing: 0.16em; padding-inline: 1.25rem; }
}
@media (min-width: 761px) and (max-width: 860px) {
  .links { gap: 1.5rem; }
  .lang { margin-left: 1.5rem; }
  .nav-pill { padding-inline: 1rem; }
}
/* the mark's hit area (88px) reached 6px past its painted edge onto the
   French language link on the narrowest phones: it keeps 80px there, still
   well over the 53px the mark paints */
@media (max-width: 374px) {
  .brand-hit { width: 80px; }
}
@media (max-width: 760px) {
  .nav-pill { letter-spacing: 0.12em; padding: 13px 14px; }
  .lang { margin-right: 10px; }
}
@media (max-width: 359px) {
  .nav-pill { font-size: 10px; letter-spacing: 0.04em; padding: 13px 10px; margin-right: 5px; }
  .lang { margin-right: 8px; }
  /* the phone menu's pill, beside the language on a short phone: in French
     the language ran 23px off a 320px screen */
  .menu .menu-cta { letter-spacing: 0.1em; padding: 15px 16px; }
}
@media (max-width: 359px) and (orientation: portrait) and (max-height: 620px) {
  .menu { column-gap: 16px; }
}

/* the film's last beat: the free call is the button; the diagnostic, one
   line under it in the fine print, is a plain underlined link (it opens the
   same lightbox, on the diagnostic) */
.ask-micro a {
  color: #fff;
  text-decoration: underline;
  text-decoration-color: rgba(255, 255, 255, 0.5);
  text-underline-offset: 0.22em;
}
.ask-micro a:hover { text-decoration-color: #fff; }
.ask-micro a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

/* a list inside a block (what SOLU does, what the licence covers): the
   paragraph after it keeps the paragraphs' rhythm */
.socle .reads + p { margin-top: 1.25rem; }

/* each package: who it is right for, one line between what it is and its
   examples (the label in the body's bright tone) */
.menu-rows .row-fit {
  grid-column: 1;
  grid-row: 3;
  margin: 0.35rem 0 0;
  max-width: 50ch;
  font-size: max(13.5px, 0.9375rem);
  line-height: 1.6;
  color: #c9cdd4;
}
.menu-rows .row-fit b { font-weight: 700; color: #e8ebf1; }
.menu-rows .row-ex { grid-row: 4; }

@media (max-width: 760px) {
  .menu-rows .row-fit { grid-row: 3; }
  .menu-rows .row-ex { grid-row: 4; }
  .menu-rows .row-price { grid-row: 5; }
  /* the package names on a phone: the widest word sets the size, as the
     Services rooms do ("Automations" is 10.1em in the serif, the French
     "Automatisations" 13em; at 28px it ran 18 to 82px past the column
     from 393 down to 320 wide) */
  .menu-rows .row-name { font-size: min(1.75rem, 8.4vw); }
  html[lang="fr-CA"] .menu-rows .row-name { font-size: min(1.75rem, 6.6vw); }
}

/* ---------- the film's last beat, desktop: the statement's widest line ----------
   Nothing goes over the ring's stroke (PRODUCT.md). While the beat is read
   (frames 175–182) the ring's left arc sits at 50vw minus 7.3% (beside the
   third line) to 8% (beside the first two) of the frame's drawn width,
   max(100vw, 177.78vh) (measured on the frames, qa/copy-v11-2026-09-29/,
   s3_ring.mjs and act1_fit.py). The statement starts at 8.5vw, so it steps
   down only as far as its widest line needs to clear the arc by 8px:
   - English, "20-minute call.", 12em (the old "Good systems" was 10.4em):
     7% smaller at 1440 by 900, 17% at 1280 by 800, unchanged at 1920 and
     2560;
   - French, « un appel gratuit », 13.7em (the old « Les bons systèmes »
     crossed the arc as much): 14% smaller at 1920 and 2560, and never
     under 2.75rem, just above the ask's 2.625rem, so the headline stays
     the larger of the two: that floor holds it at 1440 (18.5% smaller,
     clear of the stroke, touching its glow) and at 1280 by 800, where its
     widest line still reaches the arc, less than the old French line did.
   From frame 186 the ring sweeps across the whole column, as it always
   has; the pre-settle dims the plate under the copy there (v3-main.js). */
@media (min-width: 761px) {
  html:not(.m)[lang="en"] #s3 .statement {
    font-size: min(3.375rem, calc((41.5vw - max(7.34vw, 13.05vh) - 8px) / 12));
  }
  html:not(.m)[lang="fr-CA"] #s3 .statement {
    font-size: max(2.75rem, min(3.375rem, calc((41.5vw - max(8.02vw, 14.26vh) - 8px) / 13.7)));
  }
}


/* ===========================================================================
   Prices, restructured (2026-10-06, Xavier's phone review): "a build" said
   once, the three packages at a glance, each row with its price under its
   name, the examples folded on touch screens, the licence's steps as two
   lines. The package rows flow as a column on phones.
   ======================================================================== */

/* what a build is, after the caption */
.socle .build-note {
  margin-top: 1.4rem;
  max-width: 58ch;
  color: #c9cdd4;
}
.socle .build-note b { color: #fff; font-weight: 700; }

/* the three at a glance; since copy v1.2 (2026-10-11) the entry step comes
   first, with a word ("Start", « Départ ») in the number slot, so the slot
   is wide enough for the word (« Départ » is 46px on a phone) */
.price-index {
  list-style: none;
  margin: 2rem 0 0;
  padding: 0;
  max-width: 44rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.price-index li {
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.price-index a {
  display: grid;
  grid-template-columns: 3.8rem minmax(0, 1fr) auto;
  column-gap: 0.9rem;
  align-items: baseline;
  padding: 0.85rem 0;
  color: inherit;
  text-decoration: none;
  transition: color 0.18s ease;
}
.price-index a:hover .pi-name { color: #fff; text-decoration: underline; text-underline-offset: 0.2em; }
.price-index a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.price-index .pi-n {
  font-family: var(--mono);
  font-size: max(10.5px, 0.6875rem);
  letter-spacing: 0.08em;
  color: rgba(255, 255, 255, 0.4);
}
.price-index .pi-name {
  font-family: var(--sans);
  font-weight: 600;
  font-size: max(14.5px, 0.95rem);
  line-height: 1.35;
  color: #e8ebf1;
}
.price-index .pi-price {
  font-family: var(--mono);
  font-size: max(13.5px, 0.9rem);
  line-height: 1.35;
  color: #fff;
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.price-index .pi-price small {
  display: block;
  font-family: var(--sans);
  font-weight: 500;
  font-size: max(11.5px, 0.75rem);
  color: var(--body-gray);
  white-space: normal;
}
.price-index + .menu-rows { margin-top: 2.2rem; }

/* the examples, folded: a details row inside the package, not an FAQ row */
.socle .menu-rows details.row-ex { border: 0; }
.socle .menu-rows .row-ex summary {
  display: inline-flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: 0.6rem;
  margin: 0;
  padding: 0.45rem 0;
  font-family: var(--mono);
  font-weight: 400;
  font-size: max(10px, 0.625rem);
  line-height: 1.4;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  cursor: pointer;
  list-style: none;
}
.socle .menu-rows .row-ex summary::-webkit-details-marker { display: none; }
.socle .menu-rows .row-ex summary::after {
  content: "+";
  font-family: var(--sans);
  font-size: 0.95rem;
  line-height: 1;
  color: rgba(255, 255, 255, 0.5);
}
.socle .menu-rows details[open].row-ex summary::after { content: "−"; }
.socle .menu-rows .row-ex summary:hover,
.socle .menu-rows details[open].row-ex summary { color: rgba(255, 255, 255, 0.8); }
.socle .menu-rows .row-ex ul { margin-top: 0.35rem; }

/* the licence's steps */
.socle .steps {
  margin: 0.9rem 0 0;
  max-width: 40rem;
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.socle .steps > div {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1.5rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.socle .steps dt {
  font-size: clamp(15px, 1.05vw, 19px);
  line-height: 1.5;
  color: #e4e7ec;
  font-weight: 500;
}
.socle .steps dd {
  margin: 0;
  font-family: var(--mono);
  font-size: max(13.5px, 0.9rem);
  color: #fff;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.socle .steps + p { margin-top: 1.25rem; }

@media (max-width: 760px) {
  /* a column: name, price, what it is, who it is for, the examples */
  .menu-rows .row { display: block; padding: 1.7rem 0; }
  .menu-rows .row-name { font-size: min(1.55rem, 7.4vw); }
  html[lang="fr-CA"] .menu-rows .row-name { font-size: min(1.55rem, 6.4vw); }
  .menu-rows .row-name em { margin-left: 0.6rem; }
  .menu-rows .row-price { margin-top: 0.6rem; font-size: 1.35rem; text-align: left; }
  .menu-rows .row-price .then { margin-top: 0.25rem; }
  .menu-rows .row-desc { margin-top: 1rem; max-width: none; }
  .menu-rows .row-fit { margin-top: 0.8rem; max-width: none; }
  .menu-rows .row-ex { margin-top: 0.45rem; }
  /* the slot holds a word since copy v1.2 (« Départ » is 46px here), so the
     French price column is capped: its "puis à partir de…" line wraps in two
     and the names keep the width they had with three rows (measured
     2026-10-11: 111px, 02 and 03 on three lines) */
  .price-index a { grid-template-columns: max(2.95rem, 46px) minmax(0, 1fr) auto; column-gap: 0.7rem; padding: 0.75rem 0; }
  html[lang="fr-CA"] .price-index .pi-price { max-width: 138px; }
  .price-index .pi-name { font-size: 14.5px; }
  .price-index .pi-price { font-size: 13.5px; }
  .price-index .pi-price small { font-size: 11.5px; }
  .socle .steps > div { gap: 1rem; }
}
