/* ---------------------------------------------------------------
   THE PORTFOLIO

   One stylesheet for Home, Contact and The Notebook. The look is the
   Modernist system: one red, hard 2px rules, no rounded corners
   anywhere, photographs in black and white until you hover them.

   Every colour and easing lives in :root. If the red ever changes,
   it changes here and nowhere else.
   --------------------------------------------------------------- */

:root {
  --ground: #f3f2f2;
  --ink: #201e1d;
  --accent: #ec3013;
  --accent-press: #dd2b0f;
  --body: #444141;
  --meta: #605d5d;
  --rule-soft: rgba(32, 30, 29, .18);
  --dot: rgba(32, 30, 29, .14);
  --white: #fff;

  --ease: cubic-bezier(.2, .7, .2, 1);
  --ease-fall: cubic-bezier(.45, 0, .75, .9);

  --max: 1560px;
  --lane: 84px;          /* the spine's lane down the left edge */
  --gutter: 32px;
  --hero-lane: 30px;     /* the hero sits over the lane on purpose */
  --spine-left: 8px;
  --spine-w: 64px;
}

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

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: "Archivo", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: var(--ink); text-decoration: none; }
a:hover { color: var(--accent); }

button, input, textarea, select { font-family: inherit; }

:focus { outline: none; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.band :focus-visible, .job-card :focus-visible { outline-color: var(--white); }

::selection { background: rgba(236, 48, 19, .3); }

img { display: block; max-width: 100%; }

.page {
  position: relative;
  background-color: var(--ground);
  background-image: radial-gradient(var(--dot) 1px, transparent 1.5px);
  background-size: 26px 26px;
  background-attachment: fixed;
  min-height: 100vh;
}

.wrap {
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 var(--gutter) 0 var(--lane);
}
.wrap--hero {
  padding-left: var(--hero-lane);
  position: relative;
  z-index: 31;
}
.anchor { scroll-margin-top: 74px; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--ground);
  padding: 12px 16px; font-size: 12px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
}
.skip:focus { left: 8px; top: 8px; color: var(--ground); }

/* ---- keyframes ------------------------------------------------ */

@keyframes bg-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes bg-marquee-back { from { transform: translateX(-50%); } to { transform: translateX(0); } }
@keyframes bg-rise { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
@keyframes bg-float-a { 0%, 100% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, -14px, 0); } }
@keyframes bg-float-b { 0%, 100% { transform: translate3d(0, 0, 0); } 50% { transform: translate3d(0, 12px, 0); } }
@keyframes bg-ov-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes bg-card-pop { 0% { opacity: 0; transform: translateY(34px) scale(.9); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes bg-card-fall { 0% { opacity: 1; transform: translateY(0) rotate(0deg); } 100% { opacity: .35; transform: translateY(118vh) rotate(8deg); } }
@keyframes bg-pol-pop { from { opacity: 0; transform: translateY(22px) scale(.7); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes bg-pol-fall { 0% { opacity: 1; transform: translateY(0) rotate(0deg); } 100% { opacity: .4; transform: translateY(116vh) rotate(-13deg); } }
@keyframes bg-fade-out { to { opacity: 0; } }

/* ---- reveal on scroll -----------------------------------------
   Only hidden when the script is running to bring it back. Without
   javascript the page simply shows everything.                   */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .8s var(--ease), transform .8s var(--ease);
}
.js [data-reveal].is-in { opacity: 1; transform: none; }

/* ---- the spine ------------------------------------------------ */

.spine {
  position: fixed;
  left: var(--spine-left);
  top: 0;
  width: var(--spine-w);
  height: 100vh;
  z-index: 30;
  pointer-events: none;
}
.spine-line { width: 100%; height: 100%; display: block; overflow: visible; }
.spine-guide { transition: opacity .45s ease; }
.spine-tail {
  position: absolute;
  left: calc(var(--spine-left) * -1);
  top: 0;
  width: 100vw;
  height: 100%;
  display: block;
  overflow: visible;
  opacity: 0;
  transition: opacity .25s ease;
}
.spine-arrow {
  position: absolute;
  left: 0; top: 0;
  width: 22px; height: 22px;
  margin: -11px 0 0 -11px;
  will-change: transform;
}
.spine-arrow svg {
  width: 100%; height: 100%; display: block;
  filter: drop-shadow(0 2px 4px rgba(32, 30, 29, .25));
}
.spine-arrow path { fill: var(--accent); }
.spine.is-white .spine-arrow svg { filter: drop-shadow(0 2px 6px rgba(32, 30, 29, .35)); }
.spine.is-white .spine-arrow path { fill: var(--white); }
.spine.is-white .spine-guide { opacity: 0; }

/* ---- header --------------------------------------------------- */

.hdr {
  position: sticky; top: 0; z-index: 40;
  background: var(--ground);
  border-bottom: 2px solid var(--ink);
}
.hdr-in {
  max-width: var(--max);
  margin: 0 auto;
  padding: 14px var(--gutter) 14px var(--lane);
  display: flex; align-items: center; justify-content: space-between;
  gap: 32px;
}
.brand { display: flex; align-items: center; gap: 11px; }
/* The BMG spine G. Its negative margin keeps it from adding to the line
   it sits on, so the header is no taller than it was with the old 11px
   square: the mark hangs into the header's own padding instead. */
.brand-mark { display: block; flex: none; width: 28px; height: 28px; margin: -6px 0; }
.brand b { font-weight: 800; font-size: 15px; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }

.nav {
  display: flex; align-items: center; gap: 28px;
  font-size: 12px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
}
.nav-l { padding: 4px 0; border-bottom: 2px solid transparent; }
a.nav-l:hover { border-bottom-color: var(--accent); }
.nav-l.is-here { border-bottom-color: var(--accent); color: var(--accent); }
.nav-cta {
  background: var(--accent); color: var(--white);
  padding: 10px 16px; font-weight: 700; letter-spacing: .12em;
  white-space: nowrap;
}
a.nav-cta:hover { background: var(--accent-press); color: var(--white); }
.nav-cta.is-here { background: var(--ink); color: var(--ground); }

/* ---- shared pieces -------------------------------------------- */

.eyebrow {
  display: flex; gap: 20px; align-items: center;
  font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--meta);
}
.eyebrow .hot { color: var(--accent); }
.eyebrow .line { flex: 1; height: 2px; background: var(--ink); opacity: .25; }

.rule { height: 2px; background: var(--ink); }
.rule--soft { opacity: .25; }
.rule--faint { opacity: .2; }

.display {
  margin: 0;
  font-weight: 900;
  font-size: clamp(52px, 7.8vw, 150px);
  line-height: .84;
  letter-spacing: -.045em;
  text-transform: uppercase;
}
.display > span { display: block; }
.hot { color: var(--accent); }

.num { font-size: 11px; font-weight: 800; color: var(--accent); letter-spacing: .1em; }
.kicker { font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--accent); }

.btns { display: flex; flex-wrap: wrap; gap: 12px; padding-top: 4px; }
.btn {
  display: inline-block;
  padding: 15px 22px;
  font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  border: 0; border-radius: 0; cursor: pointer;
}
.btn--ink { background: var(--ink); color: var(--ground); }
.btn--ink:hover { background: var(--accent); color: var(--white); }
.btn--line { border: 2px solid var(--ink); padding: 13px 22px; background: transparent; color: var(--ink); }
.btn--line:hover { background: var(--ink); color: var(--ground); }
.btn--white { background: var(--white); color: var(--accent); padding: 17px 26px; font-size: 13px; font-weight: 800; }
.btn--white:hover { background: var(--ink); color: var(--white); }
.btn--wline { border: 2px solid var(--white); color: var(--white); padding: 15px 26px; font-size: 13px; font-weight: 800; background: transparent; }
.btn--wline:hover { background: var(--white); color: var(--accent); }

/* a section's heading row */
.sh {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px;
  padding: 48px 0 22px;
  border-bottom: 2px solid var(--ink);
}
.sh h2 {
  margin: 0; font-weight: 800;
  font-size: clamp(30px, 3.6vw, 58px);
  line-height: .95; letter-spacing: -.03em; text-transform: uppercase;
}
.sh .hint {
  font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--meta); padding-bottom: 8px;
}
.sh--small h2 { font-size: clamp(22px, 2vw, 30px); line-height: normal; letter-spacing: -.02em; }
/*  on the feed the board heading follows the tally's own rule, so
    the 48px a heading normally keeps above itself is empty air  */
#posts .sh--small { padding-top: 22px; }

/* ---- image slots ----------------------------------------------
   Every photograph is a slot with a stable id. Until a file is
   named for it in content.js it draws itself as an empty frame
   that says what belongs there.                                  */

