/* ============================================================
   SHEAUXCASE — SHARED FOUNDATION

   Tokens, the components that appear on more than one page, and
   the form system. This file is the source of truth for anything
   in it; style-guide.html documents it by linking it, so the two
   cannot drift.

   index.html links this file for the header, footer and buttons,
   then adds its own inline block for the hero, What We Do, the
   photo break and the two closing sections. Its inline rules come
   after this link, so they win wherever the two overlap.
   ============================================================ */

:root {
  /* --- palette --- */
  --paper:     #FFFFFF;
  --ink:       #2A2724;
  --ink-soft:  #55504B;
  --ink-faint: #7A736C;

  /* --- type --- */
  /* One family, three weights, set against the wordmark rather than
     against habit. The logo H measures a 13.05% stem-to-cap ratio;
     Inter 400 measures 12.33% and Inter 900 measures 27.40%, so the
     old 900 headings ran at twice the mark they sat under.

       400 — every heading and page title
       500 — small subheads, labels, nav, buttons
       900 — the two display moments only: the hero wordmark and the
             WHAT WE DO knockout, where mass IS the idea

     Frame 2028-75 set its titles in a serif (Habibi); that was
     deliberately not adopted — the layout came across, the second
     typeface did not. */
  --font-body: 'Inter', 'Helvetica Neue', Arial, sans-serif;

  /* --- easing --- */
  --ease:     cubic-bezier(0.65, 0.02, 0.16, 1);
  --ease-out: cubic-bezier(0.16, 0.84, 0.34, 1);

  /* --- derived, named so they stop being magic numbers --- */
  --rule:      color-mix(in srgb, var(--ink) 16%, transparent);
  --rule-firm: color-mix(in srgb, var(--ink) 18%, transparent);
  --tint:      color-mix(in srgb, var(--ink)  4%, var(--paper));


  /* --- footer wordmark (frame 2017-135) --- */
  --logo-w-footer: min(87vw, 1560px);
  --footer-spread: 18px;      /* SVG user units the outermost letter travels */
}

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* `[hidden]` is only a UA rule at `display: none`, and author styles
   beat the UA sheet whatever the specificity. So any class that sets
   `display` silently un-hides the element: `.sent` sets `display:
   grid`, which put the post-submit confirmation on screen underneath
   the live form. Belt and braces, once, for every hidden thing. */
[hidden] { display: none !important; }

/* Form controls do not inherit type from the page — left alone they
   fall back to the UA's Arial. Every control that is styled sets its
   own font, but this catches the ones that are not, and any added
   later. It is the base every page should have had from the start. */
input, select, textarea, button {
  font-family: inherit;
  font-size: inherit;
  color: inherit;
}

/* ============================================================
   PAGE TRANSITIONS

   Cross-document view transitions: the browser holds the old page,
   paints the new one, and animates between them. No script, no
   intercepted clicks, no loading state to get stuck in — and where
   it is unsupported the links simply navigate as they always did.

   The outgoing page leaves faster than the incoming one arrives,
   which is what stops the two reading as one slow fade.
   ============================================================ */

@view-transition { navigation: auto; }

::view-transition-old(root) { animation: sxPageOut 200ms var(--ease) both; }
::view-transition-new(root) { animation: sxPageIn  380ms var(--ease-out) both; }

@keyframes sxPageOut {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateY(-10px); }
}

@keyframes sxPageIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

/* The header is identical on every page, so the wordmark should not
   blink out and back. Naming it hands it to the browser as the same
   object on both sides, and it simply stays put while the page
   underneath it changes. */
.site__logo { view-transition-name: sx-mark; }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
  .site__logo { view-transition-name: none; }
}

/* ============================================================
   SHARED COMPONENTS
   ============================================================ */

.eyebrow {
  margin: 0;
  font-size: clamp(0.6875rem, 0.55vw, 0.8125rem);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.875rem;
  padding: 0 clamp(1.25rem, 1.7vw, 1.75rem);
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  font: 500 0.9375rem/1 var(--font-body);
  letter-spacing: 0.01em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 220ms ease, color 220ms ease, opacity 220ms ease;
}

.btn:hover, .btn:focus-visible { background: var(--ink); color: var(--paper); }
.btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.btn--invert { border-color: var(--paper); color: var(--paper); }
.btn--invert:hover, .btn--invert:focus-visible { background: var(--paper); color: var(--ink); }
.btn--invert:focus-visible { outline-color: var(--paper); }

