/* ==========================================================================
   Masthead — the signature hero.

   Contract: the FINAL composition is the CSS default. The .js-anim class is
   added by an inline head script only when JS is on AND reduced-motion is off;
   everything that starts hidden lives behind that class. No JS, failed JS, or
   reduced-motion all render the hero complete and correct.

   LCP note: the word never starts transparent or clipped — only translated —
   so the largest text block paints on the first frame.
   ========================================================================== */

.masthead {
  position: relative;
  padding: var(--space-16) var(--gutter) var(--section);
  overflow: clip;
}

.masthead__inner {
  max-width: var(--container);
  margin-inline: auto;
}

.masthead__eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-8);
  color: var(--ink-soft);
}
.masthead__eyebrow::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--paper-edge);
}

/* ---- Stage: the word and the prints share one coordinate space ---------- */
.masthead__stage {
  container-type: inline-size;
  position: relative;
  isolation: isolate;
}

.masthead__word {
  margin: 0;
  font-family: var(--l99-font-signage);
  /* Re-derived by measurement for Norwester: at 0.01em tracking the six glyphs
     span the container exactly at 31.87cqw. Tracking is positive here where
     Fraunces wanted it negative — condensed caps need air. The trailing space
     after the L is reclaimed by the negative margin on the last letter, so the
     ink hits the right edge rather than the box. */
  font-size: 31.87cqw;
  font-weight: 400;
  line-height: 0.82;
  letter-spacing: 0.01em;
  /* Forest, not ink. This is the largest element on the site by a wide margin,
     and as charcoal it was neutral -- 7.5% saturation, i.e. black -- so the
     brand's second-largest colour allocation (forest, 27% of the recipe)
     appeared nowhere in the thing everyone sees first.

     Contrast is not what decided this: charcoal is 13.53:1 on cream and forest
     is 13.02:1, both AAA, a difference no one can see. What changes is that the
     word now belongs to the same family as the trail subline beneath it
     instead of reading as grey-plus-green. */
  color: var(--green-deep);
  white-space: nowrap;
}

.masthead__letter {
  display: inline-block;
  /* Explicit position + z-index, not will-change: js/hero.js drops will-change
     at 1400ms, which would destroy the stacking context the weave depends on. */
  position: relative;
  z-index: var(--z-letter);
  will-change: transform;
}
/* The letters the plane passes BEHIND. Everything else it passes in front of,
   which is what makes it read as threading through the word rather than
   sliding across it. */
.masthead__letter--front { z-index: var(--z-letter-front); }
.masthead__letter:last-child { margin-right: -0.01em; }

/* Subline completes the sentence: TRAVEL / with your tribe.
   Held in the open right-hand space below the word — the counterweight to the
   prints, which all sit across the left. */
.masthead__subline {
  /* In flow directly beneath the word rather than pinned to the floor of the
     stage: the eye has to run from TRAVEL straight into the rest of the
     sentence, and a measured offset would only ever be a guess against the
     baseline. The prints are absolute, so they still lie over the top. */
  position: relative;
  z-index: var(--z-subline);
  max-width: none;
  /* Measured, not guessed. Norwester's caps fill their line box almost
     exactly, and this hand overflows its own -- Architects Daughter's ascent
     metric is 0.986 em against a 0.95 line-height -- so the two need a real gap
     or they read as a collision at display size. The gap went UP with the face
     change: Caveat's ascent was 0.960 em. */
  margin: 1.2cqw 0 0;
  text-align: right;
  font-family: var(--l99-font-hand);
  /* Architects Daughter has one weight, and at this size a synthesised bold
     fills the counters in a, e and D. Its natural stroke is heavier than
     Caveat's bold was, so nothing is lost. The sizes below dropped 7% with the
     face change -- a pure x-height correction (0.400 -> 0.429).

     The CEILING is not that correction; it is a collision constraint, and it is
     the reason this line is not simply Caveat's size scaled. Architects Daughter
     sets 34.5% wider than Caveat at the same nominal size, so "with your tribe."
     went from 482px to 616px and its left edge -- this line is right-aligned --
     marched into the third polaroid, printing over "Vienna, Austria" by 20px.
     Both terms are solved from that edge, and they are solved at DIFFERENT
     widths because the tightest point is not the widest. The caption below sits
     on its rem floor from 1024 up to about 1200 and only then starts scaling,
     so around 1024 the captions are relatively wider and the third one reaches
     furthest right. 6.25cqw is solved there, by sweeping the size against the
     measured right edge of "Vienna, Austria" rather than by scaling Caveat's
     number -- the two do not scale together, because the caption is on a rem
     floor while the subline is on the container.
     Re-measure if the print positions or the caption size ever move. */
  font-size: clamp(1.77rem, 6.25cqw, 4.9rem);
  line-height: 0.95;
  letter-spacing: 0;
  color: var(--green-display);
}