.slot {
  display: block; position: relative;
  width: 100%; height: 100%;
  background: rgba(127, 127, 127, .08);
  overflow: hidden;
}
.slot img { width: 100%; height: 100%; object-fit: cover; }
.slot-ph {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; padding: 14px; text-align: center;
  font: 500 13px/1.3 system-ui, -apple-system, sans-serif;
  letter-spacing: .01em; color: var(--meta);
}
.slot-ph::before {
  content: ""; position: absolute; inset: 6px;
  border: 1.5px dashed currentColor; opacity: .45; pointer-events: none;
}
.slot-ph svg { width: 22px; height: 22px; opacity: .8; }
.slot-ph small { font-size: 10px; letter-spacing: .08em; text-transform: uppercase; opacity: .7; }

/* inside a frame whose height comes from its aspect ratio */
.tile-img, .pol-img, .post-art { position: relative; }
.tile-img > .slot, .pol-img > .slot, .post-art > .slot { position: absolute; inset: 0; }
/* a tile's photograph drifts a few pixels against the page, so it is
   cut a little tall and the drift never uncovers the tile behind it */
.tile-img > .slot { inset: -16px 0; height: auto; }

/* ---- hero ----------------------------------------------------- */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  border-bottom: 2px solid var(--ink);
  position: relative;
}
.hero-l {
  padding: 60px 40px 46px 0;
  border-right: 2px solid var(--ink);
  display: flex; flex-direction: column; gap: 28px;
  animation: bg-rise .8s ease both;
}
.hero-copy {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 36px;
}
.lede { margin: 0; font-size: 19px; line-height: 1.45; text-wrap: pretty; max-width: 34ch; }
.sub { margin: 0; font-size: 14px; line-height: 1.6; color: var(--meta); text-wrap: pretty; max-width: 38ch; }

.list { margin-top: auto; padding-top: 30px; display: flex; flex-direction: column; gap: 16px; }
.list-h {
  display: flex; align-items: baseline; gap: 18px;
  font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--meta);
}
.list-h .k { color: var(--ink); }
.list-h .line { flex: 1; height: 2px; background: var(--ink); }
/* two and two, for the same reason the row below is four across */
.list-g { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 36px; }
.list-r {
  display: flex; gap: 12px; align-items: baseline;
  padding: 12px 0; border-bottom: 1px solid var(--rule-soft);
}
.list-r b { font-size: 15px; font-weight: 700; }
.list-r .q { font-size: 12px; color: var(--meta); margin-left: auto; }

.hero-r { position: relative; min-height: 700px; }
.hero-clip { position: absolute; left: 0; top: 0; right: calc(var(--gutter) * -1); bottom: 0; overflow: hidden; }
.hero-img {
  position: absolute; left: 0; top: -70px; right: 0; bottom: -80px;
  filter: grayscale(1); transition: filter .6s ease;
}
.hero-img:hover { filter: grayscale(0); }

.float { position: absolute; }
.float--a { left: -40px; top: 368px; width: 190px; height: 240px; }
.float--b { right: -20px; bottom: 60px; width: 160px; height: 200px; }
.float-f {
  position: absolute; inset: 0;
  border: 2px solid var(--ink); background: var(--ground);
  box-shadow: 0 18px 40px rgba(32, 30, 29, .16);
  animation: bg-float-a 7s ease-in-out infinite;
}
.float--b .float-f { animation: bg-float-b 9s ease-in-out infinite; }
.float-f > div { position: absolute; inset: 6px; filter: grayscale(1); }

.badge {
  position: absolute; left: 20px; bottom: 0;
  background: var(--accent); color: var(--white);
  padding: 10px 16px;
  font-size: 11px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  pointer-events: none;
}

/* contact's hero is the same frame with a shorter photograph */
.hero--contact .display { font-size: clamp(48px, 7.2vw, 138px); }
.hero--contact .hero-r { min-height: 600px; }
.hero--contact .hero-clip { right: 0; }
.hero--contact .hero-img { top: 40px; }
.hero--contact .float--a { top: 300px; z-index: 2; }

/* A hero with no photographs, as on Contact: the copy takes the whole
   width, with no column rule down the middle. */
.hero--solo { grid-template-columns: minmax(0, 1fr); }
.hero--solo .hero-l { border-right: 0; padding-right: 0; }
/* the headline was sized for half the width; it has all of it now */
.hero--solo .display { font-size: clamp(48px, 11.5vw, 210px); }

/* ---- marquee -------------------------------------------------- */

.mq { background: var(--accent); color: var(--white); overflow: hidden; border-bottom: 2px solid var(--ink); }
.mq-t { display: flex; width: max-content; animation: bg-marquee 34s linear infinite; }
.mq-g {
  display: flex; gap: 56px; padding: 14px 28px;
  font-size: 15px; font-weight: 800; letter-spacing: .24em; text-transform: uppercase;
  white-space: nowrap;
}

/* ---- tiles: selected work, and currently ---------------------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-left: 2px solid var(--ink);
  border-top: 2px solid var(--ink);
}
.tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Selected Work runs the width of the screen, lane to gutter, while its
   heading keeps to the page column. Below --max the column is already
   the screen, so nothing moves there; above it the grid grows into the
   centring margin on both sides instead of leaving it empty. */
#work { max-width: none; }
#work .sh { max-width: calc(var(--max) - var(--lane) - var(--gutter)); margin-inline: auto; }

/* a button centres its contents top to bottom unless told otherwise,
   and the tiles in a row are not all the same height */
.tile {
  display: flex; flex-direction: column; justify-content: flex-start; align-items: stretch;
  position: relative; z-index: 1;
  width: 100%; margin: 0; padding: 0;
  font: inherit; color: inherit; text-align: left;
  background: var(--ground);
  border: 0;
  border-right: 2px solid var(--ink);
  border-bottom: 2px solid var(--ink);
  border-radius: 0;
  cursor: pointer;
  transition: transform .55s var(--ease), background-color .35s ease, box-shadow .55s ease;
  will-change: transform;
}
.js .tile[data-reveal] {
  transition: transform .55s var(--ease), background-color .35s ease, box-shadow .55s ease, opacity .8s var(--ease);
}
.tile-clip { display: block; overflow: hidden; }
.tile-img { display: block; aspect-ratio: 4 / 5; filter: grayscale(1); transition: filter .45s ease; }
.tiles--3 .tile-img { aspect-ratio: 16 / 15; }
.tile-cap {
  display: flex; gap: 14px;
  padding: 18px 20px 22px;
  border-top: 2px solid var(--ink);
  transition: border-color .35s ease;
}
.tile-cap .num { padding-top: 3px; transition: color .35s ease; }
.tile-tx { display: flex; flex-direction: column; gap: 5px; }
.tile-t { font-weight: 800; font-size: 19px; letter-spacing: -.01em; transition: color .35s ease; }
.tile-m {
  font-size: 11px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase;
  color: var(--meta); transition: color .35s ease;
}

.tile:hover, .tile:focus-visible {
  z-index: 3;
  background: var(--accent);
  box-shadow: 0 30px 60px rgba(32, 30, 29, .22);
}
.tile:hover .tile-img, .tile:focus-visible .tile-img { filter: grayscale(0); }
.tile:hover .tile-cap, .tile:focus-visible .tile-cap { border-top-color: var(--white); }
.tile:hover .tile-t, .tile:focus-visible .tile-t,
.tile:hover .tile-m, .tile:focus-visible .tile-m,
.tile:hover .tile-cap .num, .tile:focus-visible .tile-cap .num { color: var(--white); }
.tile:focus-visible { outline-color: var(--ink); }

/* a job tile fills with red when it is opened */
.job-card {
  position: absolute; inset: 0;
  background: var(--accent); color: var(--white);
  display: flex; flex-direction: column; gap: 13px;
  padding: 26px 26px 28px;
  overflow-y: auto;
  opacity: 0; pointer-events: none; transform: scale(.97);
  transition: opacity .34s ease, transform .34s var(--ease);
}
.tile.is-open .job-card { opacity: 1; pointer-events: auto; transform: none; }
.job-x {
  position: absolute; top: 10px; right: 14px;
  width: 28px; height: 28px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 21px; font-weight: 600; line-height: 1;
  color: rgba(255, 255, 255, .8);
  background: none; border: 0; cursor: pointer;
}
.job-x:hover { color: var(--white); }
.job-k { font-size: 11px; font-weight: 800; letter-spacing: .2em; text-transform: uppercase; color: rgba(255, 255, 255, .75); }
.job-card h3 {
  margin: 0; font-weight: 900; font-size: clamp(21px, 1.9vw, 27px);
  line-height: 1; letter-spacing: -.02em; text-transform: uppercase; text-wrap: pretty;
}
.job-rule { height: 2px; background: rgba(255, 255, 255, .55); flex: none; }
.job-card p { margin: 0; font-size: 14px; line-height: 1.58; color: var(--white); text-wrap: pretty; }
.job-card p + p { color: rgba(255, 255, 255, .9); }