.btn[disabled] { opacity: 0.45; pointer-events: none; }

/* ---------- reveals ----------
   One shot, added by script and then unobserved: a reveal that
   replays every time you scroll back past it stops being an
   arrival and becomes a distraction. */

[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity   700ms var(--ease-out) var(--d, 0ms),
    transform 700ms var(--ease-out) var(--d, 0ms);
}

[data-reveal].is-in { opacity: 1; transform: none; }

/* ============================================================
   SITE HEADER AND FOOTER
   ============================================================ */

/* Sticky on every page. It starts transparent so it can sit over
   the hero without a band across it, and takes on paper and a
   hairline once you have scrolled past the top — which is the only
   point at which it needs to separate itself from anything. */
.site {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: clamp(1.15rem, 3vh, 1.9rem) clamp(1.25rem, 5.8vw, 5rem);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color 300ms var(--ease), border-color 300ms var(--ease);
}

.site.is-stuck {
  background: var(--paper);
  border-bottom-color: var(--rule);
}

/* A header the hero does not have to share the screen with. Where
   `data-show-after` is set (its value is a count of viewport
   heights) the header waits off the top edge until that much has
   been scrolled, then slides down.

   Hidden here means hidden to the pointer and to the tab order as
   well as to the eye: left merely transparent it would still
   swallow hovers on the photographs drifting beneath it, and still
   put a burger button in the tab order that nobody can see. */
.site[data-show-after] {
  transform: translateY(-100%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition:
    transform        480ms var(--ease-out),
    opacity          260ms var(--ease),
    background-color 300ms var(--ease),
    border-color     300ms var(--ease),
    visibility       0s linear 480ms;
}

.site[data-show-after].is-revealed {
  transform: none;
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition-delay: 0s, 0s, 0s, 0s, 0s;
}

@media (prefers-reduced-motion: reduce) {
  .site[data-show-after] { transition-duration: 1ms, 1ms, 1ms, 1ms, 0s; }
}

.site__mark {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: var(--ink);
}

/* logo.svg carries the ink token as a baked fill rather than
   currentColor: it is loaded through <img>, and inside an <img>
   the SVG has no inherited colour for currentColor to resolve
   against — it would fall back to black. Half its shapes had no
   class and were doing exactly that; the root fill covers them. */
.site__logo {
  display: block;
  width: clamp(118px, 12vw, 158px);
  height: auto;
}

.site__nav { display: flex; gap: clamp(1rem, 2.4vw, 2.25rem); }

.site__nav a {
  position: relative;
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--ink-soft);
  padding-block: 0.35rem;
  transition: color 220ms var(--ease);
}

.site__nav a:hover { color: var(--ink); }

/* The same wipe the service rows use, at one pixel. */
.site__nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 340ms var(--ease);
}

.site__nav a:hover::after,
.site__nav a:focus-visible::after { transform: scaleX(1); transform-origin: left center; }

.site__nav a[aria-current="page"] { color: var(--ink); }
.site__nav a[aria-current="page"]::after { transform: scaleX(1); }

/* ---------- the hamburger ----------
   Two bars that become the cross. Sits above the overlay it opens,
   so the same control closes it — a menu you can open but have to
   hunt for a way out of is worse than no menu. */

.site__burger {
  display: none;
  position: relative;
  z-index: 62;
  width: 2.5rem;
  height: 2.5rem;
  margin-right: -0.5rem;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.site__burger span {
  position: absolute;
  left: 50%;
  width: 1.5rem;
  height: 1.5px;
  margin-left: -0.75rem;
  background: var(--ink);
  transition: transform 380ms var(--ease), opacity 200ms var(--ease);
}

.site__burger span:nth-child(1) { top: calc(50% - 5px); }
.site__burger span:nth-child(2) { top: calc(50% + 5px); }

.site.is-open .site__burger span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.site.is-open .site__burger span:nth-child(2) { transform: translateY(-5px) rotate(-45deg); }

.site__burger:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---------- footer navigation ---------- */

/* Centred under the wordmark, which is itself centred — the
   surrounding .footer__fine centres its text, but a flex container
   ignores that and needs telling. */
.footer__nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(0.75rem, 2vh, 1.15rem) clamp(1.5rem, 3.2vw, 3rem);
  margin-bottom: clamp(1.5rem, 3.5vh, 2.5rem);
}

