/* ==========================================================================
   JX Marketing Group — stylesheet
   One file for every page. Tokens first, then base, layout, components,
   motion, and page-specific rules at the end.

   The system comes from the logo: a grotesque uppercase statement with an
   italic serif aside tucked under its right half. Two typefaces, one grey,
   one ink. Headings are "tucks" (.tuck). Asides start at column 7 of 12,
   which is where "Group" sits under "MARKETING".

   Editing notes for whoever writes next:
   - Location: every "Ottawa" in page copy is inside an element with
     [data-location]. The titles, descriptions, footer line and the JSON-LD
     take theirs from LOCATION, LOCATION_FOOTER and AREA_SERVED in
     _src/build.py.
   - Placeholders: every unfinished slot has [data-placeholder].
   - Words we do not use: elevate, seamless, cutting-edge, unlock, leverage,
     transform, craft, bespoke, digital presence, landscape, next level,
     journey, solutions. No exclamation marks. No em dashes.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Fonts
   The logo is set in Helvetica Neue Medium and Times Italic. macOS ships
   both; iOS ships Helvetica Neue and Times New Roman (no Times); Windows
   ships Times New Roman only. The local() names are tried in that order and
   the open faces are downloaded only where nothing matches.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "JX Grotesk";
  src: local("Helvetica Neue"), local("HelveticaNeue"),
       url("../assets/fonts/hanken-grotesk-var.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JX Grotesk";
  src: local("Helvetica Neue Medium"), local("HelveticaNeue-Medium"),
       url("../assets/fonts/hanken-grotesk-var.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JX Grotesk";
  src: local("Helvetica Neue Bold"), local("HelveticaNeue-Bold"),
       url("../assets/fonts/hanken-grotesk-var.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JX Italic";
  src: local("Times Italic"), local("Times-Italic"),
       local("Times New Roman Italic"), local("TimesNewRomanPS-ItalicMT"),
       url("../assets/fonts/tinos-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  color-scheme: light;

  /* Colour: the logo's ink and grey, and steps between them. */
  --ink:          #231F20;   /* logo near-black. text, buttons, rules that matter   */
  --ink-2:        #4A4644;   /* secondary text, 7.5:1 on field                       */
  --muted:        #66625F;   /* tertiary text, 4.8:1 on field. never below 13px      */
  --line:         #C9C6C2;   /* hairlines. decorative only                           */
  --well:         #D8D5D1;   /* reserved slots, photo well                           */
  --field:        #E6E6E6;   /* the logo grey. page ground                           */
  --sheet:        #F4F4F3;   /* working surfaces: form stage, work entry, inputs     */
  --white:        #FFFFFF;   /* focused input only                                   */
  --on-ink:       #E6E6E6;   /* text on ink                                          */
  --on-ink-muted: #B8B3AD;   /* secondary text on ink, 7.8:1                         */
  --error:        #8C2A21;   /* form errors only. 6.8:1 on field                     */

  /* Type */
  --font-sans:  "JX Grotesk", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-serif: "JX Italic", "Times New Roman", Times, serif;

  --fs-h1:        clamp(2.75rem, 1.35rem + 5.6vw, 7.25rem);   /* 44 to 116px */
  --fs-h1-aside:  clamp(1.5rem, 1rem + 1.8vw, 2.75rem);       /* 24 to 44px  */
  --fs-h2:        clamp(1.875rem, 1.25rem + 2.3vw, 3.375rem);  /* 30 to 54px  */
  --fs-h2-aside:  clamp(1.25rem, 1rem + 1vw, 2rem);            /* 20 to 32px  */
  --fs-h3:        1.5rem;                                      /* 24px        */
  --fs-lede:      clamp(1.25rem, 1.1rem + 0.5vw, 1.3125rem);   /* 20 to 21px  */
  --fs-body:      1.0625rem;   /* 17px */
  --fs-small:     0.875rem;    /* 14px */
  --fs-utility:   0.8125rem;   /* 13px */

  /* Space: 8px base. Sections breathe; components do not. */
  --s-1: 8px;  --s-2: 16px; --s-3: 24px; --s-4: 32px;
  --s-5: 48px; --s-6: 64px; --s-7: 96px; --s-8: 128px;
  --section: clamp(80px, 11vw, 160px);

  /* Grid */
  --gutter: 24px;
  --margin: clamp(20px, 5vw, 72px);
  --max: 1440px;
  --header-h: 76px;

  /* Motion. Three curves, chosen by how far the thing has to travel:
     --ease-soft for short moves (a reveal rises 16px), --ease-out for long
     ones (the statement clears its own height, the lockup crosses the
     page), --ease-inout for anything that starts and stops in place. One
     stagger step, so every cascade on the site beats at the same rate. */
  --ease-soft:  cubic-bezier(0.22, 0.68, 0.28, 1);
  --ease-out:   cubic-bezier(0.22, 1, 0.36, 1);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --d-1: 200ms;
  --d-2: 400ms;
  --d-3: 640ms;
  --d-4: 900ms;
  --stagger: 70ms;
}

