/*! Sappar Studio — Copyright (c) 2026 Carrier Nation LLC. All rights reserved. */
/**
 * THE SITE FOOTER STYLESHEET — the single style authority.
 *
 * Markup authority is partials/footer.html; injection and guards live in
 * scripts/build-pages.mjs. index.html and roadmap.html each carried a full
 * private copy of both, which is how the nav diverged and is why this is a
 * shared file from the start rather than after the drift.
 *
 * 🚨 CONSTRAINT ON THIS REDESIGN: colours and fonts are UNCHANGED. Every
 * `color`, `font-family`, `font-size`, `font-weight` and `letter-spacing`
 * below is carried over verbatim from the previous footer. What changed is
 * structure, rhythm and alignment only. If you are tempted to "improve" a
 * value here, that is a separate decision and not part of this pass.
 *
 * ⚠ Self-sufficient, like css/nav.css: it declares its own box-sizing, its own
 * base typeface, and consumes only tokens it can be sure of. A stylesheet
 * injected into more than one page cannot assume the host page's reset.
 *
 * 🚨 THAT CLAIM USED TO BE FALSE WHERE IT MATTERED MOST, and it is worth
 * knowing why it read as true. This file pinned JetBrains Mono on the column
 * headings and the copyright, so a reader scanning it saw font-family
 * declarations and concluded the typography was owned here. The BASE family was
 * never declared, so the tagline and every footer link simply inherited the host
 * page's body font — Inter on index.html and roadmap.html, and therefore
 * invisible while those were the only two hosts. The first host with a serif
 * body (/news/) rendered the whole footer in Source Serif 4.
 *
 * The lesson generalises past this file: a comment describing a property is not
 * a measurement of it. Both this claim and the wordmark below were established
 * by diffing what the stylesheet DECLARES against what it CONSUMES, and then by
 * measuring computed styles on every host page — not by reading the prose above.
 *
 * ── EVERY CONSUMED TOKEN CARRIES A LITERAL FALLBACK ──────────────────────────
 *
 * `var(--fog-1, #8c8c92)` and so on throughout, matching nav.css's
 * `var(--font-ui, "Inter", sans-serif)` pattern. The fallbacks are the brand-kit
 * values, identical to what every current host declares, so no computed value
 * changes on index.html, roadmap.html or /news/.
 *
 * They exist because the host pages do NOT all supply these. Measured: this file
 * consumes nine tokens; privacy.html, terms.html and sms.html declare seven —
 * BOTH --hair AND --hair-strong are missing, so every border in the footer would
 * collapse to `none` — and mission.html declares only two of the nine. A
 * component injected into pages it does not control cannot require tokens it
 * does not define, and "the hosts it has today happen to define them" is the
 * same coincidence documented above, one layer down.
 *
 * 🚨 .brand-lg DELIBERATELY NO LONGER USES --font-display, though it did until
 * 2026-08-13 and the change reads like a downgrade. --font-display means INTER
 * on index.html and roadmap.html and CORMORANT GARAMOND on every legal page. The
 * footer wordmark is Inter, always — so reading a token whose meaning the host
 * sets would render "Studio" in a serif the moment a legal page adopted this
 * footer. Measured by overriding the token on a live page: the trail followed it
 * to Cormorant while the signature (pinned below) held. Use --font-ui here.
 */

.site-footer-scope,
footer.site,
footer.site *{ box-sizing: border-box; }

