/* ===== fonts.css ===== */
/* =========================================================
   Self-hosted fallback faces.

   These used to arrive through @fontsource, imported in main.jsx and bundled
   by Vite. The port drops the npm packages: the woff2 files are committed in
   src/assets/fonts/ and declared here by hand, so the repo carries no runtime
   dependency at all and the build cannot silently change which files ship.

   Aleo stands in for Adelle, which comes from the Adobe Fonts kit linked in
   the layout head. It was the closest free face to the same brief when the
   alternatives were compared, so if the kit is slow, blocked, or the Creative
   Cloud subscription ever lapses, the site degrades to something in the right
   register rather than to a generic slab. Only 300 and 700 are declared
   because those are the only slab weights the design uses.

   Inter stands in for Helvetica Neue, which resolves natively on macOS and
   falls back everywhere else.

   Both are SIL OFL, so committing the files is fine.

   SUBSETS: latin and latin-ext only. The @fontsource build also shipped
   cyrillic, greek and vietnamese, roughly forty files this site never asks
   for. The unicode-range values below are lifted verbatim from the
   @fontsource CSS so the split behaves exactly as it did before. latin-ext
   is what carries U+2020, the dagger the provenance markers use.
   ========================================================= */

@font-face {
  font-family: 'Aleo';
  font-style: normal;
  font-display: swap;
  font-weight: 300;
  src: url(/assets/fonts/aleo-latin-ext-300-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Aleo';
  font-style: normal;
  font-display: swap;
  font-weight: 300;
  src: url(/assets/fonts/aleo-latin-300-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Aleo';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/fonts/aleo-latin-ext-700-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Aleo';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/fonts/aleo-latin-700-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url(/assets/fonts/inter-latin-ext-400-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url(/assets/fonts/inter-latin-400-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 500;
  src: url(/assets/fonts/inter-latin-ext-500-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 500;
  src: url(/assets/fonts/inter-latin-500-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 600;
  src: url(/assets/fonts/inter-latin-ext-600-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 600;
  src: url(/assets/fonts/inter-latin-600-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/fonts/inter-latin-ext-700-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-display: swap;
  font-weight: 700;
  src: url(/assets/fonts/inter-latin-700-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ===== tokens.css ===== */
/* =========================================================
   Bird Bear Beast brand tokens
   Single source of truth for the site. Scoped to .bbb.

   Every value here is sourced from a real brand asset, not chosen:
     red / yellow  sampled from inspo/Proposal Template 070826.pdf
     paper / char  from public/brand/beast logo *.svg
     type stack    from pdffonts on the same proposal

   TYPE
   Display is Adelle, served from Adobe Fonts, which Brian's Creative Cloud
   subscription covers for web use. Klinic Slab was the face the printed
   proposal is set in and remains the closer match, but its Lost Type licence
   is Personal only: no commercial use, no webfont embedding. Adelle avoids
   that purchase without dropping register.

   Aleo is the self-hosted fallback, chosen because it was the nearest free
   face when the alternatives were compared. If the Adobe kit is missing or
   blocked the site still reads correctly.
   ========================================================= */

/*
  Scoped to .bbb rather than :root so the site's palette cannot be reached
  or overridden by anything else sharing the document; /explore still runs
  its own copy of these tokens under .xp.
*/
.bbb {
  /* ---- colour ---- */
  --paper: #f8f0e2;
  --char: #333333;
  --red: #e53244;
  --yellow: #fff200;

  /* secondary greys, from the proposal's headline and rule weights */
  --grey: #4f4c4d;
  --grey-soft: #a7a5a6;

  /*
    ---- type ----
    `adelle` is the family name kit lrd3ffj defines, lowercase, verified
    against the kit CSS. The kit also carries adelle-condensed and
    adelle-ultrathin, neither of which this design uses.

    WEIGHT GAP: the kit currently ships adelle at 400 and 700 only. The
    design calls for 300 on the light display type, so those lines render at
    400 until Adelle Light is added to the web project. Not broken, just
    heavier than intended. Adding Light in Adobe Fonts fixes it with no code
    change.
  */
  --slab: adelle, Aleo, Georgia, serif;
  --sans: 'Helvetica Neue', Helvetica, Inter, system-ui, -apple-system, sans-serif;
  --serif: 'Tiempos Headline', 'Iowan Old Style', Georgia, serif;

  /* ---- measure ---- */
  --pad: clamp(20px, 4.5vw, 64px);
  --maxw: 1440px;

  /*
    One size for every page title. The routes used to open at four different
    display sizes: 104px on /work and /wonder, 96px on a case study, 78px on
    /practice, 76px on / and /contact. Read back to back that is four
    templates rather than one site. This is /contact's scale, the one that
    was chosen, stated once here so the next page added cannot invent a
    fifth.

    Only the size is shared. Weight, leading and colour stay with the page,
    because the em device inside each headline is deliberately different:
    weight contrast on home, tone contrast on /practice, red on /contact.
  */
  --h1: clamp(32px, 5.6vw, 76px);

  /* one easing curve everywhere */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/*
  No @font-face for the display face. Adelle arrives from the Adobe Fonts
  kit, injected into index.html at build time (see vite.config.js), and Aleo
  is imported in main.jsx from @fontsource.

  The Klinic local() declarations that used to sit here are gone on purpose.
  They rendered Klinic on this machine only, so the site looked different to
  Brian than to every visitor, which is exactly how "looks fine to me" bugs
  survive review.
*/

/* ---- reset, scoped to the site tree ---- */
.bbb *,
.bbb *::before,
.bbb *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Body ground, so overscroll shows paper rather than white. */
body.bbb-active {
  background: #f8f0e2 !important;
  transition: none !important;
}

.bbb {
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-size: 16px;
  line-height: 1.55;
  /*
    `clip` rather than `hidden` on purpose: hidden computes overflow-y to
    auto, which silently breaks position:sticky, and the header depends on
    sticky. clip creates no scroll container.
  */
  overflow-x: clip;
}

.bbb a {
  color: inherit;
  text-decoration: none;
}

.bbb img {
  display: block;
  max-width: 100%;
  height: auto;
}

/*
  The lockup SVGs carry their size as inches (width="9.11in") rather than
  unitless px, and Chrome will not derive a reliable intrinsic ratio from
  that once the element is absolutely positioned: the box grows unbounded
  in height. Stating the ratio from the viewBox fixes it everywhere at once.
  beast logo 333333.svg  → 655.77 x 156.44
*/
.bbb .bbb-lockup {
  aspect-ratio: 655.77 / 156.44;
  height: auto;
  object-fit: contain;
  object-position: left center;
}

.bbb ::selection {
  background: var(--yellow);
  color: var(--char);
}

/*
  Display type gets balanced line breaks so a headline never strands its last
  word on a line of its own. Tuning `max-width` per headline would fix it for
  one typeface and break again the moment the face changes, which is exactly
  what happened when Adelle replaced the narrower fallback and "exists." fell
  onto a fourth line by itself.

  balance is capped by browsers at a handful of lines, so it is for headings
  only. Body copy gets `pretty`, which just prevents orphans without
  re-flowing the whole block.
*/
.bbb h1,
.bbb h2,
.bbb h3,
.bbb .balance {
  text-wrap: balance;
}

.bbb p,
.bbb li,
.bbb dd {
  text-wrap: pretty;
}

/*
  These are paragraphs by markup but display type by role: short, set large,
  and read as a statement rather than as prose. They want balance, not pretty.
  Listed here rather than in each page's stylesheet because it is one
  typographic rule about the display scale, not a per-page layout decision.
*/
.bbb .hm-say,
.bbb .hm-arrive h1,
.bbb .cs-lede,
.bbb .pr-say,
.bbb .pr-lede,
.bbb .wo-stmt p,
.bbb .wo-wip-line,
.bbb .ct-lede {
  text-wrap: balance;
}

/* ---- primitives shared across pages ---- */

/* the proposal's running head: small serif, folio opposite */
.bbb .runhead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-family: var(--serif);
  font-size: 13px;
  letter-spacing: 0.01em;
}

/* the 01 / 02 / 03 numeral with its hairline rules above and below */
.bbb .numeral {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 34px;
  line-height: 1;
  color: var(--red);
  letter-spacing: -0.02em;
}

.bbb .rule {
  height: 1px;
  background: var(--red);
  border: 0;
}

/* the proposal's // separator */
.bbb .sep {
  opacity: 0.55;
}

.bbb .wrap {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--pad);
}

@media (prefers-reduced-motion: reduce) {
  .bbb *,
  .bbb *::before,
  .bbb *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* creature mask: inherits currentColor, so it inverts on any band */
.bbb .bbb-creature {
  display: block;
  aspect-ratio: 4096 / 2130;
  background: currentColor;
  -webkit-mask: url(/brand/creature.svg) center / contain no-repeat;
  mask: url(/brand/creature.svg) center / contain no-repeat;
  flex: none;
}

/* numeral block: rule, figure, rule */
.bbb .bbb-num .rule { margin-bottom: 10px; }
.bbb .bbb-num .numeral { display: block; margin-bottom: 10px; }

/* ===== layout.css ===== */
/* =========================================================
   Layout: the roll-up header and the footer.
   ========================================================= */

.bbb {
  background: var(--paper);
  color: var(--char);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  /* containing block for the header sentinel */
  position: relative;
}

.bbb-hold,
.bbb-head-in,
.bbb-foot-in {
  width: 100%;
  max-width: 1340px;
  margin: 0 auto;
  padding: 0 var(--pad);
}

/* ---------------- the roll-up header ---------------- */

/*
  Lockup width at each end of the move. Everything else interpolates off
  these two, so retuning the header is a two-line change.
*/
.bbb-head {
  --lw-rest: clamp(178px, 20vw, 258px);
  --lw-cond: clamp(116px, 12vw, 158px);
  --hp: clamp(24px, 3.4vw, 50px);
  --ratio: 4.192; /* lockup viewBox 655.77 / 156.44 */

  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 90;
  padding-top: calc(var(--hp) * (1 - 0.42 * var(--t)));
  /* the rule holder supplies the bottom gap, so the rule sits on the edge */
  padding-bottom: 0;
  /* paper fades in only as it condenses, so the arrival has no furniture */
  background: rgb(248 240 226 / calc(var(--t) * 0.94));
  backdrop-filter: blur(calc(var(--t) * 7px));
  -webkit-backdrop-filter: blur(calc(var(--t) * 7px));
  transition: padding 0.12s linear;
}

.bbb-head-in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.bbb-head-mark {
  display: block;
  flex: none;
  width: calc(var(--lw-rest) + (var(--lw-cond) - var(--lw-rest)) * var(--t));
  transition: width 0.12s linear;
}

/* the hairline that A2 pins under the header, drawn in as it lands */
.bbb-head-ruleholder {
  max-width: 1340px;
  margin: 0 auto;
  padding: 0 var(--pad);
  margin-top: calc(var(--hp) * (0.42 + 0.18 * var(--t)));
}

.bbb-head-rule {
  height: 1px;
  border: 0;
  background: var(--char);
  opacity: 0.22;
  transform: scaleX(var(--t));
  transform-origin: left;
}

/* ---------------- nav ---------------- */

.bbb-nav {
  display: flex;
  gap: clamp(14px, 2vw, 30px);
  /* arrives in the last 40% of the move */
  opacity: clamp(0, calc((var(--t) - 0.6) * 2.5), 1);
  transform: translateY(calc((1 - var(--t)) * 8px));
}

.bbb-head[data-condensed='false'] .bbb-nav {
  pointer-events: none;
}

.bbb-nav-a {
  font-family: var(--sans);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--grey);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
  transition: color 0.22s var(--ease), border-color 0.22s var(--ease);
}

.bbb-nav-a:hover,
.bbb-nav-a:focus-visible {
  color: var(--red);
}

.bbb-nav-a.on {
  color: var(--char);
  border-bottom-color: var(--red);
}

/* ---------------- main ---------------- */

/*
  Fixed header, so content needs its own top offset. Home clears the resting
  header (which is tall); interior pages clear the condensed one.
*/
.bbb-main {
  flex: 1;
  padding-top: calc(clamp(24px, 3.4vw, 50px) * 1.6 + clamp(116px, 12vw, 158px) / 4.192 + 26px);
}

.bbb-main.is-home {
  padding-top: calc(clamp(24px, 3.4vw, 50px) * 1.6 + clamp(178px, 20vw, 258px) / 4.192 + 30px);
}

/* Height of this governs how much scroll the roll-up takes. */
.bbb-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 62vh;
  pointer-events: none;
}

/* ---------------- shared page furniture ---------------- */

.bbb-label {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--red);
  border-top: 1px solid var(--red);
  padding-top: 12px;
  margin-bottom: clamp(20px, 3vw, 34px);
}

.bbb .sep {
  color: var(--red);
  font-weight: 400;
  opacity: 1;
}

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

.bbb-foot {
  background: var(--char);
  color: var(--paper);
  margin-top: clamp(60px, 10vw, 130px);
  padding: clamp(40px, 6vw, 78px) 0 clamp(30px, 4vw, 48px);
}

.bbb-foot-brand {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2vw, 26px);
  border-bottom: 1px solid rgba(248, 240, 226, 0.28);
  padding-bottom: clamp(22px, 3vw, 34px);
  margin-bottom: clamp(26px, 4vw, 44px);
}

.bbb-foot-creature {
  width: clamp(72px, 9vw, 116px);
  color: var(--red);
}

.bbb-foot-line {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.bbb-foot-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: clamp(22px, 3.4vw, 52px);
}

.bbb-foot h2 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: 12px;
}

.bbb-foot-mail {
  display: block;
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(16px, 1.7vw, 21px);
  letter-spacing: -0.018em;
  line-height: 1.2;
  word-break: break-word;
  margin-bottom: 7px;
  transition: color 0.22s var(--ease);
}

.bbb-foot-mail:hover {
  color: var(--yellow);
}

.bbb-foot-tel {
  font-size: 13.5px;
  color: rgba(248, 240, 226, 0.75);
  transition: color 0.22s var(--ease);
}

.bbb-foot-tel:hover {
  color: var(--yellow);
}

.bbb-foot address {
  font-style: normal;
  font-size: 13.5px;
  line-height: 1.7;
  color: rgba(248, 240, 226, 0.75);
}

.bbb-foot address span {
  display: block;
}

.bbb-foot-nav {
  list-style: none;
  font-size: 13.5px;
  line-height: 1.85;
}

.bbb-foot-nav a {
  color: rgba(248, 240, 226, 0.75);
  transition: color 0.22s var(--ease);
}

.bbb-foot-nav a:hover {
  color: var(--yellow);
}

/* ---------------- reduced motion ---------------- */

/*
  No interpolation: the header simply is the condensed one, everywhere. The
  hook attaches no listeners in this mode, so --t is pinned at 1 and these
  rules only need to remove the transitions.
*/
@media (prefers-reduced-motion: reduce) {
  .bbb-head,
  .bbb-head-mark,
  .bbb-nav {
    transition: none;
  }
}

/* ---------------- narrow ---------------- */

@media (max-width: 720px) {
  .bbb-head-in {
    flex-wrap: wrap;
    gap: 12px;
  }
  .bbb-nav {
    gap: 14px;
    width: 100%;
  }
  .bbb-nav-a {
    font-size: 10px;
    letter-spacing: 0.14em;
  }
  /* nav wraps onto its own line, so both states need more clearance */
  .bbb-main,
  .bbb-main.is-home {
    padding-top: calc(clamp(178px, 20vw, 258px) / 4.192 + 96px);
  }

  /*
    THE FOOTER WAS THE TALLEST THING ON A PHONE. minmax(190px, 1fr) fits one
    column into a 390px screen, so all three stacked and the footer ran to
    480px, 57% of the viewport, on every page.

    The three are not equally wide, though, so the fix is not three columns
    at any cost. "Start here" carries the two slab links and needs the room;
    the address and the four nav items are short enough to sit side by side.
    So the CTA takes the full width and the other two pair beneath it, which
    is two rows rather than three and reads as a hierarchy rather than as a
    grid that ran out of space.

    Scoped entirely inside this query, so the desktop footer is untouched.
  */
  .bbb-foot {
    padding: 30px 0 26px;
  }
  .bbb-foot-brand {
    padding-bottom: 16px;
    margin-bottom: 20px;
  }
  .bbb-foot-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 22px 18px;
  }
  .bbb-foot-cols > :first-child {
    grid-column: 1 / -1;
  }
  /* The two links stop being a stacked pair once they have a full row. */
  .bbb-foot-cols > :first-child {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 4px 22px;
  }
  .bbb-foot-cols > :first-child h2 {
    flex: 1 0 100%;
    margin-bottom: 6px;
  }
  /*
    Four stacked nav items are the tallest thing in the bottom row and set its
    height; the address beside them only runs to two lines. Two short columns
    square the row off against the address instead of towering over it.

    A grid rather than `columns: 2`, which fills column-major and would print
    Work / Wonder across the first row, putting the nav in an order that is
    neither the header's nor the one it reads in. Grid fills row-major, so
    what you read across is the order the nav is actually in.
  */
  .bbb-foot-nav {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 12px;
  }
}

/* ---------------- status band ---------------- */

/*
  Full bleed red, the hard colour edge the printed work uses, carrying one
  line of small caps. Sits at the top of the content flow, immediately under
  the header, and scrolls away with the page.

  Gated on NOTICE.show in content/projects.js. Remove it there, not here.
*/
.bbb-notice {
  background: var(--red);
  color: var(--paper);
  padding: 11px 0;
  margin-bottom: clamp(24px, 4vw, 46px);
}

/*
  Inline, not flex. Flex makes each child its own item and collapses the
  whitespace inside <Sep />, so the separator renders as "PROGRESS//THE"
  with no breathing room. Inline layout keeps the spaces the component
  actually contains, and wraps naturally at narrow widths.
*/
.bbb-notice .bbb-hold {
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.7;
}

.bbb-notice b {
  font-weight: 700;
}

.bbb-notice span {
  opacity: 0.92;
}

/* the // separator is red on paper elsewhere; here it has to invert */
.bbb-notice .sep {
  color: var(--paper);
  opacity: 0.55;
}

/* ===== workindex.css ===== */
/* =========================================================
   The work index table: A2's core, shared by / and /work.
   ========================================================= */

.wx {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 296px;
  gap: clamp(24px, 4vw, 60px);
  align-items: start;
}

.wx.no-plate {
  grid-template-columns: minmax(0, 1fr);
}

/* ---------------- table ---------------- */

.wx-colhead,
.wx-link {
  display: grid;
  grid-template-columns: 46px minmax(0, 1.35fr) 92px minmax(0, 1.5fr) 22px;
  gap: 16px;
  align-items: baseline;
}

.wx-colhead {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--red);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--red);
}

.wx-table {
  list-style: none;
}

.wx-row {
  border-bottom: 1px solid rgba(51, 51, 51, 0.16);
}

.wx-link {
  padding: 15px 0;
  padding-left: 0;
  transition: background 0.22s var(--ease), padding-left 0.32s var(--ease);
  outline-offset: 3px;
}

.wx-row.on .wx-link {
  background: rgba(229, 50, 68, 0.05);
  padding-left: 9px;
}

.wx-no {
  font-size: 11px;
  letter-spacing: 0.06em;
  color: var(--grey-soft);
  font-variant-numeric: tabular-nums;
}

.wx-name {
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(17px, 1.85vw, 25px);
  line-height: 1.08;
  letter-spacing: -0.022em;
  transition: color 0.22s var(--ease);
}

.wx-row.on .wx-name {
  color: var(--red);
}

.wx-name sup {
  font-size: 0.36em;
  color: var(--red);
  vertical-align: super;
  margin-left: 0.2em;
}

.wx-lock {
  display: inline-block;
  font-style: normal;
  font-family: var(--sans);
  font-weight: 400;
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--red);
  border: 1px solid currentColor;
  padding: 2px 6px;
  margin-left: 10px;
  vertical-align: middle;
}

.wx-year {
  font-size: 12px;
  letter-spacing: 0.05em;
  color: var(--grey);
  font-variant-numeric: tabular-nums;
}

.wx-disc {
  font-size: 11.5px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--grey);
  line-height: 1.6;
}