@media (max-width: 719px) {
  :root { --gutter: 16px; --header-h: 64px; }
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 16px);
  background: var(--field);
}
html.reduce-motion { scroll-behavior: auto; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  min-height: 100vh;
  background: var(--field);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.55;
  font-weight: 400;
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

h1, h2, h3, h4, p, ul, ol, dl, dd, figure, fieldset { margin: 0; }
ul, ol { padding: 0; list-style: none; }
fieldset { padding: 0; border: 0; min-width: 0; }
legend { padding: 0; }
img, svg, video, iframe { display: block; max-width: 100%; }
img { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
em, i { font-family: var(--font-serif); font-style: italic; }
strong, b { font-weight: 500; }
address { font-style: normal; }
[id] { scroll-margin-top: calc(var(--header-h) + var(--s-3)); }

::selection { background: var(--ink); color: var(--on-ink); }

/* Focus: a 2px ink ring, only for keyboard focus where the browser can
   tell the difference, always where it cannot. */
:focus { outline: 2px solid var(--ink); outline-offset: 4px; }
@supports selector(:focus-visible) {
  :focus:not(:focus-visible) { outline: none; }
}
:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.ink :focus-visible, .ink :focus { outline-color: var(--on-ink); }

.skip-link {
  position: absolute;
  top: 8px; left: 8px;
  z-index: 100;
  padding: 10px 14px;
  background: var(--ink);
  color: var(--on-ink);
  font-size: var(--fs-utility);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; outline-color: var(--on-ink); }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   3. Type
   -------------------------------------------------------------------------- */
h1 { font-size: var(--fs-h1); font-weight: 500; line-height: 0.95; letter-spacing: 0.01em; text-transform: uppercase; }
h2 { font-size: var(--fs-h2); font-weight: 500; line-height: 1.02; letter-spacing: -0.015em; }
h3, .h3 { font-size: var(--fs-h3); font-weight: 500; line-height: 1.2; letter-spacing: -0.005em; }
h4, .h4 { font-size: var(--fs-body); font-weight: 500; line-height: 1.4; }
h1, h2, h3 { text-wrap: balance; }

.lede { font-size: var(--fs-lede); line-height: 1.45; max-width: 34em; }
.prose { max-width: 62ch; }
.prose p + p { margin-top: 1.1em; }
.prose p { color: var(--ink-2); }
.prose > p:first-child { color: var(--ink); }
.small { font-size: var(--fs-small); line-height: 1.5; color: var(--muted); }
.muted { color: var(--muted); }

.utility {
  font-size: var(--fs-utility);
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.aside, .tuck-aside {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

/* Links: a resting underline in the muted tone, ink on hover. Nothing moves. */
a { color: inherit; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; text-decoration-color: var(--muted); transition: text-decoration-color var(--d-1) ease-out; }
a:hover, a:focus-visible { text-decoration-color: currentColor; }
a[href^="mailto:"] { overflow-wrap: anywhere; }
.ink a { text-decoration-color: var(--on-ink-muted); }

/* Text links that say where they go. */
.link { display: inline-block; text-decoration: none; padding-bottom: 2px; border-bottom: 1px solid var(--ink); transition: border-color var(--d-1) ease-out, color var(--d-1) ease-out; }
.link:hover, .link:focus-visible { color: var(--ink-2); border-color: var(--ink-2); }
.ink .link { border-color: var(--on-ink); }
.ink .link:hover, .ink .link:focus-visible { color: var(--on-ink-muted); border-color: var(--on-ink-muted); }

/* --------------------------------------------------------------------------
   4. The tuck
   A grotesque statement with an italic aside under its right half.
   Used for every h1 and for section h2s. The aside starts at column 7.
   -------------------------------------------------------------------------- */
.tuck {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
}
.tuck-line { grid-column: 1 / 13; display: block; }
.tuck-aside {
  grid-column: 7 / 13;
  display: block;
  margin-top: 0.55em;
  font-size: var(--fs-h1-aside);
  line-height: 1.18;
  max-width: 26ch;
  color: var(--ink);
}
h2.tuck .tuck-line { grid-column: 1 / 10; }
h2.tuck .tuck-aside { font-size: var(--fs-h2-aside); margin-top: 0.7em; max-width: 30ch; }
.tuck-aside.muted { color: var(--muted); }

@media (max-width: 899px) {
  .tuck-aside { grid-column: 3 / 13; }
  h2.tuck .tuck-line { grid-column: 1 / 13; }
  h2.tuck .tuck-aside { grid-column: 3 / 13; }
}

/* Inside pages: the statement, then the lede under the right half. */
.hero-lede { margin-top: clamp(40px, 6vw, 80px); }
.hero-lede .lede { max-width: 30em; }
.hero-lede .fig { max-width: 440px; }

/* A lone aside: the italic voice speaking with no statement above it. */
.lone-aside {
  grid-column: 7 / 13;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--fs-h2-aside);
  line-height: 1.3;
  max-width: 30ch;
}
@media (max-width: 899px) { .lone-aside { grid-column: 3 / 13; } }

/* --------------------------------------------------------------------------
   5. Layout
   -------------------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--margin);
}
.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  row-gap: var(--s-4);
}
.col-1-5  { grid-column: 1 / 6; }
.col-1-6  { grid-column: 1 / 7; }
.col-1-7  { grid-column: 1 / 8; }
.col-7-13 { grid-column: 7 / 13; }
.col-1-13 { grid-column: 1 / 13; }

@media (max-width: 899px) {
  .grid > [class*="col-"] { grid-column: 1 / 13; }
  .grid > .well { grid-column: 1 / 8; }
  /* The drawing follows the words it illustrates. */
  .grid > .fig-slot { order: 1; margin-top: var(--s-2); }
}
@media (max-width: 719px) {
  .grid > .well { grid-column: 1 / 13; max-width: 320px; }
}

.section { padding-block: var(--section); }
.section + .section { padding-top: 0; }
.section + .section.ink { padding-top: var(--section); }
.hero + .section, .services + .section { padding-top: 0; }
.stack > * + * { margin-top: var(--s-4); }
.stack-sm > * + * { margin-top: var(--s-2); }

main { display: block; }

/* Ink surfaces */
.ink { background: var(--ink); color: var(--on-ink); }
.ink .muted, .ink .small { color: var(--on-ink-muted); }
.ink .tuck-aside { color: var(--on-ink); }
.ink .prose p { color: var(--on-ink-muted); }
.ink .prose > p:first-child { color: var(--on-ink); }
.ink ::selection { background: var(--on-ink); color: var(--ink); }

/* --------------------------------------------------------------------------
   6. Header and navigation
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--header-h);
  background: var(--field);
  border-bottom: 1px solid transparent;
  transition: border-color var(--d-1) ease-out, transform var(--d-2) var(--ease-out), background-color var(--d-2) var(--ease-out), color var(--d-2) var(--ease-out);
}
.site-header.is-scrolled { border-color: var(--line); }
.site-header.is-tucked { transform: translateY(-100%); }
.nav-open .site-header { transform: none; }

.site-header .wrap {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-4);
}
.brand { display: inline-flex; align-items: center; padding-block: 6px; text-decoration: none; color: var(--ink); }
.brand svg { width: clamp(148px, 12vw, 172px); height: auto; }
.brand:focus-visible { outline-offset: 6px; }

.site-nav ul { display: flex; align-items: center; gap: clamp(20px, 2.4vw, 36px); }
.site-nav a {
  display: inline-block;
  padding: 14px 0;
  font-size: var(--fs-utility);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color var(--d-1) ease-out;
}
.site-nav a:hover, .site-nav a:focus-visible { border-color: var(--ink); }
.site-nav a[aria-current="page"] { border-color: var(--ink); }
.site-nav .btn { display: inline-flex; margin-left: clamp(4px, 1vw, 12px); padding: 13px 24px; border-bottom-color: var(--ink); }
.site-nav .btn:hover, .site-nav .btn:focus-visible, .site-nav .btn[aria-current="page"] { border-color: var(--ink); }

.nav-toggle {
  display: none;
  align-items: center;
  min-height: 44px;
  padding: 0 4px;
  font-size: var(--fs-utility);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

@media (max-width: 899px) {
  .nav-toggle { display: inline-flex; }
  /* The brand and the toggle sit above the menu overlay inside the header's
     own stacking context, so the menu can always be closed. */
  .site-header .brand, .nav-toggle { position: relative; z-index: 41; }
  .site-nav {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: var(--ink);
    color: var(--on-ink);
    padding: calc(var(--header-h) + var(--s-5)) var(--margin) var(--s-6);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--d-2) var(--ease-out), visibility 0s linear var(--d-2);
  }
  .nav-open .site-nav { opacity: 1; visibility: visible; transition-delay: 0s; }
  .nav-open .site-header { background: var(--ink); color: var(--on-ink); border-color: transparent; transition: border-color var(--d-1) ease-out, background-color var(--d-2) var(--ease-out), color var(--d-2) var(--ease-out); }
  .nav-open .brand { color: var(--on-ink); }
  .nav-open .nav-toggle { color: var(--on-ink); }
  .site-nav :focus-visible, .site-nav :focus, .nav-open .site-header :focus-visible, .nav-open .site-header :focus { outline-color: var(--on-ink); }
  .site-nav ul { flex-direction: column; align-items: flex-start; gap: 0; }
  .site-nav li { width: 100%; border-top: 1px solid rgba(230, 230, 230, 0.18); }
  .site-nav li:last-child { border-top: 0; margin-top: var(--s-5); }
  .site-nav a {
    display: block;
    width: 100%;
    padding: 18px 0;
    font-size: clamp(1.75rem, 7vw, 2.5rem);
    font-weight: 500;
    letter-spacing: -0.01em;
    text-transform: none;
    border: 0;
    color: var(--on-ink);
    transform: translateY(12px);
    opacity: 0;
    transition: transform var(--d-3) var(--ease-out), opacity var(--d-3) var(--ease-out);
    transition-delay: calc(var(--i, 0) * 50ms + 80ms);
  }
  .nav-open .site-nav a { transform: none; opacity: 1; }
  /* Closing is not opening in reverse: the links leave together and fast. */
  html:not(.nav-open) .site-nav a { transition: transform var(--d-1) ease-in, opacity var(--d-1) ease-in; transition-delay: 0s; }
  .site-nav a[aria-current="page"] { font-family: var(--font-serif); font-style: italic; }
  .site-nav .btn { margin: 0; width: 100%; background: var(--on-ink); color: var(--ink); border-color: var(--on-ink); font-size: var(--fs-utility); letter-spacing: 0.08em; text-transform: uppercase; padding: 18px 24px; text-align: center; }
  .site-nav .btn:hover, .site-nav .btn:focus-visible { background: transparent; color: var(--on-ink); }

  /* Without JavaScript the menu is a plain row of links under the logo. */
  .no-js .nav-toggle { display: none; }
  .no-js .site-header { height: auto; }
  .no-js .site-header .wrap { flex-wrap: wrap; padding-block: 12px; }
  .no-js .site-nav { position: static; width: 100%; background: none; color: inherit; padding: 0; opacity: 1; visibility: visible; overflow: visible; }
  .no-js .site-nav ul { flex-direction: row; flex-wrap: wrap; gap: 0 20px; }
  .no-js .site-nav li { width: auto; border: 0; }
  .no-js .site-nav li:last-child { margin-top: 0; }
  .no-js .site-nav a { display: inline-block; width: auto; transform: none; opacity: 1; padding: 10px 0; font-size: var(--fs-utility); letter-spacing: 0.08em; text-transform: uppercase; color: inherit; font-family: var(--font-sans); font-style: normal; }
  .no-js .site-nav .btn { width: auto; padding: 13px 24px; background: var(--ink); color: var(--on-ink); border-color: var(--ink); }
}