/* 🚨 THE FOOTER NEUTRALISES THE ELEMENTS IT OWNS, because a page-local BARE
   ELEMENT rule reaches inside it. This is the same leak as the old private
   `footer { … }` rules, one level down and much harder to see: nothing here is
   named "footer", so no search for the word finds it.

   Measured, injecting the identical partial into each host:
     privacy.html  `li{margin-bottom:8px}` + `p{margin-bottom:16px}` (its legal
                   lists) -> the link column grew 96.4px to 120.4px and the
                   footer stood 404.5px against the homepage's 371.5px
     vellum-alternative.html and its two siblings `p{margin-bottom:18px}`
                   -> 432.5px
   Same markup, same CSS, same tokens, five different heights.

   ⚠ index.html and /news/ were immune only because each carries a global
   `*{margin:0;padding:0}` reset — the host supplying by accident what the
   component failed to declare, which is this file's recurring failure mode.

   ⚠ DESCENDANT-WIDE, not an element list. The first version of this reset named
   h5/p/ul/ol/li/figure and still missed one: `.f-cols` is a <nav>, so a page's
   bare `nav{border-bottom:…}` slipped straight through and left privacy.html 1px
   taller. Enumerating the elements the partial happens to use today is a list
   that goes stale the moment the markup gains a tag — the same enumerated-list
   rot that this codebase has been bitten by before. `footer.site *` cannot go
   stale.

   Specificity holds by construction: `footer.site *` is (0,1,0) and every rule
   below that sets a margin, padding or border on a descendant is at least
   (0,1,1), so the component's own spacing always wins. `footer.site` itself is
   not matched by the selector, so its own border-top and padding are untouched.
   Verified by measurement, not by reading specificity: h5 keeps its 18px bottom
   margin, .tag its 18px top margin, .row-1 its bottom border.

   ⚠ THE PROPERTY LIST WAS ENUMERATED, NOT GUESSED. Chasing leaks one at a time
   lost the race repeatedly, so every computed property of all 61 elements in the
   footer subtree was diffed against index.html on five hosts. What that found,
   beyond margin/padding/border:

     background + position + top + z-index + backdrop-filter on `.f-cols`
        — it is a <nav>, and the legal pages style their own sticky page nav with
          a bare `nav{position:sticky; backdrop-filter:blur(20px);
          background:rgba(6,6,7,.85)}`. That painted a translucent, blurred,
          STICKY panel behind the four link columns. It is the defect Severus
          spotted: "the box which holds Product / Features / …".
     max-width on <svg> — a bare `svg{max-width:100%}`.

   position/inset/z-index are reset because a host making part of the footer
   `sticky` is a layout break, not a tint. */
footer.site *{
  margin: 0;
  padding: 0;
  border: 0;
  /* ⚠ `color: inherit`, and it is NOT redundant with the base colour on
     footer.site. Inheritance has no specificity, so ANY matching rule beats it —
     the legal pages' bare `li{color:…}` for their own lists recoloured every
     footer list item, even though footer.site declares the colour they should
     have inherited. Restating it here as `inherit` puts the descendants back
     under the component's own base. */
  color: inherit;
  background: none;
  position: static;
  inset: auto;
  z-index: auto;
  backdrop-filter: none;
  box-shadow: none;
  filter: none;
  transform: none;
  max-width: none;
}

/* 🚨 LINK DECORATION IS THE COMPONENT'S OWN CONCERN, and this file used to leave
   it to the host. index.html carries a global `a{color:inherit;text-decoration:
   none}`; most other pages do not. So the footer's links rendered UNDERLINED
   everywhere except the two original hosts — including on /news/, which shipped
   that way, because the verification that declared the footers "identical"
   sampled family, size, colour and height and never sampled text-decoration.

   ⚠ That is the recurring lesson in its narrowest form: the properties you
   compare are a scope you chose, and a divergence outside that scope reads as
   agreement. Declared here so the answer no longer depends on the host. */
footer.site a{ text-decoration: none; }

/* 🚨 FORM CONTROLS DO NOT INHERIT TYPOGRAPHY. A <button> takes the UA
   stylesheet's own font and line-height rather than its ancestors', so the
   footer's language buttons rendered at line-height `normal` (16px tall) on a
   host with no button reset, against an inherited 17.05px (19.05px tall) on
   index.html — and that 3px, times one flex row, was the last 2px of a footer
   that stood 371.5px on the homepage and 369.5px on /news/.

   ⚠ This is the exact assumption the header above says this file must not
   make: it leaned on the HOST PAGE's reset. index.html and roadmap.html both
   have one, so it held for as long as they were the only hosts.

   Declared at (0,1,1) so `footer.site .langs button` at (0,2,1) still wins for
   the family and size it sets deliberately; only the properties nothing else
   claims are picked up here. */
footer.site button{
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  letter-spacing: inherit;
}