/* ---- the work overlay ----------------------------------------- */

.ov {
  position: fixed; inset: 0; z-index: 90;
  overflow: hidden;
  animation: bg-ov-in .4s ease both;
}
/* reduced motion: the lanes stand still and the overlay scrolls instead */
.ov.is-still { overflow-y: auto; overflow-x: hidden; }
.ov-scrim {
  position: fixed; inset: 0;
  background: rgba(243, 242, 242, .5);
  -webkit-backdrop-filter: blur(18px) saturate(.9);
  backdrop-filter: blur(18px) saturate(.9);
}
.ov-close {
  position: fixed; top: 20px; right: 24px; z-index: 4;
  background: var(--ink); color: var(--ground);
  padding: 13px 18px; border: 0; border-radius: 0;
  font-size: 11px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  cursor: pointer;
}
.ov-close:hover { background: var(--accent); }
/* The polaroid field sits under the card, always: its own stacking
   layer at 2, the card at 3, so a raised polaroid never covers the copy. */
.ov-field { position: fixed; inset: 0; pointer-events: none; z-index: 2; overflow: hidden; }
.ov.is-still .ov-field { position: absolute; left: 0; right: 0; top: 0; bottom: auto; overflow: visible; }

.pol {
  position: absolute; left: 0; top: 0; margin: 0;
  width: clamp(170px, min(22vw, 38vh), 360px);
  pointer-events: auto;
  will-change: transform;
}
.pol-pop { animation: bg-pol-pop .58s var(--ease) both; }
.pol:hover, .pol:focus-within { z-index: 50 !important; }
.pol-in { position: relative; background: var(--white); padding: 13px 13px 0; box-shadow: 0 22px 44px rgba(32, 30, 29, .28); }

/* While the pictures are still being chosen the caption is the polaroid's
   name instead. Plain and monospaced, so nobody mistakes it for finished
   copy. Turn labels off in content.js and this rule goes quiet with it. */
.pol-cap.is-label {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 15px; font-weight: 700; letter-spacing: .12em;
}
.pol-img { aspect-ratio: 1 / 1; }

/* Copywriting's polaroids are links to the writing itself: a cover, where
   it ran, the title, and the line under it. */
a.pol-in { display: block; color: inherit; text-decoration: none; cursor: pointer; }
.pol-img.is-wide { aspect-ratio: 16 / 10; }
.pol-text { display: flex; flex-direction: column; gap: 5px; padding: 11px 4px 15px; }
.pol-src {
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--meta); transition: color .2s ease;
}
.pol-title {
  font-family: "Caveat", cursive; color: var(--accent);
  font-size: clamp(22px, min(2.2vw, 3.8vh), 34px); line-height: 1;
}
.pol-sub {
  font-size: 12.5px; line-height: 1.45; color: var(--body);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
a.pol-in:hover .pol-title, a.pol-in:focus-visible .pol-title {
  text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px;
}
a.pol-in:hover .pol-src, a.pol-in:focus-visible .pol-src { color: var(--accent); }
/* while labels are on, a link card keeps its title and wears its name here */
.pol-tag {
  position: absolute; left: 0; top: 0; z-index: 2;
  padding: 3px 7px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 12px; font-weight: 700; letter-spacing: .08em;
  background: var(--accent); color: var(--white);
}
.pol-cap {
  font-family: "Caveat", cursive; color: var(--accent);
  font-size: clamp(20px, min(2.1vw, 3.6vh), 32px);
  line-height: 1.05;
  padding: 9px 5px 14px;
  min-height: 24px;
}

.ov-cardwrap {
  position: fixed; left: 50%; top: 50%;
  width: min(92vw, 440px);
  transform: translate(-50%, -50%);
  z-index: 3;
}
.ov-pop { position: relative; animation: bg-card-pop .52s var(--ease) both; }
.ov-card {
  background: var(--ground); border: 2px solid var(--ink);
  padding: 34px 30px 32px;
  display: flex; flex-direction: column; gap: 15px;
  position: relative;
}
.ov-x {
  position: absolute; top: 6px; right: 9px;
  width: 30px; height: 30px; padding: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 21px; font-weight: 600; line-height: 1;
  color: var(--meta); background: none; border: 0; cursor: pointer;
}
.ov-x:hover { color: var(--accent); }
.ov-k { font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--meta); }
.ov-card h3 {
  margin: 0; font-weight: 900; font-size: clamp(25px, 2.8vw, 38px);
  line-height: .95; letter-spacing: -.03em; text-transform: uppercase;
  color: var(--accent); text-wrap: pretty;
}
.ov-card p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--body); text-wrap: pretty; }

.ov.is-out .ov-pop { animation: bg-card-fall .66s var(--ease-fall) both; }
.ov.is-out .pol-pop { animation: bg-pol-fall .62s var(--ease-fall) both; }
.ov.is-out .ov-scrim { animation: bg-fade-out .5s ease .16s both; }
.ov.is-out .ov-close { opacity: 0; transition: opacity .25s ease; }

/* ---- about ---------------------------------------------------- */

.about {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr);
  border-bottom: 2px solid var(--ink);
}
.about-ph { position: relative; min-height: 560px; border-right: 2px solid var(--ink); overflow: hidden; }
.about-img {
  position: absolute; left: 0; right: 0; top: -50px; bottom: -90px;
  filter: grayscale(1); transition: filter .6s ease;
}
.about-img:hover { filter: grayscale(0); }
.about-tx { padding: 56px 0 56px 44px; display: flex; flex-direction: column; gap: 26px; }
.about-lead {
  margin: 0; font-weight: 700; font-size: clamp(22px, 2.3vw, 34px);
  line-height: 1.22; letter-spacing: -.02em; text-wrap: pretty; max-width: 26ch;
}
.about-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 28px; align-items: start; }
.about-cols p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--body); text-wrap: pretty; }

.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border-top: 2px solid var(--ink); margin-top: 6px;
}
.stat { padding: 20px 20px 0; border-left: 2px solid var(--ink); display: flex; flex-direction: column; gap: 4px; }
.stat:first-child { padding-left: 0; border-left: 0; }
.stat-n { display: flex; align-items: baseline; font-weight: 800; font-size: 32px; letter-spacing: -.02em; }
.stat-l { font-size: 11px; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--meta); }

/* ---- what i do ------------------------------------------------ */

/* Four across, always. Left to fit themselves the columns went three
   and one as the window narrowed, which left Communications alone on
   a row of its own. So the count is fixed, and it is the padding and
   the headings that give as the window closes in. Only on a phone
   does it fold, and then evenly: two and two, then a single column. */
.svc { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); border-bottom: 2px solid var(--ink); }
.svc > div {
  min-width: 0;
  padding: 32px clamp(12px, 1.9vw, 24px) 40px;
  border-left: 2px solid var(--ink);
  display: flex; flex-direction: column; gap: 12px;
}
.svc > div:first-child { padding-left: 0; border-left: 0; }
.svc > div:last-child { padding-right: 0; }
.svc .num { letter-spacing: .16em; }
.svc h3 { margin: 0; font-weight: 800; font-size: clamp(15px, 1.75vw, 21px); letter-spacing: -.01em; }
.svc p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--meta); text-wrap: pretty; }

.wrap--currently { padding-bottom: 60px; }

/* ---- the red bands -------------------------------------------- */

.band { background: var(--accent); color: var(--white); border-bottom: 2px solid var(--ink); overflow: hidden; }
.band-in {
  max-width: var(--max); margin: 0 auto;
  padding: 82px var(--gutter) 90px var(--lane);
  display: flex; flex-direction: column; gap: 32px;
  position: relative;
}
.band .over { font-size: 11px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase; opacity: .85; }
.band h2 {
  margin: 0; font-weight: 900;
  font-size: clamp(40px, 6.6vw, 128px);
  line-height: .86; letter-spacing: -.045em; text-transform: uppercase;
  max-width: 20ch;
}
.band h2 > span { display: block; }
.band .btns { gap: 14px; align-items: center; padding-top: 0; }
.band .spine-target { position: relative; z-index: 31; }