/* --------------------------------------------------------------------------
   7. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 13px 24px;
  background: var(--ink);
  color: var(--on-ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  font-size: var(--fs-utility);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  line-height: 1;
  white-space: nowrap;
  transition: background-color var(--d-1) ease-out, color var(--d-1) ease-out, border-color var(--d-1) ease-out;
}
.btn:hover, .btn:focus-visible { background: transparent; color: var(--ink); }
.btn:disabled { background: var(--ink-2); border-color: var(--ink-2); color: var(--on-ink); cursor: default; }
.btn:disabled:hover { background: var(--ink-2); color: var(--on-ink); }

.ink .btn { background: var(--on-ink); color: var(--ink); border-color: var(--on-ink); }
.ink .btn:hover, .ink .btn:focus-visible { background: transparent; color: var(--on-ink); }

.btn-text {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0;
  font-size: var(--fs-utility);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-bottom: 1px solid transparent;
  transition: border-color var(--d-1) ease-out;
}
.btn-text:hover, .btn-text:focus-visible { border-color: currentColor; }

/* --------------------------------------------------------------------------
   8. Hero
   -------------------------------------------------------------------------- */
.hero { padding-top: clamp(56px, 9vw, 128px); padding-bottom: var(--section); }
.hero-home {
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100svh - var(--header-h));
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-bottom: clamp(40px, 6vw, 80px);
}
.hero-foot { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); align-items: end; margin-top: clamp(var(--s-6), 8vw, var(--s-7)); }
.hero-foot .lede { grid-column: 1 / 7; }
.hero-foot .hero-cta { grid-column: 7 / 13; }
@media (max-width: 899px) {
  .hero-foot .lede, .hero-foot .hero-cta { grid-column: 1 / 13; }
  .hero-foot .hero-cta { margin-top: var(--s-4); }
}

/* --------------------------------------------------------------------------
   9. Ledger: a definition list with one hairline between rows.
   Term left, description right, an italic aside at the far right.
   -------------------------------------------------------------------------- */
.ledger { border-top: 1px solid var(--line); }
.ledger-row {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: baseline;
  padding: var(--s-4) 0;
  border-bottom: 1px solid var(--line);
}
.ledger-row dt { grid-column: 1 / 5; font-size: var(--fs-h3); font-weight: 500; line-height: 1.2; letter-spacing: -0.005em; }
.ledger-row dd { grid-column: 5 / 10; color: var(--ink-2); max-width: 62ch; }
.ledger-row dd p + p { margin-top: 0.8em; }
.ledger-row .aside { grid-column: 10 / 13; color: var(--muted); font-size: var(--fs-body); max-width: none; }
@media (min-width: 900px) { .ledger-row dd:not(.aside):last-child { grid-column: 5 / 11; } }
@media (max-width: 899px) {
  .ledger-row { row-gap: var(--s-1); padding: var(--s-3) 0; }
  .ledger-row dt, .ledger-row dd { grid-column: 1 / 13; }
  .ledger-row .aside { grid-column: 3 / 13; }
}

/* Two-column fit lists */
.fit { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: var(--s-5); }
.fit > div { grid-column: span 6; }
.fit h3 { margin-bottom: var(--s-3); }
.fit li { position: relative; padding: 12px 0; border-top: 1px solid var(--line); color: var(--ink-2); }
.fit li:last-child { border-bottom: 1px solid var(--line); }
@media (max-width: 719px) { .fit > div { grid-column: 1 / 13; } }

/* --------------------------------------------------------------------------
   10. Footer
   -------------------------------------------------------------------------- */