/* the affordance that says these are pages, not just rows */
.wx-go {
  font-size: 14px;
  color: var(--red);
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity 0.24s var(--ease), transform 0.28s var(--ease);
  text-align: right;
}

.wx-row.on .wx-go {
  opacity: 1;
  transform: none;
}

.wx-notes {
  margin-top: 20px;
  font-size: 12px;
  line-height: 1.9;
  color: var(--grey-soft);
}

.wx-notes span {
  display: block;
}

.wx-notes sup {
  color: var(--red);
  font-weight: 700;
}

/* ---------------- the anchored plate ---------------- */

.wx-aside {
  position: sticky;
  top: calc(clamp(116px, 12vw, 158px) / 4.192 + 74px);
}

.wx-plate img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.wx-plate figcaption {
  margin-top: 12px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--grey);
  border-top: 1px solid var(--red);
  padding-top: 10px;
}

.wx-plate figcaption b {
  display: block;
  font-family: var(--slab);
  font-weight: 700;
  font-size: 15px;
  color: var(--char);
  margin-bottom: 4px;
  letter-spacing: -0.012em;
}

/* ---------------- narrow ---------------- */

@media (max-width: 1040px) {
  .wx {
    grid-template-columns: minmax(0, 1fr);
  }
  /* the plate stops earning its column before it stops earning its place */
  .wx-aside {
    display: none;
  }
}

