/* ═══════════════════════════════════════════════════════════
   FOOTER
   Layout: identity + proof + capture on the left, six link
   groups on the right, one oversized line running underneath.

   Two decisions that make it NB's rather than generic:
   the proof marks carry their issuing body instead of being
   decorative chips, and the capture asks for a brochure rather
   than a newsletter — which is what this audience came for.
   ═══════════════════════════════════════════════════════════ */

.footer {
  position: relative;
  /* THE WHOLE FOOTER READS LIGHTER, AND IT IS THREE TOKENS RATHER
     THAN A DOZEN RULES. Every colour in this file resolves from the
     three on-dark values, so redefining them HERE lifts the section
     and nothing else on the site - the alternative was hunting every
     declaration and leaving the next one to be found by eye.

     The faint step moves furthest, from .20 to .38: it carries the
     copyright and the studio credit, and at .20 on this navy it was
     a grey nobody was going to read. */
  --on-dark:       rgba(251, 250, 247, .86);
  --on-dark-mute:  rgba(251, 250, 247, .62);
  --on-dark-faint: rgba(251, 250, 247, .38);

  /* 6, LIKE EVERY SECTION AFTER THE HERO. The travelling picture
     is fixed at z-index 5 and paints over anything below it; at the
     2 this carried on the other page the footer disappeared behind
     it. That page has no travelling picture, which is why it was
     never wrong there. */
  z-index: 6;

  /* IT STARTS WHERE THE REVIEWS END. The footer was a flat navy
     against a near-black page and the join read as two plates butted
     together - a different colour beginning at a line. The top of
     this gradient IS the page ground, so there is nothing to see at
     the boundary, and the navy arrives far enough down that the
     change reads as depth rather than as an edge.

     UPWARDS IN TONE, not down. The obvious footer gets darker toward
     the bottom; this one lifts, which puts the lightest ground under
     the smallest type - the fine print and the credit - and reads as
     the ground coming up to meet the end of the document.

     A PERCENTAGE, NOT A LENGTH. The section is a different height at
     every breakpoint and on a phone the columns stack to four times
     the depth; a fixed 46rem would finish the blend in the header on
     desktop and somewhere inside the links on a phone. */
  background: linear-gradient(180deg,
    var(--page-night)  0%,
    var(--navy)       58%);
  /* 7rem, down from 11. The reveal only works while the footer fits
     the window - a fixed element can never show more of itself than
     the viewport holds - and this section was 875px against a 900px
     screen. Every value below came off for the same reason, and the
     footer is better for it: it was airy to the point of loose. */
  padding: 7rem 0 0;
  /* NO RULE AT THE JOIN. The whole point is that there is no join. */
  color: var(--on-dark);
  overflow: hidden;
}

.ft-top { row-gap: 5rem; padding-bottom: 5rem; }

/* ── Left: identity, proof, capture ─────────────────────── */
.ft-left { grid-column: content-start / span 6; }

.ft-mark {
  display: block;
  width: 11rem;
  margin-bottom: 3.4rem;
}
.ft-mark img { width: 100%; height: auto; }

/* Proof marks. Each states WHO certifies it — an unattributed
   badge is decoration, and this audience checks. Three across on
   one row; left to wrap, the third dropped to a half-width orphan. */
.ft-proof {
  display: grid;
  /* TWO TRACKS, BECAUSE THERE ARE TWO BADGES. This was three, left
     over from when a Google Reviews badge stood beside them, and the
     empty third track squeezed both of the real ones - on a tablet
     hard enough that "IGBC Platinum" broke over two lines.

     CAPPED RATHER THAN FRACTIONAL. At 1fr each they would take half
     of a six-column block on a desktop, which is a very large box
     for two words and a line of small caps. minmax(0, 22rem) gives
     them a ceiling and still lets the grid shrink them where the
     room is not there. */
  grid-template-columns: repeat(2, minmax(0, 22rem));
  justify-content: start;
  gap: 1rem;
  margin-bottom: 4.4rem;
}
.ft-badge {
  display: flex;
  flex-direction: column;
  gap: .5rem;
  min-width: 0;
  padding: 1.3rem 1.4rem;
  border: var(--hair) solid var(--line-dark);
  border-radius: .3rem;
  background: rgba(250,247,241,.03);
  transition: border-color .5s var(--ease), background .5s var(--ease);
}
.ft-badge b {
  font-family: var(--font-sans);
  font-size: 1.45rem;
  font-weight: 600;
  color: var(--ivory);
  letter-spacing: -.005em;
}
.ft-badge span {
  color: var(--on-dark-faint);
  font-size: .95rem;
  line-height: 1.45;
  letter-spacing: .1em;
}
@media (hover: hover) {
  a.ft-badge:hover { border-color: var(--line-dark-lift); background: rgba(250,247,241,.06); }
}