.site-footer { border-top: 1px solid var(--line); padding: var(--s-6) 0 var(--s-5); }
/* The masthead: the logo at the full width of the page, once, at the end. */
.footer-mast { padding-bottom: var(--s-6); margin-bottom: var(--s-5); border-bottom: 1px solid var(--line); }
.brand-mast { display: block; padding: 0; }
.footer-mast svg { width: 100%; height: auto; }
.footer-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: var(--s-5); align-items: start; }
.footer-contact { grid-column: 1 / 7; }
.footer-nav { grid-column: 7 / 13; }
.footer-nav ul { display: grid; gap: 0; }
.footer-nav a { display: inline-block; padding: 9px 0; text-decoration: none; border-bottom: 1px solid transparent; transition: border-color var(--d-1) ease-out; }
.footer-nav a:hover, .footer-nav a:focus-visible { border-color: var(--ink); }
.footer-contact a { text-decoration: none; padding-bottom: 2px; border-bottom: 1px solid var(--ink); transition: border-color var(--d-1) ease-out, color var(--d-1) ease-out; }
.footer-contact a:hover, .footer-contact a:focus-visible { color: var(--ink-2); border-color: var(--ink-2); }
.footer-contact .aside { font-size: var(--fs-lede); line-height: 1.3; margin-bottom: var(--s-2); }
.footer-meta { grid-column: 1 / 13; display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5); margin-top: var(--s-3); padding-top: var(--s-3); border-top: 1px solid var(--line); font-size: var(--fs-small); color: var(--muted); }
.footer-meta span:last-child { margin-left: auto; }
@media (max-width: 899px) {
  .footer-contact { grid-column: 1 / 8; }
  .footer-nav { grid-column: 8 / 13; }
  .footer-meta span:last-child { margin-left: 0; }
}
@media (max-width: 599px) {
  .footer-contact { grid-column: 1 / 13; }
  .footer-nav { grid-column: 1 / 13; }
  .footer-nav ul { display: flex; flex-wrap: wrap; gap: 0 24px; }
}

/* --------------------------------------------------------------------------
   11. Forms
   -------------------------------------------------------------------------- */
.field { display: grid; gap: 8px; }
.field + .field, .field-group + .field, .field + .field-group, .field-group + .field-group { margin-top: var(--s-4); }
.field label, .field-group legend { font-weight: 500; }
.field-group legend { margin-bottom: var(--s-1); }
.field-group > .choices + .field-hint, .field-group > .field-error:not([hidden]) { margin-top: var(--s-1); }
.field-hint { font-family: var(--font-serif); font-style: italic; font-size: var(--fs-body); color: var(--muted); overflow-wrap: anywhere; }
.field-optional, .field-note { font-family: var(--font-serif); font-style: italic; font-weight: 400; color: var(--muted); }
.field-error { font-size: var(--fs-small); color: var(--error); }
.field-error[hidden] { display: none; }

.input, .textarea, .select {
  width: 100%;
  min-height: 52px;
  padding: 13px 16px;
  background: var(--sheet);
  color: var(--ink);
  border: 1px solid var(--muted);
  border-radius: 0;
  -webkit-appearance: none;
  appearance: none;
  transition: background-color var(--d-1) ease-out, border-color var(--d-1) ease-out;
}
.textarea { min-height: 132px; resize: vertical; line-height: 1.5; }
.input::placeholder, .textarea::placeholder { color: var(--muted); opacity: 1; font-family: var(--font-serif); font-style: italic; }
.input:hover, .textarea:hover, .select:hover { border-color: var(--ink); }
.input:focus, .textarea:focus, .select:focus { background: var(--white); border-color: var(--ink); outline: none; }
.input:focus-visible, .textarea:focus-visible, .select:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.is-invalid .input, .is-invalid .textarea, .is-invalid .select { border-color: var(--error); }
.select-wrap { position: relative; }
.select-wrap::after { content: ""; position: absolute; right: 18px; top: 50%; width: 8px; height: 8px; border-right: 1px solid var(--ink); border-bottom: 1px solid var(--ink); transform: translateY(-70%) rotate(45deg); pointer-events: none; }
.select { padding-right: 44px; }

/* Choice groups: radios and checkboxes as full rows */
.choices { display: grid; gap: 0; border-top: 1px solid var(--line); }
.choice { position: relative; display: flex; align-items: center; gap: 14px; min-height: 52px; padding: 12px 0; border-bottom: 1px solid var(--line); cursor: pointer; }
.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.choice-mark { flex: none; width: 18px; height: 18px; border: 1px solid var(--ink); border-radius: 50%; display: grid; place-items: center; transition: background-color var(--d-1) ease-out; }
.choice-mark::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--on-ink); opacity: 0; transition: opacity var(--d-1) ease-out; }
.choice input[type="checkbox"] + .choice-mark { border-radius: 0; }
.choice input[type="checkbox"] + .choice-mark::after { border-radius: 0; }
.choice input:checked + .choice-mark { background: var(--ink); }
.choice input:checked + .choice-mark::after { opacity: 1; }
.choice input:focus-visible + .choice-mark, .choice input:focus + .choice-mark { outline: 2px solid var(--ink); outline-offset: 3px; }
.choice:hover .choice-mark { background: var(--well); }
.choice input:checked:hover + .choice-mark { background: var(--ink); }
.choice-label { color: var(--ink); }
.is-invalid .choices { border-top-color: var(--error); }
.is-invalid .choice:last-child { border-bottom-color: var(--error); }
@media (forced-colors: active) {
  .choice-mark { forced-color-adjust: none; border-color: CanvasText; background: Canvas; }
  .choice:hover .choice-mark { background: Canvas; }
  .choice input:checked + .choice-mark, .choice input:checked:hover + .choice-mark { background: CanvasText; }
  .choice-mark::after { background: Canvas; }
  .choice input:focus-visible + .choice-mark { outline-color: Highlight; }
}

/* --------------------------------------------------------------------------
   12. Motion
   Hidden initial states apply only under html.anim, which the page adds
   only when it is visible and its animation loop is running (see the head
   script and main.js). Without JavaScript, in a background tab, or in a
   frozen preview, everything is simply visible. Everything collapses to
   its final state under prefers-reduced-motion.
   -------------------------------------------------------------------------- */
.anim [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  /* The fade finishes before the travel does, so the element settles into
     place instead of arriving and fading at the same moment. */
  transition: opacity var(--d-2) var(--ease-soft), transform var(--d-3) var(--ease-soft);
  transition-delay: calc(var(--i, 0) * var(--stagger) + var(--delay, 0ms));
}
.anim [data-reveal].in { opacity: 1; transform: none; }

/* Staggered children: parent has data-reveal data-stagger, children get --i */
.anim [data-reveal][data-stagger] { opacity: 1; transform: none; transition: none; }
.anim [data-reveal][data-stagger] > * {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--d-2) var(--ease-soft), transform var(--d-3) var(--ease-soft);
  transition-delay: calc(var(--i, 0) * var(--stagger));
}
.anim [data-reveal][data-stagger].in > * { opacity: 1; transform: none; }

/* The tuck reveal. The statement rises out of a mask, then the aside
   rises after it. Only transform and opacity animate, so the reveal runs
   on the compositor and cannot stall in a throttled or background tab.
   The masks pad and pull back by the same amount, so layout is identical
   with or without animation and descenders are never clipped. */
.tuck-line, .tuck-aside {
  overflow: hidden;
  padding-bottom: 0.25em;
  margin-bottom: -0.25em;
  padding-inline: 0.08em;
  margin-inline: -0.08em;
}
.tuck-in { display: block; }
.anim .tuck-line[data-reveal], .anim .tuck-aside[data-reveal] { opacity: 1; transform: none; transition: none; }
.anim .tuck-line[data-reveal] .tuck-in {
  transform: translateY(108%);
  transition: transform var(--d-4) var(--ease-out);
  transition-delay: var(--delay, 0ms);
}
.anim .tuck-line[data-reveal].in .tuck-in { transform: none; }
.anim .tuck-aside[data-reveal] .tuck-in {
  transform: translateY(110%);
  opacity: 0;
  transition: transform var(--d-4) var(--ease-out), opacity var(--d-2) var(--ease-soft);
  transition-delay: var(--delay, 260ms);
}
.anim .tuck-aside[data-reveal].in .tuck-in { transform: none; opacity: 1; }