.band--contact .band-in { padding-top: 74px; padding-bottom: 82px; gap: 30px; }
.band--contact h2 { font-size: clamp(36px, 5.6vw, 104px); max-width: 22ch; }
.band--contact p { margin: 0; font-size: 17px; line-height: 1.5; max-width: 46ch; text-wrap: pretty; opacity: .92; }

.band--blog .band-in {
  padding-top: 70px; padding-bottom: 78px;
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 48px; align-items: end;
}
.band--blog .band-l { display: flex; flex-direction: column; gap: 24px; }
.band--blog h2 { font-size: clamp(36px, 5.4vw, 100px); max-width: 18ch; }
.sub-form { display: flex; flex-direction: column; gap: 14px; }
.sub-row { display: flex; flex-wrap: wrap; gap: 12px; }
.sub-row input {
  flex: 1; min-width: 220px;
  border: 2px solid var(--white); background: transparent; color: var(--white);
  padding: 15px 16px; font-size: 15px; border-radius: 0;
}
.sub-row input::placeholder { color: rgba(255, 255, 255, .7); }
.sub-row .btn { padding: 16px 24px; font-size: 13px; font-weight: 800; }
.sub-note { font-size: 12px; opacity: .85; }

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

.ftr {
  max-width: var(--max); margin: 0 auto;
  padding: 34px var(--gutter) 52px var(--lane);
  display: flex; flex-wrap: wrap; gap: 24px;
  justify-content: space-between; align-items: flex-end;
}
.ftr-l { display: flex; flex-direction: column; gap: 8px; }
.ftr-l b { font-weight: 800; font-size: 14px; letter-spacing: .14em; text-transform: uppercase; }
.ftr-l span { font-size: 12px; color: var(--meta); }
.ftr nav { display: flex; gap: 22px; font-size: 12px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; }

/* ---- contact -------------------------------------------------- */

.brief {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  border-bottom: 2px solid var(--ink);
}
.form {
  padding: 44px 44px 56px 0;
  border-right: 2px solid var(--ink);
  display: flex; flex-direction: column; gap: 26px;
}
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 22px; }
.form-row--3 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.field { display: flex; flex-direction: column; gap: 8px; }
.field > span, .field-l {
  font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.field input, .field select, .field textarea {
  border: 2px solid var(--ink); background: var(--ground);
  padding: 13px 14px; font-size: 15px; color: var(--ink);
  border-radius: 0;
}
.field input[type="date"] { padding: 12px 14px; }
.field textarea { line-height: 1.5; resize: vertical; }
.need { display: flex; flex-direction: column; gap: 10px; }
.chips { display: flex; flex-wrap: wrap; gap: 10px; }
.chip {
  border: 2px solid var(--ink); background: transparent; color: var(--ink);
  padding: 11px 15px;
  font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  cursor: pointer; border-radius: 0;
  transition: background-color .25s ease, color .25s ease;
}
.chip[aria-pressed="true"] { background: var(--ink); color: var(--ground); }
.send-row { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.send {
  position: relative; z-index: 31;
  background: var(--accent); color: var(--white); border: none;
  padding: 17px 26px;
  font-size: 13px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  cursor: pointer; border-radius: 0;
}
.send:hover { background: var(--ink); }
.send-note { font-size: 12px; color: var(--meta); }
.sent {
  background: var(--ink); color: var(--ground);
  padding: 20px 22px;
  display: flex; flex-direction: column; gap: 6px;
}
.sent[hidden] { display: none; }
.sent b { font-weight: 800; font-size: 15px; letter-spacing: .1em; text-transform: uppercase; }
.sent span { font-size: 14px; color: #d7d3d3; }
.sent a { color: var(--white); border-bottom: 1px solid currentColor; }

/* "worked with" runs in from the far left edge of the window and is
   cut off square at the column rule */
.clients {
  margin-top: auto; padding-top: 30px;
  margin-right: -44px; margin-left: -100vw; margin-bottom: -22px;
  overflow: hidden;
  display: flex; flex-direction: column; gap: 10px;
}
.clients-l {
  padding-left: 100vw;
  font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--meta);
}
.clients-t { display: flex; width: max-content; animation: bg-marquee-back 150s linear infinite; }
.clients-g {
  display: flex; align-items: baseline; gap: 34px; padding-right: 34px;
  white-space: nowrap;
  font-weight: 900; font-size: clamp(44px, 5vw, 88px);
  line-height: 1; letter-spacing: -.035em; text-transform: uppercase;
}
.clients-g .o { color: transparent; -webkit-text-stroke: 2px var(--ink); }
.clients-g .d { color: var(--accent); }

.aside { padding: 44px 0 56px 44px; display: flex; flex-direction: column; gap: 30px; }
.direct { display: flex; flex-direction: column; gap: 14px; }
.direct-i { display: flex; flex-direction: column; gap: 2px; }
.direct-i a { font-weight: 800; font-size: 19px; letter-spacing: -.01em; overflow-wrap: anywhere; }
.direct-i span { font-size: 12px; color: var(--meta); }
.based { border-top: 2px solid var(--ink); padding-top: 22px; display: flex; flex-direction: column; gap: 12px; }
.based .k { font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--meta); }
.based b { font-weight: 800; font-size: 19px; }
.based p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--body); text-wrap: pretty; }
.radius { display: flex; flex-direction: column; gap: 10px; }
.radius-h {
  display: flex; align-items: baseline; gap: 14px;
  font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--meta);
}
.radius-h .k { color: var(--ink); }
.radius-h .line { flex: 1; height: 2px; background: var(--ink); opacity: .25; }
.radius p { margin: 0; font-size: 12px; line-height: 1.6; color: var(--meta); text-wrap: pretty; }

/* 340 of map inside a 2px rule. Leaflet's own controls are measured
   the old way, so its box is left to size itself as it expects. */
.map-box { position: relative; height: 344px; border: 2px solid var(--ink); isolation: isolate; background: #e8e6e6; }
.map-box .leaflet-container, .map-box .leaflet-container * { box-sizing: content-box; }
#map { position: absolute; inset: 0; background: var(--ground); }
.map-box .leaflet-tile-pane { filter: grayscale(1) contrast(1.04) brightness(1.03); }
.map-box .leaflet-container { background: #e8e6e6; font-family: "Archivo", system-ui, sans-serif; }
.map-box .leaflet-control-attribution { font-size: 9px; background: rgba(243, 242, 242, .85); color: var(--meta); }
.map-box .leaflet-control-attribution a { color: var(--meta); }
.map-box .leaflet-bar { border: 2px solid var(--ink); border-radius: 0; box-shadow: none; }
.map-box .leaflet-bar a { border-radius: 0 !important; color: var(--ink); border-bottom: 2px solid var(--ink); }
.map-box .leaflet-bar a:last-child { border-bottom: 0; }
.map-box .leaflet-bar a:hover { background: var(--accent); color: var(--white); }
.map-box .leaflet-popup-content-wrapper, .map-box .leaflet-popup-tip { border-radius: 0; }
.map-pin { width: 14px; height: 14px; background: var(--accent); border: 2px solid var(--ink); box-sizing: border-box; }
.map-legend {
  position: absolute; left: 10px; bottom: 10px; z-index: 500;
  background: var(--ground); border: 2px solid var(--ink);
  padding: 10px 12px;
  display: flex; flex-direction: column; gap: 7px;
}
.map-legend b { font-size: 9px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase; color: var(--meta); }
.map-legend .row { display: flex; align-items: center; gap: 8px; font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }
.map-legend .row em { font-style: normal; font-weight: 600; letter-spacing: .06em; color: var(--meta); }
.map-legend .key { width: 16px; height: 0; border-top: 2px solid var(--accent); }
.map-legend .k2 { border-top-style: dashed; }
.map-legend .k3 { border-top-style: dotted; }

/* ---- the notebook --------------------------------------------- */

.mast {
  padding: 56px 0 26px;
  border-bottom: 2px solid var(--ink);
  display: flex; flex-direction: column; gap: 24px;
  animation: bg-rise .8s ease both;
}
.mast-g { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 48px; align-items: end; }
.mast .display { font-size: clamp(52px, 8vw, 148px); }
.mast p { margin: 0 0 12px; font-size: 17px; line-height: 1.5; text-wrap: pretty; }

.feature {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  border-bottom: 2px solid var(--ink);
}
.feature-ph { position: relative; min-height: 460px; overflow: hidden; border-right: 2px solid var(--ink); }
.feature-img {
  position: absolute; left: 0; right: 0; top: -40px; bottom: -70px;
  filter: grayscale(1); transition: filter .6s ease;
}
.feature-img:hover { filter: grayscale(0); }
.flag {
  position: absolute; left: 0; top: 0;
  background: var(--accent); color: var(--white);
  padding: 9px 15px;
  font-size: 11px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase;
}
.js .feature.is-loading .feature-tx > * { visibility: hidden; }
.feature-tx { padding: 44px 0 48px 44px; display: flex; flex-direction: column; gap: 20px; justify-content: center; }
.meta-row {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.feature h2 {
  margin: 0; font-weight: 900; font-size: clamp(30px, 3.4vw, 54px);
  line-height: .98; letter-spacing: -.03em; text-wrap: pretty;
}
.feature p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--body); text-wrap: pretty; max-width: 46ch; }
.read {
  font-size: 12px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  border-bottom: 2px solid var(--accent); align-self: flex-start; padding-bottom: 4px;
}

.stack { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); border-bottom: 2px solid var(--ink); }
.stack-l { padding: 42px 44px 46px 0; border-right: 2px solid var(--ink); display: flex; flex-direction: column; gap: 20px; }
.stack-l .eyebrow { gap: 18px; }
.stack h2 {
  margin: 0; font-weight: 900; font-size: clamp(28px, 3.2vw, 50px);
  line-height: .96; letter-spacing: -.03em; text-transform: uppercase; text-wrap: pretty;
}
.stack-l p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--body); text-wrap: pretty; max-width: 48ch; }
.stack-r { padding: 42px 0 46px 44px; display: flex; flex-direction: column; gap: 14px; justify-content: center; }
.stack-r .k { font-size: 11px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--meta); }
.embed { border: 2px solid var(--ink); background: var(--white); }
.embed iframe { display: block; border: 0; background: var(--white); width: 100%; }
.stack-r .note { font-size: 12px; color: var(--meta); text-wrap: pretty; }