@media (max-width: 720px) {
  .wx-colhead {
    display: none;
  }
  .wx-link {
    grid-template-columns: 34px minmax(0, 1fr) 20px;
    gap: 4px 12px;
    padding: 16px 0;
  }
  .wx-year,
  .wx-disc {
    grid-column: 2;
  }
  .wx-year {
    margin-top: 4px;
  }
  .wx-go {
    grid-column: 3;
    grid-row: 1;
    opacity: 0.5;
    transform: none;
  }
}

/* ===== home.css ===== */
/* =========================================================
   Home: A1's arrival, then A2's index, then the way out.
   ========================================================= */

/* ---------------- arrival ---------------- */

.hm-arrive {
  padding-bottom: clamp(56px, 11vw, 150px);
}

.hm-arrive h1 {
  font-family: var(--slab);
  font-weight: 300;
  font-size: var(--h1);
  line-height: 1.08;
  letter-spacing: -0.03em;
  max-width: 21ch;
}

.hm-arrive h1 em {
  font-style: normal;
  font-weight: 700;
}

.hm-stand {
  margin-top: clamp(26px, 4vw, 46px);
  max-width: 48ch;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--grey);
}

.hm-colophon {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(178px, 1fr));
  gap: 20px 30px;
  border-top: 1px solid var(--red);
  padding-top: 14px;
  margin-top: clamp(36px, 6vw, 70px);
  max-width: 820px;
}