/* Insurance: if main.js never runs, everything shows itself after 2.5s.
   main.js adds html.reveals-live the moment it has taken charge of the
   reveals, which switches this off — without that gate the net fires on
   every page and every reveal below the fold is already finished by the
   time the reader scrolls to it. */
@keyframes jx-show { to { opacity: 1; transform: none; } }
.anim:not(.reveals-live) [data-reveal]:not(.in),
.anim:not(.reveals-live) [data-reveal][data-stagger]:not(.in) > *,
.anim:not(.reveals-live) .tuck-line[data-reveal]:not(.in) .tuck-in,
.anim:not(.reveals-live) .tuck-aside[data-reveal]:not(.in) .tuck-in { animation: jx-show 0s 2500ms forwards; }

/* Page transitions. Out on the click and in on arrival, so a move between
   pages is one continuous fade rather than a fade and then a cut. The enter
   fills backwards only: once it has run it stops applying, so it can never
   hold the page open against .is-leaving. */
@keyframes jx-enter { from { opacity: 0; } }
.anim body { opacity: 1; transition: opacity var(--d-1) ease-out; animation: jx-enter var(--d-2) var(--ease-soft) backwards; }
.anim.is-leaving body { opacity: 0; }

/* Reduced motion: final state, no transitions. Layout never changes. */
.reduce-motion [data-reveal], .reduce-motion [data-reveal] > *, .reduce-motion .tuck-in {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
  animation: none !important;
}
.reduce-motion .site-header, .reduce-motion .site-nav, .reduce-motion .site-nav a, .reduce-motion body { transition: none !important; }
.reduce-motion body { animation: none !important; }

/* --------------------------------------------------------------------------
   13. Home: the three services, one scroll-linked moment.
   A pinned stage; WEBSITES wipes into META ADS and then into GOOGLE ADS as
   the reader scrolls, the drawing and the paragraph crossfade with it, and a
   three-part hairline at the foot says which of the three you are on. --p is
   written by main.js. The hand-overs sit at a third and two thirds of --p;
   every number below is one of those two, or a ramp measured from them.
   Adding or removing a service means re-cutting those fractions here and in
   updateServices() in main.js.
   -------------------------------------------------------------------------- */
.services { --p: 0; height: 260vh; position: relative; }
.services-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-content: center;
  padding-top: var(--header-h);
  overflow: hidden;
}
.services-words { grid-column: 1 / 13; position: relative; display: grid; }
.services-word {
  grid-area: 1 / 1;
  font-size: clamp(3rem, 1rem + 10.5vw, 11rem);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  margin: 0;
}
.services-word-1 { clip-path: inset(0 0 clamp(0%, calc((var(--p) - 0.2233) / 0.22 * 100%), 100%) 0); }
.services-word-2 { clip-path: inset(clamp(0%, calc((0.4433 - var(--p)) / 0.22 * 100%), 100%) 0 clamp(0%, calc((var(--p) - 0.5567) / 0.22 * 100%), 100%) 0); }
.services-word-3 { clip-path: inset(clamp(0%, calc((0.7767 - var(--p)) / 0.22 * 100%), 100%) 0 0 0); }

.services-copy { grid-column: 1 / 13; position: relative; margin-top: clamp(var(--s-4), 4vh, var(--s-6)); }
.services-item {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: start;
}
.services-item-fig { grid-column: 1 / 6; }
.services-item-fig .fig { max-width: 460px; }
.services-item-text { grid-column: 7 / 13; }
.services-item p { max-width: 34em; }
/* The first service sits in flow and sets the height of the row; the others
   are laid over it. They hand over rather than dissolve: each one is out at
   the hand-over mark, exactly where the next starts, so two paragraphs are
   never legible at once. A short rise carries the eye across the change.
   --in and --out are the same number counted from each side of a hand-over,
   which keeps every change symmetrical. The middle service has both: it
   arrives from below and leaves upwards, like the two either side of it. */
.services-item-1 {
  position: relative;
  --out: clamp(0, calc((0.3333 - var(--p)) / 0.04), 1);
  opacity: var(--out);
  transform: translateY(calc((1 - var(--out)) * -20px));
}
.services-item-2 {
  position: absolute;
  inset: 0;
  --in: clamp(0, calc((var(--p) - 0.3333) / 0.04), 1);
  --out: clamp(0, calc((0.6667 - var(--p)) / 0.04), 1);
  opacity: min(var(--in), var(--out));
  transform: translateY(calc((1 - var(--in)) * 20px - (1 - var(--out)) * 20px));
  pointer-events: none;
}
.services-item-3 {
  position: absolute;
  inset: 0;
  --in: clamp(0, calc((var(--p) - 0.6667) / 0.04), 1);
  opacity: var(--in);
  transform: translateY(calc((1 - var(--in)) * 20px));
  pointer-events: none;
}
.services-item-2.is-active, .services-item-3.is-active { pointer-events: auto; }
.services-item-1.is-passed { pointer-events: none; }

/* Which of the three you are on. */
.services-progress { grid-column: 1 / 13; display: grid; grid-template-columns: repeat(3, 1fr); column-gap: var(--gutter); margin-top: clamp(var(--s-4), 5vh, var(--s-7)); }
.services-progress span { position: relative; display: block; height: 1px; background: var(--line); }
.services-progress span::after { content: ""; position: absolute; inset: 0; background: var(--ink); transform-origin: left; transform: scaleX(0); }
.services-progress span:nth-child(1)::after { transform: scaleX(clamp(0, calc(var(--p) / 0.2933), 1)); }
.services-progress span:nth-child(2)::after { transform: scaleX(clamp(0, calc((var(--p) - 0.3333) / 0.2933), 1)); }
.services-progress span:nth-child(3)::after { transform: scaleX(clamp(0, calc((var(--p) - 0.6667) / 0.2933), 1)); }

/* In the pinned version the heading stays in the document for screen
   readers and the big words above carry it visually. */
.services-static-title { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; font-size: clamp(2.5rem, 1rem + 7vw, 6rem); font-weight: 500; line-height: 0.92; letter-spacing: 0.01em; text-transform: uppercase; margin-bottom: var(--s-3); }

/* Static version: the services stacked in plain flow, each with its
   drawing under its words. Used under reduced motion, without JavaScript,
   below 900px, on short viewports and in print. */