.posts-h {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  padding: 44px 0 20px; border-bottom: 2px solid var(--ink);
}
.posts-h h2 {
  margin: 0; font-weight: 800; font-size: clamp(26px, 3vw, 46px);
  line-height: .95; letter-spacing: -.03em; text-transform: uppercase;
}
.status {
  display: flex; align-items: center; gap: 9px;
  font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--meta);
}
.status i { width: 8px; height: 8px; background: var(--meta); display: block; }
.status[data-state="live"] i { background: var(--accent); }

.posts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); border-left: 2px solid var(--ink); }
.post {
  display: grid; grid-template-columns: minmax(0, 140px) minmax(0, 1fr); gap: 24px;
  padding: 28px 28px 30px;
  border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink);
  background: var(--ground);
}
.post-art { aspect-ratio: 4 / 5; filter: grayscale(1); transition: filter .45s ease; background: rgba(32, 30, 29, .08); }
.post-art:hover { filter: grayscale(0); }
.post-art img { width: 100%; height: 100%; object-fit: cover; }
.post-tx { display: flex; flex-direction: column; gap: 10px; }
.post .meta-row { gap: 10px; font-size: 10px; }
.post h3 { margin: 0; font-weight: 800; font-size: 21px; line-height: 1.15; letter-spacing: -.02em; text-wrap: pretty; }
.post p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--meta); text-wrap: pretty; }
.posts-msg {
  grid-column: 1 / -1;
  padding: 36px 28px 40px;
  border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink);
  font-size: 15px; line-height: 1.6; color: var(--body);
}
.posts-msg a { border-bottom: 2px solid var(--accent); font-weight: 700; }

/* ---- smaller screens ------------------------------------------
   The design is desktop first. Below here the grids fold to one
   column and the spine keeps its lane, only narrower.            */


/* ---- the gallery ----------------------------------------------
   A set of photographs, whole, rather than the eight cards' worth of
   highlights on the front page. Columns and not a grid on purpose:
   the frames are a mix of upright and wide and a masonry flow lets
   each keep its own shape instead of being cropped to a cell.

   These stay in colour. Everywhere else on the site a photograph is
   grey until you hover it, which is a device for keeping the work
   from shouting over the layout. A gallery IS the layout.         */

.set-h {
  padding: 46px 0 28px;
  display: flex; flex-direction: column; gap: 22px;
}
.set-g { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px; align-items: end; }
.set-g h2 {
  margin: 0;
  font-size: clamp(30px, 3.6vw, 56px); line-height: .98;
  letter-spacing: -.03em; font-weight: 900; text-transform: uppercase;
}
.set-g p { margin: 0 0 6px; font-size: 16px; line-height: 1.55; color: var(--body); text-wrap: pretty; max-width: 54ch; }

.gal { columns: 3; column-gap: 20px; padding-bottom: 76px; }
.gal-f { break-inside: avoid; margin: 0 0 20px; }

.gal-b {
  display: block; width: 100%; padding: 0; margin: 0;
  border: 0; background: var(--ink);
  position: relative; overflow: hidden; cursor: zoom-in;
  -webkit-tap-highlight-color: transparent;
}
.gal-b img { width: 100%; height: auto; transition: transform .8s var(--ease), opacity .4s ease; }
.gal-b::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  border: 0 solid var(--accent);
  transition: border-width .25s var(--ease);
}
.gal-b:hover img, .gal-b:focus-visible img { transform: scale(1.035); opacity: .92; }
.gal-b:hover::after, .gal-b:focus-visible::after { border-width: 4px; }

.gal-cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 40px 14px 12px;
  font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--white); text-align: left;
  background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .74));
  opacity: 0; transform: translateY(10px);
  transition: opacity .3s ease, transform .35s var(--ease);
}
.gal-b:hover .gal-cap, .gal-b:focus-visible .gal-cap { opacity: 1; transform: translateY(0); }

/* ---- the viewer ------------------------------------------------
   Above everything, including the sticky header and the spine. The
   page behind it is held still by .lb-open on the body.           */

body.lb-open { overflow: hidden; }

.lb {
  position: fixed; inset: 0; z-index: 600;
  display: none; flex-direction: column;
  background: rgba(20, 18, 17, .985);
}
.lb.is-on { display: flex; animation: bg-ov-in .22s ease both; }

.lb-stage {
  flex: 1 1 auto; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 58px 78px 8px;
  cursor: zoom-out;
}
.lb-hold {
  max-width: 100%; max-height: 100%;
  display: flex; align-items: center; justify-content: center;
  cursor: default;
}
.lb-hold img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto; object-fit: contain;
  background: rgba(255, 255, 255, .05);
  transition: opacity .25s ease;
}
.lb.is-wait .lb-hold img { opacity: .25; }