.hm-colophon dt {
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: 5px;
}

.hm-colophon dd {
  font-size: 14.5px;
  line-height: 1.45;
}

/*
  The frame. Sits inside the arrival, tied to the colophon above it, so it
  reads as part of the opening rather than as a section the reader has to
  get past before reaching the work.
*/
.hm-disciplines {
  margin-top: clamp(18px, 2.6vw, 28px);
  max-width: 820px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 2;
  color: var(--char);
}

/* ---------------- work ---------------- */

.hm-work {
  padding-bottom: clamp(46px, 8vw, 104px);
}

.hm-work-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
}

.hm-work-head .bbb-label {
  flex: 1;
}

.hm-all {
  flex: none;
  border-top: 1px solid var(--red);
  padding-top: 12px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  transition: color 0.22s var(--ease), gap 0.22s var(--ease);
}

.hm-all:hover {
  color: var(--char);
}

/* ---------------- also worked with ---------------- */

.hm-also {
  padding-bottom: clamp(40px, 7vw, 90px);
}

.hm-list {
  font-size: clamp(14.5px, 1.5vw, 18px);
  line-height: 1.78;
  max-width: 80ch;
}

/* ---------------- close ---------------- */

.hm-close {
  padding-bottom: clamp(20px, 4vw, 50px);
}

.hm-say {
  font-family: var(--slab);
  font-weight: 300;
  font-size: clamp(20px, 2.8vw, 36px);
  line-height: 1.28;
  letter-spacing: -0.02em;
  max-width: 26ch;
  margin-bottom: clamp(34px, 5vw, 60px);
}

.hm-say em {
  font-style: normal;
  font-weight: 700;
}

/*
  Sized down from A2, where this topped out at 58px and competed with the
  project names for the same attention. It is a closing line, not a headline.
*/
.hm-mail {
  display: inline-block;
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(19px, 2.4vw, 32px);
  letter-spacing: -0.028em;
  line-height: 1;
  word-break: break-word;
  border-bottom: 2px solid var(--red);
  padding-bottom: 4px;
  transition: color 0.22s var(--ease);
}

.hm-mail:hover {
  color: var(--red);
}

.hm-fine {
  margin-top: clamp(22px, 3vw, 34px);
  max-width: 54ch;
  font-size: 15px;
  line-height: 1.62;
  color: var(--grey);
}

