/*
 * hero.css: this site's hero styling (this site's file; the main agent only, and never
 * a critique or polish pass). Since decision D-12 (Stanley, 2026-10-19) the hero is the
 * intro (template-parts/intro.php): a short clay film that plays once as the page opens,
 * in place of the starter's scroll hero. The scroll hero's rules (the caption bands, the
 * "pour" entrance, the static hero and its buttons) went with it: nothing else used them.
 * Since decision D-20 (Stanley, in writing, 2026-10-20) its words say what we do, as they
 * did before D-15; since Sam's call of 2026-10-25 (items 2 and 3) the h1 is "We turn old
 * websites into new ones. Then we stay." in the display face, the free look under it,
 * then the kit's pill, to the growth check on this page since Sam's call of 2026-10-26
 * (item 4; Get in touch is in the nav's bar and the footer), with its note under it, then
 * the route to Our work and the phone.
 * D-15's "Hello." closes the page instead (site.css, the call to action). A change here
 * is a hero change and needs Stanley's written yes (Sam's calls take priority, D-51).
 *
 * Two layouts, chosen by the screen, and the same 48em that hero-site.js and the still's
 * <source> use to choose the cut:
 *   side     from 48em on a screen at least 4:3: the film fills the first screen below
 *            the nav, and the words sit in its calm left half, centred top to bottom.
 *   stacked  everywhere else: the film full width at the top (the 4:5 cut on a phone, the
 *            16:9 cut on an upright tablet), the words below it.
 * Under 4:3 the 16:9 film, cropped to fill, would put the symbol behind the words, so an
 * upright tablet stacks rather than sides.
 *
 * Where the words may go is worked out from the film's own frame, not guessed per screen.
 * Side by side, the film covers the box with its right edge kept, so the frame is --fw
 * wide and one frame pixel is --fp on screen. Measured on all 108 frames of the 16:9 cut
 * (2026-10-20): the symbol is widest as it squashes on landing (1.42 s), its clay never
 * further left than x 966 and its contact shadow than x 955 (the 50% this file used
 * before, nearly to the pixel). The words' column ends 3cqw short of x 955, and the h1
 * wraps inside it, so no word reaches the symbol on any frame. Behind the words the film
 * is its paper floor and wall throughout.
 *
 * Motion: only transform and opacity, every start state under .js and only with motion
 * allowed (T-052), so without the script, or with reduced motion, the end frame and the
 * words show at once.
 */

/* ---- The intro's ground: the page's own paper, the ground Then and now and the light
   run after it sit on, so nothing changes tone at the intro's foot. Until item 5 (Sam,
   2026-10-25) it was the film's floor (#F2EEE5), 3.2 colour-difference units off paper,
   a line across the screen on phones and upright tablets; since then the films are
   graded so their floor and wall are paper (within about 2 units), and their foot fades
   into it at every size (below). Ink on it 15.98:1, --ink-soft 7.5:1.
   It is the size container for the words, so their sums read the intro's own width (cqw)
   and not the window's, which on a desktop also counts the scrollbar. */
.intro{--intro-ground:var(--paper);--intro-rise:16px;position:relative;isolation:isolate;box-sizing:border-box;background:var(--intro-ground);color:var(--ink);overflow:clip;container-type:inline-size}

/* The film and its end frame share one box; the film sits on top. object-fit applies to
   the poster too, so the start frame crops exactly as the film will. Stacked, the box is
   capped at 48svh so the h1 and its line follow the film inside the first screen: on
   every phone measured, 320x568 to 390x844 (at 320x568 with half a pixel to spare,
   under the short phone's 42svh below). The pill and the phone are in it too from
   375x812 and on taller phones; on shorter ones (320x568, 360x640, 375x667, 360x740, a
   390x844 with Safari's bars out) they come just below the fold, and the nav's menu
   carries the same Get in touch (review findings stacked-fold-claim and
   top-block-below-fold-short-phones). Lifting them into view there would crop the film
   harder, a hero framing change that waits for Stanley's yes. The box's last tenth fades
   into the ground: the graded floor is within about 2 units of paper, not on it, and a
   hard edge would show the difference. inline-size is set, so the cap crops the film
   rather than narrowing the box. */
