/* film.css: the root hero film (site/index.html, film.js).
   Static (no JS, reduced motion) the hero is its first frame: the hut interior cut-out over frame
   0 of the walk, the title in the doorway's sky, the lead and the action on the floor. The motion
   layer turns it into a tall runway with a sticky stage (html.motion .hero--film.is-film), scrubs
   the footage and reveals the story beats. Everything the film needs from CSS is here. */

/* The accent face (em.accent) is site-wide now: base.css, tokens in tokens.css. */

/* ---------- The stage ---------- */
.hero--film { min-height: 0; height: 100svh; overflow: clip; background: var(--ink); }
.film__stage {
  position: relative;
  height: 100svh;
  overflow: hidden;
  container-type: size;   /* the interior is laid out against the stage box (cqw, cqh) */
}
.film__layer { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.film__layer[hidden] { display: none !important; }
.film__world picture, .film__world img { width: 100%; height: 100%; }
.film__world img { object-fit: cover; object-position: 50% 50%; }
.film__seq, .film__alive { display: block; }

/* The interior (3:2 landscape, 2:3 portrait) and frame 0 are one world. On landscape screens the
   interior's centre 16:9 band lands exactly on frame 0 as object-fit: cover draws it, so the view
   through the door is the composition it was made with (labs/hut-to-ocean placeInterior, in CSS). */
.film__interior img { position: absolute; max-width: none; }
@media not all and (max-aspect-ratio: 1/1) {
  .film__interior img { left: 50%; top: 50%; width: max(100cqw, 177.778cqh); height: auto; translate: -50% -50%; }
}
@media (max-aspect-ratio: 1/1) {
  .film__interior img { inset: 0; width: 100%; height: 100%; object-fit: cover; }
}

/* light for the words: the doorway's sky at the top, the floor at the bottom */
/* no shade over the film (Max, 2026-10-08): legibility comes from where the words sit */
.film__shade { display: none; }

/* ---------- The doorway: title, lead and action as one centred group ----------
   Max (2026-10-08): every text block in the intro sits in the middle of the screen as one group,
   with ordinary spacing, so nothing jumps between the doorway and the beats. No shade, scrim or
   glow behind it (Max rejected them twice): legibility comes from the brand's sand type and its size.
   The group may cross the horizon; that is accepted. */
.film__door {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--nav-h) var(--gutter) clamp(2.5rem, 7vh, 4.5rem);
  color: var(--sand);
  pointer-events: none;
}
.film__door a { pointer-events: auto; }
.film__title {
  font-family: var(--font-hero-main);
  font-weight: var(--font-hero-main-weight);
  /* Keep the longer opening's "a helping hand" together on phones without shrinking desktop. */
  font-size: min(calc(var(--film-scale) * min(var(--step-film), 5.25rem, 9.5vh)), 13cqw);
  line-height: var(--lh-hero);
  letter-spacing: -0.03em;
  /* the full width up to the cap, not the width of its widest unbreakable phrase: centred flex
     items size to their content, and a long kept accent ("d'un coup de main.") would push the
     title wider than the phone instead of letting accent.js release the phrase */
  width: 100%;
  max-width: 9.4em;
  text-wrap: balance;
  color: var(--sand);
}
.film__lead {
  margin-top: clamp(1rem, 2.6vh, 1.75rem);
  font-family: var(--font-hero-main);
  font-weight: var(--w-lead);
  font-size: calc(var(--film-scale) * var(--step-0));
  line-height: 1.4;
  width: 100%;
  max-width: 40ch;
  color: var(--sand-2);
  text-wrap: pretty;
}
.film__action { margin-top: clamp(1.25rem, 3.2vh, 2.25rem); }
@media (max-width: 767.98px) {
  .film__lead { max-width: 30ch; }
}