:is(.reduce-motion, .no-js) .services, .services.is-static { height: auto; }
:is(.reduce-motion, .no-js) .services-stage, .services.is-static .services-stage { position: static; height: auto; align-content: start; overflow: visible; padding: var(--section) var(--margin); row-gap: var(--s-6); }
:is(.reduce-motion, .no-js) .services-words, .services.is-static .services-words { display: none; }
:is(.reduce-motion, .no-js) .services-progress, .services.is-static .services-progress { display: none; }
:is(.reduce-motion, .no-js) .services-copy, .services.is-static .services-copy { grid-column: 1 / 13; display: grid; gap: 0; margin-top: 0; }
:is(.reduce-motion, .no-js) .services-item, .services.is-static .services-item { position: static !important; grid-area: auto; opacity: 1 !important; transform: none !important; pointer-events: auto !important; padding: var(--s-5) 0; border-top: 1px solid var(--line); }
:is(.reduce-motion, .no-js) .services-item:last-child, .services.is-static .services-item:last-child { border-bottom: 1px solid var(--line); }
:is(.reduce-motion, .no-js) .services-item-text, .services.is-static .services-item-text { grid-column: 1 / 13; }
:is(.reduce-motion, .no-js) .services-item-fig, .services.is-static .services-item-fig { grid-column: 1 / 13; order: 1; margin-top: var(--s-4); }
:is(.reduce-motion, .no-js) .services-static-title, .services.is-static .services-static-title { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
@media (max-width: 899px), (max-height: 559px), print {
  .services { height: auto; }
  .services-stage { position: static; height: auto; align-content: start; overflow: visible; padding: var(--section) var(--margin); row-gap: var(--s-6); }
  .services-words, .services-progress { display: none; }
  .services-copy { grid-column: 1 / 13; display: grid; gap: 0; margin-top: 0; }
  .services-item { position: static !important; grid-area: auto; opacity: 1 !important; transform: none !important; pointer-events: auto !important; padding: var(--s-5) 0; border-top: 1px solid var(--line); }
  .services-item:last-child { border-bottom: 1px solid var(--line); }
  .services-item-text { grid-column: 1 / 13; }
  .services-item-fig { grid-column: 1 / 13; order: 1; margin-top: var(--s-4); }
  .services-static-title { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
}

/* --------------------------------------------------------------------------
   14. Figures
   Hairline drawings that illustrate the sentence they sit beside: the ad
   and the page it feeds, the type scale, the shape of a Work entry. Drawn
   in the site's own two tones, decorative (aria-hidden), and carrying one
   slow loop each. Everything is drawn in its finished state unless the
   page is animating, so a still page is never a page with holes in it.
   -------------------------------------------------------------------------- */
.fig { --delay: 0ms; position: relative; width: 100%; align-self: start; }
/* In a hero the drawing comes after the sentence it belongs to. */
.hero .fig { --delay: 300ms; }
.fig svg { display: block; width: 100%; height: auto; }
.fig .frame, .fig .sheet, .fig .rule, .fig .trace, .fig .travel { fill: none; stroke: var(--line); stroke-width: 1; }
.fig .sheet { fill: var(--sheet); }
.fig .travel { stroke: var(--ink); stroke-width: 1.5; stroke-linecap: round; opacity: 0; }
.fig .b { fill: var(--line); }
.fig .b-ink { fill: var(--ink); }
.fig .b-well { fill: var(--well); }
.fig .b-sheet { fill: var(--sheet); }
.fig .frame-ink { stroke: var(--ink); }
.fig .bar { fill: none; stroke: var(--ink); stroke-width: 12; }
.fig .frame-em { stroke: var(--ink); opacity: 0; }
.fig .dot { fill: var(--line); }
.fig .dot-in { fill: var(--ink); }
.fig .select { fill: none; stroke: var(--ink); stroke-width: 1; }
.fig .b-hollow { fill: none; stroke: var(--line); stroke-width: 1; }
.fig .target { fill: var(--ink); opacity: 0; }
.panel .fig .sheet { fill: var(--field); }

/* Drawn in: the ground fades up, the frames stroke themselves on, the parts
   follow. The drawing itself does not travel — the lines do the arriving. */
.anim .fig[data-reveal] { transform: none; transition: opacity var(--d-2) var(--ease-soft); }
.anim .fig .frame, .anim .fig .sheet, .anim .fig .rule, .anim .fig .trace {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 950ms var(--ease-soft);
  transition-delay: calc(var(--i, 0) * var(--stagger) + var(--delay) + 120ms);
}
.anim .fig.in .frame, .anim .fig.in .sheet, .anim .fig.in .rule, .anim .fig.in .trace { stroke-dashoffset: 0; }
.anim .fig .b { opacity: 0; transition: opacity var(--d-3) var(--ease-soft); transition-delay: calc(var(--i, 0) * var(--stagger) + var(--delay) + 400ms); }
.anim .fig.in .b { opacity: 1; }

/* Every loop holds its first frame through its delay (animation-fill-mode:
   backwards). Without it a bar, a selection box or an ink dot sits in its
   finished state until the delay elapses and then snaps back to empty. */

/* The click travelling from the ad to the page, and the enquiry it becomes. */
@keyframes fig-travel {
  0%   { stroke-dashoffset: 100; opacity: 0; }
  8%   { opacity: 1; }
  46%  { stroke-dashoffset: 0; opacity: 1; }
  54%  { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes fig-target {
  0%, 48%   { opacity: 0; }
  56%, 74%  { opacity: 1; }
  88%, 100% { opacity: 0; }
}
.anim .fig-flow.in .travel { stroke-dasharray: 6 94; animation: fig-travel 6.5s var(--ease-inout) infinite backwards; animation-delay: calc(var(--delay) + 1.6s); }
.anim .fig-flow.in .target { animation: fig-target 6.5s var(--ease-soft) infinite backwards; animation-delay: calc(var(--delay) + 1.6s); }

/* The measure passing down the type scale. */
.fig-sweep, .fig-step { position: absolute; inset: 0; pointer-events: none; opacity: 0; }
.fig-sweep::before {
  content: "";
  position: absolute;
  left: 0; right: 2.5%; top: 0;
  height: 1px;
  background: var(--ink);
}
@keyframes fig-sweep {
  0%   { transform: translateY(4%); opacity: 0; }
  12%  { opacity: 0.5; }
  82%  { opacity: 0.5; }
  100% { transform: translateY(87%); opacity: 0; }
}
.anim .fig-scale.in .fig-sweep { animation: fig-sweep 7s var(--ease-inout) infinite backwards; animation-delay: calc(var(--delay) + 1.8s); }

/* The marker stepping through the three headings of an entry. */
.fig-step::before {
  content: "";
  position: absolute;
  left: 2.6%; top: 30%;
  width: 3.4%;
  height: 2px;
  background: var(--ink);
}
@keyframes fig-step {
  0%        { transform: translateY(0); opacity: 0; }
  5%, 24%   { transform: translateY(0); opacity: 1; }
  33%, 57%  { transform: translateY(24.2%); opacity: 1; }
  66%, 92%  { transform: translateY(48.5%); opacity: 1; }
  98%, 100% { transform: translateY(48.5%); opacity: 0; }
}
.anim .fig-entry.in .fig-step { animation: fig-step 9s var(--ease-inout) infinite backwards; animation-delay: calc(var(--delay) + 1.6s); }

/* What each version of the ad returned, measured again and again. */
@keyframes fig-bar {
  0%        { stroke-dashoffset: 100; }
  30%, 84%  { stroke-dashoffset: 0; }
  94%, 100% { stroke-dashoffset: 100; }
}
.anim .fig-test.in .bar {
  stroke-dasharray: 100;
  animation: fig-bar 8s var(--ease-inout) infinite backwards;
  animation-delay: calc(var(--i, 0) * 320ms + var(--delay) + 1.4s);
}

/* The same page, looked at again at each width. */
@keyframes fig-em { 0% { opacity: 0; } 5%, 26% { opacity: 1; } 33%, 100% { opacity: 0; } }
.anim .fig-widths.in .frame-em { animation: fig-em 9s var(--ease-inout) infinite backwards; animation-delay: calc(var(--i, 0) * 3s + var(--delay) + 1.4s); }

/* Everyone the money could reach, then the ones worth reaching. */
@keyframes fig-select { 0% { stroke-dashoffset: 100; } 16%, 84% { stroke-dashoffset: 0; } 94%, 100% { stroke-dashoffset: 100; } }
@keyframes fig-dot { 0%, 12% { opacity: 0; } 26%, 84% { opacity: 1; } 92%, 100% { opacity: 0; } }
.anim .fig-audience.in .select { stroke-dasharray: 100; animation: fig-select 8s var(--ease-inout) infinite backwards; animation-delay: calc(var(--delay) + 1.2s); }
.anim .fig-audience.in .dot-in { animation: fig-dot 8s var(--ease-soft) infinite backwards; animation-delay: calc(var(--i, 0) * 130ms + var(--delay) + 1.2s); }

/* Someone already searching: the answer they were after is picked out of
   the page they were going to read anyway. */
.anim .fig-query.in .select { stroke-dasharray: 100; animation: fig-select 8s var(--ease-inout) infinite backwards; animation-delay: calc(var(--delay) + 1.2s); }
.anim .fig-query.in .target { animation: fig-dot 8s var(--ease-soft) infinite backwards; animation-delay: calc(var(--delay) + 1.5s); }

/* A loop the reader cannot see is a loop worth stopping. main.js marks a
   figure idle once it is well clear of the viewport; it picks up where it
   left off rather than restarting. */
.anim .fig.in.is-idle :is(.travel, .target, .bar, .select, .dot-in, .frame-em, .fig-sweep, .fig-step) { animation-play-state: paused; }

.reduce-motion .fig .b { opacity: 1 !important; transition: none !important; }
.reduce-motion .fig .frame, .reduce-motion .fig .sheet, .reduce-motion .fig .rule, .reduce-motion .fig .trace { stroke-dashoffset: 0 !important; transition: none !important; }
.reduce-motion .fig .travel, .reduce-motion .fig-sweep, .reduce-motion .fig-step, .reduce-motion .fig .frame-em { display: none !important; }
.reduce-motion .fig * { animation: none !important; }

/* --------------------------------------------------------------------------
   15. Work page: the index of entries
   -------------------------------------------------------------------------- */
.entry { background: var(--sheet); padding: clamp(24px, 4vw, 56px); }
.entry-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: var(--s-2) var(--s-4); margin-bottom: var(--s-5); }
.entry-head h3 { font-size: var(--fs-h2); line-height: 1.02; letter-spacing: -0.015em; text-transform: none; }
.entry-body { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: var(--s-4); }
.entry-body dt { grid-column: 1 / 4; font-weight: 500; }
.entry-body dd { grid-column: 4 / 11; color: var(--ink-2); max-width: 62ch; }
@media (max-width: 719px) {
  .entry-body { row-gap: var(--s-1); }
  .entry-body dt, .entry-body dd { grid-column: 1 / 13; }
  .entry-body dd + dt { margin-top: var(--s-3); }
}

.index { border-top: 1px solid var(--line); }
.index-row {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--gutter);
  align-items: baseline;
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
}
.index-head { padding: 12px 0; color: var(--muted); }
.index-row > :nth-child(1) { grid-column: 1 / 5; }
.index-row > :nth-child(2) { grid-column: 5 / 8; }
.index-row > :nth-child(3) { grid-column: 8 / 11; }
.index-row > :nth-child(4) { grid-column: 11 / 13; }
.index-row .reserved { font-size: var(--fs-h3); font-weight: 500; color: var(--ink-2); letter-spacing: -0.005em; }
.index-row .aside { color: var(--muted); }
/* A filled row: swap .is-reserved for .is-live, put the client name in a
   link, and the row reads as a finished entry with no other change. */
.index-row.is-live { color: var(--ink); }
.index-row.is-live > :nth-child(1) { font-size: var(--fs-h3); font-weight: 500; letter-spacing: -0.005em; }
.index-row.is-live a { text-decoration: none; border-bottom: 1px solid var(--ink); }
.index-row.is-live a:hover, .index-row.is-live a:focus-visible { color: var(--ink-2); border-color: var(--ink-2); }
@media (max-width: 719px) {
  .index-head { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .index-row { row-gap: 4px; }
  .index-row > :nth-child(1) { grid-column: 1 / 13; }
  .index-row > :nth-child(2) { grid-column: 1 / 7; }
  .index-row > :nth-child(3) { grid-column: 7 / 13; }
  .index-row > :nth-child(4) { grid-column: 1 / 13; }
}

/* Report specimen (Meta ads page) */
.specimen { background: var(--sheet); padding: clamp(24px, 4vw, 56px); }
.specimen-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.specimen table { width: 100%; min-width: 640px; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.specimen-scroll:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }
.specimen th, .specimen td { text-align: left; padding: 14px 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.specimen th { font-weight: 500; font-size: var(--fs-utility); letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.specimen td { color: var(--ink-2); }
.specimen td .aside { color: var(--muted); }
.specimen th + th, .specimen td + td { padding-left: var(--s-3); }

/* Photo well (About) */
.well { background: var(--well); aspect-ratio: 4 / 5; display: flex; align-items: flex-end; padding: var(--s-3); }
.well .aside { color: var(--ink-2); font-size: var(--fs-lede); }
.well:has(img) { padding: 0; }
/* About: the two co-founders' names carry the section, no photo. Sized to
   stay on one line in the narrow column at every width. */
.founder-names { font-size: clamp(1.75rem, 1.1rem + 1.9vw, 2.75rem); line-height: 1.08; letter-spacing: -0.02em; }
.founder-names span { display: block; }
.founder-names span + span { margin-top: 0.08em; }
.well img { width: 100%; height: 100%; object-fit: cover; }

/* --------------------------------------------------------------------------
   16. Request a call
   -------------------------------------------------------------------------- */
.book-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: var(--s-6); align-items: start; }
.book-side { grid-column: 1 / 6; position: sticky; top: calc(var(--header-h) + var(--s-4)); }
.book-main { grid-column: 7 / 13; }
.book-side .stack-sm p { color: var(--ink-2); }
@media (max-width: 899px) {
  .book-side { grid-column: 1 / 13; position: static; }
  .book-main { grid-column: 1 / 13; }
}

.steps-form { background: var(--sheet); padding: clamp(24px, 4vw, 56px); }
.steps-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); margin-bottom: var(--s-2); }
.steps-head .utility { white-space: nowrap; }
.steps-head .small { text-align: right; }
.steps-progress { position: relative; height: 1px; background: var(--line); margin-bottom: var(--s-5); }
.steps-progress-bar { position: absolute; inset: 0; background: var(--ink); transform: scaleX(var(--progress, 0.2)); transform-origin: left; transition: transform var(--d-2) var(--ease-inout); }
.step-title { font-size: var(--fs-h2); letter-spacing: -0.015em; line-height: 1.02; margin-bottom: var(--s-1); }
.step-title:focus { outline: none; }
.step-intro { color: var(--muted); font-family: var(--font-serif); font-style: italic; font-size: var(--fs-lede); margin-bottom: var(--s-5); }
.steps-actions { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); margin-top: var(--s-6); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.steps-actions .btn { margin-left: auto; }

/* Without JavaScript every step shows at once and the buttons that need
   JavaScript are hidden; the form still reads as one long questionnaire. */
.no-js [data-step][hidden] { display: block !important; margin-top: var(--s-7); }
.no-js [data-next], .no-js [data-prev], .no-js .steps-progress, .no-js .steps-head { display: none !important; }
.no-js .steps-actions [type="submit"][hidden] { display: inline-flex !important; }

/* Step transitions: leave in the direction of travel, enter from the other side */
[data-step] { transition: opacity 180ms ease-in, transform 180ms ease-in; }
[data-step].leave-forward { opacity: 0; transform: translateX(-16px); }
[data-step].leave-back { opacity: 0; transform: translateX(16px); }
[data-step].enter-forward { opacity: 0; transform: translateX(16px); transition: none; }
[data-step].enter-back { opacity: 0; transform: translateX(-16px); transition: none; }
[data-step]:not(.enter-forward):not(.enter-back):not(.leave-forward):not(.leave-back) { transition: opacity var(--d-2) var(--ease-out), transform var(--d-2) var(--ease-out); }
.reduce-motion [data-step] { transition: none !important; transform: none !important; opacity: 1 !important; }
.reduce-motion .steps-progress-bar { transition: none; }

.review-group + .review-group { margin-top: var(--s-5); }
.review-head { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); padding-bottom: var(--s-2); border-bottom: 1px solid var(--ink); }
.review-head .btn-text { min-height: 44px; margin-block: -10px; }
.review { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gutter); row-gap: 0; }
.review dt { grid-column: 1 / 5; color: var(--muted); font-size: var(--fs-small); padding: 14px 0 12px; border-bottom: 1px solid var(--line); }
.review dd { grid-column: 5 / 13; font-family: var(--font-serif); font-style: italic; font-size: var(--fs-lede); line-height: 1.4; overflow-wrap: anywhere; padding: 12px 0; border-bottom: 1px solid var(--line); }
@media (max-width: 719px) {
  .review dt { grid-column: 1 / 13; padding: 14px 0 0; border-bottom: 0; }
  .review dd { grid-column: 1 / 13; padding: 4px 0 12px; }
}