.intro__media{position:relative;inline-size:100%;aspect-ratio:4/5;max-block-size:48svh;overflow:hidden;
  -webkit-mask-image:linear-gradient(#000 90%,transparent);mask-image:linear-gradient(#000 90%,transparent)}
.intro__still{position:absolute;inset:0;display:block}
.intro__still img,.intro__film{position:absolute;inset:0;display:block;inline-size:100%;block-size:100%;object-fit:cover;object-position:50% 50%}
.intro__film{z-index:1;visibility:hidden}
.intro.is-film .intro__film{visibility:visible}
.intro.is-still .intro__film{display:none}

/* ---- The words, stacked under the film: on the ground, ink 15.98:1, --ink-soft 7.5:1. */
.intro__copy{position:relative;z-index:2;box-sizing:border-box;padding:var(--space-3) var(--frame-inline) var(--space-4)}

/* The h1: the site's display voice. Its size is --title, set per layout from the column
   it has (cqw is the intro's width), so it fills that column and the block fits the
   first screen. On a phone, as on a desktop (below), the column is 7.43em: the widest
   line, "Then we stay." (7.2em), with 3% to spare, so the h1 sets as four full lines,
   "We turn old / websites into / new ones. / Then we stay." (48px at 390x844, 46px at
   375x812; a short phone's below). Each word in its own clipped line box, padded so the clip never cuts a
   descender, nor the r's and t's terminals, which the tight tracking carries a pixel past
   the word's own box (seen at 375 and 1440). */
.intro__title{margin:0;font-family:var(--font-display);font-weight:400;font-size:var(--title,clamp(2rem,(100cqw - 2 * var(--margin)) / 7.43,3rem));line-height:.95;letter-spacing:-.03em;text-wrap:balance}
.intro__word{display:inline-block;overflow:hidden;overflow:clip;padding:.1em .05em .16em;margin:-.1em -.05em -.16em;vertical-align:top}
.intro__in{display:inline-block}
/* With the reader's own wider letter and word spacing (WCAG 1.4.12), a long word or a
   phrase held by a no-break space can outgrow a 320 column ("for businesses" needed
   346px and was cut): it may wrap inside itself only when it cannot fit, never in the
   normal layouts (audit, 2026-10-25). */
.intro__word{max-inline-size:100%}
.intro__in{overflow-wrap:anywhere}

/* The free look: the lead size, quieter. Balanced, so its two lines are even ("Send us
   your site, and you get the / three things we'd change first, free." at 375 to 2000),
   never a last word alone (audit, 2026-10-25). */
.intro__sub{margin:var(--sub-gap,var(--gap-text)) 0 0;max-inline-size:34ch;font-size:var(--fs-lead);font-weight:450;line-height:1.45;color:var(--ink-soft);text-wrap:balance}
/* Under the line: the pill with its note under it, then the route to Our work and the
   phone (Sam's call of 2026-10-26, items 4 and 7). The pill's label is nearly three
   times Get in touch's, so the proof no longer fits beside it at any size and takes its
   own row; the note sits close under the pill, as part of it. */
.intro__actions{margin:var(--actions-gap,var(--space-3)) 0 0;display:grid;justify-items:start;gap:var(--space-2);font-weight:700;font-variant-numeric:tabular-nums}
.intro__go{margin:0;display:grid;justify-items:start;gap:.5rem;min-inline-size:0;max-inline-size:100%}
/* The note: small and quiet, the line's ink (7.5:1 on paper). */
.intro__note{font-size:var(--fs-small);font-weight:450;line-height:1.4;color:var(--ink-soft)}
.intro__more{margin:0;display:flex;flex-wrap:wrap;align-items:center;gap:0 var(--space-3)}

/* The one button: the kit's pill, the face lifted 5px off its magenta plate (site.css
   scopes its own to the body, so the intro carries the same rules). White face on the
   paper ground, as the windows are on the light page (D-3). */
.intro .btn{position:relative;display:inline-flex;box-sizing:border-box;margin:var(--plate-sm) 0 0 var(--plate-sm);padding:0;font-family:var(--font-body);font-weight:700;font-size:var(--fs-body);line-height:1.2;color:var(--ink);background:var(--accent);border:0;border-radius:999px;text-decoration:none;-webkit-tap-highlight-color:transparent}
.intro .btn__face{position:relative;display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;inline-size:100%;min-block-size:3.25rem;padding:.8em 1.6em;background:var(--white);border:var(--line) solid var(--ink);border-radius:inherit;transform:translate(calc(var(--plate-sm) * -1),calc(var(--plate-sm) * -1));transition:transform var(--t-state) var(--ease-out)}
@media (hover:hover){
  .intro .btn:hover .btn__face{transform:translate(calc(var(--plate-sm) * -1 - 2px),calc(var(--plate-sm) * -1 - 2px))}
}
.intro .btn:active .btn__face{transform:translate(-1px,-1px);transition-duration:.1s}
.intro .btn:focus-visible{outline:none}
.intro .btn:focus-visible .btn__face{outline:3px solid var(--focus);outline-offset:calc(var(--plate-sm) + 3px)}
/* The growth check's pill (item 4): its label is 17.14em of the bold body face, so the
   ends are a little tighter than the kit's 1.6em and it holds one line from 360 to 2560.
   A longer label, or the reader's own larger text, wraps it into two even lines rather
   than past its column. */
.intro .intro__check{max-inline-size:calc(100% - var(--plate-sm))}
.intro .intro__check .btn__face{padding-inline:1.25em;text-align:center}
.intro__label{text-wrap:balance}
/* An inline-block as well as nowrap: as a plain nowrap span Chrome's balance would not
   break after it, and at 320 set "Take the / one-minute growth check" (8 and 23
   letters); as one box it gives "Take the one-minute / growth check" (device pass,
   2026-10-27). */
.intro__keep{display:inline-block;white-space:nowrap}
/* The phone: a text link, with the faint line the body's links have at rest. A 44px box
   with the number centred in it, as the contact page's hero has it: the lines sit 1lh
   from the box's middle (site.css), so the number must be in the middle. Padding did
   that with a mouse, but on a touch screen the engine's [data-tap] adds its own 44px
   minimum inside the padding, making a 61px box with the number at the top and its line
   10px under it (review finding tel-line-touch). */
.intro .text-link{display:inline-flex;align-items:center;min-block-size:44px;color:var(--ink)}
.intro .text-link::before{block-size:1px;background:currentColor;opacity:.4}

/* Stacked on a phone, the words sit closer under the film and the pill closer under the
   line: when the h1 was five lines the page's one button ended 13 to 22px below the
   first screen at 390x844 and 375x812, cut in half (audit, 2026-10-25, Sam's call that
   day under D-51). The film's own foot is already faded into the ground, so the 28px
   above the h1 was air on air; 8px is enough. With the four-line h1 of 2026-10-25 the
   pill ends 31px clear at 390x844. */
@media (max-width: 47.99em){
  .intro__copy{padding-block-start:var(--space-1)}
  .intro__actions{--actions-gap:var(--space-2)}
  /* The growth check's pill spans the column, its label centred and on one line from
     340 up: the body size from 360, and between them the size the column holds (the
     label's 17.14em with .6em ends and a little to spare is 18.6em of it, less the plate
     and the border). Never under 1rem, so the reader's own text size is kept: at 320,
     or with larger text, it wraps into two even lines, a hyphenated word kept whole
     (intro.php), never "Take the one- / minute growth check". Its height on one line,
     and so where it ends on the first screen, is Get in touch's. */
  .intro__go{justify-items:stretch;inline-size:100%}
  .intro .intro__check{inline-size:calc(100% - var(--plate-sm));font-size:max(1rem,min(var(--fs-body),(100cqw - 2 * var(--margin) - var(--plate-sm) - 6px) / 18.6))}
  .intro .intro__check .btn__face{padding-inline:.6em}
}

/* 44em tall or less (a 375x667 too): the film cannot give up more height without
   cropping the symbol, which fills the cut top to bottom, so the h1 gives instead, down
   to 2rem, sized so the pill ends just inside the screen (9.5rem: the space above the h1,
   the line, the gaps and the pill, measured), and the line and the pill sit a little
   closer. At 375x667 the pill now ends 2px inside the first screen (it was 54px below);
   at 320x568 the h1 and its line still fit (item 2, 2026-10-25). The bar's own Get in
   touch is on every phone's first screen regardless. */
@media (max-width: 47.99em) and (max-height: 44em){
  .intro__copy{--sub-gap:var(--space-2);--title:clamp(2rem,(100svh - var(--nav-h) - 48svh - 9.5rem) / 3.8,(100cqw - 2 * var(--margin)) / 7.43)}
  .intro__actions{--actions-gap:.75rem}
}
/* A short phone, 40em tall or less (a 320x568, a 360x640), gives the film a little less
   height, so the h1 and its line still fit the first screen, and the h1's sum above
   counts that height. */
@media (max-width: 47.99em) and (max-height: 40em){
  .intro__media{max-block-size:42svh}
  .intro__copy{--title:clamp(2rem,(100svh - var(--nav-h) - 42svh - 9.5rem) / 3.8,(100cqw - 2 * var(--margin)) / 7.43)}
}

/* ---- Stacked from 48em (an upright tablet): the 16:9 cut, full width, its right edge
   kept. */
@media (min-width: 48em){
  .intro__media{aspect-ratio:16/9;max-block-size:60svh}
  .intro__still img,.intro__film{object-position:100% 50%}
  .intro__copy{--title:clamp(2.75rem,7.5cqw,4.5rem)}
}

/* ---- Side by side, from 48em on a screen at least 4:3: the first screen below the nav,
   the film covering it with its right edge kept and centred top to bottom, so the frame
   is --fw wide and a frame pixel is --fp. The words' column runs from the nav's frame
   line to 3cqw short of the symbol at its widest (frame x 955, the squash on landing).
   The h1 is sized by that column and by the screen's height, whichever is smaller:
   --title-w makes the column 7.43em, so its widest line, "Then we stay." (7.2em), fits
   with 3% to spare and the h1 sets as "We turn old / websites into / new ones. / Then we
   stay." (items 2 and 3, Sam, 2026-10-25; the 7.9em before was tuned to "across the UK.",
   and an h1 that leaves its column unused was an audit finding, D-52). A browser with
   wider metrics wraps it inside the column all the same, so it never runs into the
   symbol. --title-h keeps the whole block (the h1, the line, the pill and its note, the
   route to Our work and the phone) inside the first screen with --pad to spare above and
   below; it allows for four lines of h1 and a little, so a short screen keeps its room.
   14.5rem is the block under the h1 less its two gaps: 9.5rem until the growth check's
   pill (Sam's call of 2026-10-26, item 4), whose label is too long for the route to Our
   work to sit beside it, so that route and the note each take a row (87px more at
   1366x657). Where the height sets the h1 rather than the column (the short windows),
   it is held to the column's 7.43em all the same, so it stays four lines rather than
   closing up into three (1280x600). A 4:3 window has the narrowest
   column, the film cropped closest to the words, and so the smallest h1: chosen, so the
   symbol keeps its room. Measured 2026-10-25 (1024x768 to 2560x1440, and the short
   windows 1366x657, 1280x720, 1280x600, 1440x700), and again on 2026-10-26 with the
   pill: see the commits for the numbers; the h1 is four lines at every one and the block
   fits between the nav and the foot of the screen. Behind the words, the darkest pixel of the film from the landing to its end:
   ink 13.9:1, --ink-soft 7.0:1 (1024x576 to 2560x1600, 2026-10-20). */
@media (min-width: 48em) and (min-aspect-ratio: 4/3){
  .intro{--intro-h:calc(100svh - var(--nav-h));--h:var(--intro-h);--fw:max(100cqw,var(--h) * 16 / 9);display:grid;align-items:center;min-block-size:var(--intro-h)}
  /* The film's foot fades into the paper below, as the stacked layouts' does (item 5,
     Sam, 2026-10-25: with no fade the film's bottom row met Then and now along a
     dead-straight line). Not a fixed tenth: on a wide, short window the contact shadow
     sits close to the foot (frame y 900, which is --h / 2 - 0.1875 --fw above it: 38px at
     1366x657, 26px at 2560x1080, 189px at 2000x1200), so the fade is that gap less half a
     rem, between 1.5rem and 10rem, and never reaches the symbol's own shadow. */
  .intro__media{--fade:clamp(1.5rem,var(--h) / 2 - .1875 * var(--fw) - .5rem,10rem);position:absolute;inset:0;max-block-size:none;aspect-ratio:auto;-webkit-mask-image:linear-gradient(to top,transparent,#000 var(--fade));mask-image:linear-gradient(to top,transparent,#000 var(--fade))}
  .intro__copy{
    --x:max(var(--margin),(100cqw - 82rem) / 2);
    --fp:calc(var(--fw) / 1920);
    --column:calc(100cqw - 965 * var(--fp) - var(--x) - 3cqw);
    --pad:clamp(1rem,3svh,2.5rem);
    --sub-gap:clamp(1rem,.5rem + 1.2svh,1.75rem);
    --actions-gap:clamp(1.25rem,.5rem + 2svh,2.25rem);
    --title-w:calc(var(--column) / 7.43);
    --title-h:calc((var(--h) - 2 * var(--pad) - 14.5rem - 2 * var(--sub-gap)) / 4.2);
    --title:clamp(2.25rem,min(var(--title-w),var(--title-h)),5.75rem);
    inline-size:min(46rem,var(--column));margin:0 0 0 var(--x);padding:var(--pad) 0}
  .intro__title{max-inline-size:7.43em}
  /* The growth check's pill keeps one line in the narrowest column, a 4:3 window's (346px
     at 1024x768): its label is 17.14em, with 1.25em ends and a 3px border each side, so
     20em of the column (less the plate and the border) leaves a few pixels to spare;
     wider columns keep the body size. */
  .intro .intro__check{font-size:clamp(1rem,(var(--column) - var(--plate-sm) - 6px) / 20,var(--fs-body))}
}

/* ---- The arrival. Start states only under .js and with motion allowed; without either,
   the end frame and the words are simply there. Until hero-site.js decides (.is-film or
   .is-still), the studio is empty and the words wait below their lines. */
@media (prefers-reduced-motion: no-preference){
  .js .intro:not(.is-still):not(.is-done) .intro__still{opacity:0}
  .js .intro:not(.is-landed):not(.is-still) .intro__in{transform:translateY(calc(100% + .3em))}
  .js .intro:not(.is-landed):not(.is-still) :is(.intro__sub,.intro__actions){opacity:0;transform:translateY(var(--intro-rise))}

  /* The failsafe (T-052): if hero-site.js never runs (blocked, failed, a browser too old),
     the end frame and the words appear at 4 s. It stands down the moment the script marks
     the intro .is-armed, and the script takes over from there. */
  .js .intro:not(.is-armed) :is(.intro__still,.intro__in,.intro__sub,.intro__actions){animation:intro-failsafe 0s 4s forwards}

  /* The words (hero-site.js adds .is-landed 250ms after the film rolls, as the symbol
     drops; until the audit of 2026-10-25 it waited for the landing): the h1 rises word by word out of its line, 45ms apart (the site's
     heading rise, P1), on the site's long expo tail with no overshoot; then the line, as
     the last word is on its way, and the pill and the phone. */
  .js .intro.is-landed:not(.is-still) .intro__in{animation:intro-rise .72s var(--ease-arrive) calc(var(--i, 0) * 45ms) both}
  .js .intro.is-landed:not(.is-still) .intro__sub{animation:intro-up .7s var(--ease-arrive) .4s both}
  .js .intro.is-landed:not(.is-still) .intro__actions{animation:intro-up .7s var(--ease-arrive) .52s both}
}
@keyframes intro-failsafe{to{opacity:1;transform:none}}
@keyframes intro-rise{from{transform:translateY(calc(100% + .3em))}to{transform:none}}
@keyframes intro-up{from{opacity:0;transform:translateY(var(--intro-rise))}to{opacity:1;transform:none}}

/* ---- The flight (item 6, Sam's call of 2026-10-25, D-55; hero-site.js). Nothing here
   applies until the script arms it (.is-flight), so without the script, under reduced
   motion or Save-Data, or before the film has landed, the page is the page.
   The plates: the empty studio over the film, cropped exactly as the film is (the same
   box, object-fit and object-position), so with the cut-out laid over them they give
   back the film's last frame. The floor plate keeps the contact shadow and fades as the
   symbol lifts, uncovering the clean one under it. Their opacity is the script's. */
.intro__plates{position:absolute;inset:0;z-index:2;display:none;opacity:0;pointer-events:none}
.intro.is-flight .intro__plates{display:block}
.intro__plate{position:absolute;inset:0;display:block;inline-size:100%;block-size:100%;object-fit:cover;object-position:50% 50%}
@media (min-width: 48em){
  .intro__plate{object-position:100% 50%}
}
/* The symbol in the air, and its shadow: one fixed layer over the page and under the nav
   (40), the cursor and the curtain, which never takes the pointer. Each picture is laid
   out at its size on the film, at the top left, and the script moves it only by
   transform (and its opacity), so a scroll never asks for layout. */
.flight{position:fixed;inset:0;z-index:30;overflow:hidden;overflow:clip;pointer-events:none;contain:strict}
.flight__symbol,.flight__shade{position:absolute;top:0;left:0;display:block;max-inline-size:none;opacity:0;transform-origin:50% 50%;will-change:transform,opacity;-webkit-user-select:none;user-select:none}

/* The environment layer: one fixed glow behind the whole page. It drifts 6% left and 8%
   down over 90 seconds and back once, then rests where it began, which is where reduced
   motion holds it from the start: it no longer loops (review finding a11y-7, option A;
   D-31; Stanley's written yes of 2026-10-21, "Run once, then settle", for the whole site,
   this glow named on the Sitewide board), so nothing moves on and on with no way to stop
   it (WCAG 2.2.2). It still starts a third of the way out, as it did. Every section, the
   intro included, sets its own opaque ground, so it shows only in the overscroll. Still
   under reduced motion; engine.css pauses it on a hidden tab. */
.environment{position:fixed;inset:-10%;z-index:-1;pointer-events:none;
  background:radial-gradient(ellipse 55% 45% at 70% 30%,rgba(94,30,71,.32) 0%,rgba(94,30,71,0) 70%),
             radial-gradient(ellipse 45% 40% at 20% 75%,rgba(244,243,239,.035) 0%,rgba(244,243,239,0) 70%)}
@media (prefers-reduced-motion: no-preference){
  .environment{animation:environment-drift 90s var(--ease-in-out) -30s 2 alternate}
}
@keyframes environment-drift{
  to{transform:translate3d(-6%,8%,0)}
}