footer.site{
  border-top: 1px solid var(--hair, rgba(255,255,255,0.07));
  background: #030303;
  /* Rhythm on one scale. Was 60/40 outside with an unrelated 60 and 28 inside;
     four arbitrary numbers reading as four decisions. */
  padding: 72px 0 28px;
  /* THE BASE TYPOGRAPHY, pinned — all three of these, because all three are
     inherited and the footer had been taking each of them from the host page.

     font-family: the tagline and every column link inherit it. The literal
     fallback matches nav.css's `var(--font-ui, "Inter", sans-serif)` pattern,
     so the footer still renders on a host that defines no token at all.

     font-size + line-height: these do not change any text whose size is set
     explicitly, which is why they are easy to miss — every visible element in
     the footer pins its own size. What they DO change is the <li> boxes, which
     set neither, so their height came from the host page's body. Measured: the
     footer stood 371.5px on index.html and 393.6px on /news/ — same markup,
     same fonts, same padding, 22px apart, because one host sets 1.55/16px and
     the other 1.75/17px.

     ⚠ 1.55 is not an invention: it is the value nav.css pins on nav.top and the
     value index.html already resolves to, so the two injected components and
     the reference page now agree. Computed values are unchanged on index.html
     and roadmap.html. */
  font-family: var(--font-ui, "Inter", -apple-system, BlinkMacSystemFont, sans-serif);
  font-size: 16px;
  line-height: 1.55;
  /* The base COLOUR, for the same reason as the base family: it was inherited
     from the host <body>, so it differed on every page. Every visible element
     below sets its own colour, which is why this was invisible — but it is what
     anything unstyled would inherit. #e6e6e8 is what index.html already resolved
     to, so the reference page is unchanged. */
  color: var(--fog-4, #e6e6e8);
  /* The element itself, not just its descendants: a host's GROUPED selector
     (`section, footer { position: relative }`) survives a footer-only cleanup
     because its other half still matches something real, and then positions the
     whole footer. */
  position: static;
  inset: auto;
  z-index: auto;
}

/* THE FOOTER OWNS ITS MEASURE. It used to inherit each page's `.wrap`, and the
   two pages disagreed: index.html's is 1280px/28px, roadmap.html's is
   1100px/32px — and roadmap additionally pinned `footer.site .wrap` to 1100px.
   So the same footer sat on two different grids.

   1280px matches nav.css's `--maxw`, which aligns the footer wordmark with the
   navbar wordmark at the top of the page. The 16px difference in gutter is
   deliberate: the nav's 16px is a fixed bar, the footer reads as page content. */
footer.site .wrap{
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 28px;
}

/* ── Upper band: brand, then the link columns as one right-aligned group ──
   The old grid was `2fr 1fr 1fr 1fr` across the whole width, so the columns
   floated at arbitrary positions and the last one ran to the page edge. The
   brand now takes only what it needs and the columns travel together. */
footer.site .row-1{
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 64px;
  padding-bottom: 52px;
  border-bottom: 1px solid var(--hair, rgba(255,255,255,0.07));
}

footer.site .f-brand{
  flex: 0 1 auto;
  /* The tagline used to stretch to the full 2fr column. Holding it to the
     wordmark's own measure is what makes the block read as one object. */
  max-width: 300px;
}
footer.site .brand-lg{
  font-family: var(--font-ui, "Inter", -apple-system, BlinkMacSystemFont, sans-serif); font-size: 40px; font-weight: 300;
  letter-spacing: -0.035em; color: var(--bone, #ffffff); line-height: 1;
}
/* =========================================================
   FOOTER-SCOPED WORDMARK — makes this stylesheet self-sufficient.

   🚨 WHY THIS BLOCK EXISTS. It is the same failure css/nav.css already fixed
   for the navbar, in the component that did not get the treatment.

   This file set the signature's SIZE but never its IDENTITY, so the face came
   from whatever the host page happened to declare for `.sappar-sig` in its own
   <style>. index.html and roadmap.html both declare it — with !important — so
   the wordmark rendered in Great Vibes on both and the dependency was
   invisible. That was never a rule. It was a coincidence that held while the
   site footer had exactly two hosts, and it silently became load-bearing.

   The first host without a page-level rule rendered the wordmark in INTER
   ITALIC: the family inherited from .brand-lg's var(--font-display), and the
   italic was nothing but the <em> user-agent default. Identical markup,
   different brand — and no error, no build failure, nothing to notice.

   ⚠ !important is REQUIRED and specificity is NOT enough. The page-level rules
   declare font-family with !important, and no selector weight beats that:
   `footer.site .brand-lg .sappar-sig` is (0,3,0) and still loses. nav.css uses
   !important for precisely this reason.

   Values are index.html's — the same source nav.css cites, so the navbar and
   the footer wordmark cannot drift apart.

   ⚠ The rule removed here was `footer.site .brand-lg .ital`, which was DEAD:
   `.ital` is used widely in page body copy but never inside `.brand-lg`, so it
   styled nothing while looking exactly like the rule that gave the signature
   its face. Leaving it would have left two plausible sources for one fact.
   ========================================================= */
footer.site .brand-lg .sappar-sig{
  /* The signature sits at 1.2em inside the 40px wordmark and needs its optical
     baseline nudge. Both original pages defined these two identically. */
  font-size: 1.2em;
  vertical-align: 0.02em;
  font-family: "Great Vibes", cursive !important;
  font-style: normal !important;
  font-weight: 400 !important;
  /* .brand-lg tightens to -0.035em for the Inter trail. The signature is a
     script face and must not inherit that. */
  letter-spacing: 0 !important;
}
footer.site .brand-lg .brand-lg-trail{ color: var(--fog-3, #c8c8cc); font-weight: 300; }
footer.site .tag{
  font-size: 13px; color: var(--fog-2, #a0a0a6);
  /* 10px was too tight against a 40px wordmark — the tagline read as a
     descender of it rather than as its own line. */
  margin-top: 18px;
  line-height: 1.6;
}

footer.site .f-cols{
  display: grid;
  /* Four equal columns. Was three of unequal content (3 / 3 / 5 items), so
     the block hung two items lower on the right and the lower edge was
     ragged. Company split into Company + Legal gives 3 / 3 / 3 / 3. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 48px;
  flex: 1 1 auto;
  /* Sized so the longest link — "Book formatting software", 161.5px at 13.5px —
     sets on ONE line: (824 − 3×48) ÷ 4 = 170px. At 760px the columns came out
     154px, it wrapped, and the Compare column hung a line lower, which is the
     ragged edge this redesign exists to remove. Measured per locale: the
     German string is the longest and still fits. */
  max-width: 824px;
  /* Aligns the first link row's cap-height with the top of the wordmark
     rather than with the box. Measured, not guessed: see the completion doc. */
  padding-top: 6px;
}

footer.site h5{
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fog-1, #8c8c92);
  margin-bottom: 18px;
  font-weight: 400;
}
footer.site ul{ list-style: none; display: flex; flex-direction: column; gap: 11px; margin: 0; padding: 0; }
footer.site li a{
  font-size: 13.5px; color: var(--fog-3, #c8c8cc);
  transition: color .2s;
  /* The links are the only thing in the footer that moves. A colour-only
     hover on a 13.5px item in a dark column is easy to miss; the inline-block
     lets the transition have a box to act on without shifting the row. */
  display: inline-block;
}
footer.site li a:hover{ color: var(--bone, #ffffff) }

/* ── Lower band: one utility strip ──
   Previously the copyright appeared TWICE — once inside .tag and again here —
   and the X icon floated loose under the tagline, aligned to nothing. The
   strip now carries every utility: legal line left, contact / social /
   language right, separated by hairlines rather than by guesswork. */
footer.site .row-2{
  display: flex; justify-content: space-between; align-items: center;
  padding-top: 26px;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; letter-spacing: 0.06em;
  color: var(--fog-1, #8c8c92);
  flex-wrap: wrap; gap: 16px;
}
footer.site .f-utils{
  display: flex; align-items: center; gap: 18px;
}
footer.site .f-rule{
  width: 1px; height: 11px;
  background: var(--hair-strong, rgba(255,255,255,0.14));
  flex: 0 0 auto;
}
footer.site .f-contact{
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace; font-size: 11px; letter-spacing: 0.06em;
  color: var(--fog-1, #8c8c92);
  text-transform: uppercase;
  transition: color .2s;
}
footer.site .f-contact:hover{ color: var(--bone, #ffffff) }

footer.site .langs{ display: flex; gap: 12px }
footer.site .langs button{
  color: var(--fog-1, #8c8c92); font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px; letter-spacing: 0.08em;
  background: none; border: 0; padding: 0; cursor: pointer;
}
footer.site .langs button:hover{ color: var(--bone, #ffffff) }
footer.site .langs button.lang-active{ color: var(--bone, #ffffff); border-bottom: 1px solid var(--fog-2, #a0a0a6); padding-bottom: 1px; }

footer.site .footer-x{
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--fog-1, #8c8c92);
  transition: color 180ms ease;
}
footer.site .footer-x:hover{ color: var(--bone, #ffffff); }

/* ── Responsive ──
   The old single 820px breakpoint dropped four columns to two and left the
   brand stretched above them. Two steps instead: the columns wrap under the
   brand first, then halve. */
@media (max-width: 1080px){
  footer.site .row-1{ flex-direction: column; gap: 48px; }
  footer.site .f-brand{ max-width: none; }
  footer.site .f-cols{ max-width: none; width: 100%; padding-top: 0; }
}
@media (max-width: 720px){
  footer.site{ padding-top: 56px; }
  footer.site .f-cols{ grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 36px 32px; }
  footer.site .row-2{ justify-content: flex-start; gap: 20px; }
}