.lb-bar {
  flex: none;
  display: flex; align-items: baseline; justify-content: space-between; gap: 24px;
  padding: 14px 26px 22px;
  color: var(--white);
}
.lb-cap { font-size: 12px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.lb-n {
  flex: none;
  font-size: 11px; font-weight: 700; letter-spacing: .2em;
  color: rgba(255, 255, 255, .5);
  font-variant-numeric: tabular-nums;
}

.lb-x, .lb-arw {
  position: absolute; z-index: 2;
  background: transparent; border: 0; color: var(--white);
  cursor: pointer; padding: 0;
  transition: color .2s ease, opacity .2s ease, background .2s ease;
}
.lb-x {
  top: 12px; right: 16px;
  width: 42px; height: 42px;
  font-size: 30px; line-height: 1;
}
.lb-x:hover { color: var(--accent); }

.lb-arw {
  top: 50%; transform: translateY(-50%);
  width: 56px; height: 72px;
  display: flex; align-items: center; justify-content: center;
}
.lb-arw svg { width: 26px; height: 26px; }
.lb-prev { left: 8px; }
.lb-next { right: 8px; }
.lb-arw:hover { background: var(--accent); }
.lb-arw[disabled] { opacity: .2; cursor: default; background: transparent; }

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


/* ---- the shelf of shoots ---------------------------------------
   One card stands for a whole shoot: the cover, who and where, and
   the one line that says what the day was. Clicking it opens the set
   at its own address, so the second shoot does not push the first one
   off the bottom of a page that grows for ever.

   It is one column while there is one of them and two from there on,
   which is what auto-fit does without being told how many there are. */

/*  A list and not a grid. A shoot is a wide thing - the cover beside
    what the day was, the way the notebook's feature card reads - and
    the next one goes under this one rather than beside it. Two narrow
    columns of these would make each cover too small to be worth
    putting up.  */
.projs {
  display: grid; grid-template-columns: minmax(0, 1fr);
  gap: 26px;
  padding: 10px 0 80px;
}

.proj {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  border: 2px solid var(--ink);
  background: var(--white);
  color: var(--ink);
  transition: transform .55s var(--ease), background-color .35s ease, box-shadow .55s ease;
  will-change: transform;
}
/*  The lean toward the pointer is written by the script, which also
    writes a transform on the way in. Saying both here keeps the
    entrance from cancelling the hover.  */
.js .proj[data-reveal] {
  transition: transform .55s var(--ease), background-color .35s ease,
    box-shadow .55s ease, opacity .8s var(--ease);
}

/*  The whole card fills and lifts, the way a tile on the front page
    does. Everything written on it goes white, including the red: on a
    red card the accent has nothing left to be.  */
.proj:hover, .proj:focus-visible {
  background: var(--accent);
  color: var(--white);
  box-shadow: 0 30px 60px rgba(32, 30, 29, .22);
}
.proj:focus-visible { outline-color: var(--ink); }
.proj:hover .proj-ph, .proj:focus-visible .proj-ph { border-right-color: var(--white); }
.proj:hover .proj-n, .proj:focus-visible .proj-n { background: var(--white); color: var(--accent); }
.proj:hover .proj-s, .proj:focus-visible .proj-s,
.proj:hover .proj-go, .proj:focus-visible .proj-go,
.proj:hover .proj-go b, .proj:focus-visible .proj-go b,
.proj:hover .eyebrow, .proj:focus-visible .eyebrow,
.proj:hover .eyebrow .hot, .proj:focus-visible .eyebrow .hot { color: var(--white); }
.proj:hover .eyebrow .line, .proj:focus-visible .eyebrow .line {
  background: var(--white); opacity: .55;
}

.proj-ph {
  position: relative; display: block; overflow: hidden;
  border-right: 2px solid var(--ink);
  transition: border-color .35s ease;
  aspect-ratio: 3 / 2; background: var(--ink);
}
.proj-ph img {
  width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(1);
  transition: filter .45s ease;
}
.proj:hover .proj-ph img, .proj:focus-visible .proj-ph img { filter: grayscale(0); }

.proj-n {
  position: absolute; left: 0; top: 0;
  background: var(--accent); color: var(--white);
  transition: background-color .35s ease, color .35s ease;
  font-size: 12px; font-weight: 900; letter-spacing: .14em;
  padding: 8px 12px;
}

.proj-tx { display: flex; flex-direction: column; justify-content: center;
  gap: 16px; padding: 30px 34px; }
.proj-t {
  font-size: clamp(22px, 2.4vw, 38px); line-height: 1;
  letter-spacing: -.025em; font-weight: 900; text-transform: uppercase;
  text-wrap: balance;
}
.proj-s { font-size: 16px; line-height: 1.55; color: var(--body); text-wrap: pretty;
  max-width: 52ch; transition: color .35s ease; }
.proj-go {
  /*  centred with the rest of the block rather than pinned to the
      bottom: one sentence of blurb next to a half-page cover leaves a
      hole you can park a car in otherwise  */
  padding-top: 4px;
  display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  font-size: 12px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--accent);
  transition: color .35s ease;
}
.proj-go::after { content: "\2192"; transition: transform .3s var(--ease); }
.proj:hover .proj-go::after, .proj:focus-visible .proj-go::after { transform: translateX(5px); }
.proj-go b { font-weight: 600; letter-spacing: .1em; color: var(--meta); }

/* ---- one set's own page ---------------------------------------- */

.crumb {
  margin: 0; padding: 26px 0 0;
  font-size: 11px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--meta);
}
.crumb a { color: var(--meta); }
.crumb a:hover { color: var(--accent); }
.crumb span { padding: 0 8px; color: var(--rule-soft); }

.mast--set { padding-top: 26px; }
/*  A shoot's name is a sentence, not a word: it needs to sit smaller
    than THE GALLERY does or it runs off the side of a phone.  */
.mast .display--set { font-size: clamp(32px, 4.6vw, 76px); max-width: 16ch; }

/*  The feed's masthead carries a paragraph, not a line. A two-word
    heading does not need the wider column, so the text gets it, and
    the two sit on the same top edge instead of the text hanging off
    the heading's baseline as a tall strip.  */
/*  the same two columns and gap as the tally below, so the paragraph's
    left edge and the first cell's rule fall on one line  */
.mast--feed .mast-g { grid-template-columns: minmax(0, 1fr) minmax(0, 1.75fr); gap: 32px; align-items: start; }
.mast--feed .mast-g p { margin-bottom: 0; padding-top: .35em; }
/*  no rule under the feed's mast: the PERSONAL METRICS eyebrow is
    the rule, the label sitting in it the way SOCIAL AGGREGATES sits
    in the grey one above  */
.mast--feed { border-bottom: 0; }
.eyebrow--rule .line { opacity: 1; }
.eyebrow--rule + .tally { padding-top: 30px; }


/* ---- the photographs arriving ----------------------------------
   Not the shared data-reveal: that staggers in threes, which is right
   for three columns of text and wrong for twenty photographs - they
   land in clumps and the grid looks like it simply appeared. This one
   is handed a delay per picture by gallery.js, so they come in one
   after another down the page.

   Each arrives grey and warms up afterwards. The filter is on its own
   clock - slower than the fade, and starting after it - so a frame
   lands as a black and white photograph and the colour comes into it
   a beat later, which is roughly what a print does in a tray.

   --rise-d is the picture's place in the queue, written on the figure
   by gallery.js. Everything that is staggered reads it from here and
   adds its own head start, so the script sets one number and knows
   none of these timings.                                          */

.js .gal-f[data-rise] {
  --rise-d: 0ms;
  opacity: 0;
  transform: translateY(32px) scale(.985);
  filter: grayscale(1);
  transition:
    opacity 1.15s var(--ease) var(--rise-d),
    transform 1.15s var(--ease) var(--rise-d),
    filter 1.6s ease calc(var(--rise-d) + .5s);
}
.js .gal-f[data-rise].is-up {
  opacity: 1;
  transform: none;
  filter: grayscale(0);
}

/* ---- the line round the picture --------------------------------
   One rect, its own length called 100 so the dash can be written in
   percentages whatever shape the frame is, drawn on while the colour
   is coming up and left there afterwards as the border.

   The viewBox is the photograph's own proportions, so the stretch to
   fit is even and the line moves at one speed the whole way round.
   non-scaling-stroke keeps it 2px at any size, and the outer half of
   it is clipped by the button's overflow, which puts the line exactly
   on the edge of the picture instead of a hair inside it.

   Without javascript there is no dash and no wait: the frame is just
   there, like the photograph it is round.                         */

.gal-line {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  overflow: visible;
}
.gal-line rect {
  fill: none;
  stroke: var(--accent);
  stroke-width: 4;              /* half of it is clipped: 2px shows */
  vector-effect: non-scaling-stroke;
}
.js .gal-f[data-rise] .gal-line rect {
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
  transition: stroke-dashoffset 1.3s var(--ease) calc(var(--rise-d) + .35s);
}
.js .gal-f[data-rise].is-up .gal-line rect { stroke-dashoffset: 0; }

/* ---- the box ---------------------------------------------------
   Between the shelf and a set the screen goes white and a box sits
   there glowing with a ring going round it, for about as long as it
   takes to think "oh, here we go". It is a second and a half of
   theatre and it is meant to be.

   It is also doing something: the moment it appears the set page and
   its first photographs start downloading, so the wait is not spent
   on nothing.                                                     */

#opening {
  position: fixed; inset: 0; z-index: 900;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 30px;
  background: var(--white);
  opacity: 0;
  animation: bg-open-in .28s ease forwards;
}
@keyframes bg-open-in { to { opacity: 1; } }

.open-mark { position: relative; width: 176px; height: 176px; }

/*  the ring: a faint circle to go round, and the arc that goes.
    The circumference at r=72 is 452, so 132 of dash is a bit under a
    third of the way round.  */
.open-track {
  position: absolute; inset: 0;
}
.open-track circle {
  fill: none; stroke: var(--accent); stroke-width: 4; opacity: .16;
}
.open-ring {
  position: absolute; inset: 0;
  animation: bg-open-spin 1.1s linear infinite;
}
.open-ring circle {
  fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: butt;
  stroke-dasharray: 132 320;
}
@keyframes bg-open-spin { to { transform: rotate(360deg); } }

/*  the box: drawn in the one red, breathing  */
.open-box {
  position: absolute; left: 50%; top: 50%;
  width: 84px; height: 84px; margin: -42px 0 0 -42px;
  color: var(--accent);
  filter: drop-shadow(0 0 10px rgba(236, 48, 19, .55));
  animation: bg-open-glow 1.5s ease-in-out infinite;
}
.open-box path, .open-box rect, .open-box line {
  fill: none; stroke: currentColor; stroke-width: 2.4;
  stroke-linecap: square; stroke-linejoin: miter;
}
@keyframes bg-open-glow {
  0%, 100% { transform: scale(1); filter: drop-shadow(0 0 8px rgba(236, 48, 19, .45)); }
  50%      { transform: scale(1.06); filter: drop-shadow(0 0 22px rgba(236, 48, 19, .8)); }
}

