/* Fennmore — public website.
   One stylesheet, no framework, no build step. The brand palette and the two
   typefaces are the same ones the CRM, the portals and the marketing artwork
   use, so a page here and a post on Instagram look like the same company.

   Fonts are self-hosted subsets rather than Google Fonts: no third-party
   request means the privacy notice's promise about tracking stays true, and
   the page paints without waiting on someone else's CDN. */

@font-face { font-family: 'Caladea'; src: url('/fonts/caladea-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Caladea'; src: url('/fonts/caladea-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'Caladea'; src: url('/fonts/caladea-400i.woff2') format('woff2');
  font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Carlito'; src: url('/fonts/carlito-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Carlito'; src: url('/fonts/carlito-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap; }

:root {
  --ink: #071829;
  --navy: #0B2440;
  --navy-mid: #0E2C4C;
  --gold: #C9A961;
  --gold-light: #E3D2A6;
  --stone: #F2F1ED;
  --slate: #4A5A6B;
  --mist: #A9BDD1;
  --paper: #FFFFFF;
  --line: rgba(11, 36, 64, 0.14);
  --serif: 'Caladea', Cambria, Georgia, 'Times New Roman', serif;
  --sans: 'Carlito', Calibri, 'Segoe UI', system-ui, -apple-system, sans-serif;
  --page: 1180px;
  --gut: 28px;
  --shadow: 0 18px 48px rgba(7, 24, 41, 0.10);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

/* ------------------------------------------------------- page transitions --
   Moving between pages dissolves instead of snapping. This is the browser's
   own cross-document view transition: two declarations, no script, no
   single-page-app machinery, and no cost at all in a browser that does not
   support it — there, links behave exactly as they always have.

   The header is given its own name so it is treated as the same object either
   side of the change and holds still while the page beneath it turns over.
   Without that it would fade out and back in, which reads as a flicker. */
@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: pageOut .42s cubic-bezier(.4, 0, 1, 1) both; }
  ::view-transition-new(root) { animation: pageIn .85s cubic-bezier(.22, .61, .36, 1) both; }
  @keyframes pageOut { to { opacity: 0; } }
  @keyframes pageIn  { from { opacity: 0; transform: translateY(10px); } }
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }

  /* The blanket rule above collapses every animation to almost no duration,
     which for a looping cross-fade means it lands on its final keyframe — and
     the final keyframe of every hero frame is opacity 0. The result would be a
     black hero for exactly the people least able to tolerate a surprise. So
     the sequence is switched off properly here and the first photograph is
     simply shown, still, for as long as they are on the page. */
  .hero-lead .frame { animation: none !important; opacity: 0; }
  .hero-lead .frame:nth-child(1) { opacity: 1; }
  .hero-lead .frame img { animation: none !important; transform: none !important; }
  .hero-lead h1 .w > span,
  .hero-lead .eyebrow, .hero-lead .lede, .hero-lead .btns {
    animation: none !important; opacity: 1 !important; transform: none !important;
  }
  .hero-lead .eyebrow::after { animation: none !important; transform: scaleX(1) !important; }
  .hero-ticks, .scroll-cue { display: none; }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 18px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

/* height:auto is doing real work here. Every image on the site carries width
   and height attributes so the browser can reserve the right space before the
   file arrives — but with max-width:100% and no height:auto, a narrowing column
   shrinks the width while the height attribute holds, and the picture squashes.
   The attributes stay (they prevent the page jumping about as images load);
   this line makes them behave. */
img { max-width: 100%; height: auto; display: block; }
a { color: var(--navy); text-decoration-color: rgba(201, 169, 97, 0.7); text-underline-offset: 3px; }
a:hover { color: var(--gold); }

h1, h2, h3, h4 { font-family: var(--serif); font-weight: 700; line-height: 1.16; margin: 0 0 0.5em; letter-spacing: -0.005em; }
h1 { font-size: clamp(2.1rem, 1.35rem + 2.6vw, 3.5rem); }
h2 { font-size: clamp(1.65rem, 1.2rem + 1.6vw, 2.5rem); }
h3 { font-size: clamp(1.15rem, 1.02rem + 0.5vw, 1.4rem); }
p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

.wrap { width: min(100% - (var(--gut) * 2), var(--page)); margin-inline: auto; }
.narrow { width: min(100% - (var(--gut) * 2), 760px); margin-inline: auto; }

.eyebrow {
  font-family: var(--sans);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold);
  margin: 0 0 0.9em;
}
.lede { font-size: clamp(1.05rem, 1rem + 0.4vw, 1.28rem); color: var(--slate); }
.on-dark .lede { color: var(--mist); }

/* Skip link — keyboard users should not have to tab the whole nav on
   every page before reaching the thing they came for. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--gold); color: var(--ink); padding: 12px 18px; font-weight: 700;
}
.skip:focus { left: 12px; top: 12px; }

:focus-visible { outline: 3px solid var(--gold); outline-offset: 3px; }

/* ---------------------------------------------------------------- header -- */
.site-head {
  view-transition-name: site-head;
  position: sticky; top: 0; z-index: 100;
  background: rgba(7, 24, 41, 0.94);
  backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid rgba(201, 169, 97, 0.22);
}
.site-head .bar { display: flex; align-items: center; gap: 24px; min-height: 76px; }
.brand { display: flex; align-items: baseline; gap: 10px; text-decoration: none; margin-right: auto; }
.brand .name {
  font-family: var(--serif); font-size: 1.5rem; font-weight: 700; color: #fff; letter-spacing: 0.02em;
}
.brand .rule { width: 26px; height: 1px; background: var(--gold); }
.brand .sub {
  font-size: 0.62rem; letter-spacing: 0.24em; text-transform: uppercase; color: var(--gold-light);
}
.nav { display: flex; align-items: center; gap: 26px; }
.nav a {
  color: #E7EEF5; text-decoration: none; font-size: 0.95rem; padding: 6px 0;
  border-bottom: 1px solid transparent;
}
.nav a:hover, .nav a[aria-current="page"] { color: #fff; border-bottom-color: var(--gold); }
/* Sign in appears twice in the markup — once beside the links for the mobile
   disclosure, once in the header bar for desktop. Each viewport shows one. */
.nav .btn { display: none; }
.head-cta { display: flex; align-items: center; gap: 12px; }
.navtoggle { display: none; }

/* --------------------------------------------------------------- buttons -- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--sans); font-size: 0.95rem; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  padding: 14px 26px; border-radius: 2px; border: 1px solid transparent;
  text-decoration: none; cursor: pointer; transition: background .18s, color .18s, border-color .18s;
}
.btn-gold { background: var(--gold); color: var(--ink); }
.btn-gold:hover { background: var(--gold-light); color: var(--ink); }
.btn-ghost { border-color: rgba(255, 255, 255, 0.45); color: #fff; background: transparent; }
.btn-ghost:hover { border-color: var(--gold); color: var(--gold-light); background: rgba(201, 169, 97, 0.08); }
.btn-line { border-color: var(--navy); color: var(--navy); background: transparent; }
.btn-line:hover { background: var(--navy); color: #fff; }
.btn-sm { padding: 10px 18px; font-size: 0.82rem; }
.btns { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 30px; }

/* ------------------------------------------------------------------ hero -- */
/* Every hero on the site is the same block. Previously the height came from
   padding, so a page with two lines of standfirst and a button stood taller
   than one with neither, and moving between pages felt like the furniture was
   being rearranged. Now the height is set once and the copy sits centred
   inside it, whatever there is of it. */
.hero {
  position: relative; color: #fff; background: var(--ink); overflow: hidden;
  min-height: clamp(480px, 60vh, 620px);   /* narrow screens; the desktop figure is set below */
  display: flex; align-items: center;
}
.hero .shot { position: absolute; inset: 0; }
.hero .shot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero .veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(105deg, rgba(7, 24, 41, 0.94) 0%, rgba(7, 24, 41, 0.80) 46%, rgba(7, 24, 41, 0.42) 100%),
    linear-gradient(0deg, rgba(7, 24, 41, 0.55), rgba(7, 24, 41, 0.05));
}
/* No width here on purpose: this element also carries .wrap, which sets the
   page column and centres it. Setting width:100% would out-specify .wrap and
   run the copy into the edge of the window. */
.hero .inner { position: relative; padding: 56px 0; }
/* The entrance animations below legitimately begin at zero opacity and settle
   at one within a second of load. What must never happen is the copy being
   hidden by something tied to scroll position, which is why no scroll-driven
   animation on this page touches opacity at all. */