/* Capture. A brochure is what this audience actually wants —
   a newsletter is what a developer's footer usually offers and
   almost nobody signs up for. */
.ft-capture h3 {
  font-family: var(--font-display);
  font-weight: 400;

  font-size: 2.8rem;
  line-height: 1.1;
  letter-spacing: -.012em;
  color: var(--ivory);
  margin-bottom: .8rem;
}
.ft-capture p { font-size: 1.5rem; color: var(--on-dark-mute); margin-bottom: 2rem; max-width: 36rem; }

.ft-form { display: flex; gap: 1rem; max-width: 42rem; }
.ft-form input {
  flex: 1;
  min-width: 0;
  height: 5.4rem;
  padding: 0 1.8rem;
  background: rgba(250,247,241,.05);
  border: var(--hair) solid var(--line-dark);
  border-radius: 100vmax;
  color: var(--ivory);
  font-family: var(--font-sans);
  font-size: 1.55rem;
  transition: border-color .4s var(--ease), background .4s var(--ease);
}
.ft-form input::placeholder { color: rgba(250,247,241,.26); }
.ft-form input:focus {
  outline: none;
  border-color: var(--gold-lift);
  background: rgba(250,247,241,.08);
}
.ft-send {
  flex: none;
  display: grid;
  place-items: center;
  width: 5.4rem; height: 5.4rem;
  border-radius: 50%;
  background: var(--gold);
  color: var(--ivory);
  transition: background .45s var(--ease), transform .45s var(--ease-out);
}
.ft-send svg { width: 1.8rem; height: 1.8rem; }
@media (hover: hover) {
  .ft-send:hover { background: var(--gold-lift); transform: translateX(.3rem); }
}
.ft-send:focus-visible { outline: 2px solid var(--gold-lift); outline-offset: 3px; }

/* ── Right: six link groups, three across ───────────────── */
.ft-cols {
  grid-column: span 9 / content-end;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 3.6rem var(--gap);
}
.ft-group h4 {
  font-family: var(--font-sans);
  font-size: 1.5rem;
  font-weight: 400;
  letter-spacing: .16em;
  text-transform: uppercase;
  /* GOLD, AND FOUR PIXELS UP FROM 1.1rem. The headings were the
     quietest thing in the footer and the links under them read as
     the headings; size fixed the hierarchy and the colour separates
     the kinds - a heading is a label, the links are destinations, and
     on this ground white said they were the same sort of thing.

     --gold-lift RATHER THAN --gold. The deeper value is mixed for
     paper; against the near-black at the top of the footer gradient
     it goes muddy. Every eyebrow on a dark ground in this site uses
     the lifted one. */
  color: var(--gold-lift);
  /* 1.3rem, down from 2. A heading has to sit closer to the list it
     names than the list sits to the next heading, or the eye pairs
     each label with the block above it instead of below. The row gap
     between groups is 3.6rem, so this is well inside it. */
  margin-bottom: 1.3rem;
}
.ft-group ul { display: flex; flex-direction: column; gap: 1.1rem; }
.ft-group a {
  font-size: 1.55rem;
  color: var(--on-dark);
  transition: color .35s var(--ease);
}
@media (hover: hover) { .ft-group a:hover { color: var(--ivory); } }

/* ── The line ────────────────────────────────────────────
   Full-bleed and deliberately cropped at both edges, so it reads
   as continuing past the frame rather than a headline that
   happens to be large. */
.ft-line {
  position: relative;
  /* NO RULE ABOVE IT. The band already separates itself: it is the
     only thing in the footer set at display size and it has five
     rems of air over it. A hairline as well was drawing a boundary
     the size of the type had already drawn. */
  padding: 3rem 0 3.5rem;
}