.footer__nav a {
  position: relative;
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--ink-soft);
  border: 0;
  transition: color 220ms var(--ease);
}

.footer__nav a:hover { color: var(--ink); }

.footer__nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -3px;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 340ms var(--ease);
}

.footer__nav a:hover::after,
.footer__nav a:focus-visible::after { transform: scaleX(1); transform-origin: left center; }

@media (max-width: 620px) {
  /* Four items wrap into a ragged two lines at this width. One
     per line reads as a list rather than as a broken row. */
  .footer__nav {
    flex-direction: column;
    align-items: center;
    gap: clamp(0.7rem, 2.2vh, 1.1rem);
  }
}

/* ============================================================
   FULL-SCREEN MENU  (phones)

   The links become the page rather than a panel over it. Kept out
   of the flow with visibility rather than display so it can be
   animated, and so the links stay unreachable by tab while closed.
   ============================================================ */

@media (max-width: 760px) {
  .site__burger { display: block; }

  .site__nav {
    position: fixed;
    inset: 0;
    z-index: 61;
    display: grid;
    align-content: center;
    justify-items: start;
    gap: clamp(0.75rem, 3vh, 1.75rem);
    padding: 20vh clamp(1.5rem, 9vw, 4rem) 10vh;
    background: var(--paper);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition:
      opacity    300ms var(--ease),
      transform  420ms var(--ease-out),
      visibility 0s linear 320ms;
  }

  .site.is-open .site__nav {
    opacity: 1;
    visibility: visible;
    transform: none;
    transition-delay: 0s, 0s, 0s;
  }

  .site__nav a {
    font-size: clamp(1.9rem, 9vw, 3rem);
    font-weight: 400;
    letter-spacing: -0.02em;
    color: var(--ink);
    padding-block: 0.15em;
  }

  /* The underline is a hover affordance and there is no hover
     here; the current page is marked by weight instead. */
  .site__nav a::after { display: none; }
  .site__nav a[aria-current="page"] { font-weight: 500; }

  /* Nothing behind the menu should scroll while it is open. */
  body.nav-open { overflow: hidden; }
}


/* ============================================================
   PAGE SHELL
   ============================================================ */

.page { padding: clamp(3rem, 10vh, 6.5rem) clamp(1.25rem, 5.8vw, 5rem) 0; }

.page__head { max-width: 68ch; display: grid; gap: clamp(0.9rem, 2.2vh, 1.5rem); }

.page__title {
  margin: 0;
  font-size: clamp(2.1rem, 6.2vw, 5.5rem);
  font-weight: 400;
  line-height: 1.02;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.page__lede {
  margin: 0;
  max-width: 46ch;
  font-size: clamp(0.9375rem, 1.15vw, 1.25rem);
  line-height: 1.55;
  color: var(--ink-soft);
}

.page__body {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  align-items: start;
  gap: clamp(2.5rem, 6vw, 6rem);
  margin-top: clamp(2.75rem, 8vh, 5.5rem);
}

/* ---------- the reassurance column ---------- */

.points { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }

.points li { padding-block: clamp(1rem, 2.6vh, 1.5rem); border-top: 1px solid var(--rule); }
.points li:last-child { border-bottom: 1px solid var(--rule); }

.points h2 {
  margin: 0 0 0.35rem;
  font-size: clamp(0.9375rem, 1.05vw, 1.125rem);
  font-weight: 500;
  letter-spacing: -0.012em;
}

.points a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule-firm);
  transition: border-color 200ms var(--ease);
}

.points a:hover { border-color: var(--ink); }

.points p { margin: 0; max-width: 34ch; font-size: 0.84375rem; line-height: 1.55; color: var(--ink-soft); }

/* ============================================================
   FORMS

   Underlined fields rather than boxes: the site's whole structural
   language is the hairline, and a page of rounded input boxes
   would be the one place that stops being true. Focus draws the
   line in from the left — the same wipe as the service rows and
   the nav, at the scale of a single field.
   ============================================================ */

.form { display: grid; gap: clamp(1.25rem, 3vh, 1.9rem); }

.form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 3vh, 1.9rem) clamp(1.25rem, 2.5vw, 2rem);
}

.field--wide { grid-column: 1 / -1; }

.field { position: relative; display: grid; gap: 0.4rem; }

.field > label {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  transition: color 220ms var(--ease);
}

.field:focus-within > label { color: var(--ink); }