.submit-error { padding: var(--s-2) 0; color: var(--error); }
.submit-error[hidden] { display: none; }
.honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }

.success { padding: clamp(24px, 4vw, 56px); background: var(--sheet); }
.success[hidden] { display: none; }
.success h2:focus { outline: none; }

/* --------------------------------------------------------------------------
   17. Panels and numbered ledgers
   A sheet panel is a near-white surface that holds one section. Numerals
   appear only where the content is a real sequence.
   -------------------------------------------------------------------------- */
.panel { background: var(--sheet); padding: clamp(32px, 5vw, 80px); }

.ledger-num .ledger-row dt { display: flex; align-items: baseline; gap: var(--s-3); }
.num {
  flex: none;
  min-width: 1.1em;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.25rem, 1.4rem + 2.4vw, 3.5rem);
  line-height: 0.8;
  letter-spacing: 0;
  color: var(--muted);
  font-variant-numeric: lining-nums;
}

/* --------------------------------------------------------------------------
   18. Home intro: the logo reveal.
   html.intro is set by the head script (visible tab, first Home load of
   the session). main.js runs the sequence; without it, or if the
   animation loop is dead, .intro is removed and the page is simply there.
   -------------------------------------------------------------------------- */
.hero-home { position: relative; }
.hero-logo { display: none; }
.intro .hero-logo {
  display: block;
  position: absolute;
  /* Above the header (z-index 50), so the lockup is never clipped by the
     opaque header bar as it flies up into the corner. */
  z-index: 60;
  top: clamp(56px, 9vw, 128px);
  left: var(--margin);
  width: min(calc(100% - 2 * var(--margin)), 1000px);
  aspect-ratio: var(--ratio);
  color: var(--ink);
  transform-origin: 0 0;
  transition: transform 800ms var(--ease-inout);
  pointer-events: none;
}
.hero-logo-row { display: flex; width: 100%; }
.hero-logo .g { flex: 0 0 var(--w); overflow: hidden; padding-bottom: 3px; margin-bottom: -3px; }
.hero-logo .g svg { display: block; width: 100%; height: auto; }
.intro .hero-logo .g svg {
  transform: translateY(112%);
  transition: transform 760ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 45ms + 240ms);
}
.intro-letters .hero-logo .g svg { transform: none; }
.hero-logo-group { position: absolute; display: block; }
.hero-logo-group svg { display: block; width: 100%; height: auto; }
.intro .hero-logo-group svg {
  transform: translateY(45%);
  opacity: 0;
  transition: transform 640ms var(--ease-out), opacity 520ms var(--ease-out);
  transition-delay: 560ms;
}
.intro-letters .hero-logo-group svg { transform: none; opacity: 1; }