.open-say {
  font-size: 11px; font-weight: 800; letter-spacing: .26em; text-transform: uppercase;
  color: var(--meta); text-align: center; padding: 0 20px;
}
.open-say b { display: block; color: var(--ink); margin-top: 7px; letter-spacing: .16em; }


/* ---- the captions, parked --------------------------------------
   Blaine is rewriting these. They are hidden rather than removed:
   the words are still in the markup and in data-cap, and deleting
   this block is all it takes to have them back.

   .gal-cap goes display:none, which takes the dark gradient at the
   foot of each picture with it - that scrim is the caption's own
   background and there is nothing left for it to sit behind.

   .lb-cap goes visibility:hidden instead, because the viewer's bar
   is a space-between row: drop the caption out of the layout and the
   counter slides over to where the caption used to be.            */

.gal-cap { display: none; }
.lb-cap { visibility: hidden; }


/* ---- the feed ---------------------------------------------------
   Copywriting shown in the shape it ran in. The board is the same
   column masonry as the gallery; a pin is the familiar post - who,
   the thing, the three numbers - drawn in this site's hand: a 2px
   rule, hard corners, the one red. The numbers are reports, not
   buttons, and are styled so a hand does not expect them to press. */

.tally {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.75fr);
  gap: 32px; align-items: end;
  padding: 36px 0 34px;
  border-bottom: 2px solid var(--ink);
}
.tally-big { display: flex; flex-direction: column; gap: 8px; align-self: start; }   /* level with the followers, not the split */
.tally-n {
  font-size: clamp(56px, 8.4vw, 150px); line-height: .9;
  font-weight: 900; letter-spacing: -.04em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.tally-l { font-size: 12px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--meta); }
/*  The right-hand side is five across on one line - who follows
    Blaine, likes, comments, shares, who follows the brands - beside
    the one big number. Three across on a tablet, two on a phone.  */
.tally-r {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 26px 0; align-self: center;     /*  level with the middle of the big number's block  */
}
.tally-r > div {
  display: flex; flex-direction: column; gap: 6px;
  padding: 0 12px 6px 16px; border-left: 2px solid var(--ink);
}
.tally-r b {
  font-size: clamp(22px, 2.4vw, 34px); line-height: 1; font-weight: 900; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.tally-r span {
  font-size: 11px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--meta);
}

.board { columns: 3; column-gap: 22px; padding: 26px 0 76px; }

.pin {
  break-inside: avoid; margin: 0 0 22px;
  background: var(--white); border: 2px solid var(--ink);
  display: flex; flex-direction: column;
}
.pin-h {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 14px; border-bottom: 2px solid var(--ink);
}
.pin-av {
  flex: none; width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: var(--white);
  font-size: 14px; font-weight: 900;
}
.pin-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pin-who b { font-size: 13px; font-weight: 800; letter-spacing: .02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pin-who span { font-size: 11px; color: var(--meta); letter-spacing: .06em; }
.pin-sample {
  margin-left: auto; flex: none;
  font-size: 9px; font-weight: 800; letter-spacing: .18em; text-transform: uppercase;
  color: var(--accent); border: 2px solid var(--accent); padding: 3px 6px;
}

.pin-media { display: block; background: var(--ink); border-bottom: 2px solid var(--ink); }
.pin-media img { width: 100%; height: auto; display: block; }

.pin-cap { margin: 0; padding: 14px 16px 4px; font-size: 14px; line-height: 1.55; color: var(--body);
  text-wrap: pretty; white-space: pre-line; }

/*  a text post IS the copy, so it is set like something to read and
    not like a caption under something else  */
.pin-copy {
  margin: 0; padding: 22px 20px 10px;
  font-size: 17px; line-height: 1.45; font-weight: 500; letter-spacing: -.005em;
  color: var(--ink); text-wrap: pretty; white-space: pre-line;
}
.pin-title {
  margin: 0; padding: 20px 20px 0;
  font-size: 19px; line-height: 1.1; font-weight: 900; letter-spacing: -.02em;
  text-transform: uppercase; color: var(--accent); text-wrap: balance;
}
.pin-title + .pin-copy { padding-top: 12px; }
.pin-title + .pin-copy::before { display: none; }
.pin--text .pin-copy::before { content: ""; display: block; width: 28px; height: 2px; background: var(--accent); margin-bottom: 14px; }

.pin-f {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 12px 16px 14px;
}
.pin-stat {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 800; letter-spacing: .04em;
  color: var(--ink); font-variant-numeric: tabular-nums;
  cursor: default;
}
.pin-stat svg { width: 18px; height: 18px; fill: none; stroke: var(--ink); stroke-width: 2; stroke-linecap: square; stroke-linejoin: miter; }
.pin-stat:first-child svg { stroke: var(--accent); }
.pin-link {
  margin-left: auto;
  font-size: 10px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--meta);
}
.pin-link:hover { color: var(--accent); }

/*  the way from the card to the board  */
.ov-cta { align-self: flex-start; margin-top: 4px; }

/*  The rain goes between the page's dots and its content. A stacking
    context on the page is what lets a child sit under the content
    but over the page's own background - without it, z-index -1 is
    under the background too, and nothing shows.  */
.page--rain, .page--trail { isolation: isolate; }
.rain, .trail { position: fixed; inset: 0; width: 100%; height: 100%; z-index: -1; pointer-events: none; }

/* ---- the pulse --------------------------------------------------
   An orange wash crossing the dot grid, the way a wave runs over a
   keyboard's lights. It is the same grid drawn again in the red,
   laid over the grey one dot for dot, and shown only through a soft
   band that travels across the screen - so each dot lights as the
   band reaches it and goes grey again as it passes. The band falls
   from the top in about three seconds and comes round every nine.

   No script. The page's own grid is attached to the viewport, so a
   fixed layer with the same size and no offset lands on it exactly.
   The page is a stacking context so the layer can sit under the
   content but over the page's own background; the cards cover it,
   the margins show it.                                           */