.film__cue, .film__caption {
  position: absolute;
  z-index: 2;
  bottom: clamp(1.25rem, 3.5vh, 2.25rem);
  margin: 0;
  max-width: none;
  font-family: var(--font-mono);
  font-size: var(--step--2);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--sand);
  pointer-events: none;
}
.film__cue { left: var(--gutter); display: flex; align-items: center; gap: 0.75rem; }
.film__cue-line { width: 1px; height: 40px; background: linear-gradient(var(--sand), rgb(239 230 214 / 0)); }
html.motion .film__cue-line { animation: film-cue 2.4s var(--ease-inout) infinite; }
@keyframes film-cue {
  0% { transform: scaleY(0); transform-origin: top; }
  45% { transform: scaleY(1); transform-origin: top; }
  55% { transform: scaleY(1); transform-origin: bottom; }
  100% { transform: scaleY(0); transform-origin: bottom; }
}
.film__caption { right: calc(var(--gutter) + 92px); text-transform: none; letter-spacing: 0.01em; font-family: var(--font-body); font-size: 0.75rem; opacity: 0.85; max-width: 24ch; text-align: right; }
/* clear of the gauge's depth readout, which sits in the bottom-right corner below 1024px */
@media (max-width: 1023.98px) { .film__caption { right: calc(var(--gutter) + 3.5rem); } }
@media (max-width: 767.98px) {
  .film__cue { display: none; }
  .film__caption { left: var(--gutter); right: auto; text-align: left; bottom: clamp(0.75rem, 2vh, 1.25rem); font-size: 0.6875rem; }
  .film__door { padding-bottom: calc(clamp(0.75rem, 2vh, 1.25rem) + 2.2rem); }
}

/* The doorway's words leave on a trigger (film.js setDoor): at 9.8% of the walk the title,
   lead, action and cue rise a little, blur and fade in 0.4 s, and come back in 0.8 s when the
   scroll returns. Transitions run on the clock and always complete, so at rest the words are
   either all there or gone, never parked half-faded or half-blurred. The caption leaves the
   same way before the hand-off. .is-snap applies a state without a transition (first state
   after a reload part-way down). */
html.motion .is-film .film__door,
html.motion .is-film .film__cue,
html.motion .is-film .film__caption {
  transition: opacity var(--dur-2) var(--ease-out), transform var(--dur-2) var(--ease-out), filter var(--dur-2) var(--ease-out), visibility 0s linear 0s;
}
html.motion .is-film .film__door.is-gone { transform: translate3d(0, -6vh, 0); filter: blur(8px); }
html.motion .is-film :is(.film__door, .film__cue, .film__caption).is-gone {
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-1) var(--ease-inout), transform var(--dur-1) var(--ease-inout), filter var(--dur-1) var(--ease-inout), visibility 0s linear var(--dur-1);
}
html.motion .is-film :is(.film__door, .film__cue, .film__caption).is-snap { transition: none !important; }
/* a reload part-way down the film: the doorway stays hidden until the page is back where it
   was (preboot.js adds html.film-restore, film.js removes it once restored) */
html.film-restore .film__door, html.film-restore .film__cue { visibility: hidden; }

/* past the doorway the hero's own action has gone: the nav's action takes the granite fill
   (as it does past any other hero) without the nav's ink ground over the film */
html.film-past-door .nav-action { background: var(--granite-fill); color: var(--sand); border-color: transparent; }
@media (hover: hover) and (pointer: fine) { html.film-past-door .nav-action:hover { background: var(--granite-press); } }

/* ---------- The story beats (shown only by the motion layer) ---------- */
.film__beats { position: absolute; inset: 0; z-index: 2; pointer-events: none; display: none; }
html.motion .is-film .film__beats { display: block; }
.beat {
  position: absolute;
  left: 0;
  right: 0;
  padding-inline: var(--gutter);
  text-align: center;
  color: var(--sand);
  visibility: hidden;
}
/* Every beat, above the water and below it, is centred in the screen as one group (headline and
   supporting line together), in the same place as the doorway, so nothing jumps between beats.
   data-place still decides the entrance: masks above the waterline, a blur below it. */
.beat { top: 50%; translate: 0 -50%; }
.beat__head {
  margin: 0 auto;
  max-width: 12em;
  font-family: var(--font-hero-main);
  font-weight: var(--font-hero-main-weight);
  font-size: calc(var(--film-scale) * var(--step-beat));
  line-height: var(--lh-display);
  letter-spacing: -0.028em;
  text-wrap: balance;
  color: var(--sand);
}
.beat__sub {
  margin: clamp(0.9rem, 2.4vh, 1.5rem) auto 0;
  width: 100%;
  max-width: 64ch;
  font-family: var(--font-hero-main);
  font-weight: var(--w-lead);
  font-size: calc(var(--film-scale) * var(--step-1));
  line-height: 1.4;
  color: var(--sand-2);
  text-wrap: pretty;
}
/* The beach invitation uses two gently tapered desktop lines. */
.beat__sub[data-i18n="film.b2.s"] { max-width: 43ch; }
/* support-shape.js measures each language at the current width, giving supporting copy a
   longer first line and shorter lines beneath. Without JS, ordinary wrapping remains. */