.ft-marquee {
  display: flex;
  width: max-content;
  will-change: transform;
  animation: ft-slide 34s linear infinite;
}
.ft-marquee.is-paused { animation-play-state: paused; }
.ft-marquee span {
  display: flex;
  align-items: center;
  gap: 4rem;
  padding-right: 4rem;
  font-family: var(--font-display);
  font-weight: 400;

  font-size: 8.6rem;
  line-height: 1;
  letter-spacing: -.03em;
  color: var(--ivory);
  white-space: nowrap;
}
.ft-marquee em {
  font-style: italic;

  color: var(--gold-lift);
}
/* a small gold rule as the separator */
.ft-marquee i {
  flex: none;
  width: 4.4rem; height: 1rem;
  border-radius: .2rem;
  background: var(--gold);
}

@keyframes ft-slide {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .ft-marquee { animation: none; }
}

/* ── Base bar ────────────────────────────────────────────
   Three items, one row. Flex rather than the 16-column grid:
   auto-placing a spanned middle item into the leftover tracks
   gave it a fraction of the width it needed and the centre note
   wrapped into a column one word wide. */
.ft-base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 3rem;
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding: 2.2rem var(--pad) 2.6rem;
  border-top: var(--hair) solid var(--line-dark);
}
.ft-base p { color: var(--on-dark-faint); }

@media (max-width: 1200px) {
  .ft-left { grid-column: content-start / span 7; }
  .ft-cols { grid-column: span 9 / content-end; gap: 4rem var(--gap); }
  .ft-marquee span { font-size: 8rem; }
}
@media (max-width: 991px) {
  /* A LINE AT THE JOIN, BUT ONLY HERE. On desktop the footer is
     uncovered from behind the page and its gradient starts on the
     exact colour the reviews end on - the whole point is that there
     is no edge to see. At these widths it is an ordinary block
     following an ordinary section in the same near-black, and
     without a rule the two run together with no telling where one
     stops. */
  .footer {
    padding-top: 8rem;
    border-top: var(--hair) solid var(--line-dark);
  }
  .ft-top { row-gap: 5rem; padding-bottom: 5rem; }
  .ft-left, .ft-cols { grid-column: content; }
  .ft-cols { gap: 3.6rem var(--gap); }
  .ft-marquee span { font-size: 5.6rem; gap: 2.6rem; padding-right: 2.6rem; }
  .ft-marquee i { width: 3rem; height: 1.4rem; }

}
/* ── Tablet only ─────────────────────────────────────────
   TWO ROWS, AND EACH ONE USES ITS WHOLE WIDTH. Below 992 the
   identity block and the link columns stop sharing a row, so this
   block gets the full width and everything in it was stacking down
   the left with the right-hand half empty.

     Row one — the mark and the two badges, side by side. They are
     one statement, who this is and what they are certified as, and
     on a full-width row there is no reason for the mark to sit alone
     above them.

     Row two — the brochure block, its heading and line on the left
     and the field on the right. THAT is where the empty space was:
     inside this block, beside a two-line paragraph. An earlier pass
     moved the whole capture up beside the mark instead, which filled
     the wrong gap and left this one.

   A BAND, NOT A CEILING. Scoped to 768-991 rather than "up to 991",
   because on a phone neither row has a second column to give and the
   stack is correct there. */
@media (min-width: 768px) and (max-width: 991px) {
  .ft-left {
    display: grid;
    /* auto for the mark so it takes its own width and the badges
       take the rest, rather than both being handed half a row. */
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: 4.5rem;
    row-gap: 5rem;
    align-items: center;
  }
  /* The margins were the space to whatever used to sit below each of
     them; the grid owns that now. */
  .ft-mark  { grid-column: 1; grid-row: 1; margin-bottom: 0; }
  .ft-proof { grid-column: 2; grid-row: 1; margin-bottom: 0; }

  .ft-capture {
    grid-column: 1 / -1;
    grid-row: 2;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: 4.5rem;
    align-items: center;
  }
  .ft-capture h3 { grid-column: 1; grid-row: 1; }
  .ft-capture p  { grid-column: 1; grid-row: 2; margin-bottom: 0; }
  /* Spanning both rows so it centres against the pair rather than
     sitting on the heading's baseline. */
  .ft-form       { grid-column: 2; grid-row: 1 / span 2; }
}