.hm-inline {
  border-bottom: 1px solid var(--red);
  transition: color 0.22s var(--ease);
}

.hm-inline:hover {
  color: var(--red);
}

@media (max-width: 620px) {
  .hm-work-head {
    flex-direction: column;
    gap: 0;
  }
  .hm-all {
    border-top: 0;
    padding-top: 0;
    margin-top: -14px;
    margin-bottom: 22px;
  }
}

/* ===== work.css ===== */
/* /work: the full index. */

.wk-head {
  padding-bottom: clamp(38px, 6vw, 74px);
}

/*
  Mixed weight, the same device as the home arrival: light sets the phrase up
  and bold lands the noun. The em carries no italic and no colour change, so
  weight is the only variable, which is what keeps it reading as one system
  across / , /work and /practice rather than three separate treatments.
*/
.wk-head h1 {
  font-family: var(--slab);
  font-weight: 300;
  font-size: var(--h1);
  line-height: 0.94;
  letter-spacing: -0.038em;
}

.wk-head h1 em {
  font-style: normal;
  font-weight: 700;
}

.wk-lede {
  margin-top: clamp(20px, 3vw, 32px);
  max-width: 52ch;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--grey);
}

.wk-count {
  margin-top: clamp(22px, 3vw, 34px);
  border-top: 1px solid var(--red);
  padding-top: 12px;
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
}

.wk-index {
  padding-bottom: clamp(20px, 4vw, 50px);
}

/* ===== case.css ===== */
/* =========================================================
   Case study. One template, two densities.
   ========================================================= */

.cs-back {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: clamp(28px, 4.5vw, 56px);
  transition: color 0.22s var(--ease);
}

.cs-back:hover {
  color: var(--char);
}

/* ---------------- head ---------------- */

.cs-meta {
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
  border-top: 1px solid var(--red);
  padding-top: 12px;
  margin-bottom: clamp(18px, 2.6vw, 28px);
}

.cs-head h1 {
  font-family: var(--slab);
  font-weight: 700;
  font-size: var(--h1);
  line-height: 0.94;
  letter-spacing: -0.038em;
}

.cs-head h1 sup {
  font-size: 0.2em;
  color: var(--red);
  vertical-align: super;
  margin-left: 0.14em;
}

.cs-lede {
  margin-top: clamp(20px, 3vw, 34px);
  font-family: var(--slab);
  font-weight: 300;
  font-size: clamp(18px, 2.1vw, 28px);
  line-height: 1.34;
  letter-spacing: -0.018em;
  max-width: 40ch;
  color: var(--grey);
}

/*
  With no written body, the lede is carrying the page, so it gets set larger
  and given more room. This single rule is most of what separates the two
  densities.
*/
.cs.is-tight .cs-lede {
  font-size: clamp(21px, 3vw, 40px);
  line-height: 1.24;
  max-width: 26ch;
  color: var(--char);
}

/* ---------------- cover ---------------- */

.cs-cover {
  margin: clamp(34px, 5.5vw, 72px) 0 clamp(34px, 5vw, 64px);
}

.cs-cover img {
  width: 100%;
  aspect-ratio: 20 / 7;
  object-fit: cover;
}

.cs.is-tight .cs-cover img {
  aspect-ratio: 20 / 9;
}

/* ---------------- body ---------------- */

.cs-body {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(26px, 4vw, 54px);
  margin-bottom: clamp(40px, 6vw, 80px);
}

.cs-block {
  border-top: 1px solid rgba(51, 51, 51, 0.2);
  padding-top: 14px;
}

.cs-block-no {
  display: block;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--grey-soft);
  margin-bottom: 10px;
  font-variant-numeric: tabular-nums;
}

.cs-block h2 {
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(18px, 1.9vw, 24px);
  line-height: 1.14;
  letter-spacing: -0.02em;
  margin-bottom: 10px;
}

.cs-block p {
  font-size: 15px;
  line-height: 1.64;
  color: var(--grey);
}

/* ---------------- shots ---------------- */

/*
  FOUR COLUMNS, BUT COLLAPSING.

  REAL SHOTS KEEP THEIR OWN RATIO. Cropping is a decision made against the
  subject, and a blanket aspect-ratio here would silently overrule it, which is
  the one thing this layout must not do. Hence no aspect-ratio and no
  object-fit on the general case: the picture is the shape it was cut to, and
  `span` only ever changes how much room it is given, never its shape.

  The track count is pinned to four by the 25% minimum rather than left to the
  viewport, which is what makes `span` mean the same thing at every width. It
  used to be minmax(280px, …), where the count changed as the window changed
  and "two columns" meant half the hold at one size and all of it at another.

  auto-fit is still doing one specific job on top of that: COLLAPSING TRACKS
  NOTHING OCCUPIES. A run of two shots gets two tracks and fills the hold, and
  a lone manual cover gets one and is drawn full width. A plain repeat(4, 1fr)
  throws that away and strands a two-shot run at quarter width with half the
  row empty, which is a regression in every gallery that has no spans at all.

  Four down to two down to one, so a span always resolves to something whole.
*/
.cs-shots {
  display: grid;
  gap: clamp(14px, 2vw, 26px);
  grid-template-columns: repeat(auto-fit, minmax(calc(25% - 20px), 1fr));
  align-items: start;
  margin-bottom: clamp(40px, 6vw, 76px);
}

.cs-shots figure[data-span='2'] { grid-column: span 2; }
.cs-shots figure[data-span='3'] { grid-column: span 3; }
.cs-shots figure[data-span='4'] { grid-column: span 4; }

/*
  Two rows, for the one shape the single-row grid cannot make: a tall piece
  held beside a stack of shorter ones, which is how a poster and its details
  want to sit. The height cap comes off with it — 80vh exists so a lone
  portrait cannot own a whole screen, and a shot with work stacked alongside
  it is not alone.
*/
.cs-shots figure[data-rows='2'] { grid-row: span 2; }
.cs-shots figure[data-rows='2'] img { max-height: none; }

@media (max-width: 1100px) {
  .cs-shots { grid-template-columns: repeat(auto-fit, minmax(calc(50% - 14px), 1fr)); }
  .cs-shots figure[data-span='3'],
  .cs-shots figure[data-span='4'] { grid-column: span 2; }
}