.support-line { display: block; white-space: nowrap; }
/* Line masks (film.js splitLinesInPlace), for the doorway title and the beats. Each line keeps
   exactly the place it had before the split: the mask is padded for ascenders, descenders (j, f,
   g) and the italic's overhang, and gives the room back with a relative shift and one negative
   margin (one per gap, so nothing collapses). Lines are nowrap: they never re-wrap once cut. */
.film-tmask {
  display: block;
  position: relative;
  top: -0.2em;
  /* Edna Italic leans past its box (the j's hook on the left, the f and the full stop on the
     right) and its descenders run deep: 0.26em at the sides, 0.24em below */
  padding: 0.2em 0.26em 0.24em;
  margin: 0 -0.26em -0.44em;
}
.film-tmask.is-clip { overflow: hidden; overflow: clip; }
.film-tline { display: block; white-space: nowrap; }
.beat { isolation: isolate; }

/* ---------- The runway (motion layer) ---------- */
html.motion .hero--film.is-film { height: auto; overflow: visible; }
html.motion .hero--film.is-film .film__stage { position: sticky; top: 0; height: 100svh; height: 100lvh; }
html.motion .is-film .film__seq,
html.motion .is-film .film__alive { visibility: hidden; }
html.motion .is-film .film__world,
html.motion .is-film .film__interior,
html.motion .is-film .film__seq { will-change: transform, opacity; }

.film__hint {
  position: fixed;
  left: 50%;
  bottom: max(14px, env(safe-area-inset-bottom));
  translate: -50% 0;
  z-index: var(--z-overlay);
  margin: 0;
  font: 0.6875rem/1 var(--font-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--sand);
  padding: 6px 10px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--ink) 70%, transparent);
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
  pointer-events: none;
}
.film__hint.is-on { opacity: 0.85; }

/* ---------- The live water (water.js): one fixed canvas behind the underwater chapters ---------- */
.film-water {
  position: fixed;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  visibility: hidden;
}
.film-water.is-on { visibility: visible; }
/* while it shows, <body> lets it through (a body background paints over negative z-index
   layers); the gauge's --water colour comes back the moment the canvas is off */
html.water-live body { background: transparent; }

/* ---------- The descent: the next line of the same story ---------- */
.descent--film .descent__text { text-align: center; width: 100%; }
.descent--film .section-title {
  font-family: var(--font-hero-main);
  font-weight: var(--font-hero-main-weight);
  font-size: calc(var(--film-scale) * var(--step-beat));
  line-height: var(--lh-display);
  letter-spacing: -0.028em;
  width: 100%;
  max-width: 12em;
  margin-inline: auto;
}
.descent--film .descent__text .lead {
  margin-inline: auto;
  width: 100%;
  max-width: 64ch;
  font-family: var(--font-hero-main);
  font-weight: var(--w-lead);
  font-size: calc(var(--film-scale) * var(--step-1));
  line-height: 1.4;
  color: var(--sand-2);
  text-wrap: pretty;
}
.descent--film .descent__text { order: -1; margin-top: 0; margin-bottom: var(--s-8); }
.descent--film .descent__grid { display: flex; flex-direction: column; align-items: center; }
.descent--film .descent__media { width: min(100%, 34.58rem); margin-inline: auto; }
@media (min-width: 768px) {
  .descent--film .descent__grid { display: flex; }
  .descent--film .descent__text { padding-bottom: 0; }
}
html.motion .descent--film { padding-top: clamp(4rem, 14vh, 9rem); }

/* ---------- Reduced motion: the first frame, nothing moves ---------- */
@media (prefers-reduced-motion: reduce) {
  .film__seq, .film__alive, .film__beats, .film-water, .film__hint { display: none !important; }
}