/* ---- The writing ---------------------------------------------------------
   You cannot stroke-animate a font, so this is a reveal — but one animated
   custom property drives both the reveal edge and the pen nib, which is what
   keeps them in exact lockstep. Registering --write as a <number> is what makes
   it interpolate rather than snap.

   initial-value: 1 means the resting state is fully written, so no-JS and
   reduced-motion get the finished line, consistent with the hero contract.
   ------------------------------------------------------------------------- */
@property --write {
  syntax: '<number>';
  /* Must inherit: the reveal is on a child and the nib on a sibling, and both
     read the value animated on their shared parent. With inherits: false they
     see the initial value instead and the reveal never moves. */
  inherits: true;
  initial-value: 1;
}

.masthead__scribe {
  --write: 1;
  --scribe-w: 0px;   /* set once by JS from the measured text width */
  position: relative;
  display: inline-block;
}

.masthead__write {
  display: block;
  /* GUARDRAIL EXCEPTION: clip-path is neither transform nor opacity. It is the
     only way to do a directional reveal, it is composited, and this is a
     one-shot entrance — not the per-frame interaction the rule guards against. */
  clip-path: inset(-0.35em calc(100% * (1 - var(--write))) -0.35em -0.05em);
}

/* The nib is what sells it as a pen. Translated in pixels off the measured
   width so it stays a transform and never triggers layout. */
.masthead__nib {
  position: absolute;
  left: 0;
  bottom: 0.16em;
  width: 0.1em;
  height: 0.1em;
  border-radius: 50%;
  background: var(--ink-pen);
  opacity: 0;
  transform: translateX(calc(var(--write) * var(--scribe-w)));
  pointer-events: none;
}

.masthead__headline {
  margin: 0;
  font-size: inherit;
  letter-spacing: normal;
  text-transform: none;
}

.masthead__word { display: block; }

/* ---- Photo prints ------------------------------------------------------- */
.print {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--w);
  margin: 0;
  z-index: var(--z-print-1);
}

/* A polaroid: thin even border on three sides, deep margin at the foot.
   The caption lives IN that margin — which is what the margin is for — so it
   is a flow child rather than an absolute overlay, and its own padding is what
   gives the frame its shape. Percentage padding resolves against the frame
   width, so every print keeps the same proportions at any size. */
/* Rotation lives on its own layer so it can animate independently of the
   hover lift, and so the resting CSS state stays the finished one. */
.print__tilt { transform: rotate(var(--rot)); }

.print__inner {
  transform: translateY(0);
  transition: transform var(--l99-dur-micro) var(--l99-ease-standard);
  background: var(--polaroid);
  padding: 5.5% 5.5% 0;
  box-shadow: var(--shadow-print);
  border-radius: 2px;
}
.print img {
  width: 100%;
  height: auto;
  border-radius: 1px;
}

/* Marginalia — a caption jotted on the polaroid by hand. It rotates with the
   frame because it was written on it, and sits a degree off square because
   nobody writes on a straight line. */
.print figcaption {
  display: block;
  padding: 6% 6% 11%;
  /* See the phone block at the foot of this file: the caption's rem floor does
     not scale with the frame, so at 375-440 it is the tallest part of a
     polaroid and has to be trimmed there rather than here. */
  text-align: center;
  font-family: var(--l99-font-hand);
  /* Solved from LINE FILL, which is what makes a polaroid read as a polaroid:
     the caption has to sit inside the foot with white either side, not span it
     edge to edge. At 1.97cqw the longest caption ran 70% of the frame width and
     the shortest 63%, and the whole stack stopped looking like photographs with
     something written on them. 1.55cqw puts them near 50-55%.

     Note these are floor-bound below ~1200: the frames here are 230-335px, and
     any fraction of THEIR width that reads as authentic handwriting would be
     illegible, so the size comes off the stage with a floor rather than off the
     frame like .polaroid does. That is the honest compromise for a thumbnail --
     see --polaroid-cap in components.css for the version that can be exact. */
  font-size: clamp(1.05rem, 1.55cqw, 1.35rem);
  line-height: 1.16;
  letter-spacing: 0.01em;
  color: var(--ink-pen);
  transform: rotate(-1.1deg);
}