@media (max-width: 640px) {
  .cs-shots { grid-template-columns: 1fr; }
  .cs-shots figure[data-span='2'],
  .cs-shots figure[data-span='3'],
  .cs-shots figure[data-span='4'] { grid-column: span 1; }
  /* One column has no room to hold anything beside it, so the pairing this
     was for does not exist and the height cap comes back. */
  .cs-shots figure[data-rows='2'] { grid-row: span 1; }
  .cs-shots figure[data-rows='2'] img { max-height: 80vh; }
}

/*
  RUNS. A project that ran a decade is several bodies of work, not one, and an
  undivided grid makes the reader work out which page belongs to which piece.
  A run is one piece: the report, the brochure, the lobby.

  The label is the quiet one already used for cs-facts dt rather than a third
  heading weight, because a run title is a caption for a group, not a rank in
  the writing. Untitled runs are the common case and are invisible — a project
  with no groups declared lays out exactly as it always has.

  Spacing moves from .cs-shots to .cs-run so consecutive runs breathe like the
  body sections above them; the plates branch keeps its own margin, having no
  run around it.
*/
.cs-run .cs-shots {
  margin-bottom: 0;
}

.cs-run + .cs-run {
  margin-top: clamp(34px, 5vw, 62px);
}

.cs-run:last-of-type {
  margin-bottom: clamp(40px, 6vw, 76px);
}

.cs-run-title {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  border-top: 1px solid rgba(51, 51, 51, 0.2);
  padding-top: 12px;
  margin-bottom: 16px;
}

/*
  MOTION. Sits in the same grid as the stills and obeys the same rule: the clip
  is the shape it was cut to, capped on the tall axis so it cannot own a screen.

  The chrome is present in the markup and removed by site.js only once it has
  decided to autoplay, so a reader without JS, or one who has asked for reduced
  motion, still gets something they can start. See the note in case.njk.
*/
.cs-motion {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 80vh;
  background: var(--paper);
}

/*
  Centred, and bounded on the tall axis rather than the wide one. A lone
  portrait shot in the full 1340px hold would otherwise stand about 1600px
  high and own a whole screen on its own. Capping height and letting width
  follow keeps one image from outranking the writing, at any ratio.
*/
.cs-shots figure {
  display: flex;
  justify-content: center;
}

.cs-shots img {
  display: block;
  width: auto;
  max-width: 100%;
  max-height: 80vh;
}

/*
  The no-imagery fallback. Plates are generated to order at four fixed ratios,
  and a run of them only reads as photography if it is held to one, so this is
  the one place a forced ratio is right. Never on the same page as real shots:
  the template picks one branch or the other.
*/
.cs-shots.is-plates img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  max-height: none;
}

/* ---------------- facts ---------------- */

.cs-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 20px 34px;
  border-top: 1px solid var(--red);
  padding-top: 15px;
}

.cs-facts dt {
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: 6px;
}

.cs-facts dd {
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--char);
}

.cs-prov {
  margin-top: clamp(26px, 4vw, 42px);
  font-size: 12.5px;
  line-height: 1.85;
  color: var(--grey-soft);
  max-width: 74ch;
}

/* ---------------- next ---------------- */

.cs-next {
  margin-top: clamp(44px, 7vw, 92px);
  border-top: 1px solid rgba(51, 51, 51, 0.2);
  padding-top: clamp(20px, 3vw, 30px);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 20px;
  flex-wrap: wrap;
}

.cs-next-lbl {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: 8px;
}

.cs-next-name {
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(23px, 4vw, 50px);
  line-height: 1;
  letter-spacing: -0.034em;
  transition: color 0.22s var(--ease);
}

.cs-next a:hover .cs-next-name {
  color: var(--red);
}

.cs-next-mail {
  font-size: 12.5px;
  color: var(--grey);
  border-bottom: 2px solid var(--red);
  padding-bottom: 2px;
  transition: color 0.22s var(--ease);
}

.cs-next-mail:hover {
  color: var(--red);
}

/* ===== practice.css ===== */
/* /practice: who, what, approach, values, capabilities. */

.pr-head {
  padding-bottom: clamp(44px, 7vw, 90px);
}

/*
  SLAB HERE IS DELIBERATE, AND IT DEPARTS FROM THE PRINTED SOURCE.

  Page 4 of the proposal sets "Agency services// Consultancy thinking" in the
  grotesque, not the slab. This headline was originally built to match, and it
  was changed on purpose, so please do not "restore fidelity" and change it
  back. The reason: the proposal is a sequence, where you meet the slab cover
  and then a grotesque section opener minutes later, so the face change reads
  as a device. Nobody experiences this page that way. They arrive from a search
  result having never seen the home page, and a lone grotesque headline reads
  as a mistake rather than as a section marker.

  What does translate from that spread is the tone split, grey to charcoal
  across the //, and that is kept below in .pr-head h1 em. The typeface was
  carrying nothing on its own.

  Mixed weight was added on top of that tone split, matching the home arrival
  and /work: light sets the phrase up, bold lands the payoff. So this headline
  now shifts on two axes at once, grey light to charcoal bold. Weight is the
  device the three pages share, so if the contrast ever reads as too much,
  drop the colour here rather than the weight.

  LEADING. This was 0.94, inherited from when the headline was solid 700. The
  y of "Agency" sits directly above the l and k of "Consultancy thinking", and
  at 0.94 they touched: light strokes made the collision obvious where the
  bold had hidden it. 1.08 is the home arrival's value, which already clears
  the same problem at the same --h1 size (the p of "shops" over the k of
  "keep"), so this is the tested number rather than a guessed one.
*/
.pr-head h1 {
  font-family: var(--slab);
  font-weight: 300;
  font-size: var(--h1);
  line-height: 1.08;
  letter-spacing: -0.038em;
  color: var(--grey);
}

.pr-head h1 em {
  font-style: normal;
  font-weight: 700;
  color: var(--char);
}

.pr-lede {
  margin-top: clamp(20px, 3vw, 32px);
  max-width: 48ch;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--grey);
}

/* ---------------- who / what ---------------- */

.pr-two {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(26px, 4vw, 62px);
  padding-bottom: clamp(48px, 8vw, 104px);
}

.pr-h {
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(21px, 2.4vw, 31px);
  line-height: 1.1;
  letter-spacing: -0.024em;
  color: var(--red);
  margin-bottom: 14px;
}

.pr-two p {
  font-size: 15.5px;
  line-height: 1.66;
  color: var(--grey);
  max-width: 50ch;
}

/* ---------------- approach ---------------- */