@media (max-width: 767px) {
  /* TWO EQUAL HALVES WITH REAL AIR BETWEEN THEM. The gap was the
     page gutter, which at this width is 2rem - enough to stop the
     columns touching and not enough to read as two columns. */
  .ft-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 3.6rem 5rem;
  }
  /* THE HEADINGS COME DOWN A LITTLE SO THE GAP CAN GO UP. At 1.5rem
     with .16em of tracking, "PARTNER WITH US" is wider than half a
     390px screen minus a real gutter - it wraps to two lines on the
     narrowest phone whatever the gap is. Down to 1.35 and .12 it
     fits with room to spare, and it is still well above the 1.1rem
     these were before. */
  .ft-group h4 { font-size: 1.35rem; letter-spacing: .12em; }

  /* Half height, like the type it sits between. The bar is drawn
     against a 4rem line here rather than an 8.6rem one. */
  .ft-marquee i { height: .5rem; width: 3rem; }
  .ft-mark { width: 9rem; }
  .ft-marquee span { font-size: 4rem; }
  .ft-badge { min-width: 13rem; padding: 1.2rem 1.4rem; }

  /* THE BASE BAR STACKS AND CENTRES. Two items pushed to opposite
     ends of a row only reads as a bar while there IS a row; wrapped
     onto two lines at the left margin they read as two stray notes
     under the marquee. Centred, they close the page.

     column-reverse RATHER THAN REORDERING THE MARKUP, so the address
     comes first here and the credits last without the desktop bar
     changing which end each one sits at. */
  .ft-base {
    flex-direction: column-reverse;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 1.1rem;
  }

  /* THE CREDIT BREAKS AT ITS SENTENCE, NOT WHEREVER THE COLUMN RUNS
     OUT. Left to wrap on its own the line folded after "BULL" and
     put the studio's name across two lines with one word stranded.
     Broken here, each half is a whole statement. */
  .ft-by span { display: block; }
}

/* The studio credit. Only the name lifts out of the fine-print
   weight — the line belongs to the footer's small print, not beside
   the client's own two entries. */
.ft-by b { font-weight: 500; color: var(--on-dark-mute); }

/* ── The reveal ──────────────────────────────────────────
   THE FOOTER IS UNCOVERED, NOT SCROLLED TO. Fixed to the bottom of
   the window and painted behind the page; the reviews slide up off
   it like a card off a table.

   WHICH MAKES IT READ FROM THE BOTTOM UP, and that is the whole
   reason for it. The strip of footer you can see runs from the
   page's lower edge down to the window's, so it grows UPWARD as you
   scroll: the copyright first, then the running line, then the
   columns and the mark last. In normal flow the order is exactly
   inverted — the logo and the six columns arrive first and the
   copyright is the thing you never reach.

   UNDER THE PAGE, NOT OVER IT. Every section above sits at 6 with
   an opaque ground, and being beneath them is what makes the effect
   work: the footer is not moving, the page in front of it is.

   BEHIND A CLASS, so the page still works without the script and
   without the effect. .ft-space is display:none by default, so a
   browser that never runs footer.js gets an ordinary footer at the
   end of an ordinary document rather than a screen of blank ground.
   Desktop only, and js/sections/footer.js decides: below the tablet
   breakpoint the class never goes on and everything here stays
   inert. It also slides the footer down when the window is shorter
   than the footer is. */
.ft-space,
.ft-shade { display: none; }

/* ONE STEP ABOVE THE FOOTER, STILL UNDER THE WHOLE PAGE. Two layers
   between the footer at 1 and the scenes at 3, which is all this
   needs: the shade hides the footer, the page hides the shade. It ends at the spacer, the one place the
   footer is meant to be seen. */
html.ft-reveal .ft-shade {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: var(--ft-h, 0px);
  z-index: 2;
  background: var(--page);
  pointer-events: none;
}

html.ft-reveal .footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  /* 1, UNDER THE PAGE BUT STILL A POSITIVE LAYER. This was -2, which
     put it under the page correctly and made the entire footer
     UNCLICKABLE: a negative z-index child paints behind its own
     ancestors' boxes, so every hit test landed on the body instead of
     on the links. .scene now carries a floor of 3 (see core.css) so
     there is room beneath the page without going negative. */
  z-index: 1;
}

html.ft-reveal .ft-space {
  display: block;
  height: var(--ft-h, 0px);
  /* IT HOLDS SPACE, IT DOES NOT TAKE CLICKS. An empty block still
     answers a hit test, and this one lies directly over the revealed
     footer. */
  pointer-events: none;
}