.hero .copy { max-width: 640px; }
.hero h1 { color: #fff; }
.hero .lede { color: #DCE6EF; }

/* -------------------------------------------------------------- hero motion --
   The landing page hero.

   Four photographs, each held for ten seconds and dissolved into the next over
   two, while every frame drifts on its own axis so the sequence never appears
   to loop. A scrim shapes the light rather than merely darkening it, and a
   trace of film grain sits over the whole thing — at three per cent it is not
   consciously visible, but its absence is: without it large flat gradients on
   a good screen band into visible steps.

   All of it is CSS. A video would cost several megabytes, is refused autoplay
   on a great many phones, and could not be this sharp.
   -------------------------------------------------------------------------- */
.hero-lead {
  min-height: min(calc(100svh - 76px), 880px);
}
/* The copy block is centred in the frame. In a full-height hero that puts the
   buttons low enough to collide with the closing line, so the foot of the hero
   is reserved and the centring happens in what is left.

   That reservation has to scale with the window. As a fixed 210px it made the
   hero taller than a short laptop window — the hero then grew past the bottom
   of the screen and took the sequence marks with it, which is why they
   disappeared off the page. Tied to viewport height it keeps the same
   proportions on a large display and simply asks for less room on a small one. */
.hero-lead .inner { padding-bottom: clamp(104px, 16vh, 200px); }
.hero-lead .stage { position: absolute; inset: 0; overflow: hidden; }
.hero-lead .frame { position: absolute; inset: 0; opacity: 0; will-change: opacity; }
.hero-lead .frame img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  animation: heroBreathe 120s ease-in-out infinite alternate;
  will-change: transform;
}
/* Each frame pivots on a different point, so one photograph pulls away as the
   next leans in. Same animation, four different centres of gravity. */
.hero-lead .frame:nth-child(1) img { transform-origin: 32% 42%; }
.hero-lead .frame:nth-child(2) img { transform-origin: 68% 58%; animation-direction: alternate-reverse; }
.hero-lead .frame:nth-child(3) img { transform-origin: 45% 70%; }
.hero-lead .frame:nth-child(4) img { transform-origin: 60% 35%; animation-direction: alternate-reverse; }
@keyframes heroBreathe {
  from { transform: scale(1.04); }
  to   { transform: scale(1.13); }
}

/* The cycle. Every frame runs the same 48-second animation and is offset in
   time; four frames at twelve seconds each. Within its own timeline a frame
   fades up over two seconds, holds for ten, and fades away over two — and the
   offsets are spaced so each fade-out is covered exactly by the next fade-in.
   Get that spacing wrong by a second and the hero goes black between pictures,
   which is precisely what the first attempt at this did.

     frame 1   -3s   visible 0-13s,  gone by 16s
     frame 2   13s   visible 16-29s, gone by 32s
     frame 3   29s   visible 32-45s, gone by 48s
     frame 4   45s   visible 48-61s, gone by 64s
     frame 1 again at 61s, covering frame 4 as the cycle closes

   The negative delay on the first frame is what stops the page opening on a
   two-second fade from black: it begins already at full opacity. */
.hero-lead .frame { animation: heroCycle 64s linear infinite; }
.hero-lead .frame:nth-child(1) { animation-delay: -3s; }
.hero-lead .frame:nth-child(2) { animation-delay: 13s; }
.hero-lead .frame:nth-child(3) { animation-delay: 29s; }
.hero-lead .frame:nth-child(4) { animation-delay: 45s; }
@keyframes heroCycle {
  0%       { opacity: 0; }
  4.69%    { opacity: 1; }   /* 3s fade in  */
  25%      { opacity: 1; }   /* holds to 16s */
  29.69%   { opacity: 0; }   /* 3s fade out */
  100%     { opacity: 0; }
}

/* A shaped scrim: a directional wash so the type always has ground beneath it,
   a lift from the foot, and a vignette to hold the eye in the frame. */
/* These photographs are bright — a sunrise above cloud is nearly white on the
   left where the headline sits. The wash is therefore weighted hard to the
   left and eased off across the right, so the type has a dark ground while the
   light in the picture is left alone to do its work. */
.hero-lead .veil {
  background:
    /* The column the type sits in — dark where the words are, gone by the
       middle of the frame. It falls away fast on purpose: a wash that reaches
       the right-hand side would put out the sunrise, which is the only reason
       this photograph is here. */
    linear-gradient(92deg,
      rgba(7, 24, 41, 0.92) 0%,
      rgba(7, 24, 41, 0.84) 22%,
      rgba(7, 24, 41, 0.55) 42%,
      rgba(7, 24, 41, 0.18) 60%,
      rgba(7, 24, 41, 0.00) 76%),
    /* Just enough weight at the foot to carry the closing line and the ticks. */
    linear-gradient(0deg, rgba(7, 24, 41, 0.58) 0%, rgba(7, 24, 41, 0.00) 30%),
    /* And the faintest darkening at the very top, so the header does not float
       on a bright sky. */
    linear-gradient(180deg, rgba(7, 24, 41, 0.34) 0%, rgba(7, 24, 41, 0.00) 18%);
}
/* With the wash pulled back this far the type carries some of its own contrast
   — but NOT the headline. Each of its words sits inside a mask with overflow
   hidden so it can rise into place, and a soft shadow spreading out of a glyph
   is cut off square by that mask, leaving a grey rectangle behind every word.
   The headline instead relies on the gradient above, which is deepest exactly
   where the headline is. */
/* The standfirst is large enough to carry a wide, soft shadow. The eyebrow is
   not: eleven-pixel letters with 0.22em of tracking sitting inside a 26px blur
   have more halo than letter, and the result reads as out of focus rather than
   as contrast. It gets a tight, dark shadow instead — one pixel of spread,
   doing the same job without the fog. */
.hero-lead .lede { text-shadow: 0 1px 26px rgba(7, 24, 41, .8), 0 1px 3px rgba(7, 24, 41, .4); }
.hero-lead .eyebrow { text-shadow: 0 1px 2px rgba(7, 24, 41, .95), 0 0 1px rgba(7, 24, 41, .9); }
.hero-foot { text-shadow: 0 1px 18px rgba(7, 24, 41, .75); }
.hero-lead h1 { text-shadow: none; }
/* Brand gold against a sunrise is gold on gold. The lighter tint of the same
   colour keeps the brand and wins back the contrast. */
.hero-lead .eyebrow { color: var(--gold-light); }
.hero-lead .grain {
  position: absolute; inset: 0; pointer-events: none; opacity: .05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---- the headline ----
   Each word rises out of its own mask. The masks are what make it read as
   typesetting rather than a fade — but an inline-block with overflow hidden
   crops descenders, so every word carries a little room below the baseline
   and pulls it back with a negative margin. */
.hero-lead h1 { margin-bottom: 0.42em; }
.hero-lead h1 .w {
  display: inline-block; overflow: hidden; vertical-align: bottom;
  padding-bottom: 0.14em; margin-bottom: -0.14em;
}
.hero-lead h1 .w > span {
  display: inline-block;
  animation: wordRise 1.4s cubic-bezier(.16, 1, .3, 1) both;
  animation-delay: calc(var(--i) * .075s + .35s);
}
@keyframes wordRise {
  from { transform: translateY(108%); }
  to   { transform: none; }
}
/* Eyebrow, standfirst and buttons follow the headline in. */
.hero-lead .eyebrow { animation: heroRise 1.3s cubic-bezier(.22,.61,.36,1) both .15s; }
.hero-lead .lede    { animation: heroRise 1.5s cubic-bezier(.22,.61,.36,1) both 1.05s; }
.hero-lead .btns    { animation: heroRise 1.5s cubic-bezier(.22,.61,.36,1) both 1.3s; }
@keyframes heroRise {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to   { opacity: 1; transform: none; }
}
/* A hairline that draws itself under the eyebrow. */
.hero-lead .eyebrow::after {
  content: ''; display: block; width: 54px; height: 1px; background: var(--gold);
  margin-top: 14px; transform: scaleX(0); transform-origin: left center;
  animation: ruleDraw 1.5s cubic-bezier(.22,.61,.36,1) both .7s;
}
@keyframes ruleDraw { to { transform: scaleX(1); } }

/* ---- sequence ticks ----
   Four marks at the foot of the frame, each filling across the ten seconds its
   photograph is on screen. Ambient rather than a control: it tells you the
   picture is going to change, so the change is not a surprise. */
.hero-ticks { position: absolute; left: 0; right: 0; bottom: clamp(40px, 6.5vh, 62px); z-index: 2; }
.hero-ticks .row { display: flex; gap: 10px; }
.hero-ticks i {
  display: block; width: 34px; height: 2px; background: rgba(255, 255, 255, 0.22);
  position: relative; overflow: hidden;
}
.hero-ticks i::after {
  content: ''; position: absolute; inset: 0; background: var(--gold);
  transform: scaleX(0); transform-origin: left center;
  animation: tickFill 64s linear infinite;
}
.hero-ticks i:nth-child(2)::after { animation-delay: 16s; }
.hero-ticks i:nth-child(3)::after { animation-delay: 32s; }
.hero-ticks i:nth-child(4)::after { animation-delay: 48s; }
@keyframes tickFill {
  0%           { transform: scaleX(0); }
  25%          { transform: scaleX(1); }
  25.01%, 100% { transform: scaleX(0); }
}

/* ---- the opening ----
   The first photograph arrives the way a lens finds focus: fractionally
   over-scaled and soft, settling to sharp over two seconds. It is the single
   most expensive-feeling thing on the page and it costs one keyframe — but it
   only ever runs on the first frame, and only once, because a picture that
   keeps re-focusing would be a distraction rather than an arrival. */
.hero-lead .frame:nth-child(1) img {
  animation:
    heroBreathe 120s ease-in-out infinite alternate,
    heroFocus 2.4s cubic-bezier(.16, 1, .3, 1) both;
}
@keyframes heroFocus {
  from { filter: blur(16px) saturate(1.25); opacity: .55; }
  55%  { filter: blur(3px)  saturate(1.08); opacity: 1; }
  to   { filter: blur(0)    saturate(1); opacity: 1; }
}

/* A hairline of gold along the foot of the hero, drawn from the centre out as
   the page settles. It is the join between the photograph and the page, and
   it makes the hero feel finished rather than cropped. */
.hero-lead::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; z-index: 4;
  background: linear-gradient(90deg, rgba(201,169,97,0) 0%, rgba(201,169,97,.55) 50%, rgba(201,169,97,0) 100%);
  transform: scaleX(0); transform-origin: center;
  animation: hemDraw 2.2s cubic-bezier(.22,.61,.36,1) both 1.9s;
}
@keyframes hemDraw { to { transform: scaleX(1); } }

/* The closing line: small, letter-spaced, centred at the foot of the frame.
   It is the last thing read before the page begins, so it earns its place by
   saying the one thing the headline could not fit. */
.hero-foot {
  position: absolute; left: 0; right: 0; bottom: clamp(72px, 11vh, 96px); z-index: 3;
  text-align: center; pointer-events: none;
}
.hero-foot p {
  margin: 0; font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase; color: rgba(255, 255, 255, 0.88);
  animation: heroRise 1.6s cubic-bezier(.22,.61,.36,1) both 1.6s;
}

/* The hero does not end on a line. It dissolves into whatever follows, so the
   eye is carried down rather than stopped. */
.hero-hem {
  position: absolute; left: 0; right: 0; bottom: 0; height: 130px; z-index: 1;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.06) 55%, rgba(255, 255, 255, 0.16) 100%);
  pointer-events: none;
}