.pr-approach {
  background: #fff;
  padding: clamp(44px, 7vw, 96px) 0 clamp(48px, 8vw, 104px);
  margin-bottom: clamp(44px, 7vw, 96px);
}

.pr-section-title {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(28px, 5vw, 66px);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: var(--grey);
  margin-bottom: clamp(38px, 6vw, 82px);
}

.pr-section-title em {
  font-style: normal;
  color: var(--red);
}

.pr-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: clamp(26px, 4vw, 56px);
}

.pr-step .rule {
  margin-bottom: 10px;
}

.pr-step .numeral {
  display: block;
  margin-bottom: 12px;
}

.pr-step h3 {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 15px;
  margin-bottom: 12px;
}

.pr-step p {
  font-size: 13.5px;
  line-height: 1.66;
  color: var(--grey);
  margin-bottom: 12px;
}

/* ---------------- values ---------------- */

.pr-values {
  background: var(--char);
  color: var(--paper);
  padding: clamp(46px, 8vw, 108px) 0;
  margin-bottom: clamp(44px, 7vw, 96px);
}

.pr-values-lbl {
  font-family: var(--sans);
  font-weight: 700;
  font-size: clamp(16px, 1.9vw, 25px);
  margin-bottom: clamp(30px, 5vw, 62px);
}

.pr-values-lbl em {
  font-style: normal;
  color: var(--red);
}

.pr-values .sep {
  color: var(--paper);
  opacity: 0.5;
  margin: 0 2px;
}

/*
  One flowing line, and the layout mode is the whole point.

  This was repeat(auto-fit, minmax(150px, max-content)), which builds tracks of
  a uniform minimum and sizes words into them. "Humor." got the same 150px as
  "Compassion.", and the difference showed up as dead air between them, so the
  gaps looked random when it was the tracks that were regular. "Hard Graft."
  landed in a track narrower than its own text and broke in half, and seven
  values into six columns orphaned "Wonder." on a row of its own.

  Flex fixed the gaps but not the wrap: it treats each value as an atom and
  drops whole items to the next row, which leaves a ragged shelf.

  Inline is the answer. The line breaks between values the way a sentence
  breaks between words, filling each line to the edge. nowrap on the item
  keeps two-word values whole, because "Hard Graft" is one value and breaking
  it reads as two.

  SIZE. Stepped down from clamp(18px, 2.2vw, 30px) so all seven fit across at
  desktop width, where the wrap stops happening at all. It costs 5px at the
  top end and buys a single statement instead of an inventory.
*/
.pr-values-list {
  list-style: none;
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(16px, 1.8vw, 25px);
  line-height: 1.35;
  letter-spacing: -0.022em;
  color: var(--yellow);
}

.pr-values-list li {
  display: inline;
  white-space: nowrap;
}

/* ---------------- how we operate ---------------- */

.pr-how {
  padding-bottom: clamp(44px, 7vw, 92px);
}

.pr-how-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: clamp(24px, 3.6vw, 50px);
}

.pr-how-no {
  display: block;
  font-family: var(--slab);
  font-weight: 700;
  font-size: 28px;
  line-height: 1;
  color: var(--red);
  margin-bottom: 11px;
}

.pr-how-grid h3 {
  font-family: var(--slab);
  font-weight: 700;
  font-size: 19px;
  line-height: 1.14;
  letter-spacing: -0.018em;
  margin-bottom: 8px;
}

.pr-how-grid p {
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--grey);
}

/* ---------------- capabilities ---------------- */

.pr-caps {
  padding-bottom: clamp(44px, 7vw, 92px);
}

.pr-caps-second {
  margin-top: clamp(34px, 5vw, 60px);
}

.pr-list {
  font-size: clamp(14.5px, 1.5vw, 18px);
  line-height: 1.78;
  max-width: 80ch;
}

/* ---------------- close ---------------- */

/*
  No creature here, deliberately. This section used to open with the mark in
  red above the closing line, and it was the only page that did: the header
  lockup carries the creature and the footer has its own, so /practice was the
  one page stacking three in a viewport once you scrolled to the bottom. The
  mark works by being rare. This section now matches .hm-close exactly, which
  closes on the statement alone.
*/
.pr-close {
  padding-bottom: clamp(20px, 4vw, 50px);
}

.pr-say {
  font-family: var(--slab);
  font-weight: 300;
  font-size: clamp(20px, 2.9vw, 38px);
  line-height: 1.26;
  letter-spacing: -0.022em;
  max-width: 26ch;
  margin-bottom: clamp(26px, 4vw, 42px);
}

.pr-say em {
  font-style: normal;
  font-weight: 700;
}

.pr-cta {
  display: inline-block;
  font-family: var(--sans);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--red);
  padding: 13px 20px;
  transition: background 0.22s var(--ease);
}

.pr-cta:hover {
  background: var(--char);
}

/* ===== wonder.css ===== */
/* /wonder: statement, then a table that never goes stale. */

.wo-head {
  padding-bottom: clamp(30px, 5vw, 60px);
}

.wo-head h1 {
  font-family: var(--slab);
  font-weight: 700;
  font-size: var(--h1);
  line-height: 0.94;
  letter-spacing: -0.038em;
}

.wo-sub {
  margin-top: clamp(18px, 2.6vw, 28px);
  max-width: 46ch;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--grey);
}

.wo-stmt {
  padding-bottom: clamp(38px, 6vw, 76px);
}

.wo-stmt p {
  font-family: var(--slab);
  font-weight: 300;
  font-size: clamp(20px, 2.8vw, 36px);
  line-height: 1.28;
  letter-spacing: -0.022em;
  max-width: 28ch;
  border-top: 1px solid var(--red);
  padding-top: clamp(18px, 2.6vw, 28px);
}

/* ---------------- holding state ---------------- */

/*
  Shown instead of the statement and the table while
  WONDER.underConstruction is true. It sits in the same typographic slot the
  statement uses, a red-ruled label over light display slab, so an unfinished
  page still reads as part of the site rather than as a hole in it.
*/

.wo-wip {
  padding-bottom: clamp(30px, 5vw, 64px);
}

.wo-wip-line {
  font-family: var(--slab);
  font-weight: 300;
  font-size: clamp(26px, 3.8vw, 48px);
  line-height: 1.04;
  letter-spacing: -0.028em;
}

.wo-wip-note {
  margin-top: clamp(20px, 2.8vw, 32px);
  max-width: 52ch;
  font-size: clamp(15px, 1.4vw, 18px);
  line-height: 1.62;
  color: var(--grey);
}