/* Kept deliberately -- see the matching note on .polaroid:hover in
   components.css for why a lift on a non-clickable figure is not a false
   affordance here. */
@media (hover: hover) {
  .print:hover .print__inner { transform: translateY(-6px); }
}

/* ---- The flight path ------------------------------------------------------
   Its own layer with its own perspective, so the plane can yaw and pitch in
   real 3D without the stage's container-query or isolation context caring.
   The element is injected by js/hero.js — see the note there for why it is not
   in the markup.
   ------------------------------------------------------------------------- */
.masthead__flight {
  position: absolute;
  inset: 0;
  z-index: var(--z-plane);
  perspective: 1200px;
  pointer-events: none;
}

.masthead__plane {
  position: absolute;
  /* Sits over the right half of the word, where the V, E and L are. */
  left: 46%;
  top: 26%;
  width: 26%;
  height: auto;
  transform-origin: 50% 50%;
  /* Resting state is "already flown past": invisible until the flight runs. */
  opacity: 0;
}

@media (max-width: 63.99em) {
  .masthead__plane { left: 40%; top: 22%; width: 34%; }
}

/* On a phone the plane flies HIGH, across the top half of the word. The prints
   sit at --z-print-* (4, 5, 6) and the plane at --z-plane (2), so the frames
   paint over it: at the tablet position it would span roughly 59-127px against
   print tops at 78px and lose its bottom half behind them. Flying above them
   avoids that with no z-index change, which matters — the existing stack is
   exactly what makes the plane pass behind the V and L and in front of the E. */
@media (max-width: 40em) {
  .masthead__plane { left: 38%; top: 2%; width: 32%; }
}

/* ---- Actions ------------------------------------------------------------ */
.masthead__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-6);
  margin-top: var(--space-16);
}

/* ---- Entrance: only under .js-anim -------------------------------------- */
/* The written line starts unrevealed only under .js-anim, so removing the class
   restores it — same as the letters and prints. Never set this inline from JS:
   reveal() removes a class and cannot undo an inline style, which would strand
   the text permanently invisible on any failure path. */
.js-anim .masthead__scribe { --write: 0; }
.js-anim .masthead__letter { transform: translateY(0.14em); }
.js-anim .print { opacity: 0; }
.js-anim .print__tilt { transform: rotate(0deg); }

/* ---- Print placement ----------------------------------------------------
   Prints sit LOW on the word, overlapping roughly the bottom third of the
   letterforms and hanging below the baseline. We read letters from their tops,
   so a low-sitting print can be generous without hurting the read. Horizontal
   gaps between prints let whole letters show through.

   All three live across the left 56%; the italic subline holds the right.
   ------------------------------------------------------------------------- */
.masthead__stage { padding-bottom: 5cqw; }

/* --y is generous because the caption's font-size has a rem floor: as the
   container narrows the caption stops shrinking, so the polaroid grows taller
   relative to its own width and eats further into the word. Tuned at the
   tightest point of this layout (~1030px), not at 1440. */
.print--1 { --x:  0%; --y: 16.7cqw; --w: 25%; --rot: -5deg;   z-index: var(--z-print-1); }
.print--2 { --x: 22%; --y: 20.7cqw; --w: 17%; --rot:  4.5deg; z-index: var(--z-print-2); }
.print--3 { --x: 36%; --y: 16.7cqw; --w: 19%; --rot: -2deg;   z-index: var(--z-print-3); }

/* Two prints and a left-aligned subline hold up to 1024px. The three-print
   arrangement needs real width; at tablet size it crowds the word and the
   right-hand void that the italic subline depends on disappears. */
@media (max-width: 63.99em) {
  /* The prints span the full width here, so the subline cannot sit in flow
     directly under the word — it would end up behind them. It goes to the
     floor of the stage instead, and the stage reserves exactly the depth the
     prints and the subline need. */
  .masthead__stage { padding-bottom: 35cqw; }
  .print--1 { --x:  0%; --y: 16.5cqw; --w: 36%; --rot: -4deg; }
  .print--2 { --x: 42%; --y: 19.5cqw; --w: 33%; --rot:  4deg; }
  .print--3 { display: none; }
  .masthead__subline {
    position: absolute;
    left: 0;
    bottom: 0;
    margin: 0;
    text-align: left;
  }
}