/* The landing headline is set a little larger than the rest of the site — it
   is the first thing anyone reads, and on a full-height frame it can afford
   the room. */
.hero-lead h1 { font-size: clamp(2.35rem, 1.3rem + 3.3vw, 4.1rem); }

/* A quiet invitation to scroll. */
.scroll-cue {
  position: absolute; left: 50%; bottom: clamp(36px, 6vh, 56px); transform: translateX(-50%);
  width: 1px; height: 52px; background: linear-gradient(180deg, transparent, rgba(201, 169, 97, .8));
  z-index: 2;
}
.scroll-cue::after {
  content: ''; position: absolute; left: -3px; bottom: 0; width: 7px; height: 7px;
  border-radius: 50%; background: var(--gold);
  animation: cueDrop 4.6s ease-in-out infinite;
}
@keyframes cueDrop {
  0%, 100% { transform: translateY(0); opacity: 1; }
  50%      { transform: translateY(-16px); opacity: .2; }
}

/* ---- parallax on the way out ----
   Where the browser can drive an animation from scroll position, the picture
   leaves more slowly than the page and the words lift away as they go. It is
   the difference between scrolling a document and moving through a space.
   Where it cannot, nothing happens and nothing is missed. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-lead .stage {
      animation: heroPark linear both;
      animation-timeline: view();
      animation-range: exit 0% exit 100%;
    }
    @keyframes heroPark { to { transform: translateY(14%) scale(1.05); } }
    /* The copy drifts up as the hero leaves — but it does NOT fade.
       An earlier version animated opacity to zero here, and in Safari the
       scroll timeline could resolve as already finished on a restored scroll
       position, which applied the final keyframe and left the landing page
       with no headline, no standfirst and no buttons at all. Nothing that can
       hide the page's only message may be driven by scroll position: if this
       animation lands on its last frame at the wrong moment the worst that
       now happens is the words sit thirty pixels higher than they should. */
    .hero-lead .copy {
      animation: heroLift linear both;
      animation-timeline: view();
      animation-range: exit 0% exit 72%;
    }
    @keyframes heroLift { to { transform: translateY(-34px); } }
  }
}