.field .req { color: var(--ink-faint); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.5rem 0 0.6rem;
  border: 0;
  border-bottom: 1px solid var(--rule-firm);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font: 400 clamp(0.9375rem, 1vw, 1.0625rem)/1.4 var(--font-body);
  appearance: none;
}

.field textarea { resize: vertical; min-height: 5.5rem; }

.field input::placeholder,
.field textarea::placeholder { color: color-mix(in srgb, var(--ink-faint) 70%, transparent); }

.field input:focus,
.field select:focus,
.field textarea:focus { outline: none; }

/* The drawn focus line, sitting on top of the resting hairline. */
.field__line {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 380ms var(--ease);
  pointer-events: none;
}

.field:focus-within .field__line { transform: scaleX(1); }

/* Keyboard users still get a visible ring; it just sits on the
   field rather than replacing the drawn line. */
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
  border-radius: 2px;
}

/* Select needs its own arrow once appearance is stripped. */
.field--select { position: relative; }

.field--select select { padding-right: 1.5rem; cursor: pointer; }

.field--select > .arrow {
  position: absolute;
  right: 0.15rem;
  bottom: 0.85rem;
  width: 9px; height: 9px;
  border-right: 1.5px solid var(--ink-soft);
  border-bottom: 1.5px solid var(--ink-soft);
  transform: rotate(45deg);
  pointer-events: none;
  transition: border-color 220ms var(--ease);
}

.field--select:focus-within > .arrow { border-color: var(--ink); }

/* ---------- uploads ---------- */

.uploads {
  display: grid;
  gap: clamp(0.9rem, 2vh, 1.4rem);
  justify-items: start;
  padding-top: clamp(1.25rem, 4vh, 2.25rem);
}

/* The subhead weight, same as .points h2 and the Why Us headings. */
.uploads__title {
  margin: 0;
  padding-top: clamp(0.75rem, 2.5vh, 1.5rem);
  border-top: 1px solid var(--rule);
  width: 100%;
  font-size: clamp(1rem, 1.32vw, 1.5rem);
  font-weight: 500;
  letter-spacing: -0.012em;
}

.uploads__spec { margin: 0; font-size: 0.875rem; line-height: 1.6; color: var(--ink-soft); }
.uploads__spec b { color: var(--ink); font-weight: 700; }

.uploads__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.6rem, 1.6vw, 1.25rem);
  width: 100%;
  padding-top: clamp(0.5rem, 1.5vh, 1rem);
}

.upload { display: grid; gap: 0.55rem; justify-items: start; }

.upload__label { font-size: clamp(0.8125rem, 0.9vw, 1rem); line-height: 1.3; }

/* Outlined, like every other secondary control on the site. The
   label above each one already says what it is, so the button does
   not have to shout to be found. */
.upload__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 1.9rem;
  padding: 0 0.85rem;
  border: 1px solid var(--rule-firm);
  border-radius: 20px;
  background: transparent;
  color: var(--ink-soft);
  font-size: 0.8125rem;
  font-weight: 400;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 220ms ease, color 220ms ease;
}

.upload__btn:hover { border-color: var(--ink); color: var(--ink); }

.upload input:focus-visible + .upload__btn { outline: 2px solid var(--ink); outline-offset: 3px; }

.upload input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

.upload__name {
  font-size: 0.6875rem;
  line-height: 1.4;
  color: var(--ink-faint);
  overflow-wrap: anywhere;
  min-height: 1.4em;
}

.upload.is-set .upload__name { color: var(--ink-soft); }

@media (max-width: 620px) {
  .uploads__row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- footnote and actions ---------- */

.form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  padding-top: clamp(0.5rem, 1.5vh, 1rem);
}

.form__note { margin: 0; max-width: 34ch; font-size: 0.78125rem; line-height: 1.5; color: var(--ink-faint); }

/* ---------- the sent state ---------- */

.sent {
  border-top: 1px solid var(--ink);
  padding-top: clamp(1.5rem, 4vh, 2.5rem);
  display: grid;
  gap: 0.9rem;
  justify-items: start;
}

.sent h2 {
  margin: 0;
  font-size: clamp(1.6rem, 3.4vw, 2.75rem);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.01em;
}

.sent p { margin: 0; max-width: 44ch; font-size: 0.9375rem; line-height: 1.6; color: var(--ink-soft); }

/* ============================================================
   NARROW SCREENS
   ============================================================ */