.page--pulse { isolation: isolate; }
.page--pulse::before {
  content: "";
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image: radial-gradient(rgba(236, 48, 19, .42) 1.15px, transparent 1.75px);
  background-size: 26px 26px;
  -webkit-mask-image: linear-gradient(180deg, transparent 42%, #000 50%, transparent 58%);
          mask-image: linear-gradient(180deg, transparent 42%, #000 50%, transparent 58%);
  -webkit-mask-size: 100% 250%;
          mask-size: 100% 250%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: bg-pulse 9s linear infinite;
}
/*  the band sits at the mask's middle; sliding the mask from its
    bottom edge to its top carries the band down the screen, and
    the long hold at the end is the pause before the next one  */
@keyframes bg-pulse {
  0%   { -webkit-mask-position: 0 100%; mask-position: 0 100%; }
  34%  { -webkit-mask-position: 0 0%;   mask-position: 0 0%; }
  100% { -webkit-mask-position: 0 0%;   mask-position: 0 0%; }
}

@media (max-width: 1100px) {
  .board { columns: 2; }
  .gal { columns: 2; }
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiles--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .nav { gap: 20px; }
}

@media (max-width: 900px) {
  .tally { grid-template-columns: minmax(0, 1fr); gap: 22px; }
  .mast--feed .mast-g { grid-template-columns: minmax(0, 1fr); }
  .tally-r { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px 0; }
  .projs { gap: 20px; }
  .proj { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; }
  .proj-ph { border-right: 0; border-bottom: 2px solid var(--ink); }
  .proj:hover, .proj:focus-visible { box-shadow: 0 18px 36px rgba(32, 30, 29, .2); }
  .proj:hover .proj-ph, .proj:focus-visible .proj-ph {
    border-right-color: var(--ink); border-bottom-color: var(--white);
  }
  .set-g { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .lb-stage { padding: 54px 20px 6px; }
  .lb-arw { width: 44px; height: 60px; }
  .lb-prev { left: 0; }
  .lb-next { right: 0; }
  .nav .nav-x { display: none; }      /* instagram is in the footer too */
  .hero { grid-template-columns: minmax(0, 1fr); }
  .hero-l { padding: 44px 0 40px; border-right: 0; border-bottom: 2px solid var(--ink); }
  .hero-r, .hero--contact .hero-r { min-height: 520px; }
  .float--a, .hero--contact .float--a { left: 18px; top: auto; bottom: 120px; width: 150px; height: 190px; }
  .float--b { right: 0; bottom: 40px; width: 130px; height: 164px; }

  .about { grid-template-columns: minmax(0, 1fr); }
  .about-ph { min-height: 420px; border-right: 0; border-bottom: 2px solid var(--ink); }
  .about-tx { padding: 40px 0 44px; }

  .tiles--3 { grid-template-columns: minmax(0, 1fr); }
  .tiles--3 .tile-img { aspect-ratio: 16 / 10; }

  .brief { grid-template-columns: minmax(0, 1fr); }
  .form { padding: 36px 0 48px; border-right: 0; border-bottom: 2px solid var(--ink); }
  .clients { margin-right: 0; }
  .aside { padding: 36px 0 48px; }

  .mast-g { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .feature { grid-template-columns: minmax(0, 1fr); }
  .feature-ph { min-height: 320px; border-right: 0; border-bottom: 2px solid var(--ink); }
  .feature-tx { padding: 32px 0 38px; }
  .stack { grid-template-columns: minmax(0, 1fr); }
  .stack-l { padding: 36px 0 38px; border-right: 0; border-bottom: 2px solid var(--ink); }
  .stack-r { padding: 32px 0 40px; }
  .posts { grid-template-columns: minmax(0, 1fr); }
  .band--blog .band-in { grid-template-columns: minmax(0, 1fr); gap: 32px; }

  .sh { flex-direction: column; align-items: flex-start; gap: 10px; }
  .sh .hint { padding-bottom: 0; }
}

@media (max-width: 760px) {
  /*  body's overflow-x: hidden is not enough on a phone. Anything that
      pokes past the right edge widens the layout viewport instead of
      being cut off, and the browser shrinks the whole page to fit it.
      clip rather than hidden, so this never becomes a scroll container
      and the sticky header goes on working.  */
  html { overflow-x: clip; }

  :root {
    --lane: 18px;
    --gutter: 18px;
    --hero-lane: 18px;
    --spine-left: 0px;
    --spine-w: 44px;
  }

  /*  No lane. The spine runs behind the page instead of beside it,
      so the content can be centred in the screen and simply pass
      over the line. See the note in the scratchpad, or: a fixed
      element paints above unpositioned content whatever its z-index,
      so the spine going down is only half of it - the sections have
      to come up too.  */
  .spine { z-index: 0; }
  .wrap,
  .band,
  .ftr { position: relative; z-index: 1; }
  .hdr-in { flex-wrap: wrap; gap: 10px 16px; padding-top: 12px; padding-bottom: 10px; }
  .nav { width: 100%; gap: 14px; justify-content: space-between; font-size: 11px; }
  /*  A thumb needs more than one line of 11px type to land on. The
      padding grows what can be tapped; the negative margin hands the
      room back, so the header is no taller for it. The underline on
      the current page moves from the border to the text, or it would
      sit 14px adrift of the word it belongs to.  */
  .nav-l { padding: 14px 0; margin: -10px 0; border-bottom: 0; }
  .nav-l.is-here {
    text-decoration: underline; text-decoration-thickness: 2px;
    text-underline-offset: 6px; text-decoration-color: var(--accent);
  }
  .nav-cta { padding: 13px 12px; margin: -4px 0; letter-spacing: .1em; }
  .ftr nav { flex-wrap: wrap; gap: 10px 18px; }
  .ftr nav a { padding: 13px 0; margin: -13px 0; }
  .job-x { width: 40px; height: 40px; top: 4px; right: 8px; }

  /*  The smallest type on the site, lifted a point where a phone is
      the likeliest place to read it.  */
  .post .meta-row { font-size: 11px; }
  .map-legend b { font-size: 10px; }
  .map-legend .row { font-size: 11px; }
  .brand-mark { width: 24px; height: 24px; margin: -4px 0; }
  .anchor { scroll-margin-top: 104px; }

  .hero-l { gap: 22px; }
  .hero-copy { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .eyebrow { flex-direction: column; align-items: flex-start; gap: 6px; }
  .eyebrow--rule { flex-direction: row; align-items: center; gap: 16px; }
  .eyebrow .line { display: none; }
  .mq-g { font-size: 13px; gap: 36px; }

  .band-in, .band--contact .band-in, .band--blog .band-in { padding-top: 56px; padding-bottom: 64px; }
  .post { grid-template-columns: minmax(0, 96px) minmax(0, 1fr); gap: 16px; padding: 22px 18px 24px; }
  .post h3 { font-size: 18px; }
  /*  The card gives the photographs more of the screen. Tighter type and
      padding rather than a narrower box: a narrower column only makes
      the same words taller.  */
  .ov-card { padding: 22px 18px 20px; gap: 11px; }
  .ov-card h3 { font-size: 22px; }
  .ov-card p { font-size: 14px; line-height: 1.5; }
  .ov-close { top: 12px; right: 12px; }
}

@media (max-width: 700px) {
  .board { columns: 1; column-gap: 0; padding-bottom: 54px; }
  .pin { margin-bottom: 16px; }
  .tally { padding: 26px 0 24px; }
  .tally-r { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 0; }
  .open-mark { width: 140px; height: 140px; }
  .open-box { width: 66px; height: 66px; margin: -33px 0 0 -33px; }
  .projs { gap: 18px; padding-bottom: 54px; }
  .proj-tx { padding: 18px 16px 22px; gap: 12px; }
  .proj-s { font-size: 15px; }
  .gal { columns: 1; column-gap: 0; }
  .gal-f { margin-bottom: 14px; }
  .gal-cap { opacity: 1; transform: none; }
  .lb-bar { flex-direction: column; align-items: flex-start; gap: 6px; padding: 10px 18px 18px; }
  .lb-cap { font-size: 11px; }
  .svc { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svc > div { padding: 28px 20px 32px; }
  .svc > div:nth-child(odd) { padding-left: 0; border-left: 0; }
  .svc > div:nth-child(even) { padding-right: 0; }
  .svc > div:nth-child(n + 3) { border-top: 2px solid var(--ink); }
  .svc h3 { font-size: 19px; }
}

@media (max-width: 520px) {
  .pol-src { font-size: 9px; letter-spacing: .1em; }
  .pol-sub { font-size: 11.5px; }
  .list-g { grid-template-columns: minmax(0, 1fr); }
  .display, .hero--contact .display { font-size: min(52px, 13vw); }
  .mast .display { font-size: min(52px, 12.2vw); }
  /*  Two across, as on a tablet. Currently keeps one: its cards hold
      paragraphs. The captions tighten to fit a half-width tile.  */
  .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .tiles--3 { grid-template-columns: minmax(0, 1fr); }
  .tile-cap { gap: 10px; padding: 12px 12px 14px; }
  .tile-t { font-size: 15px; }
  .tile-m { letter-spacing: .1em; }
  .svc { grid-template-columns: minmax(0, 1fr); }
  .svc > div, .svc > div:nth-child(even) { padding: 24px 0 28px; border-left: 0; }
  .svc > div + div { border-top: 2px solid var(--ink); }
  .stats { grid-template-columns: minmax(0, 1fr); }
  .stat, .stat:first-child { padding: 16px 0; border-left: 0; border-bottom: 1px solid var(--rule-soft); }
  .list-r .q { display: none; }
}

@media (max-width: 360px) {
  .nav-cta { white-space: normal; max-width: 118px; line-height: 1.2; }
}

/* ---- reduced motion -------------------------------------------
   No parallax, nothing hidden waiting to be revealed, nothing that
   moves on its own. The spine stays: it only moves when you do.  */

@media (prefers-reduced-motion: reduce) {
  .js .gal-f[data-rise] { opacity: 1; transform: none; filter: none; transition: none; }
  .js .gal-f[data-rise] .gal-line rect { stroke-dashoffset: 0; transition: none; }
  .open-ring, .open-box, #opening { animation: none; }
  .page--pulse::before { display: none; }
  .open-ring circle { stroke-dasharray: none; opacity: .4; }
  #opening { opacity: 1; }
  .proj, .proj-ph img, .proj-go::after { transition: none; }
  .proj:hover, .proj:focus-visible { transform: none; }
  .gal-b img { transition: none; }
  .gal-b:hover img, .gal-b:focus-visible img { transform: none; }
  .lb.is-on { animation: none; }
  html { scroll-behavior: auto; }
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .ov-pop, .pol-pop { animation-duration: .01s; }
  .mq-t, .clients-t, .float-f { animation: none; }
  .hero-l, .mast { animation: none; }
}