/* ---------------- the table ---------------- */

.wo-index {
  padding-bottom: clamp(20px, 4vw, 50px);
}

.wo-colhead,
.wo-row {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr) minmax(0, 1.35fr);
  gap: 18px;
  align-items: baseline;
}

.wo-colhead {
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--red);
  padding-bottom: 9px;
  border-bottom: 1px solid var(--red);
}

.wo-table {
  list-style: none;
}

.wo-row {
  padding: 16px 0;
  border-bottom: 1px solid rgba(51, 51, 51, 0.16);
}

.wo-cat {
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey-soft);
}

.wo-item {
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(16px, 1.6vw, 21px);
  line-height: 1.2;
  letter-spacing: -0.018em;
}

.wo-link {
  border-bottom: 1px solid var(--red);
  transition: color 0.22s var(--ease);
}

.wo-link:hover {
  color: var(--red);
}

.wo-link i {
  font-style: normal;
  font-size: 0.7em;
  color: var(--red);
}

.wo-note {
  font-size: 14.5px;
  line-height: 1.58;
  color: var(--grey);
}

.wo-empty {
  font-size: 15px;
  color: var(--grey-soft);
  border-top: 1px solid var(--red);
  padding-top: 14px;
}

@media (max-width: 720px) {
  .wo-colhead {
    display: none;
  }
  .wo-row {
    grid-template-columns: 1fr;
    gap: 5px;
    padding: 15px 0;
  }
}

/* ===== contact.css ===== */
/* /contact: details on the left, Web3Forms on the right. */

.ct {
  padding-bottom: clamp(24px, 4vw, 56px);
}

.ct-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: clamp(30px, 5vw, 80px);
  align-items: start;
}

/* ---------------- left ---------------- */

.ct-left h1 {
  font-family: var(--slab);
  font-weight: 700;
  font-size: var(--h1);
  line-height: 0.94;
  letter-spacing: -0.038em;
}

.ct-left h1 em {
  font-style: normal;
  color: var(--red);
}

.ct-lede {
  margin-top: clamp(20px, 3vw, 30px);
  max-width: 42ch;
  font-size: clamp(15px, 1.4vw, 17.5px);
  line-height: 1.62;
  color: var(--grey);
}

.ct-details {
  margin-top: clamp(30px, 5vw, 56px);
  display: grid;
  gap: 20px;
  border-top: 1px solid var(--red);
  padding-top: 16px;
}

.ct-details dt {
  font-size: 10.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red);
  margin-bottom: 5px;
}

.ct-details dd {
  font-size: 15px;
  line-height: 1.6;
}

.ct-details address {
  font-style: normal;
}

.ct-details address span {
  display: block;
}

.ct-details a {
  border-bottom: 1px solid rgba(229, 50, 68, 0.5);
  transition: color 0.22s var(--ease), border-color 0.22s var(--ease);
}

.ct-details a:hover {
  color: var(--red);
  border-color: var(--red);
}

/* ---------------- form ---------------- */

.ct-form,
.ct-nokey {
  background: #fff;
  border: 1px solid rgba(51, 51, 51, 0.16);
  padding: clamp(20px, 3vw, 34px);
}

.ct-field {
  margin-bottom: 16px;
}

.ct-field label {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 7px;
}

.ct-field label i {
  font-style: normal;
  font-weight: 400;
  color: var(--grey-soft);
  letter-spacing: 0.1em;
}

.ct-field input,
.ct-field textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  color: var(--char);
  background: var(--paper);
  border: 1px solid rgba(51, 51, 51, 0.2);
  padding: 11px 12px;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}

.ct-field textarea {
  resize: vertical;
  min-height: 130px;
}

.ct-field input:focus,
.ct-field textarea:focus {
  outline: 0;
  border-color: var(--red);
  background: #fff;
}

/*
  :user-invalid, not :invalid. An empty required field is invalid from the
  moment it renders, so :invalid would paint every field as an error before
  the reader has typed a character. :user-invalid waits for interaction.
*/
.ct-field input:user-invalid,
.ct-field textarea:user-invalid {
  border-color: rgba(229, 50, 68, 0.75);
  background: rgba(229, 50, 68, 0.04);
}

/* honeypot: off-screen rather than display:none, which bots detect */
.ct-botcheck {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.ct-send {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--red);
  border: 0;
  padding: 14px 26px;
  cursor: pointer;
  transition: background 0.22s var(--ease);
}

.ct-send:hover:not(:disabled) {
  background: var(--char);
}

.ct-send:disabled {
  opacity: 0.6;
  cursor: default;
}

.ct-status {
  margin-top: 14px;
  font-size: 14px;
  line-height: 1.55;
  min-height: 1.2em;
}

.ct-status.is-ok {
  color: var(--char);
  border-left: 3px solid var(--red);
  padding-left: 11px;
}

.ct-status.is-error {
  color: var(--red);
}

/* ---------------- missing-key fallback ---------------- */

.ct-nokey p {
  font-size: 14.5px;
  line-height: 1.62;
  color: var(--grey);
  margin-bottom: 16px;
}

.ct-nokey code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: rgba(51, 51, 51, 0.07);
  padding: 1px 5px;
}

.ct-nokey-mail {
  font-family: var(--slab);
  font-weight: 700;
  font-size: clamp(17px, 1.9vw, 24px);
  letter-spacing: -0.024em;
  word-break: break-word;
  border-bottom: 2px solid var(--red);
  padding-bottom: 3px;
  transition: color 0.22s var(--ease);
}

.ct-nokey-mail:hover {
  color: var(--red);
}

@media (max-width: 860px) {
  .ct-grid {
    grid-template-columns: 1fr;
  }
}

/* ===== base.css ===== */
/* =========================================================
   Global base. Deliberately almost empty.

   Everything that looks like the brand lives in src/site/tokens.css scoped
   to .bbb, and the design-direction archive keeps its own copy under .xp.
   Nothing here may set colour, type or spacing, or the two would collide,
   which is exactly what happened when the previous global stylesheet
   declared the palette on :root.
   ========================================================= */

html {
  box-sizing: border-box;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: #f8f0e2;
  min-height: 100vh;
}

/*
  Skip smooth scrolling for people who asked not to have motion; otherwise
  in-page anchors are a long animated ride they did not ask for.
*/
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* Visible focus everywhere, since the site is largely links and a form. */
:focus-visible {
  outline: 2px solid #e53244;
  outline-offset: 2px;
}