/* The header logo stays out of sight until the lockup has landed on it. */
.intro .site-header .brand { opacity: 0; }
.intro-done .site-header .brand { opacity: 1; }
.intro-done .hero-logo { visibility: hidden; }

/* --------------------------------------------------------------------------
   19. Small utilities
   -------------------------------------------------------------------------- */
.mt-3 { margin-top: var(--s-3); } .mt-4 { margin-top: var(--s-4); }
.mt-5 { margin-top: var(--s-5); } .mt-6 { margin-top: var(--s-6); }
.mb-3 { margin-bottom: var(--s-3); } .mb-5 { margin-bottom: var(--s-5); }
[hidden] { display: none !important; }

/* Print: the site should read on paper too. */
@media print {
  .site-header, .site-footer .footer-nav, .nav-toggle, .skip-link { display: none; }
  body { background: #fff; color: #000; }
  .ink, .ink .tuck-aside, .ink .prose p, .ink .small, .ink .muted { background: none; color: #000; }
  body { animation: none !important; }
  [data-reveal], [data-reveal] > *, .tuck-in, .fig .b { opacity: 1 !important; transform: none !important; }
  .fig .frame, .fig .sheet, .fig .rule, .fig .trace { stroke-dashoffset: 0 !important; }
  .fig .travel, .fig-sweep, .fig-step, .fig .frame-em { display: none !important; }
}