@media (max-width: 900px) {
  .page__body { grid-template-columns: minmax(0, 1fr); gap: clamp(2rem, 6vh, 3rem); }
  /* The reassurance reads better under the form than above it on a
     phone — the form is what the page is for. */
  .page__body > .points { order: 2; }
  .page__body > .form-wrap { order: 1; }
}

@media (max-width: 620px) {
  .form__grid { grid-template-columns: minmax(0, 1fr); }
  .site { padding-inline: 1.25rem; }
  .site__nav { gap: 1.1rem; }
}

@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
  .field__line,
  .site__nav a::after { transition: none; }
}

/* ============================================================
   FOOTER — "TRACK-IN"
   The hero draws the mark; the footer should not repeat that.
   Here the wordmark arrives slightly too widely spaced and
   closes up to its true spacing as you scroll it into view —
   scroll-linked, so it runs both ways and stays tied to the
   reader's own motion.

   Everything below the @supports gate is enhancement only:
   without scroll-driven animation support the footer simply
   renders finished, which is the correct resting state.
   ============================================================ */

.footer {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 8vh 4vw;
  background: var(--paper);
  /* Same trap as the What We Do section: `hidden` would make this a
     scroll container and freeze --sxFooter at a single progress
     value, so the letters would never track in. */
  overflow: clip;
}

/* Only the logo sits in flow, so the grid centres the logo itself
   on the viewport and the fine print hangs off it — matching the
   Figma, where the wordmark is on the centre line rather than the
   logo-plus-text block being centred as a unit. */
.footer__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.footer__logo {
  width: var(--logo-w-footer);
  /* Names the timeline the letters and fine print animate along.
     Deliberately never transformed — the subject's own layout
     position is what drives the timeline. */
  view-timeline-name: --sxFooter;
}

.footer__logo svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
  shape-rendering: geometricPrecision;
}

.footer__logo .letter path {
  fill: var(--ink);
  fill-opacity: 1;
  stroke: none;
}

.footer__fine {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: clamp(1.5rem, 4.4vh, 3.25rem);
  text-align: center;
}

.footer__fine p {
  margin: 0;
  font-size: clamp(0.75rem, 0.28vw + 0.66rem, 0.875rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.5;
  color: var(--ink-faint);
}

.footer__fine p + p { margin-top: 0.7em; }

.footer__fine a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--ink-faint) 35%, transparent);
  transition: color 200ms ease, border-color 200ms ease;
}

.footer__fine a:hover,
.footer__fine a:focus-visible { color: var(--ink); border-color: var(--ink); }

@supports (animation-timeline: view()) {
  @media not (prefers-reduced-motion: reduce) {

    /* Each letter slides in from its own side. --d is the letter's
       signed distance from the centre of the wordmark (-1 … +1),
       so the outer letters travel furthest and the whole thing
       reads as tracking rather than ten separate moves. */
    .footer__logo .letter {
      animation-name: sxTrackIn;
      animation-duration: auto;
      animation-timing-function: var(--ease-out);
      animation-fill-mode: both;
      animation-timeline: --sxFooter;
      animation-range: cover 8% cover 48%;
    }

    .footer__logo svg {
      animation-name: sxFooterRise;
      animation-duration: auto;
      animation-timing-function: var(--ease-out);
      animation-fill-mode: both;
      animation-timeline: --sxFooter;
      animation-range: cover 8% cover 52%;
    }

    .footer__fine {
      animation-name: sxFooterFine;
      animation-duration: auto;
      animation-timing-function: var(--ease-out);
      animation-fill-mode: both;
      animation-timeline: --sxFooter;
      animation-range: cover 30% cover 62%;
    }
  }
}

@keyframes sxTrackIn {
  from { transform: translateX(calc(var(--d) * var(--footer-spread))); opacity: 0; }
  to   { transform: translateX(0); opacity: 1; }
}

@keyframes sxFooterRise {
  from { transform: translateY(16px); }
  to   { transform: translateY(0); }
}

@keyframes sxFooterFine {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

@media (max-width: 700px) {
  :root { --logo-w-footer: 88vw; --footer-spread: 11px; }
}

/* Over a full-height hero the header must not take a slice of the
   viewport for itself — the hero is meant to fill the screen, so
   there the header floats above it instead of sitting in the flow. */
.site--float {
  position: fixed;
  left: 0;
  right: 0;
}