@media (max-width: 40em) {
  /* Captions wrap to two lines at this width, so the prints run deeper and
     the stage has to reserve more beneath them. Retuned with the narrower
     frames above: the reserve now clears the prints by the gap the subline
     needs and no more, so the written line reads as the second half of the
     sentence instead of a caption stranded at the floor. */
  /* Two terms, but the balance between them flipped when the captions came off
     the prints. It used to be dominated by the constant, because a polaroid's
     depth had two parts: the photograph scaled with the width, the caption did
     not -- its font-size bottomed out on a rem floor. With no caption the frame
     is depth-proportional all the way down, so the reserve is now mostly cqw
     and the constant is small. Re-solved from measurements at 375 and 640
     (the ends of this block, and the pair that disagreed most): the written
     line lands ~20px under the frames across the range. The previous figure
     held at 375 and 440 but collapsed to a 1px gap by 640.

     TRAP: cqw here resolves against the VIEWPORT, not the stage. container-type
     is on .masthead__stage itself, and an element cannot query itself — with no
     ancestor container these units fall back to the small viewport. It reads
     like 17.4% of the stage and it is not.

     Both terms moved: 17.4cqw + 5.5rem -> 24.6cqw + 2.2rem. The constant rose
     with the face change, then fell well below where it started once the
     captions came off the prints here -- a frame with no caption is barely
     half as deep -- while the slope had to rise to keep the gap honest at the
     wide end of this block. Architects
     Daughter is 34.5% wider than Caveat, so captions that fitted two lines now
     take three, the frames run deeper, and the subline — absolutely positioned
     at the floor of this reserve — was printing over BOTH of them at 375
     (74x12px and 74x14px of text on text). The new figure is solved from the
     measured caption bottom, not scaled: it restores the ~20px gap described
     above. It moved three times while the captions were being worked on -- that
     coupling is the thing to watch, so re-measure whenever the caption size,
     its presence, or the frame widths change. */
  .masthead__stage { padding-bottom: calc(24.6cqw + 2.2rem); }
  /* Phones only. At 375 the old 36%/33% frames spanned 69% of the stage and
     stood 1.46x the height of the word — the photographs out-weighed the
     wordmark and the composition read upside down. These put their combined
     mass at 53% and drop the overlap from 37% of cap height to 25%, so more of
     the letterforms survive. Left at 36%/33% above 40em, where the word is
     185px tall and already wins; narrowing there only opened a void down the
     right-hand side. */
  .print--1 { --x:  0%; --y: 21.5cqw; --w: 28%; }
  .print--2 { --x: 33%; --y: 22.5cqw; --w: 25%; }
  /* The caption's font-size has a rem floor, so as the frame narrows the
     caption stops shrinking and becomes the deepest part of the polaroid —
     "Phi Phi Islands, Thailand" runs to three lines here. Trimming it is what
     pays for pushing the frames further down the word without dragging the
     written line down with them. */
  /* Captions come OFF the prints on phones.

     At this width the frames are 84-94px. A caption legible on one is
     necessarily huge in proportion to it -- 10.7% of the frame width against
     the 3.9% a polaroid actually carries -- so it filled the foot edge to edge
     and stopped the object reading as a photograph with something written on
     it. Shrinking it far enough to look right put it under 14px, below the
     legibility floor this site holds everywhere else. There was no size that
     was both, so the caption goes rather than losing on both counts.

     Kept in the accessibility tree, not deleted: it costs nothing, and the
     same words are on screen further down the page in the gallery, at a size
     where they work. Every one of these photographs also carries alt text that
     already names what the caption names.

     The foot moves to the frame. It has to: the caption element WAS the deep
     bottom margin -- that is what its 11% padding was for -- so hiding it
     without this leaves an even white border on four sides, which is a mounted
     print, not a polaroid. 22% against 5.5% sides is roughly the real ratio. */
  .print__inner { padding-bottom: 22%; }
  .print figcaption {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  /* Held a step above its old 1.9rem floor. Against a 107px word, 30px of
     handwriting looked like an afterthought rather than the other half of
     "TRAVEL with your tribe". */
  .masthead__subline { font-size: clamp(2.15rem, 8cqw, 5.75rem); }
  .masthead__actions { margin-top: var(--space-10); }
  .masthead { padding-top: var(--space-12); }
}