/* --------------------------------------------------------------- section -- */
.sec { padding: clamp(56px, 8vw, 104px) 0; }
.sec-stone { background: var(--stone); }
.sec-navy { background: var(--navy); color: #fff; }
.sec-navy h2, .sec-navy h3 { color: #fff; }
.sec-navy p { color: #DCE6EF; }
.sec-tight { padding: clamp(40px, 5vw, 64px) 0; }
.sec-head { max-width: 62ch; margin-bottom: clamp(32px, 4vw, 52px); }

/* ----------------------------------------------------------------- grids -- */
.grid { display: grid; gap: clamp(20px, 2.4vw, 32px); }
.g2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(28px, 4vw, 64px); align-items: center; }

/* ----------------------------------------------------------------- cards -- */
.card {
  background: #fff; border: 1px solid var(--line); border-radius: 3px;
  padding: clamp(22px, 2.6vw, 34px);
}
.sec-stone .card { border-color: rgba(11, 36, 64, 0.10); }
.card h3 { margin-bottom: 0.45em; }
.card p { color: var(--slate); font-size: 0.98rem; }
.sec-navy .card { background: var(--navy-mid); border-color: rgba(201, 169, 97, 0.24); }
.sec-navy .card p { color: var(--mist); }

.num { font-family: var(--serif); font-size: 2.1rem; color: var(--gold); line-height: 1; display: block; margin-bottom: 14px; }

/* Feature panel: a picture and a block of words, alternating side by side. */
.panel { border: 1px solid var(--line); border-radius: 3px; overflow: hidden; background: #fff; display: flex; flex-direction: column; }
/* min-height:0 matters more than it looks. A flex or grid item containing an
   image takes its automatic minimum size from that image's intrinsic height,
   which silently overrides aspect-ratio — a portrait photograph then renders
   at full height instead of being cropped to the panel's shape. */
.panel .shot { aspect-ratio: 16 / 10; min-height: 0; overflow: hidden; }
.panel .shot img { width: 100%; height: 100%; object-fit: cover; }
.panel .body { padding: clamp(24px, 2.6vw, 36px); display: flex; flex-direction: column; flex: 1; }
.panel .body p { color: var(--slate); flex: 1; }
.panel .body .btn { align-self: flex-start; margin-top: 20px; }

.tick { list-style: none; margin: 0; padding: 0; }
.tick li { position: relative; padding-left: 30px; margin-bottom: 14px; color: var(--slate); }
.tick li::before {
  content: ''; position: absolute; left: 4px; top: 0.62em; width: 12px; height: 6px;
  border-left: 2px solid var(--gold); border-bottom: 2px solid var(--gold); transform: rotate(-45deg);
}
.sec-navy .tick li { color: #DCE6EF; }

.quote { border-left: 3px solid var(--gold); padding-left: 26px; font-family: var(--serif); font-style: italic;
  font-size: clamp(1.15rem, 1rem + 0.7vw, 1.5rem); line-height: 1.45; }

/* ------------------------------------------------------------------ call -- */
.call { background: var(--navy); color: #fff; }
.call .inner { padding: clamp(48px, 6vw, 84px) 0; display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 56px); align-items: center; }
.call h2 { color: #fff; margin-bottom: 0.4em; }
.call p { color: var(--mist); margin: 0; }
.call .btns { margin: 0; justify-content: flex-end; }
/* A navy section running straight into the navy call band reads as one very
   tall block with an unexplained gap in it. A hairline says "new thought". */
.sec-navy + .call .inner { border-top: 1px solid rgba(201, 169, 97, 0.22); }

/* ----------------------------------------------------------------- forms -- */
.form { background: #fff; border: 1px solid var(--line); border-radius: 3px; padding: clamp(24px, 3vw, 40px); }
.field { margin-bottom: 20px; }
.field label { display: block; font-size: 0.82rem; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--navy); margin-bottom: 7px; }
.field .hint { font-size: 0.85rem; color: var(--slate); margin: 0 0 8px; text-transform: none;
  letter-spacing: 0; font-weight: 400; }
.field input, .field select, .field textarea {
  width: 100%; max-width: 100%; font-family: var(--sans); font-size: 1rem; color: var(--ink);
  background: #fff; border: 1px solid rgba(11, 36, 64, 0.28); border-radius: 2px; padding: 12px 14px;
}
.field textarea { min-height: 140px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--gold); outline: none;
  box-shadow: 0 0 0 3px rgba(201, 169, 97, 0.22); }
/* Two fields side by side.
   Their labels are rarely the same length, and a label that wraps to two lines
   would push its input below its neighbour's. So the pair of fields dissolves
   into the row's own grid (display: contents) and the labels are pinned to the
   first grid row, the controls to the second. Both rows size to their tallest
   member, so the inputs line up whatever the wording — and changing a label
   later cannot quietly break the alignment. */
.frow { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: 20px; row-gap: 0; margin-bottom: 20px; }
.frow > * { min-width: 0; }
.frow .field { display: contents; }
.frow .field > label { grid-row: 1; align-self: end; }
.frow .field > :not(label) { grid-row: 2; }
.field label .hint { display: inline; margin: 0; }
/* The consent line is a label, but it is a sentence rather than a field name —
   so it opts out of the small-caps treatment the other labels wear. */
.field label.consent, .consent {
  display: flex; gap: 12px; align-items: flex-start;
  font-size: 0.92rem; font-weight: 400; line-height: 1.5;
  text-transform: none; letter-spacing: 0; color: var(--slate); margin-bottom: 0;
}
.consent input { width: 18px; height: 18px; margin-top: 3px; flex: none; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.formnote { font-size: 0.88rem; color: var(--slate); margin-top: 18px; }
.alert { border-left: 3px solid var(--gold); background: var(--stone); padding: 14px 18px; margin-bottom: 22px; font-size: 0.95rem; }
.alert-bad { border-left-color: #A33; background: #FBF1F1; }

/* ------------------------------------------------------------------ misc -- */
.prose h2 { margin-top: 1.6em; }
.prose h2:first-child { margin-top: 0; }
.prose p { color: var(--slate); }
.meta { font-size: 0.85rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--slate); }
.mediastrip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; }
.mediastrip img { aspect-ratio: 3 / 4; object-fit: cover; width: 100%; height: 100%; min-height: 0; }
.badge { display: inline-block; border: 1px solid rgba(201, 169, 97, 0.55); color: var(--gold);
  font-size: 0.7rem; letter-spacing: 0.18em; text-transform: uppercase; padding: 6px 12px; border-radius: 2px; }

/* ---------------------------------------------------------------- footer -- */
.site-foot { background: var(--ink); color: #C7D4E0; padding: clamp(48px, 6vw, 76px) 0 32px; font-size: 0.94rem; }
.site-foot h4 { color: #fff; font-family: var(--sans); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase; margin-bottom: 16px; }
.site-foot a { color: #C7D4E0; text-decoration: none; }
.site-foot a:hover { color: var(--gold-light); }
.foot-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: clamp(24px, 3vw, 48px); }
.foot-grid ul { list-style: none; margin: 0; padding: 0; }
.foot-grid li { margin-bottom: 10px; }
.foot-note { margin-top: clamp(32px, 4vw, 52px); padding-top: 26px; border-top: 1px solid rgba(255, 255, 255, 0.12);
  color: #8FA3B5; font-size: 0.82rem; line-height: 1.7; }
.protect { border: 1px solid rgba(201, 169, 97, 0.35); padding: 16px 18px; border-radius: 2px;
  color: #C7D4E0; font-size: 0.86rem; margin-top: 20px; }

/* From here up, every hero is exactly this tall. The figure is the tallest
   hero's content (the business page, four lines of headline plus a standfirst
   and a button) plus its padding, rounded up — so nothing is ever squeezed and
   nothing has to grow. Change the hero copy substantially and re-measure. */
@media (min-width: 861px) {
  /* Every hero except the landing page: one height, 50px clear of the tallest
     content (438px of copy plus 112px of padding). The landing page is
     deliberately taller — it is doing a different job — and is excluded here
     rather than fighting this rule on source order. */
  .hero:not(.hero-lead) { min-height: 600px; }
}

/* ------------------------------------------------------------ responsive --
   The site is built narrow-first in behaviour even though it is written
   desktop-down: every grid collapses to one column, the navigation becomes a
   disclosure, and nothing relies on hover to be usable. */
@media (max-width: 1000px) {
  .g4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  :root { --gut: 20px; }
  body { font-size: 17px; }

  .navtoggle {
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent; border: 1px solid rgba(255, 255, 255, 0.4); color: #fff;
    width: 44px; height: 44px; border-radius: 2px; cursor: pointer; padding: 0;
  }
  .navtoggle span { display: block; width: 20px; height: 2px; background: #fff; position: relative; }
  .navtoggle span::before, .navtoggle span::after {
    content: ''; position: absolute; left: 0; width: 20px; height: 2px; background: #fff;
  }
  .navtoggle span::before { top: -6px; }
  .navtoggle span::after { top: 6px; }

  .site-head .bar { min-height: 66px; }
  .nav {
    display: none; position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--ink); border-bottom: 1px solid rgba(201, 169, 97, 0.3);
    padding: 8px 0 18px;
  }
  .site-head.open .nav { display: flex; }
  .nav a { padding: 14px var(--gut); border-bottom: 1px solid rgba(255, 255, 255, 0.08); font-size: 1.02rem; }
  .nav a:hover, .nav a[aria-current="page"] { border-bottom-color: rgba(255, 255, 255, 0.08); color: var(--gold-light); }
  .nav .btn { display: inline-flex; margin: 14px var(--gut) 0; }

  .head-cta .btn { display: none; }

  .g2, .g3, .g4, .split, .frow { grid-template-columns: minmax(0, 1fr); }
  /* One column: the paired-row trick above is not needed and would stack every
     label above every input. Put the fields back to ordinary blocks. */
  .frow { margin-bottom: 0; }
  .frow .field { display: block; }
  .frow .field > label, .frow .field > :not(label) { grid-row: auto; }
  .call .inner { grid-template-columns: minmax(0, 1fr); }
  .call .btns { justify-content: flex-start; }
  /* One height for every inner hero. The floor has to clear the tallest copy
     any of them carries — the business page's standfirst is the long one, and
     at 320px it needed 516px — or the pages quietly stop matching each other
     on the narrowest phones, which is exactly what was happening. */
  .hero:not(.hero-lead) { min-height: clamp(540px, 64vh, 580px); }
  /* On a phone the landing hero fills the screen it is given, less the header. */
  .hero-lead { min-height: calc(100svh - 66px); }
  .hero .copy { max-width: none; }
  /* The scroll cue stays on a phone. It is the smallest possible piece of
     motion and it does the most work: it tells a visitor arriving on a
     full-height photograph that there is a page underneath it. */
  .scroll-cue { display: block; bottom: 30px; height: 40px; }
  .hero-ticks { bottom: 76px; }
  /* Narrow screens need a vertical wash rather than the desktop's diagonal —
     but not so dark that the photograph stops being a photograph. */
  .hero .veil { background: linear-gradient(180deg, rgba(7, 24, 41, 0.74) 0%, rgba(7, 24, 41, 0.90) 60%, rgba(7, 24, 41, 0.95) 100%); }
  /* The landing page keeps its photograph on a phone. The wash is light across
     the top third, where there is no type, and deepens through the band the
     copy occupies — so the picture is still a picture rather than a texture
     behind a dark panel. */
  /* On a phone the wash has to be nearly absent across the top — a sunrise sky
     is close to white, and any veil over it turns the whole upper half grey —
     then arrive quickly through the band the copy occupies. */
  .hero-lead .veil {
    background:
      linear-gradient(180deg,
        rgba(7, 24, 41, 0.10) 0%,
        rgba(7, 24, 41, 0.08) 15%,
        /* The eyebrow lands at roughly a third of the way down. It is the
           smallest type on the page and the palest colour on it, so the wash
           has to have arrived by the time it gets there — otherwise it sits on
           a peach sky and reads as faint however crisp its edges are. */
        rgba(7, 24, 41, 0.58) 25%,
        rgba(7, 24, 41, 0.80) 36%,
        rgba(7, 24, 41, 0.88) 68%,
        rgba(7, 24, 41, 0.95) 100%);
  }
  /* A landscape photograph cropped to a phone shows only a narrow slice of its
     middle. Pushing that slice right and down finds the part of each of these
     four that actually has something in it — the sun, the ridge line and the
     cloud floor — instead of a column of empty sky. */
  .hero-lead .frame img { object-position: 66% 58%; }
  /* With the wash lightened so the photograph reads, the type needs to carry
     its own contrast rather than rely on the panel behind it. A wide, soft
     shadow does that without looking like a drop shadow — it simply darkens
     the few pixels around each letter, wherever the picture happens to be
     bright that second. */
  .hero-lead .lede { text-shadow: 0 1px 28px rgba(7, 24, 41, .9), 0 1px 4px rgba(7, 24, 41, .55); }
  .hero-lead .eyebrow { text-shadow: 0 1px 2px rgba(7, 24, 41, .95), 0 0 1px rgba(7, 24, 41, .9); }
  .hero-lead h1, .hero-lead .btns { text-shadow: none; }
  .hero-foot { display: none; }   /* no room for it beneath the buttons */
  .hero-hem { height: 90px; }
  .hero .inner { padding: 46px 0; }
  .mediastrip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-grid { grid-template-columns: 1fr; }
  .btns .btn { flex: 1 1 auto; }
}

@media (max-width: 420px) {
  .brand .sub, .brand .rule { display: none; }
  .btn { padding: 13px 18px; font-size: 0.86rem; }
}

@media print {
  .site-head, .site-foot, .call, .btns { display: none !important; }
  body { font-size: 11pt; color: #000; }
}

/* ===========================================================================
   MOTION
   ---------------------------------------------------------------------------
   Everything below is behaviour rather than layout: how the page reveals
   itself as you scroll, and how it answers the pointer.

   Two rules govern all of it. Nothing may hide content if the script fails —
   the reveal styles are scoped to a class JavaScript adds, so with no script
   the page is simply already visible. And nothing moves for anyone who has
   asked their machine for less movement; the reduced-motion block near the
   top of this file collapses every duration here to nothing.
   =========================================================================== */

/* ------------------------------------------------------- scroll reveals -- */
.js-reveal .reveal {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
}
.js-reveal .reveal.in {
  opacity: 1;
  transform: none;
  /* Long and heavily eased. A quick reveal announces itself; a slow one is
     only noticed as the page feeling unhurried, which is the point. */
  transition: opacity 1.5s cubic-bezier(.16, 1, .3, 1),
              transform 1.5s cubic-bezier(.16, 1, .3, 1);
}
/* Items in a row arrive in sequence rather than as a block. */
.js-reveal .reveal.in:nth-child(2) { transition-delay: .15s; }
.js-reveal .reveal.in:nth-child(3) { transition-delay: .30s; }
.js-reveal .reveal.in:nth-child(4) { transition-delay: .45s; }
.js-reveal .reveal.in:nth-child(5) { transition-delay: .60s; }
.js-reveal .reveal.in:nth-child(6) { transition-delay: .75s; }

/* A photograph that eases in rather than snapping in. */
.js-reveal .reveal-shot { overflow: hidden; }
.js-reveal .reveal-shot img { transform: scale(1.07); transition: transform 2.4s cubic-bezier(.16, 1, .3, 1); }
.js-reveal .reveal-shot.in img { transform: scale(1); }

/* -------------------------------------------------------- heading rules -- */
/* A short gold rule under every section heading. Typographic punctuation, and
   it draws itself as the heading arrives. Done in CSS off the existing markup
   rather than by adding a class to thirty headings by hand — one rule here
   governs every section on the site, and a new section inherits it free. */
.sec-head h2::after {
  content: ''; display: block; width: 62px; height: 2px;
  background: var(--gold); margin-top: 24px;
  transform-origin: left center;
}
.js-reveal .sec-head.reveal h2::after { transform: scaleX(0); }
.js-reveal .sec-head.reveal.in h2::after {
  transform: scaleX(1);
  transition: transform 1.3s .45s cubic-bezier(.22, .61, .36, 1);
}

/* ------------------------------------------------------------- pointer -- */
.card { transition: transform .5s cubic-bezier(.22,.61,.36,1), border-color .5s, box-shadow .5s; }
.card:hover { transform: translateY(-4px); border-color: rgba(201, 169, 97, 0.5); box-shadow: var(--shadow); }
.card:hover h3 { color: var(--gold); }
.card h3 { transition: color .4s; }
.sec-navy .card:hover { box-shadow: none; background: #10314F; }

.panel { transition: transform .5s cubic-bezier(.22,.61,.36,1), box-shadow .5s; }
.panel:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.panel .shot { overflow: hidden; }
.panel .shot img { transition: transform 1.5s cubic-bezier(.22,.61,.36,1); }
.panel:hover .shot img { transform: scale(1.05); }
.panel:hover h3 { color: var(--gold); }
.panel h3 { transition: color .4s; }

.mediastrip img { transition: transform 1.8s cubic-bezier(.22,.61,.36,1), filter .9s; filter: saturate(.9); }
.mediastrip img:hover { transform: scale(1.04); filter: saturate(1.05); }

/* The numeral on a step card, restyled as a marker with a rule running off it
   — the eye reads the sequence before it reads the words. */
.num {
  display: flex; align-items: center; gap: 14px;
  font-family: var(--serif); font-style: italic; font-size: 1.6rem;
  color: var(--gold); line-height: 1; margin-bottom: 18px;
}
.num::after { content: ''; flex: 1; height: 1px; background: rgba(201, 169, 97, 0.35); }

/* Buttons answer the pointer with a small lift rather than a colour flash. */
.btn { transition: background .32s, color .32s, border-color .32s, transform .32s; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

/* Navigation underline grows from the left instead of appearing whole. */
.nav a { position: relative; border-bottom-color: transparent; }
.nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  background: var(--gold); transform: scaleX(0); transform-origin: left center;
  transition: transform .45s cubic-bezier(.22,.61,.36,1);
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }

/* Footer links shift a hair towards the pointer. */
.foot-grid a { transition: color .35s, padding-left .35s; }
.foot-grid a:hover { padding-left: 4px; }

@media (max-width: 860px) {
  /* Hover is not a thing here, and a card that lifts under a thumb just looks
     like a mis-tap. Reveals stay — they read well on a phone. */
  .card:hover, .panel:hover, .btn:hover { transform: none; box-shadow: none; }
  .nav a::after { display: none; }
}


/* ------------------------------------------------------------- section seams --
   Where one section meets another of a different colour the join was a hard
   line. A short gradient at the head of each dark band, and a matching one at
   its foot, lets the colour arrive rather than start — so scrolling reads as
   one continuous surface changing tone rather than a stack of separate
   rectangles. Ten pixels each; you would not notice it if it were missing,
   only that the page felt more abrupt. */
.sec-navy, .call { position: relative; }
.sec-navy::before, .call::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 64px;
  background: linear-gradient(180deg, rgba(11, 36, 64, 0) 0%, rgba(11, 36, 64, 0) 100%);
  pointer-events: none;
}
.sec-stone { position: relative; }
.sec-stone::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 90px;
  background: linear-gradient(180deg, var(--paper) 0%, rgba(242, 241, 237, 0) 100%);
  pointer-events: none;
}
.sec-stone::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 90px;
  background: linear-gradient(0deg, var(--paper) 0%, rgba(242, 241, 237, 0) 100%);
  pointer-events: none;
}
/* A stone band that runs into a navy one must not fade to white at the join. */
.sec-stone:has(+ .sec-navy)::after, .sec-stone:has(+ .call)::after { display: none; }
.sec-stone + .sec-stone::before { display: none; }


/* ============================================================ the phone ====
   Everything below is about how the site behaves in a hand.

   The desktop gets hover, which is where most of its life comes from. A phone
   has none, so its character has to come from how things arrive and how they
   respond to being touched. All of it is slower than the desktop equivalent —
   a small screen shows one thing at a time, and motion that reads as brisk on
   a large display reads as hurried on a small one.
   ========================================================================== */
@media (max-width: 860px) {

  /* ---- arrival ----
     Sections rise further and settle more slowly than on desktop, and the
     stagger between cards is longer. On a phone they are read one at a time,
     so there is no reason to hurry the second one into place. */
  .js-reveal .reveal { transform: translate3d(0, 34px, 0); }
  .js-reveal .reveal.in {
    transition: opacity 1.7s cubic-bezier(.16, 1, .3, 1),
                transform 1.7s cubic-bezier(.16, 1, .3, 1);
  }
  .js-reveal .reveal.in:nth-child(2) { transition-delay: .18s; }
  .js-reveal .reveal.in:nth-child(3) { transition-delay: .36s; }
  .js-reveal .reveal.in:nth-child(4) { transition-delay: .54s; }
  .js-reveal .reveal.in:nth-child(5) { transition-delay: .72s; }
  .js-reveal .reveal.in:nth-child(6) { transition-delay: .90s; }
  .js-reveal .reveal-shot img { transition: transform 2.8s cubic-bezier(.16, 1, .3, 1); }

  /* ---- touch ----
     A press should be felt. The card yields a little and comes back, which is
     the whole of the feedback a finger gets and is worth getting right. */
  .card:active, .panel:active { transform: scale(.988); transition: transform .18s ease-out; }
  .btn:active { transform: scale(.97); transition: transform .12s ease-out; }
  a, button { -webkit-tap-highlight-color: rgba(201, 169, 97, .18); }

  /* ---- the menu ----
     It used to appear and disappear instantly. Now it unrolls, and each link
     follows the one above it in. The header's gold underline sweeps across as
     it opens, which is the detail that makes the whole thing feel considered
     rather than merely animated. */
  .nav {
    display: flex;
    max-height: 0; overflow: hidden;
    transition: max-height .62s cubic-bezier(.22, .61, .36, 1),
                opacity .45s ease, visibility .62s;
    opacity: 0; visibility: hidden;
    padding: 0 0 0;
  }
  .site-head.open .nav {
    max-height: 78vh; opacity: 1; visibility: visible;
    padding: 8px 0 18px;
    overflow-y: auto;
  }
  .nav > * {
    opacity: 0; transform: translateY(-10px);
    transition: opacity .5s cubic-bezier(.22,.61,.36,1), transform .5s cubic-bezier(.22,.61,.36,1);
  }
  .site-head.open .nav > * { opacity: 1; transform: none; }
  .site-head.open .nav > *:nth-child(1) { transition-delay: .10s; }
  .site-head.open .nav > *:nth-child(2) { transition-delay: .16s; }
  .site-head.open .nav > *:nth-child(3) { transition-delay: .22s; }
  .site-head.open .nav > *:nth-child(4) { transition-delay: .28s; }
  .site-head.open .nav > *:nth-child(5) { transition-delay: .34s; }
  .site-head.open .nav > *:nth-child(6) { transition-delay: .40s; }

  .site-head::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
    background: linear-gradient(90deg, transparent, var(--gold), transparent);
    transform: scaleX(0); transform-origin: center;
    transition: transform .7s cubic-bezier(.22,.61,.36,1);
  }
  .site-head.open::after { transform: scaleX(1); }

  /* The three bars become a cross, rather than swapping for one. */
  .navtoggle span, .navtoggle span::before, .navtoggle span::after {
    transition: transform .42s cubic-bezier(.22,.61,.36,1), opacity .28s ease;
  }
  .site-head.open .navtoggle span { background: transparent; }
  .site-head.open .navtoggle span::before { transform: translateY(6px) rotate(45deg); }
  .site-head.open .navtoggle span::after  { transform: translateY(-6px) rotate(-45deg); }

  /* ---- the hero, in a hand ----
     The photographs behind the landing page drift further and slower here than
     on a desktop. A phone crops to a narrow slice, so the same percentage of
     movement covers less ground and reads as less; giving it more restores the
     sense that the picture is alive rather than printed. */
  @keyframes heroBreathePhone {
    from { transform: scale(1.06) translate3d(0, 0, 0); }
    to   { transform: scale(1.20) translate3d(-2%, -1.5%, 0); }
  }
  /* Frames two to four carry a single animation, so their duration and name
     can be set outright. */
  .hero-lead .frame:nth-child(n+2) img { animation-duration: 150s; }
  .hero-lead .frame:nth-child(2) img,
  .hero-lead .frame:nth-child(4) img { animation-name: heroBreathePhone; }
  /* The first frame carries TWO — the drift and the opening focus-settle —
     and a single value here would have applied to both, stretching a
     two-second reveal into a two-and-a-half-minute one. Both are named. */
  .hero-lead .frame:nth-child(1) img {
    animation-name: heroBreathePhone, heroFocus;
    animation-duration: 150s, 2.4s;
  }
}

/* ---- depth on scroll, where the browser can drive it from scroll position --
   Section images ease upward slightly as their section passes, and the hero
   photograph lags behind the page it sits in front of. On a phone this is what
   separates a site that scrolls from one that moves. Progressive: browsers
   without scroll-driven animation get a page that simply sits still, which is
   what it does today. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .panel .shot img, .split img, .reveal-shot img {
      animation: driftUp linear both;
      animation-timeline: view();
      animation-range: entry 12% cover 92%;
    }
    @keyframes driftUp {
      from { transform: translateY(3.5%) scale(1.075); }
      to   { transform: translateY(-3.5%) scale(1.075); }
    }
  }
}


/* ================================================== the phone, refined =====
   A second pass, and a more honest one. The first attempt made things move;
   it did not make them feel considered. Everything here is slower than it
   was, and three things were rebuilt rather than tuned.
   ========================================================================== */

/* The page must not scroll behind an open menu. */
html.nav-open, html.nav-open body { overflow: hidden; }

@media (max-width: 860px) {

  /* ---- 1. the menu ----
     It was animating max-height. That re-runs layout on every frame of the
     transition, which on a phone drops frames and reads as the thing opening
     "in stages" — and the per-link delays sat on top of that and made it
     worse. It is now a panel that covers the screen and arrives as one piece,
     moved by transform alone, which the compositor handles without touching
     layout at all. The links no longer arrive separately; they come with it. */
  .nav {
    position: fixed; left: 0; right: 0; top: 66px;
    height: calc(100dvh - 66px);
    max-height: none; overflow-y: auto;
    display: flex; flex-direction: column; justify-content: center; align-items: stretch;
    gap: 0; padding: 0 var(--gut) 12vh;
    /* Opaque, and no backdrop-filter. The header already has one, and a
       blurred backdrop nested inside another blurred backdrop composites
       unpredictably — here it left the panel looking half transparent with
       the headline showing through, which reads as a bug rather than as
       glass. A solid ground is also simply the better decision: the menu is
       a place you have gone to, not a veil over where you were. */
    background: #06121F;
    border-bottom: none;
    z-index: 5;
    opacity: 0; visibility: hidden;
    transform: translate3d(0, -14px, 0);
    transition:
      transform 1.05s cubic-bezier(.16, 1, .3, 1),
      opacity .72s cubic-bezier(.33, 0, .2, 1),
      visibility 0s linear 1.05s;
  }
  /* Written at the same specificity as the earlier open-state rule, and after
     it, so the panel's own geometry wins rather than the dropdown's. */
  .site-head.open .nav {
    opacity: 1; visibility: visible;
    transform: none;
    padding: 0 var(--gut) 12vh;
    max-height: none;
    height: calc(100dvh - 66px);
    transition:
      transform 1.05s cubic-bezier(.16, 1, .3, 1),
      opacity .62s cubic-bezier(.33, 0, .2, 1),
      visibility 0s linear 0s;
  }
  /* Room to breathe, and type worth reading. A menu with six items on a phone
     screen has no reason to be a cramped list. */
  .nav a {
    font-family: var(--serif); font-size: 1.75rem; font-weight: 700;
    letter-spacing: -0.01em; color: #fff;
    padding: 0.44em 0; border-bottom: none;
    opacity: 0; transform: translate3d(0, 14px, 0);
    transition: opacity .8s cubic-bezier(.16,1,.3,1), transform .9s cubic-bezier(.16,1,.3,1), color .4s;
  }
  .site-head.open .nav a { opacity: 1; transform: none; }
  /* A whisper of sequence — 55ms apart, all of it finished inside the panel's
     own movement, so it reads as one gesture rather than six. */
  .site-head.open .nav a:nth-child(1) { transition-delay: .16s; }
  .site-head.open .nav a:nth-child(2) { transition-delay: .215s; }
  .site-head.open .nav a:nth-child(3) { transition-delay: .27s; }
  .site-head.open .nav a:nth-child(4) { transition-delay: .325s; }
  .site-head.open .nav a:nth-child(5) { transition-delay: .38s; }
  .nav a[aria-current="page"] { color: var(--gold-light); }
  .nav .btn {
    display: inline-flex; margin: 28px 0 0; padding: 17px 26px;
    opacity: 0; transform: translate3d(0, 14px, 0);
    transition: opacity .8s cubic-bezier(.16,1,.3,1) .44s, transform .9s cubic-bezier(.16,1,.3,1) .44s;
  }
  .site-head.open .nav .btn { opacity: 1; transform: none; }
  .navtoggle span, .navtoggle span::before, .navtoggle span::after {
    transition: transform .72s cubic-bezier(.16,1,.3,1), opacity .4s ease, background .4s ease;
  }
  .site-head::after { transition: transform 1.05s cubic-bezier(.16,1,.3,1); }

  /* ---- 2. the eyebrow ----
     Small caps under a short rule is the arrangement every template uses. Set
     wider, a shade larger, and with the rule brought inline beside the words
     instead of tucked beneath them, the same six words stop looking like a
     label and start looking like a masthead. */
  .hero-lead .eyebrow {
    display: flex; align-items: center; gap: 15px;
    font-size: 0.78rem; letter-spacing: 0.34em; font-weight: 700;
    color: var(--gold-light); margin-bottom: 1.15em;
  }
  .hero-lead .eyebrow::before {
    content: ''; flex: 0 0 auto; width: 34px; height: 1px; background: var(--gold);
    transform: scaleX(0); transform-origin: left center;
    animation: ruleDraw 1.6s cubic-bezier(.22,.61,.36,1) both .55s;
  }
  .hero-lead .eyebrow::after { display: none; }

  /* ---- 3. touch ----
     Slower on the way down and slower still on the way back, so a press is
     something the screen answers rather than something it flinches at. */
  .btn {
    transition: background .5s ease, color .5s ease, border-color .5s ease,
                transform .62s cubic-bezier(.16, 1, .3, 1);
  }
  .btn:active { transform: scale(.955); transition-duration: .5s, .5s, .5s, .34s; }
  .card:active, .panel:active {
    transform: scale(.99); transition: transform .34s cubic-bezier(.16, 1, .3, 1);
  }
  .card, .panel { transition: transform .62s cubic-bezier(.16, 1, .3, 1), box-shadow .62s, border-color .62s; }
  a, button { -webkit-tap-highlight-color: transparent; }

  /* ---- 4. the light on the water ----
     A soft bloom sitting where the sun is, breathing on a twenty-two second
     cycle. It is one radial gradient and it is almost subliminal — but a still
     photograph with a slow bloom over it stops reading as a picture and starts
     reading as a moment. This is the thing that makes the hero feel alive on a
     screen too small to show the drift. */
  .hero-lead .glow {
    position: absolute; inset: 0; z-index: 1; pointer-events: none;
    mix-blend-mode: screen;
    /* Placed over where the sun actually falls once the photograph is cropped
       to a phone — the crop is pushed right and down, so the light is not
       where it is on a desktop. */
    background: radial-gradient(52% 34% at 74% 46%,
      rgba(255, 216, 156, 0.46) 0%,
      rgba(255, 194, 126, 0.22) 40%,
      rgba(255, 182, 112, 0.00) 74%);
    animation: bloom 26s ease-in-out infinite alternate;
    will-change: opacity, transform;
  }
  @keyframes bloom {
    from { opacity: .55; transform: scale(1) translate3d(0, 0, 0); }
    to   { opacity: 1;   transform: scale(1.16) translate3d(-1.5%, 1%, 0); }
  }

  /* ---- 5. arrival ----
     Longer again than the last pass. Two seconds sounds absurd written down
     and is exactly right in the hand: the section is already in view as it
     settles, so the only thing the duration changes is whether the page feels
     hurried. */
  .js-reveal .reveal { transform: translate3d(0, 40px, 0); }
  .js-reveal .reveal.in {
    transition: opacity 2s cubic-bezier(.16, 1, .3, 1),
                transform 2s cubic-bezier(.16, 1, .3, 1);
  }
  .js-reveal .reveal.in:nth-child(2) { transition-delay: .2s; }
  .js-reveal .reveal.in:nth-child(3) { transition-delay: .4s; }
  .js-reveal .reveal.in:nth-child(4) { transition-delay: .6s; }
  .js-reveal .reveal.in:nth-child(5) { transition-delay: .8s; }
  .js-reveal .reveal.in:nth-child(6) { transition-delay: 1s; }

  /* ---- 6. the words ----
     The headline takes its time. Each word is a beat behind the one before it
     and the whole line is still arriving two seconds in. */
  .hero-lead h1 .w > span {
    animation-duration: 1.7s;
    animation-delay: calc(var(--i) * .095s + .45s);
  }
  .hero-lead .lede { animation: heroRise 1.9s cubic-bezier(.22,.61,.36,1) both 1.35s; }
  .hero-lead .btns { animation: heroRise 1.9s cubic-bezier(.22,.61,.36,1) both 1.62s; }

  /* ---- 7. room ----
     Premium is mostly space. The sections get more of it. */
  .sec { padding: clamp(68px, 15vw, 96px) 0; }
  .sec-head { margin-bottom: clamp(38px, 8vw, 54px); }
  .grid { gap: 22px; }
}

/* ---- 8. between pages ----
   The transition was quick and it moved, and on a phone a full-screen snapshot
   sliding ten pixels is enough to stutter. It is now longer and it only fades:
   nothing translates, so there is no large layer for the compositor to shift
   and nothing to drop a frame over. */
@media (max-width: 860px) and (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) { animation: pageOut .62s cubic-bezier(.4, 0, .6, 1) both; }
  ::view-transition-new(root) { animation: pageInPhone 1.15s cubic-bezier(.22, .61, .36, 1) both; }
  @keyframes pageInPhone { from { opacity: 0; } to { opacity: 1; } }
}


/* ============================================ the phone, third pass =======
   Three reports of "glitching" and I had been tuning durations. The cause was
   somewhere else entirely, and it is written up first below.
   ========================================================================== */

/* ---- 1. the flash, and the white band at the top ----
   The page background is white. The transition was fading the NEW page in
   from transparent — so for the length of that fade, every part of the
   incoming page that was not yet opaque showed the white behind it. Against a
   dark full-height hero that reads as a white band at the top and a flicker
   through the whole change, and making the fade slower made it worse, not
   better, which is why the last two attempts went the wrong way.

   The fix is to stop animating the incoming page at all. It sits underneath at
   full opacity from the first frame; only the outgoing page animates, fading
   away to reveal it. Nothing is ever translucent, so there is nothing for the
   background to show through. */
@media (max-width: 860px) {
  ::view-transition-new(root) { animation: none; opacity: 1; }
  ::view-transition-old(root) {
    animation: pageOut .5s cubic-bezier(.4, 0, .6, 1) both;
    mix-blend-mode: normal;
  }
}

@media (max-width: 860px) {

  /* ---- 2. the moving line ----
     A one-pixel rule with a dot travelling down it, drawn over a photograph
     that is itself moving. On a high-density phone screen that lands the line
     on fractional pixels every frame and it shimmers — which is exactly the
     "glitching" reported. A hairline is the wrong object to animate on a
     phone. It goes. */
  .scroll-cue { display: none; }

  /* ---- 3. the menu ----
     Too big and too slow: I over-corrected into a full-screen panel that took
     a second to arrive. It is a menu — it should be quick and it should not
     take over the screen. Back to a panel that is only as tall as its contents,
     arriving in under half a second, still moved by transform alone so it
     stays smooth. */
  .nav {
    position: absolute; top: 100%; left: 0; right: 0;
    height: auto; max-height: none;
    display: block; padding: 10px var(--gut) 22px;
    background: #06121F;
    border-bottom: 1px solid rgba(201, 169, 97, 0.28);
    opacity: 0; visibility: hidden;
    transform: translate3d(0, -10px, 0);
    transition: transform .42s cubic-bezier(.22, .61, .36, 1),
                opacity .3s ease,
                visibility 0s linear .42s;
  }
  .site-head.open .nav {
    opacity: 1; visibility: visible; transform: none;
    height: auto; max-height: none; padding: 10px var(--gut) 22px;
    transition: transform .42s cubic-bezier(.22, .61, .36, 1),
                opacity .26s ease,
                visibility 0s linear 0s;
  }
  .nav a {
    display: block;
    font-family: var(--serif); font-size: 1.22rem; font-weight: 700;
    color: #fff; padding: 13px 0; border-bottom: 1px solid rgba(255,255,255,.07);
    opacity: 1; transform: none; transition: color .3s;
  }
  .site-head.open .nav a { transition-delay: 0s; }
  .nav a:last-of-type { border-bottom: none; }
  .nav .btn {
    display: inline-flex; width: 100%; margin: 16px 0 0; padding: 14px 22px;
    opacity: 1; transform: none; transition: background .35s, color .35s;
  }
  .site-head.open .nav .btn { opacity: 1; transform: none; transition-delay: 0s; }
  /* With the menu no longer covering the screen there is nothing to lock. */
  .navtoggle span, .navtoggle span::before, .navtoggle span::after {
    transition: transform .42s cubic-bezier(.22,.61,.36,1), opacity .25s ease, background .25s ease;
  }
  .site-head::after { transition: transform .5s cubic-bezier(.22,.61,.36,1); }

  /* ---- 4. the eyebrow, back where it was ----
     White, hard against the left edge, with the rule beneath it rather than
     beside it — and a deeper ground behind it so white on a sunrise is white
     on something. */
  .hero-lead .eyebrow {
    display: block;
    color: #fff;
    font-size: 0.72rem; letter-spacing: 0.24em;
    margin-bottom: 1em;
    text-shadow: 0 1px 3px rgba(7, 24, 41, .95);
  }
  .hero-lead .eyebrow::before { display: none; }
  .hero-lead .eyebrow::after {
    display: block; content: ''; width: 46px; height: 1px; background: var(--gold);
    margin-top: 13px; transform: scaleX(0); transform-origin: left center;
    animation: ruleDraw 1.4s cubic-bezier(.22,.61,.36,1) both .5s;
  }

  /* ---- 5. the photograph, actually moving ----
     The drift was set to 150 seconds. That is not slow, it is stopped: nothing
     perceptible happens in the time anyone looks at a hero. Thirty seconds
     with real distance in it is a slow cinematic push — unmistakably alive,
     still calm. And the sequence turns over every eleven seconds rather than
     sixteen, so a photograph changes while you are still looking at it. */
  @keyframes heroPush {
    from { transform: scale(1.05) translate3d(0, 0, 0); }
    to   { transform: scale(1.22) translate3d(-3.5%, -2.5%, 0); }
  }
  .hero-lead .frame:nth-child(n+2) img {
    animation-name: heroPush;
    animation-duration: 30s;
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
  }
  .hero-lead .frame:nth-child(3) img { animation-direction: alternate-reverse; }
  .hero-lead .frame:nth-child(1) img {
    animation-name: heroPush, heroFocus;
    animation-duration: 30s, 2.4s;
    animation-timing-function: ease-in-out, cubic-bezier(.16, 1, .3, 1);
    animation-iteration-count: infinite, 1;
    animation-direction: alternate, normal;
  }

  /* Eleven seconds a photograph: 2s up, 9s held, 2s away, offsets spaced so
     each fade-out is covered exactly by the next fade-in. */
  .hero-lead .frame { animation: heroCyclePhone 44s linear infinite; }
  .hero-lead .frame:nth-child(1) { animation-delay: -2s; }
  .hero-lead .frame:nth-child(2) { animation-delay: 9s; }
  .hero-lead .frame:nth-child(3) { animation-delay: 20s; }
  .hero-lead .frame:nth-child(4) { animation-delay: 31s; }
  @keyframes heroCyclePhone {
    0%      { opacity: 0; }
    4.55%   { opacity: 1; }
    25%     { opacity: 1; }
    29.55%  { opacity: 0; }
    100%    { opacity: 0; }
  }
  .hero-ticks i::after { animation: tickFill 44s linear infinite; }
  .hero-ticks i:nth-child(2)::after { animation-delay: 11s; }
  .hero-ticks i:nth-child(3)::after { animation-delay: 22s; }
  .hero-ticks i:nth-child(4)::after { animation-delay: 33s; }
  .hero-ticks { bottom: 34px; }

  /* The bloom keeps pace with the shorter cycle. */
  .hero-lead .glow { animation-duration: 15s; }
}


/* =========================================== the phone, fourth pass =======
   The previous three passes tuned CSS that a real phone was never running.
   Two reasons, both found by testing the conditions rather than the code.
   ========================================================================== */

/* ---- 1. moving between pages ----
   The @view-transition rule at the top of this file is a Chrome feature.
   Safari does not implement cross-document view transitions, so on the phone
   most visitors will use, that rule does nothing at all and the page simply
   cuts. The transition is now driven from script (see render.js) and these are
   the two states it toggles.

   The deep navy on <html> is the important part: it is what sits in the gap
   between one page leaving and the next arriving, and it is the same colour
   the site opens on — so instead of a white flash between pages there is a
   moment of Fennmore navy, and the two pages appear to dissolve through it. */
@media (max-width: 860px) {
  html.pt { background-color: #06121F; }
  /* Longer at both ends, and eased so neither end has a hard edge. With the
     next page prefetched the moment a finger lands, these two fades meet with
     no pause between them — which is what makes it read as one movement
     rather than two events. */
  html.pt body { animation: ptArrive .8s cubic-bezier(.33, 0, .1, 1) both; }
  @keyframes ptArrive { from { opacity: 0; } to { opacity: 1; } }
  html.pt.pt-out body {
    animation: none;
    opacity: 0;
    transition: opacity .5s cubic-bezier(.5, 0, .5, 1);
  }
  /* The native transition must not also run, or the two fight each other. */
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

@media (max-width: 860px) {

  /* ---- 2. the empty band above the headline ----
     The hero centres its copy in a full-height frame, which left 195 pixels of
     pale sky above the first word — read, correctly, as white space at the top.
     The copy now sits high in the frame instead of in the middle of it, which
     also gives the photograph the whole lower half to itself. */
  .hero-lead { align-items: flex-start; }
  .hero-lead .inner { padding-top: 92px; padding-bottom: 40px; }

  /* ---- 3. the menu, closing as smoothly as it opens ----
     Opening was fine. Closing snapped, because visibility was switching at the
     end of a delay while opacity had already finished — so the panel vanished
     rather than left. Both directions now run the same curve over the same
     time, and the panel lifts as it goes. */
  .nav {
    transition: transform .52s cubic-bezier(.32, .72, .3, 1),
                opacity .44s cubic-bezier(.32, .72, .3, 1),
                visibility 0s linear .52s;
    transform: translate3d(0, -12px, 0);
  }
  .site-head.open .nav {
    transition: transform .52s cubic-bezier(.22, .61, .36, 1),
                opacity .38s cubic-bezier(.22, .61, .36, 1),
                visibility 0s linear 0s;
  }
  /* A menu link that has been tapped stays lit while the page changes, so the
     tap is acknowledged rather than the screen simply going. */
  .nav a { transition: color .38s ease, background .38s ease, padding-left .38s cubic-bezier(.22,.61,.36,1); }
  .nav a:active { color: var(--gold-light); padding-left: 8px; }

  /* ---- 4. touch ----
     Down slowly, back up more slowly still. */
  .btn {
    transition: background .55s cubic-bezier(.22,.61,.36,1),
                color .55s cubic-bezier(.22,.61,.36,1),
                border-color .55s cubic-bezier(.22,.61,.36,1),
                transform .68s cubic-bezier(.16, 1, .3, 1),
                box-shadow .55s ease;
  }
  .btn:active {
    transform: scale(.962);
    transition: transform .3s cubic-bezier(.32,.72,.3,1), background .3s, color .3s, border-color .3s;
  }
  .card, .panel { transition: transform .68s cubic-bezier(.16,1,.3,1), box-shadow .68s ease, border-color .68s ease; }
  .card:active, .panel:active { transform: scale(.988); transition: transform .3s cubic-bezier(.32,.72,.3,1); }
  .navtoggle { transition: transform .4s cubic-bezier(.22,.61,.36,1), border-color .4s ease; }
  .navtoggle:active { transform: scale(.92); }
}

/* ---- 5. movement for people who have asked for less of it ----
   Reduce Motion is on far more phones than most people expect, and the rule at
   the top of this file switched the hero off completely for all of them — no
   sequence, no drift, nothing. That is more than the setting asks for. What it
   asks for is no MOVEMENT: no panning, no zooming, no parallax, because those
   are what provoke vestibular symptoms. A photograph dissolving slowly into
   another photograph moves nothing at all.

   So the panning and the parallax stay off, and the sequence comes back —
   twice as slow, opacity only, nothing sliding or scaling anywhere. */
@media (max-width: 860px) and (prefers-reduced-motion: reduce) {
  .hero-lead .frame {
    animation: heroCyclePhone 88s linear infinite !important;
    animation-duration: 88s !important;
  }
  .hero-lead .frame:nth-child(1) { animation-delay: -4s !important; }
  .hero-lead .frame:nth-child(2) { animation-delay: 18s !important; }
  .hero-lead .frame:nth-child(3) { animation-delay: 40s !important; }
  .hero-lead .frame:nth-child(4) { animation-delay: 62s !important; }
  /* The photograph itself holds perfectly still. */
  .hero-lead .frame img { animation: none !important; transform: none !important; }
  .hero-lead .glow { animation: none !important; opacity: .8; }
}


/* ---------------------------------------------- the pale band at the top --
   A landscape photograph in a portrait viewport is scaled by object-fit until
   it fills the HEIGHT — which means the whole height of the picture is already
   showing, and object-position has no vertical room left to work in. Moving
   the crop up or down does nothing at all; I measured the top fifth of this
   photograph at 250 out of 255 at every position I tried, because the top of
   the frame is always the top of the picture, and the top of this picture is
   blown-out sunrise sky.

   The only way to lose it is to scale past what cover needs and shift the
   window down into the photograph, which is what happens below. It costs a
   little resolution — the file is 1600px wide against a 390px screen, so
   there is a great deal to spare — and it buys the cloud floor filling the
   frame instead of a white band above it.

   The wash over the top is deepened to match, so what remains of the sky
   carries into the header rather than stopping against it. */
@media (max-width: 860px) {
  @keyframes heroPush {
    from { transform: scale(1.30) translate3d(0, -6%, 0); }
    to   { transform: scale(1.46) translate3d(-3%, -9.5%, 0); }
  }
  .hero-lead .veil {
    background:
      linear-gradient(180deg,
        rgba(7, 24, 41, 0.86) 0%,
        rgba(7, 24, 41, 0.70) 9%,
        rgba(7, 24, 41, 0.52) 18%,
        rgba(7, 24, 41, 0.58) 27%,
        rgba(7, 24, 41, 0.78) 40%,
        rgba(7, 24, 41, 0.86) 70%,
        rgba(7, 24, 41, 0.94) 100%);
  }
}


/* ------------------------------------------------- a short desktop window --
   A laptop with a browser open on a 13-inch screen leaves around 620 pixels of
   page. At that height the landing hero's own contents — headline at four
   rems, standfirst, buttons, and the space reserved beneath them — add up to
   more than the window, so the hero grows past the bottom of the screen and
   takes the sequence marks with it. That is what put them off the page.

   Rather than let it overflow, the hero gets smaller: the headline steps down,
   the paddings tighten, and the scroll cue goes, since on a window this short
   the next section is nearly visible anyway. Desktop only — the phone has its
   own arrangement and is not affected. */
@media (min-width: 861px) and (max-height: 800px) {
  .hero-lead h1 { font-size: clamp(1.95rem, 1.1rem + 2.1vw, 2.85rem); }
  .hero-lead .lede { font-size: 1.02rem; }
  .hero-lead .eyebrow { margin-bottom: 0.7em; }
  .hero-lead .inner { padding-top: 30px; padding-bottom: 92px; }
  .hero-foot { bottom: 58px; }
  .hero-foot p { font-size: 0.66rem; letter-spacing: 0.17em; }
  .hero-ticks { bottom: 26px; }
  .scroll-cue { display: none; }
}
