/* =============================================================
   Atelier Monday
   Structure and behaviour after aletagency.com — a locked viewport
   per page, chapters advanced by scroll, giant serif page titles
   bleeding off the edges, and a hairline index table over the work.

   Typography and colour are the studio's own, per the graphic manual:
   Royals Serif Light for display, Arimo Regular for everything else,
   and only the seven brand colours.
   ============================================================= */

@font-face {
  font-family: "Royals Serif";
  src: url("/assets/fonts/RoyalsSerif-Light.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Arimo";
  src: url("/assets/fonts/arimo-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  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: "Arimo";
  src: url("/assets/fonts/arimo-latin-ext.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
  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;
}

:root {
  /* the seven brand colours, verbatim from the graphic manual */
  --white: #ffffff;
  --off: #f7f4f1;
  --sand: #e8e1d9;
  --stone: #dad0c4;
  --greige: #a49990;
  --noir: #332c28;
  /* One burgundy, everywhere (Pavel, 2026-09-28, from his footer
     reference): the manual's wine #6F2330 and deep #4A1416 both became
     #3A1712. The two names stay so nothing that uses them had to move. */
  --wine: #3a1712;
  --deep: #3a1712;

  /* the sand is the site ground, the way ALET sits on its warm base */
  --bg: var(--sand);
  --ink: var(--noir);
  --rule: rgba(51, 44, 40, 0.22);
  --ghost: #d1cdc4;

  --display: "Royals Serif", "Times New Roman", Times, serif;
  --sans: "Arimo", "Helvetica Neue", Helvetica, Arial, sans-serif;

  --pad: clamp(1.25rem, 2.6vw, 1.5rem);
  --bar-h: 3.4rem;

  /* One editorial scale shared by every template. Individual layouts
     choose a role from this set instead of inventing a local size. */
  --type-label: 0.8125rem;   /* the one small register, site-wide */
  --type-body: clamp(0.94rem, 0.9vw, 1.08rem);
  --type-body-lg: clamp(1rem, 1.25vw, 1.17rem);
  --type-card: clamp(1.9rem, 2.8vw, 3rem);
  /* The deck: the first written moment after every photographic
     opening. One size, one leading, one tracking on every page, and a
     phone size to match. The case studies set the standard. */
  --type-deck: clamp(2.2rem, 3.25vw, 4rem);
  --deck-leading: 0.96;
  --deck-tracking: -0.025em;
  --type-deck-sm: clamp(1.9rem, 8.6vw, 3rem);
  /* the seam between an opening photograph and its deck */
  /* THE one space between a hero photograph and the first line under
     it, on every page. The studio, 2026-09-22: "there are wildly
     different gaps under that small intro type, sometimes it is stuck
     right on the photo and sometimes there is a big space, let it run on
     one principle". Measured before: 1px on Press, 3 on Work, 7 on a
     case study, 32 on Studio, 117 on Services and Contact. Now every
     first section takes this as its padding-top and nothing else sets
     it; see the block at the end of the file. */
  --seam-top: clamp(2rem, 4.5vh, 3.25rem);
  --type-statement: clamp(2.2rem, 4.65vw, 4.7rem);
  --type-feature: clamp(3.2rem, 5.2vw, 7.25rem);
  --type-section: clamp(3.4rem, 7.2vw, 7.2rem);

  --measure-copy: 46rem;
  --measure-wide: 78rem;
  --section-y: clamp(4.5rem, 10vh, 7rem);
  --section-y-lg: clamp(6rem, 14vh, 10rem);
  --grid-gap: clamp(1rem, 2.5vw, 2.25rem);
  --card-gap: clamp(1rem, 2vw, 1.8rem);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --in-out: cubic-bezier(0.645, 0.045, 0.355, 1);
  --out: cubic-bezier(0.215, 0.61, 0.355, 1);
  --in: cubic-bezier(0.755, 0.05, 0.855, 0.06);
  --land: cubic-bezier(0.16, 1, 0.3, 1);
  --slow: 1.1s var(--ease);
  --motion-enter: 1s var(--out);
  --motion-title: 1.25s var(--land);
  --motion-card: 1.1s var(--out);
  --motion-stagger: 90ms;
  --card-scale: 1.025;
  --hero-title-bottom: clamp(0.85rem, 1.6vh, 1.35rem);
  --hero-title-leading: 0.82;
  --hero-overlay: linear-gradient(180deg, rgba(51, 44, 40, 0.34) 0%, rgba(51, 44, 40, 0.05) 42%, rgba(51, 44, 40, 0.3) 100%);
  --content-width: 90rem;
}

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

html {
  -webkit-text-size-adjust: 100%;
  /* Every page but Process is a locked viewport with no scrollbar.
     Letting one appear on Process took fifteen pixels of width away
     from that page alone, which moved the bar, the wordmark and
     everything else centred, and made the nav jump as you moved
     between pages. Reserving the gutter everywhere instead would put
     a fifteen pixel strip beside the full-bleed photography, so the
     document's scrollbar is simply not drawn on any page. Process
     still scrolls; its own stacked step bars show the progress.
     Scrollers inside a chapter keep their scrollbars: those sit
     within the layout and move nothing. */
  scrollbar-width: none;
}
html::-webkit-scrollbar { width: 0; height: 0; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Every page is one locked viewport; chapters move inside it. */
/* svh is the viewport with the browser's toolbars at their tallest.
   On a phone showing the compact toolbar the visible area is larger
   than that, which is the band of ground under the photograph. This
   page cannot scroll, so dvh has nothing to jitter against and is
   simply correct; svh stays as the fallback. */
body.locked { height: 100svh; height: 100dvh; overflow: hidden; }

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
h1, h2, h3, h4, h5, h6, p, ul, figure { margin: 0; font-weight: inherit; }
ul { padding: 0; list-style: none; }

::selection { background: var(--wine); color: var(--off); }

.skip {
  position: absolute; left: -999px; top: 0; z-index: 100;
  background: var(--noir); color: var(--off); padding: 0.75rem 1rem;
}
.skip:focus { left: 0; }
:focus-visible { outline: 1px solid currentColor; outline-offset: 3px; }

/* ---------- type primitives ---------- */
/* the small tracked uppercase label is the whole interface voice */
.lbl {
  font-family: var(--sans);
  font-size: var(--type-label);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.5;
}
.serif {
  font-family: var(--display);
  font-weight: 300;
  line-height: 1.06;
}
.muted { color: var(--greige); }

/* ---------- top bar ----------
   ALET's split bar: one link left, the wordmark centred and widely
   tracked, the rest of the nav right. */
.bar {
  position: fixed; inset: 0 0 auto 0; z-index: 60;
  /* viewport-fit=cover runs the page under the notch, so the bar grows
     by whatever the device reserves at the top and the links sit clear
     of the corners in landscape */
  height: calc(var(--bar-h) + env(safe-area-inset-top));
  padding-top: env(safe-area-inset-top);
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding-left: max(var(--pad), env(safe-area-inset-left));
  padding-right: max(var(--pad), env(safe-area-inset-right));
  color: var(--ink);
  /* The bar is fixed and always reachable, so it needs a ground of its
     own: without one, a page title scrolling past runs straight through
     the wordmark. Over a photograph it stays clear and reads white; the
     moment the ground behind it is the sand, it takes the sand with it. */
  background: var(--bg);
  transition: color 0.6s var(--ease), background-color 0.6s var(--ease);
}
.bar--over { color: var(--off); background: transparent; }
/* The index is permanently photographic. Its navigation must be correct on
   the first painted frame, before JavaScript can inspect the surface below. */
body.p-home:not(:has(.menu.is-open)) .bar {
  color: var(--off);
  background: transparent;
}
.bar__l { justify-self: start; }
.bar__c { justify-self: center; }
.bar__r { justify-self: end; display: flex; align-items: center; gap: clamp(0.9rem, 2.2vw, 1.9rem); }
.bar__links { display: flex; align-items: center; gap: clamp(0.9rem, 2.2vw, 1.9rem); }
.bar a { position: relative; padding-bottom: 0.2rem; }
.bar a::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform 0.5s var(--ease);
}
.bar a:hover::after,
.bar a[aria-current]::after { transform: scaleX(1); transform-origin: left; }
/* the wordmark sits centred, its own clear zone preserved */
.bar__mark::after { display: none; }
.wm { display: block; }
.wm svg { display: block; height: 0.5rem; width: auto; }

/* the three-language switcher */
.langs { display: flex; align-items: center; gap: 0.35rem; }
.langs a { font-size: 0.625rem; letter-spacing: 0.14em; opacity: 0.5; padding-bottom: 0.15rem; }
.langs a:hover { opacity: 0.85; }
.langs a[aria-current] { opacity: 1; }
.langs span { opacity: 0.35; font-size: 0.625rem; }

.bar__burger { display: none; width: 1.4rem; height: 0.85rem; position: relative; }
.bar__burger span {
  position: absolute; left: 0; right: 0; height: 1px; background: currentColor;
  transition: transform 0.4s var(--ease), opacity 0.3s var(--ease);
}
.bar__burger span:first-child { top: 0.2rem; }
.bar__burger span:last-child { bottom: 0.2rem; }
.bar__burger[aria-expanded="true"] span:first-child {
  top: 50%; transform: translateY(-50%) rotate(45deg);
}
.bar__burger[aria-expanded="true"] span:last-child {
  top: 50%; bottom: auto; transform: translateY(-50%) rotate(-45deg);
}

/* The landing page's wordmark and its sentence sit at 95 so they can
   stand on the opening card, which means the menu has to clear them or
   they print straight through it. The bar rises with it, but only while
   the menu is open, so it stays under the opening card where it
   belongs and the burger is still there to close with. */
.menu { position: fixed; inset: 0; z-index: 96; background: var(--sand); display: none; }
body:has(.menu.is-open) .bar {
  z-index: 97;
  color: var(--ink);
  background: transparent;
}
.menu.is-open { display: flex; flex-direction: column; justify-content: center; padding: var(--pad); }
.menu__nav { display: flex; flex-direction: column; gap: 0.5rem; }
.menu__nav a { font-family: var(--display); font-weight: 300; font-size: clamp(2.2rem, 12vw, 3.4rem); line-height: 1.15; }
.menu__foot { position: absolute; left: var(--pad); right: var(--pad); bottom: var(--pad); display: flex; justify-content: space-between; align-items: center; }

/* the screen fades on its way to the next page, so a gesture that
   navigates reads as a move rather than as a page giving way */
html.is-leaving .stage,
html.is-leaving .bar,
html.is-leaving .hint { opacity: 0; transition: opacity 0.4s var(--ease); }
@media (prefers-reduced-motion: reduce) {
  html.is-leaving .stage,
  html.is-leaving .bar,
  html.is-leaving .hint { transition: none; }
}

/* ---------- the chapter stage ----------
   One stage per page. Chapters stack and only the active one shows. */
.stage { position: relative; height: 100svh; height: 100dvh; overflow: hidden; }
.chapter {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  transition: opacity 0.9s var(--ease), visibility 0.9s;
}
.chapter.is-on { opacity: 1; visibility: visible; }
/* a chapter taller than the viewport scrolls within itself */
.chapter--scroll {
  height: 100%;
  overflow-y: auto; overscroll-behavior: contain;
  padding-top: var(--bar-h);
  padding-bottom: 3.5rem;
}

/* ---------- a phone is not a small desktop ----------
   Read off the reference, which does the same thing in two rules. On a
   real device it puts an isMobile class on the root and undoes the
   lock: the page stops being a fixed viewport with chapters stacked on
   top of one another and becomes one document that simply scrolls. The
   sections are the same sections; they flow instead of taking turns.

   The switch is on the user agent, not on the width, which is why
   narrowing a desktop browser never shows it: a narrow window still
   has a wheel and a pointer, a phone has a thumb. */
html.isMobile,
html.isMobile body.locked { height: auto; overflow: visible; }
html.isMobile .stage { height: auto; overflow: visible; }
html.isMobile .chapter {
  position: relative; inset: auto;
  min-height: 100svh;
  opacity: 1; visibility: visible;
  transition: none;
}
html.isMobile .chapter--scroll {
  height: auto;
  overflow: visible;
  padding-bottom: 4rem;
}
/* the reel keeps one screen of its own at the top of that scroll */
html.isMobile .reel { position: relative; height: 100svh; height: 100dvh; }
/* nothing takes turns any more, so nothing needs to be counted */
html.isMobile .hint { display: none; }
/* a chapter that was centring itself inside a fixed viewport has to
   keep centring itself inside its own screen */
html.isMobile .say { height: auto; min-height: 100svh; }

/* the chapter dots, centred at the foot */
.hint {
  position: fixed; inset: auto 0 1.1rem; z-index: 40;
  display: flex; justify-content: center;
  transition: color 0.6s var(--ease);
}
.hint--over { color: var(--off); }
.hint__dots { display: flex; gap: 0.45rem; }
.hint__dot {
  width: 5px; height: 5px; border-radius: 50%;
  border: 1px solid currentColor; opacity: 0.45; padding: 0;
  transition: opacity 0.4s var(--ease), background 0.4s var(--ease);
}
.hint__dot.is-on { opacity: 1; background: currentColor; }

/* ---------- the title plate ----------
   ALET's signature: a full-bleed photograph with the page name set
   enormous in the light serif, bleeding past both edges at the foot. */
.plate { position: absolute; inset: 0; }
/* Inside a chapter the plate fills its stage. On a page that scrolls
   there is no stage to fill, so it would stretch to the height of the
   whole document and every section after it would be read over the
   photograph. There it takes one screen of its own. */
#main > .plate {
  position: relative; height: 100svh;
  /* and it clips its own title. Inside a chapter the stage did that;
     here the name would otherwise hang past the photograph and finish
     on the sand below it. */
  overflow: hidden;
}
.plate__img { position: absolute; inset: 0; }
.plate__img img { width: 100%; height: 100%; object-fit: cover; }
.plate__img::after {
  content: ""; position: absolute; inset: 0;
  background: var(--hero-overlay);
}
.plate__eyebrow {
  position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%);
  text-align: center; color: var(--off);
  padding: 0 var(--pad);
}
.plate__title {
  -webkit-user-select: none;
  user-select: none;
  /* no padding: the name runs the full width of the screen, letters
     touching both edges, the way the reference sets its own */
  position: absolute; left: 0; right: 0; bottom: var(--hero-title-bottom);
  font-family: var(--display);
  font-weight: 300;
  /* Twenty per cent of the viewport until the name is long enough that
     it would not fit, and then whatever does fit. The width comes from
     the font's own advance widths, measured at build time, so a title
     is never cropped in any language. */
  font-size: min(26vw, calc(100vw / var(--em, 6)));
  line-height: var(--hero-title-leading);
  text-align: center;
  color: var(--ghost);
  white-space: nowrap;
  letter-spacing: -0.012em;
}
/* the reference's own device: one word set small and lifted off the
   baseline, so a longer name keeps its important words enormous */
.plate__sm {
  font-size: 0.38em;
  vertical-align: 0.62em;
  letter-spacing: 0.005em;
}

/* ---------- statement chapter ---------- */
.say {
  height: 100%;
  display: grid; align-content: center; justify-items: center;
  gap: clamp(1.6rem, 5vh, 3.4rem);
  padding: var(--bar-h) var(--pad) 4rem;
  text-align: center;
}
.say__lbl { max-width: 46rem; }
.say__body {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.5rem, 3.2vw, 2.8rem);
  line-height: 1.24;
  max-width: 46rem;
}
/* the reference italicises single words inside a roman line */
.say__body em { font-style: normal; }

/* ---------- home: the service ring ----------
   Labels pinned around the edges, thin leaders between them, and the
   work drifting through the middle. */
.ring { height: 100%; position: relative; }
.ring__lbl { position: absolute; white-space: nowrap; z-index: 4; }
.ring__lbl--tl { top: 12%; left: var(--pad); }
.ring__lbl--tc { top: 12%; left: 50%; transform: translateX(-50%); }
.ring__lbl--tr { top: 12%; right: var(--pad); }
.ring__lbl--bl { top: 16.5%; left: var(--pad); }
.ring__lbl--bc { top: 16.5%; left: 50%; transform: translateX(-50%); }
.ring__lbl--br { top: 16.5%; right: var(--pad); }
.ring__leaders { position: absolute; inset: 0; pointer-events: none; width: 100%; height: 100%; z-index: 2; opacity: 0.5; }
.ring__leaders line { stroke: var(--rule); stroke-width: 1; vector-effect: non-scaling-stroke; }

/* The draggable plane. The visitor grabs it and pans; each item moves
   by drag x its own depth, so the images travel at different speeds
   and the field reads as layered rather than as one sliding strip. */
.canvas {
  /* full bleed and unclipped, as the reference has it: the frames run
     under the bar and the labels, which simply sit above them */
  position: absolute; inset: 0;
  cursor: grab;
  touch-action: none;
}
.canvas.is-dragging { cursor: grabbing; }
/* The plane the visitor drags. One transform moves everything at once,
   exactly as the reference does it — the frames do not travel at
   different rates under the drag. */
.canvas__plane {
  position: absolute; inset: 0;
  will-change: transform;
}
/* Every frame is centred on the plane and then pushed out by its own
   margin, so the composition is described purely in vmax and scales
   with the viewport. */
.canvas__item {
  position: absolute;
  left: 50%; top: 50%;
  /* --x/--y carry whichever arrangement is active; the plane switches
     them and the frames ease between the two states */
  margin-left: var(--x);
  margin-top: var(--y);
  --x: var(--lx);
  --y: var(--ly);
  translate: -50% -50%;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
  transition: margin-left 1.1s var(--ease), margin-top 1.1s var(--ease);
}
.canvas.is-random .canvas__item { --x: var(--rx); --y: var(--ry); }
@media (prefers-reduced-motion: reduce) {
  .canvas__item { transition: none; }
}
.canvas__item img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: var(--crop, 50% 50%);
  pointer-events: none;
}

/* The entry, measured off the reference: each frame's image starts at
   opacity 0 and scale 1.2, then settles over ~900ms on an ease-out
   curve. The frames do not arrive in order — they are staggered across
   a window of about 870ms, which is what makes the field assemble
   rather than sweep. */
@keyframes frame-in {
  from { opacity: 0; transform: scale(1.2); }
  to   { opacity: 1; transform: none; }
}
.canvas__item img {
  animation: frame-in 900ms cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
  animation-delay: var(--in, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .canvas__item img { animation: none; }
}
.canvas__cap {
  position: absolute; inset: auto 0 -1.3rem 0;
  white-space: nowrap;
  opacity: 0; transform: translateY(-0.2rem);
  transition: opacity 0.35s var(--ease), transform 0.35s var(--ease);
  pointer-events: none;
}
.canvas__item:hover .canvas__cap { opacity: 1; transform: none; }

/* linear / random, the reference's own control over the two states */
.toggle {
  position: absolute; left: 50%; bottom: clamp(1rem, 2.4vh, 1.6rem);
  transform: translateX(-50%);
  z-index: 5;
  display: flex; align-items: center; gap: 0.7rem;
}
.toggle__sw {
  width: 3rem; height: 1.05rem; border-radius: 1rem;
  border: 1px solid var(--rule); position: relative; padding: 0;
  background: rgba(232, 225, 217, 0.8);
}
.toggle__sw::after {
  content: ""; position: absolute; top: 50%; left: 0.18rem;
  width: 0.62rem; height: 0.62rem; border-radius: 50%;
  background: var(--ink); transform: translateY(-50%);
  transition: transform 0.5s var(--ease);
}
.toggle.is-random .toggle__sw::after { transform: translate(2.1rem, -50%); }

.drag {
  position: absolute; left: 50%; bottom: clamp(3.4rem, 7vh, 4.6rem);
  transform: translateX(-50%);
  z-index: 5;
  color: var(--noir);
  background: rgba(232, 225, 217, 0.86);
  backdrop-filter: blur(6px);
  padding: 0.4rem 0.9rem;
  border-radius: 1rem;
  pointer-events: none;
  transition: opacity 0.6s var(--ease);
}
.drag.is-gone { opacity: 0; }



/* ---------- work: the index table ----------
   ALET's filter panel: a hairline table where each discipline's count
   sits at a position proportional to its size, plus the client list. */
.idx {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr) minmax(0, 0.62fr);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  max-width: 110rem; margin: 0 auto;
}
.idx__filters { border-right: 1px solid var(--rule); }
.idx__row {
  display: grid; grid-template-columns: minmax(8rem, 0.44fr) minmax(0, 1fr);
  align-items: stretch;
  border-bottom: 1px solid var(--rule);
  width: 100%; text-align: left;
  transition: background 0.4s var(--ease);
}
.idx__row:hover,
.idx__row.is-on { background: rgba(51, 44, 40, 0.05); }
.idx__name { padding: 0.6rem var(--pad); align-self: center; }
.idx__bar { position: relative; padding: 0.6rem 0; border-left: 1px solid var(--rule); }
.idx__val {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 0.4rem; white-space: nowrap;
}
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink); flex: 0 0 auto; }
.idx__all { display: block; width: 100%; text-align: left; padding: 0.6rem var(--pad); }
.idx__clients { border-right: 1px solid var(--rule); padding: 0.6rem var(--pad) 1rem; }
.idx__clients h2 { margin-bottom: 1.5rem; }
.idx__list { columns: 2; column-gap: 1.4rem; }
.idx__list li { break-inside: avoid; }
.idx__aside {
  padding: 0.6rem var(--pad) 1rem;
  display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end;
}

/* ---------- project page ----------
   One editorial field: image, title and story overlap instead of arriving
   as isolated modules. The proportions follow the work; small information
   stays small and the photographs carry the page. */
.pj { background: var(--bg); overflow: clip; }
.pjopen {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--grid-gap);
  row-gap: clamp(2.5rem, 5vh, 4.5rem);
  padding: var(--seam-top) var(--pad) clamp(2rem, 4vh, 3.5rem);
}
.pjopen__eyebrow { grid-column: 1 / 4; }
.pjopen__lead {
  grid-column: 1 / -1;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(4rem, 10.6vw, 11rem);
  line-height: 0.78; letter-spacing: -0.045em;
}
.pjopen__deck {
  grid-column: 1 / -1;
  max-width: none;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
}
.pjfacts {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--grid-gap);
  margin: 0;
  font-size: 0.68rem;
  line-height: 1.35;
  letter-spacing: 0.075em;
  text-transform: uppercase;
}
.pjfacts > div { display: grid; gap: 0.55rem; }
.pjfacts dt { color: var(--greige); }
.pjfacts dd { margin: 0; }
/* the same record on a dark ground (the Studio opening) */
.pjfacts--dark dt { color: rgba(247, 244, 241, 0.55); }
.pjfacts--dark dd { color: var(--off); }

/* Layered portrait field. Every frame owns a different scroll rate, so the
   overlap gently re-composes around the gesture rather than blinking on hover. */
.pjcollage {
  position: relative;
  height: clamp(35rem, 68vw, 68rem);
  margin: clamp(1rem, 3vh, 2rem) 0 clamp(4rem, 10vh, 8rem);
}
.pjcollage__frame { position: absolute; margin: 0; will-change: transform; }
.pjcollage__frame img { width: 100%; height: 100%; display: block; object-fit: cover; }
.pjcollage__frame--1 { left: -2.5%; top: 8%; width: 16%; height: 35%; }
.pjcollage__frame--2 { left: 10%; top: 16%; width: 27%; height: 56%; z-index: 2; }
.pjcollage__frame--3 { left: 31%; top: 5%; width: 12%; height: 23%; z-index: 3; }
.pjcollage__frame--4 { left: 34%; top: 11%; width: 34%; height: 70%; z-index: 1; }
.pjcollage__frame--5 { left: 64%; top: 18%; width: 20%; height: 40%; z-index: 2; }
.pjcollage__frame--6 { right: -1.5%; top: 9%; width: 24%; height: 49%; z-index: 3; }

.pjessay { display: grid; gap: clamp(4rem, 9vh, 8rem); padding: 0 0 clamp(6rem, 12vh, 10rem); }
.pjgallery__shot { margin: 0; }
.pjgallery__shot img { width: 100%; display: block; background: var(--stone); object-fit: cover; }
.pjgallery__shot figcaption { margin-top: 0.65rem; color: var(--greige); }
.pjgallery__shot--wide { width: calc(100% - 2 * var(--pad)); margin-inline: var(--pad); }
.pjgallery__shot--wide img { aspect-ratio: 1.9 / 1; max-height: 92svh; }
.pjgallery__shot--quiet { width: min(68rem, 72vw); margin-inline: auto; }
.pjgallery__shot--quiet img { aspect-ratio: 4 / 3; }
.pjgallery__pair {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  align-items: end;
  gap: clamp(1rem, 3vw, 3rem);
  padding: 0 var(--pad);
}
.pjgallery__pair--reverse { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: start; }
.pjgallery__pair--reverse > :first-child { order: 2; }
.pjgallery__shot--portrait img { aspect-ratio: 4 / 5; }
.pjgallery__shot--landscape img { aspect-ratio: 4 / 3; }

.pjnote {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  padding: clamp(1rem, 3vh, 2rem) var(--pad);
}
.pjnote__label { grid-column: 1 / 4; color: var(--greige); }
.pjnote__copy {
  grid-column: 4 / 12;
  max-width: none;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem, 3.15vw, 3.8rem);
  line-height: 1; letter-spacing: -0.022em;
}
.pjnote__copy p + p { margin-top: 1.4rem; }
.pjnote--right .pjnote__label { grid-column: 10 / -1; }
.pjnote--right .pjnote__copy { grid-column: 2 / 10; }

/* ALET's strongest text moments do not merely enter once: they remain
   attached to the gesture, becoming fully present near the viewport's
   centre and receding as the reader passes. No rules or decorative lines
   are borrowed; scale and motion do the hierarchy. */
[data-scroll-text] {
  opacity: var(--scroll-opacity, 1);
  transform: translate3d(0, var(--scroll-shift, 0), 0);
  will-change: opacity, transform;
}

.pjcontact {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: end;
  padding: clamp(6rem, 14vh, 10rem) var(--pad);
  background: var(--sand);
}
.pjcontact > p { grid-column: 1 / 4; align-self: start; }
.pjcontact h2 {
  grid-column: 4 / 10;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(4.5rem, 9vw, 9.25rem);
  line-height: 0.84; letter-spacing: -0.035em;
}
.pjcontact a { grid-column: 10 / -1; justify-self: end; padding-bottom: 0.45rem; border-bottom: 1px solid currentColor; }

.pjmore { padding: clamp(5rem, 10vh, 8rem) 0 clamp(6rem, 14vh, 11rem); }
.pjmore__title {
  position: relative; z-index: 4;
  display: flex; justify-content: space-between;
  padding-inline: var(--pad);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(5rem, 13vw, 14rem);
  line-height: 0.72; letter-spacing: -0.05em;
  text-transform: uppercase;
}
.pjmore__title span:last-child { text-align: right; }
.pjmore__field {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  min-height: clamp(42rem, 75vw, 72rem);
  margin-top: clamp(-1rem, -1vw, -0.25rem);
  padding-inline: var(--pad);
  align-items: start;
}
.pjmore__project { display: block; position: relative; }
.pjmore__project figure { overflow: hidden; background: var(--stone); }
.pjmore__project img { width: 100%; height: 100%; display: block; object-fit: cover; transition: transform 1.2s var(--out); }
.pjmore__project span { display: block; margin-top: 0.65rem; }
.pjmore__project--1 { grid-column: 1 / 5; margin-top: clamp(8rem, 16vw, 16rem); }
.pjmore__project--1 figure { aspect-ratio: 4 / 5; }
.pjmore__project--2 { grid-column: 4 / 8; margin-top: clamp(2rem, 5vw, 5rem); z-index: 2; }
.pjmore__project--2 figure { aspect-ratio: 5 / 6; }
.pjmore__project--3 { grid-column: 9 / 13; margin-top: clamp(11rem, 21vw, 21rem); }
.pjmore__project--3 figure { aspect-ratio: 4 / 5; }
.pjmore__project:hover img { transform: scale(1.018); }
@media (prefers-reduced-motion: reduce) { .pjmore__project img { transition: none; } }

/* ---------- process ----------
   The reference's roll-up system. Each step is a 28px bar; its panel
   hangs below and slides up over what is above as you scroll, while
   the bars of the steps still to come stay stacked at the foot. */
.p-process { background: var(--sand); }
.p-process { --process-pad: clamp(1.1rem, 1.604vw, 1.5rem); }
.p-process .bar {
  transition:
    transform 0.8s var(--land),
    color 0.6s var(--ease),
    background-color 0.6s var(--ease);
}

/* the opening plate */
.pplate { position: relative; height: 100svh; overflow: hidden; }
.plate__title--mix {
  white-space: normal;
  bottom: var(--hero-title-bottom);
  font-size: clamp(7rem, 19.56vw, 20rem);
  line-height: var(--hero-title-leading);
}
.plate__title--mix em {
  font-style: normal;
  font-size: 0.42em;
  vertical-align: 0.34em;
  padding: 0 0.06em;
}

/* the statement: the same deck seam as a case study, directly under
   the opening photograph, left and edge to edge. It stays pinned as
   the quiet backdrop, so the first step's panel is seen rolling up
   over it rather than over blank ground. */
.psay {
  position: sticky; top: 0;
  z-index: 0;
  min-height: 0;
  display: block;
  padding: var(--seam-top) var(--pad) clamp(4rem, 9vh, 7rem);
  text-align: left;
  background: var(--bg);
}
.pstep { z-index: 1; }
.psay__body {
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
  width: 100%;
  max-width: none;
}
.psay__body em { font-style: normal; }
.psay__hint {
  margin-top: clamp(2rem, 5vh, 3.5rem);
  color: var(--greige); font-size: 0.6875rem;
}
.psay__hint span { display: inline; }
.psay__hint span + span::before { content: " "; }

/* the bar: number left, name centred — 28px on the reference */
.pbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  height: 1.606rem;
  padding: 0 var(--process-pad);
  font-family: var(--sans);
  font-size: clamp(0.6875rem, 1.094vw, 0.875rem);
  letter-spacing: 0.025em;
  text-transform: uppercase;
  line-height: 1;
  text-align: left;
}
.pbar__no { justify-self: start; }
.pbar__name { justify-self: center; }
.pbar--sand   { background: var(--sand);   color: var(--noir); }
.pbar--noir   { background: var(--noir);   color: var(--off); }
.pbar--greige { background: var(--greige); color: var(--noir); }
.pbar--stone  { background: var(--stone);  color: var(--noir); }
.pbar--wine   { background: var(--wine);   color: var(--off); }
/* the head bar sits on its panel's own ground */
.pbar--head { grid-area: head; background: none; color: inherit; }
.pbar--head { margin-top: var(--bar-h); }

/* one scroll section per step; the panel pins and rolls up inside it */
.pstep { height: 190svh; position: relative; }
.pstep__pin {
  position: sticky; top: 0;
  height: 100svh;
  overflow: hidden;
}
.pstep__panel {
  position: absolute; inset: 0;
  --step-fs: 7.875vw;
  display: grid;
  /* the reference's own split, measured off its DOM: the picture takes
     44.6% of the panel and the sentence the rest, with no gutter
     between them beyond the text's own left padding */
  grid-template-columns: minmax(0, 44.6%) minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr);
  grid-template-areas:
    "head head"
    "title title"
    "fig body";
  padding: 0 0 calc(var(--stack-h, 0px) + 1rem);
  /* rolled down until its section is reached; JS raises it */
  transform: translateY(var(--roll, 100%));
  will-change: transform;
}
.pstep__panel--sand   { background: var(--sand);   color: var(--noir); }
.pstep__panel--noir   { background: var(--noir);   color: var(--off); }
.pstep__panel--greige { background: var(--greige); color: var(--noir); }
.pstep__panel--stone  { background: var(--stone);  color: var(--noir); }
.pstep__panel--wine   { background: var(--wine);   color: var(--off); }

/* The step title is the panel. On the reference it sets at 196px on a
   2560 screen, which is 7.65vw, on a line-height of 0.87 — it fills the
   width and the picture and the sentence live underneath it. Ours was
   capped at 7rem, so on a wide screen it read as a caption on an empty
   field, which is what was wrong with the whole panel. */
.pstep__title {
  grid-area: title;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3.8rem, var(--step-fs), 12.25rem);
  line-height: 0.87;
  text-transform: uppercase;
  padding: 0.06em var(--process-pad) 0;
  max-width: 15ch;
  margin-bottom: clamp(1rem, 3vh, 2.5rem);
}
.pstep__title em { font-style: normal; }
.pstep--2 .pstep__panel,
.pstep--3 .pstep__panel,
.pstep--4 .pstep__panel,
.pstep--5 .pstep__panel { --step-fs: 9.4275vw; }
.pstep--2 .pstep__title,
.pstep--3 .pstep__title,
.pstep--4 .pstep__title,
.pstep--5 .pstep__title { line-height: 0.8; max-width: none; }
.pstep--2 .pstep__title { text-align: right; }
.pstep--3 .pstep__title { text-align: center; }
.pstep--5 .pstep__title { max-width: 9ch; }
/* the picture fills its column top to bottom rather than sitting in the
   corner at a fixed 40rem, which is what left the middle of the screen
   empty */
.pstep__fig {
  grid-area: fig; align-self: stretch;
  width: 100%; margin: 0 0 0 var(--process-pad);
  overflow: hidden;
}
.pstep__fig img { width: 100%; height: 100%; object-fit: cover; }
.pstep--2 .pstep__fig,
.pstep--3 .pstep__fig,
.pstep--4 .pstep__fig {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-self: center;
  width: 57.5vw;
  margin: 0;
}
.pstep--3 .pstep__fig { width: 53.35vw; }
.pstep--4 .pstep__fig { width: 42vw; }
.pstep--5 .pstep__fig {
  grid-column: 2;
  grid-row: 3;
  width: calc(100% - var(--process-pad));
  margin: 0 var(--process-pad) 0 0;
}
/* The copy is the other half of the panel: the paragraph in sentence
   case at a reading size, and under it the step's own record, what you
   leave with and how long it takes, in the interface voice. */
.pstep__copy {
  grid-area: body; align-self: end; justify-self: center;
  display: grid;
  gap: clamp(0.9rem, 2.2vh, 1.5rem);
  max-width: min(92%, 52ch);
  margin: 0;
  padding: 0 var(--process-pad) 0 clamp(1rem, 1.56vw, 2.5rem);
}
.pstep__body {
  margin: 0;
  font-size: clamp(0.95rem, 1.15vw, 1.2rem);
  line-height: 1.55;
  text-align: left;
}
.pstep__meta {
  display: flex; flex-wrap: wrap;
  gap: 0.4rem 2rem;
  opacity: 0.75;
}
.pstep--2 .pstep__copy,
.pstep--4 .pstep__copy {
  grid-column: 2;
  grid-row: 3;
  align-self: end;
  justify-self: end;
  max-width: 46ch;
}
.pstep--3 .pstep__copy {
  grid-column: 1 / -1;
  grid-row: 3;
  align-self: end;
  justify-self: center;
  max-width: 58ch;
}
.pstep--5 .pstep__copy {
  grid-column: 1;
  grid-row: 3;
  align-self: end;
  justify-self: start;
  max-width: 42ch;
}

/* the bars of the steps still to come, pinned at the foot */
/* The bars are not on the screen when the page opens. On the reference
   they are simply left in the flow, sitting at the top edge of the step
   region, so they scroll up into view once the header and the statement
   have gone by and only then start holding the foot. Ours are fixed,
   because they have to stay at the foot for the rest of the run, so the
   arrival is driven by hand off the same measurement: the stack is held
   a full stack-height below the edge and rides up as the first step's
   section crosses it. Same picture, no scroll hijack. */
.pstack {
  position: fixed; inset: auto 0 0; z-index: 30;
  display: flex; flex-direction: column;
  pointer-events: none;
  transform: translateY(var(--stack-y, 100%));
  will-change: transform;
}
.pstack .pbar { pointer-events: auto; }
.pstack .pbar.is-open { display: none; }

@media (max-width: 48rem) {
  .p-press #main { overflow-x: clip; }
  .pstep { height: 175svh; }
  .pstep__panel {
    --step-fs: 11vw !important;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "title" "fig" "body";
    /* Keep the copy attached to its image. The flexible remainder belongs
       after the content, not between the image and the sentence. */
    grid-template-rows: auto auto auto minmax(0, 1fr);
  }
  .pstep__title,
  .pstep--2 .pstep__title,
  .pstep--3 .pstep__title,
  .pstep--4 .pstep__title,
  .pstep--5 .pstep__title {
    font-size: clamp(2.45rem, var(--step-fs), 3.4rem);
    line-height: 0.86;
    max-width: none;
    text-align: left;
  }
  .pstep__fig { width: auto; margin-right: var(--pad); align-self: start; }
  .pstep__fig img { aspect-ratio: 4 / 3; }
  .pstep__copy {
    grid-column: 1;
    grid-row: 4;
    align-self: start;
    justify-self: start;
    margin-top: 1rem;
  }
  .pstep--2 .pstep__fig,
  .pstep--3 .pstep__fig,
  .pstep--4 .pstep__fig,
  .pstep--5 .pstep__fig {
    grid-column: 1;
    grid-row: 3;
    width: auto;
    margin: 0 var(--pad);
  }
  .pstep--2 .pstep__copy,
  .pstep--3 .pstep__copy,
  .pstep--4 .pstep__copy,
  .pstep--5 .pstep__copy {
    grid-column: 1;
    grid-row: 4;
    justify-self: start;
    max-width: none;
  }
  .pbar { grid-template-columns: auto 1fr; column-gap: 0.8rem; }
  .pbar__name { justify-self: start; }
}

/* ---------- the three tiers, at the foot of Services ----------
   The steps above are the page's spectacle: five full panels rolling
   up over one another. What follows them has to be the opposite, or it
   reads as a sixth step that lost its picture. So the tiers arrive on
   the sand ground the page started on, set as a plain ruled list, with
   the way out to Contact directly under them. It is the quiet after
   the run, and it is where a visitor decides. */
.ptiers {
  position: relative; z-index: 2;
  background: var(--sand); color: var(--noir);
  padding: clamp(4rem, 14vh, 9rem) 0 clamp(7rem, 18vh, 11rem);
}
.ptiers__head {
  display: grid; justify-items: center; gap: 0.9rem;
  padding: 0 var(--pad) clamp(2rem, 6vh, 3.5rem);
  text-align: center;
}
.ptiers__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.6rem, 2.678vw, 3rem);
  line-height: 1.16;
}
.ptiers__lead { max-width: 42rem; opacity: 0.6; font-size: var(--lbl-md); }
/* the tiers head follows the shared section heading: small line left,
   serif title in the wide column */
.ptiers__head .ptiers__title { grid-column: 2; grid-row: 1; }
.ptiers__head .ptiers__lead { grid-column: 1; grid-row: 1; align-self: end; }
@media (max-width: 48rem) {
  .ptiers__head .ptiers__title,
  .ptiers__head .ptiers__lead { grid-column: 1; grid-row: auto; }
}
.ptiers__out {
  padding: clamp(2.4rem, 7vh, 4rem) var(--pad) 0;
  text-align: center;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.2rem, 2.4vw, 1.9rem);
}
.ptiers__out a { border-bottom: 1px solid currentColor; padding-bottom: 0.12em; }

/* ---------- the panel's own arrival ----------
   On the reference the title, the picture and the sentence are all at
   opacity 0 until their panel is up, and then they arrive: nothing is
   read through the roll. Ours does the same, staggered so the title
   lands first and the sentence last, which is the order they are read
   in anyway. */
.pstep__title,
.pstep__fig,
.pstep__copy {
  opacity: 0;
  transform: translateY(2.2rem);
  transition: opacity 0.9s var(--out), transform 1.1s var(--out);
}
.pstep.is-in .pstep__title,
.pstep.is-in .pstep__fig,
.pstep.is-in .pstep__copy {
  opacity: 1;
  transform: none;
}
.pstep.is-in .pstep__fig  { transition-delay: 0.12s; }
.pstep.is-in .pstep__copy { transition-delay: 0.22s; }

@media (prefers-reduced-motion: reduce) {
  .pstep__title,
  .pstep__fig,
  .pstep__copy { opacity: 1; transform: none; transition: none; }
}

/* =============================================================
   PRESS — an editorial archive rather than a directory
   The page earns confidence in three beats: the people behind the
   work, the independent publications that chose it, and the verified
   stories themselves. Photography and type carry the hierarchy; the
   rules only organise it.
   ============================================================= */
.p-press { background: var(--sand); }

/* ---------- statement ----------
   The same seam as a case study: the deck directly under the opening
   photograph, then the compact record, then the publication index. */
.printro {
  min-height: 0;
  display: block;
  padding: var(--seam-top) var(--pad) clamp(5rem, 11vh, 8rem);
}
.printro__say {
  width: 100%;
  text-align: left;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
}
.printro__say em { font-style: normal; }
.printro .pjfacts { margin-top: clamp(2.5rem, 5vh, 4.5rem); }

/* ---------- publication authority ----------
   One ruled masthead index: every publication in the same voice, on
   the same baseline grid, between two hairlines. Logotypes keep their
   own drawing; text-only outlets take the tracked caps of the site's
   interface so nothing reads as a missing asset. */
.prauthority {
  min-height: 0;
  display: block;
  margin-top: clamp(3.5rem, 8vh, 6rem);
  padding: 0;
  background: transparent; color: var(--ink);
}
.prauthority__row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: var(--grid-gap);
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}
.prauthority__mark {
  min-height: 4.4rem;
  display: grid;
  align-items: center;
  justify-items: start;
  padding: 1.1rem 0;
}
.prauthority__mark:nth-child(n + 5) { border-top: 1px solid var(--rule); }
.prmark { display: block; color: currentColor; }
.prmark svg { display: block; width: auto; max-width: 100%; }
.prmark--forbes svg { height: clamp(1.15rem, 1.5vw, 1.5rem); }
.prmark--elle svg { height: clamp(1.3rem, 1.8vw, 1.8rem); }
.prmark--creammy svg { height: clamp(1.15rem, 1.6vw, 1.6rem); }
.prmark--mediaguru svg { height: clamp(1.1rem, 1.45vw, 1.45rem); }
.prmark--type {
  font-family: var(--sans);
  font-size: clamp(0.72rem, 0.85vw, 0.85rem);
  letter-spacing: 0.14em; text-transform: uppercase;
  text-align: left;
}

/* ---------- editorial archive ---------- */
.prarchive { padding: clamp(4rem, 9vh, 6rem) var(--pad) clamp(6rem, 13vh, 9rem); }
.prarchive__head {
  display: grid; grid-template-columns: 1fr 3fr;
  align-items: end;
  margin-bottom: clamp(3.5rem, 8vh, 5rem);
}
.prarchive__head h2 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3.8rem, 9.2vw, 9.2rem);
  line-height: 0.82; letter-spacing: -0.02em;
}
.prgrid {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
  gap: clamp(4.5rem, 9vh, 7rem) clamp(1rem, 2vw, 1.8rem);
}
.prcard {
  min-width: 0;
  display: block;
}
.prcard--portrait {
  width: min(100%, 50svh);
}
.prcard--portrait.prcard--west {
  grid-column: 3 / 7;
  justify-self: end;
}
.prcard--portrait.prcard--east {
  grid-column: 7 / 11;
  justify-self: start;
  align-self: end;
}
.prcard--landscape.prcard--wide { grid-column: 2 / 12; }
.prcard--square.prcard--center { grid-column: 4 / 10; }
.prcard__fig { position: relative; overflow: hidden; background: var(--stone); }
.prcard--portrait .prcard__fig { aspect-ratio: 3 / 4; }
.prcard--landscape .prcard__fig { aspect-ratio: 3 / 2; }
.prcard--square .prcard__fig { aspect-ratio: 1 / 1; }
.prcard__fig img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.2s var(--out), filter 0.7s var(--ease);
}
.prcard__copy {
  width: 100%;
  padding-top: clamp(0.8rem, 1.7vh, 1.1rem);
}
.prcard__mast { min-height: 2rem; display: flex; align-items: center; }
.prcard__mast .prmark--forbes svg { height: clamp(1rem, 1.6vw, 1.55rem); }
.prcard__mast .prmark--elle svg { height: clamp(1.35rem, 2vw, 2rem); }
.prcard__mast .prmark--creammy svg { height: clamp(1.2rem, 1.9vw, 1.85rem); }
.prcard__mast .prmark--mediaguru svg { height: clamp(1rem, 1.7vw, 1.6rem); }
.prcard__mast .prmark--type { font-size: clamp(0.9rem, 1.3vw, 1.3rem); }
.prcard__head {
  max-width: 24ch;
  padding: clamp(0.65rem, 1.5vh, 0.95rem) 0 clamp(0.7rem, 1.5vh, 1rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.8rem, 2.75vw, 3rem);
  line-height: 1; letter-spacing: -0.012em;
}
.prcard__meta {
  display: flex; align-items: center; gap: 0.7rem;
  color: var(--greige);
}
/* a quiet note, not a chip: the article's own language is a fact of
   the archive, never a badge */
.prcard__src { opacity: 0.55; }
.prcard__src::before { content: "· "; }
/* the full-width cards spread their copy across the site grid instead
   of leaving the right half of the page empty */
.prcard--wide .prcard__copy,
.prcard--center .prcard__copy {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) minmax(0, 2fr) minmax(0, 1fr);
  column-gap: var(--grid-gap);
  align-items: start;
}
.prcard--wide .prcard__head,
.prcard--center .prcard__head { padding-top: 0.2rem; }
.prcard--wide .prcard__meta,
.prcard--center .prcard__meta { justify-content: flex-end; padding-top: 0.55rem; }
@media (hover: hover) and (pointer: fine) {
  .prcard:hover .prcard__fig img { transform: scale(1.012); }
}

/* ---------- recognition ---------- */
.praward {
  min-height: 0;
  padding: clamp(5rem, 10vh, 7rem) var(--pad) clamp(5rem, 11vh, 8rem);
  background: var(--wine); color: var(--off);
}
.praward__head {
  display: grid; grid-template-columns: 1fr 3fr; align-items: end;
  margin-bottom: clamp(3rem, 7vh, 5rem);
}
.praward__head h2 {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3.8rem, 9.2vw, 9.2rem); line-height: 0.82;
}
.praward__feature {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: clamp(2rem, 5vw, 5rem); align-items: end;
}
.praward__fig { height: min(58svh, 40rem); overflow: hidden; }
.praward__fig img {
  width: 100%; height: 112%; object-fit: cover;
  transform: translate3d(0, var(--press-award-y, -5%), 0) scale(1.02);
  transition: transform 1.1s var(--out);
  will-change: transform;
}
.praward__copy { padding-bottom: 0.4rem; }
.praward__year { padding-bottom: clamp(1.5rem, 4vh, 2.8rem); border-bottom: 1px solid rgba(247, 244, 241, 0.34); }
.praward__copy h3 {
  padding: clamp(2rem, 5vh, 3.5rem) 0;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3.4rem, 7.4vw, 7.2rem);
  line-height: 0.84; letter-spacing: -0.018em;
}
.praward__copy h3 span,
.praward__copy h3 em { display: block; }
.praward__copy h3 em { font-style: normal; padding-left: 0.42em; }
.praward__read { display: flex; justify-content: space-between; padding-top: 1rem; border-top: 1px solid rgba(247, 244, 241, 0.34); }

/* ---------- close ---------- */
.prfoot {
  min-height: 92svh;
  display: grid; grid-template-rows: 1fr auto;
  padding: clamp(5rem, 12vh, 8rem) var(--pad) clamp(2.5rem, 6vh, 4rem);
}
.prfoot h2 {
  align-self: center; justify-self: center;
  max-width: 14ch; text-align: center;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.8rem, 6.2vw, 6.2rem);
  line-height: 0.98;
}
.prfoot__links {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
}
.prfoot__links a {
  padding: 1.2rem 1rem; text-align: center;
  text-transform: uppercase; letter-spacing: 0.08em;
  border-left: 1px solid var(--rule);
  transition: background 0.4s var(--ease), color 0.4s var(--ease);
}
.prfoot__links a:first-child { border-left: 0; }
.prfoot__links a:hover { background: var(--noir); color: var(--off); }

@media (max-width: 48rem) {
  .printro { padding: 1.2rem var(--pad) 5rem; }
  .printro__say { font-size: var(--type-deck-sm); line-height: 1; }
  .printro .pjfacts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem 1rem; }

  .prauthority { margin-top: 3rem; }
  .prauthority__row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 1.25rem;
  }
  .prauthority__mark { min-height: 3.6rem; padding: 0.9rem 0; }
  .prauthority__mark:nth-child(n) { border-top: 0; }
  .prauthority__mark:nth-child(n + 3) { border-top: 1px solid var(--rule); }

  .prarchive__head,
  .praward__head { grid-template-columns: 1fr; gap: 1.7rem; }
  .prarchive__head h2,
  .praward__head h2 { font-size: clamp(3.25rem, 14.5vw, 5rem); }
  .prgrid { grid-template-columns: 1fr; gap: 4rem; }
  .prgrid .prcard {
    grid-column: 1;
    align-self: auto;
    justify-self: auto;
    width: 100%;
    display: block;
    margin: 0;
  }
  .prcard__head { font-size: clamp(1.9rem, 8vw, 2.65rem); }
  .prcard__meta { flex-wrap: wrap; }

  .praward { min-height: 0; }
  .praward__feature { display: block; }
  .praward__fig { height: auto; aspect-ratio: 4 / 3; margin-bottom: 2rem; }
  .praward__copy h3 { font-size: clamp(3.4rem, 15vw, 5rem); }

  .prfoot { min-height: 86svh; }
  .prfoot h2 { font-size: clamp(2.8rem, 12.5vw, 4.2rem); }
  .prfoot__links { grid-template-columns: 1fr; }
  .prfoot__links a { border-left: 0; border-top: 1px solid var(--rule); }
  .prfoot__links a:first-child { border-top: 0; }
}

@media (min-width: 48.01rem) and (max-width: 75rem) {
  .prcard__head { font-size: clamp(1.7rem, 2.7vw, 2.25rem); }
}

@media (prefers-reduced-motion: reduce) {
  .praward__fig img { animation: none; transform: none; }
  .prcard__fig img { transition: none; }
}

/* =============================================================
   UNIFIED COMPONENT SYSTEM
   Studio is the source of truth. These rules intentionally replace
   page-local variations with a small shared visual vocabulary.
   ============================================================= */

/* 1. Opening: navigation + full-bleed image + one title. */
body :is(.plate, .pplate, .prhero).pagehero {
  height: 100svh;
  height: 100dvh;
  min-height: 100svh;
  min-height: 100dvh;
}
body :is(.plate__title, .prhero__title) {
  bottom: var(--hero-title-bottom);
  color: rgba(247, 244, 241, 0.82);
  line-height: var(--hero-title-leading);
}

/* 2. The deck seam: the first written moment after every photographic
   opening is one shared role. The per-page classes below all resolve
   to the same tokens; nothing redefines the size locally. */

/* Work's introduction uses the same statement skeleton; its supporting
   paragraph simply follows the headline inside that shared measure. */
body .workintro {
  min-height: 0;
  display: block;
  padding: var(--seam-top) var(--pad) clamp(2.5rem, 5vh, 4rem);
  text-align: left;
}
body .workintro__statement {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2.5rem, 5vh, 4.5rem);
}
body .workintro__statement h2 {
  max-width: 100%;
  font-size: clamp(4rem, 10.6vw, 11rem);
  line-height: 0.78;
  letter-spacing: -0.045em;
  text-wrap: wrap;
}
body .workintro__aside { width: 100%; padding: 0; }
body .workintro__aside p {
  max-width: none;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
}

body .workintro {
  min-height: 0;
}
body .pt {
  min-height: min(72svh, 52rem);
  min-height: min(72dvh, 52rem);
  padding-top: var(--section-y);
  padding-bottom: var(--section-y);
}

/* 3. Section headings: one size, weight, leading and two-column grid. */
body :is(.prauthority__head, .prarchive__head, .praward__head, .ptiers__head) {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) minmax(0, 3fr);
  align-items: end;
  justify-items: stretch;
  gap: var(--grid-gap);
  text-align: left;
}
body :is(.ch__title, .prauthority__head h2, .prarchive__head h2, .praward__head h2, .ptiers__title, .pt__title) {
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(3rem, 5vw, 5.5rem);
  line-height: 0.94;
  letter-spacing: -0.018em;
  text-wrap: balance;
}

/* 4. Forms and actions: ruled fields and one serif underlined action. */
body :is(.ctform__line, .pt__line) {
  border: 0;
  border-bottom: 1px solid var(--rule);
}
body :is(.ctform__go button, .pt__go button) {
  width: auto;
  background: none;
  color: inherit;
  border: 0;
  border-bottom: 1px solid currentColor;
  padding: 0 0 0.1em;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.2rem, 2.4vw, 2.6rem);
}
body :is(.ctform__go button, .pt__go button):hover {
  background: none;
  color: inherit;
  opacity: 0.6;
}
body .pt__go { text-align: center; }

@media (max-width: 48rem) {
  body .workintro {
    min-height: 0;
    gap: 1.5rem;
    padding: 1.2rem var(--pad) 3.5rem;
  }
  body .workintro__statement { width: 100%; }
  body .workintro__statement h2 { font-size: clamp(3.1rem, 15vw, 5rem); line-height: 0.82; }
  body .workintro__aside p { font-size: var(--type-deck-sm); line-height: 0.98; }
  body .pt { min-height: 0; padding: 5rem var(--pad) 6rem; }
  body :is(.prauthority__head, .prarchive__head, .praward__head, .ptiers__head) {
    grid-template-columns: 1fr;
    gap: 1.7rem;
  }
  body :is(.ch__title, .prauthority__head h2, .prarchive__head h2, .praward__head h2, .ptiers__title, .pt__title) {
    font-size: clamp(3.25rem, 14.5vw, 5rem);
  }
}

/* =============================================================
   CONTACT
   The reference's own contact page, measured off its DOM at 2560:
   the tracked line at 29.3px, the invitation and the addresses both
   at 66.6px in the serif, the form as full-bleed lines with a 22px
   uppercase placeholder centred in each. Ours keeps every one of
   those relationships and swaps in our type and ground.
   ============================================================= */
.p-contact { background: var(--bg); }
.ctplate { position: relative; height: 100svh; overflow: hidden; }
/* the reference sets its tracked line in the middle of the plate, not
   at the top: the name is at the foot and the line is what you read
   first on the way down to it */
.p-contact .plate__eyebrow {
  position: absolute; left: 0; right: 0; top: 48%;
  text-align: center;
  font-size: var(--lbl-lg);
  color: var(--off);
  opacity: 0.9;
  padding: 0 var(--pad);
}

.ctsay {
  display: grid; place-items: center;
  min-height: 76svh;
  padding: clamp(3rem, 12vh, 8rem) var(--pad);
}
.ctsay__body {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.35rem, 2.6vw, 4.2rem);
  line-height: 1.15;
  text-align: center;
  max-width: min(78rem, 92vw);
}
.ctsay__body em { font-style: normal; }
.ctsay__line { display: inline; }
.ctsay__body .sl { white-space: normal; }

/* Contact follows the same title-to-story seam as Work and the case studies.
   The invitation is the single large written moment; practical information
   and the form then share one compact editorial grid. */
body.p-contact .ctsay {
  min-height: 0;
  display: block;
  padding: var(--seam-top) var(--pad) clamp(5rem, 11vh, 8rem);
  text-align: left;
}
body.p-contact .ctsay__body {
  width: 100%; max-width: none;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
  text-align: left; text-wrap: balance;
}
.ctconversation {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  padding: 0 var(--pad) clamp(6rem, 13vh, 10rem);
}
.ctconversation__aside { grid-column: 1 / 6; }
.ctconversation__free {
  max-width: 8.5em;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3rem, 5.2vw, 6rem);
  line-height: 0.9; letter-spacing: -0.035em;
}
.ctconversation__body {
  max-width: 32rem;
  margin-top: clamp(2rem, 5vh, 4rem);
  font-size: var(--type-body); line-height: 1.65;
}
.ctconversation__details {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--grid-gap);
  margin-top: clamp(3rem, 8vh, 6rem);
  line-height: 1.6;
}

.ctmail {
  display: grid; justify-items: center;
  gap: clamp(1.5rem, 5vh, 3rem);
  padding: 0 var(--pad) clamp(4rem, 14vh, 9rem);
  text-align: center;
}
.ctmail__lbl { font-size: 0.875rem; opacity: 0.5; }
.ctmail__body {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.35rem, 2.6vw, 4.2rem);
  line-height: 1.24;
  display: grid; gap: 0.25em;
}
.ctmail__body a { display: block; }
.ctmail__body a:hover { opacity: 0.6; }

/* the form is a stack of full-bleed lines, and the whole line is the
   field: the placeholder sits centred in it and there is no box */
.ctform { grid-column: 7 / -1; padding: 0; }
.ctform__label { margin-bottom: clamp(2.5rem, 6vh, 4.5rem); opacity: 0.62; }
.ctform__line {
  display: grid; grid-template-columns: 8rem minmax(0, 1fr);
  align-items: baseline; gap: 1rem;
  border-top: 1px solid var(--rule);
}
.ctform__line:last-of-type { border-bottom: 1px solid var(--rule); }
.ctform__line label {
  padding-left: 0.15rem;
  font-family: var(--sans); font-size: var(--type-label);
  letter-spacing: 0.1em; text-transform: uppercase; opacity: 0.55;
}
.ctform input,
.ctform textarea {
  width: 100%;
  background: none; border: 0; color: inherit;
  font: inherit;
  font-size: clamp(0.85rem, 0.86vw, 1.375rem);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-align: left; text-transform: none; letter-spacing: 0;
  padding: clamp(1.5rem, 3.5vh, 2.4rem) 0;
  resize: none;
}
.ctform textarea { line-height: 1.5; }
.ctform input::placeholder,
.ctform textarea::placeholder { color: currentColor; opacity: 0.42; }
.ctform input:focus,
.ctform textarea:focus { outline: none; opacity: 1; }
.ctform__go { text-align: right; padding: clamp(2rem, 5vh, 3.5rem) 0 0; }
.ctform__go button {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.2rem, 2.4vw, 2.6rem);
  border-bottom: 1px solid currentColor;
  padding-bottom: 0.1em;
}
.ctform__go button:hover { opacity: 0.6; }
.ctform__note {
  text-align: right;
  padding: clamp(1rem, 3vh, 1.6rem) 0 0;
  opacity: 0.7;
}
.ctform__note:empty { display: none; }

.ctfoot {
  display: flex; flex-wrap: wrap;
  justify-content: space-between; gap: 1rem;
  padding: 0 var(--pad) clamp(3rem, 10vh, 5rem);
  opacity: 0.6;
}
.ctfoot a { margin-right: 1.2rem; }

@media (max-width: 48rem) {
  body.p-contact .ctsay { padding-top: 1.2rem; padding-bottom: 4.5rem; }
  body.p-contact .ctsay__body { font-size: var(--type-deck-sm); line-height: 1; }
  .ctconversation { grid-template-columns: minmax(0, 1fr); gap: 5rem; padding-bottom: 6rem; }
  .ctconversation__aside,
  .ctform { grid-column: 1; }
  .ctconversation__free { font-size: clamp(3.6rem, 15vw, 5rem); }
  .ctconversation__details { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  .ctform__line { grid-template-columns: minmax(0, 1fr); gap: 0; padding-top: 1.1rem; }
  .ctform input,
  .ctform textarea { padding-top: 0.7rem; }
  .ctform__go,
  .ctform__note { text-align: left; }
  .ctfoot { justify-content: center; text-align: center; }
}

/* =============================================================
   CLIENT PORTAL
   The one utility screen on the site, so it is the one screen that
   should not perform: a single centred column on the sand ground, the
   two fields ruled rather than boxed, and the studio's own serif on
   the name and the button. Everything else the site does, it does not
   do here.
   ============================================================= */
.p-portal { background: var(--bg); }
.pt {
  min-height: min(88svh, 58rem);
  display: grid; place-items: center;
  padding: var(--section-y-lg) var(--pad);
}
.pt__box {
  width: min(var(--content-width), 100%);
  display: grid;
  grid-template-columns: minmax(10rem, 1fr) minmax(18rem, 2.35fr);
  gap: var(--grid-gap);
  text-align: left;
}
.pt__lbl { opacity: 0.5; display: block; align-self: start; }
.pt__title {
  grid-column: 2;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-section);
  line-height: 0.9;
  margin-bottom: clamp(2rem, 7vh, 4rem);
}
.pt__form { grid-column: 2; width: min(42rem, 100%); }
.pt__line {
  display: grid; gap: 0.45rem;
  text-align: left;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 0.6rem;
  margin-bottom: clamp(1.4rem, 4vh, 2rem);
}
.pt__line label { opacity: 0.5; }
.pt__line input {
  width: 100%;
  background: none; border: 0; color: inherit;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1rem, 1.5vw, 1.35rem);
  line-height: 1.4;
  padding: 0.1rem 0;
}
.pt__line input:focus { outline: none; }
.pt__line:focus-within { border-bottom-color: var(--ink); }
.pt__go { margin-top: clamp(1.6rem, 5vh, 2.6rem); }
.pt__go button {
  width: 100%;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.05rem, 1.7vw, 1.5rem);
  padding: 0.72em 1em;
  border: 1px solid var(--ink);
  transition: background 0.4s var(--ease), color 0.4s var(--ease);
}
.pt__go button:hover { background: var(--ink); color: var(--bg); }
.pt__note {
  margin-top: clamp(1rem, 3vh, 1.5rem);
  line-height: 1.5;
  opacity: 0.75;
  min-height: 1.2em;
}
.pt__note:empty { min-height: 0; }
.pt__foot { grid-column: 2; margin-top: clamp(2.2rem, 7vh, 3.4rem); opacity: 0.45; }
.pt__foot a { border-bottom: 1px solid currentColor; padding-bottom: 0.1em; }

/* The portal is a task, not a campaign page. One quiet, centred column is
   immediately available on every screen; photography and display titles do
   not compete with sign-in. */
.portalclean {
  position: relative;
  isolation: isolate;
  min-height: 100svh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: calc(var(--bar-h) + clamp(2rem, 6vh, 4rem)) var(--pad) clamp(2rem, 6vh, 4rem);
  background: var(--bg);
  color: var(--ink);
}
.portalclean__media {
  position: absolute;
  inset: 0;
  z-index: -2;
  overflow: hidden;
  background: var(--bg);
}
.portalclean__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(233, 226, 216, 0.68), rgba(233, 226, 216, 0.82));
}
.portalclean__media img {
  width: 100%; height: 100%;
  display: block; object-fit: cover; object-position: 50% 50%;
  opacity: 0.25;
  transform: scale(1.015);
}
.portalclean__box {
  position: relative;
  z-index: 1;
  width: min(29rem, 100%);
  padding: clamp(2rem, 5vw, 3.5rem);
  border: 1px solid rgba(51, 44, 40, 0.18);
  background: rgba(233, 226, 216, 0.82);
  backdrop-filter: blur(0.55rem);
  -webkit-backdrop-filter: blur(0.55rem);
}
.portalclean__label { margin-bottom: clamp(1.6rem, 4vh, 2.4rem); text-align: center; color: var(--greige); }
.portalclean__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3.5rem, 6vw, 5.75rem);
  line-height: 0.88; letter-spacing: -0.025em;
  margin-bottom: clamp(2.5rem, 6vh, 4rem);
  text-align: center;
}
.portalclean .pt__form { width: 100%; }
.portalclean .pt__line { margin-bottom: 1.6rem; padding-bottom: 0.75rem; }
.portalclean .pt__line input { min-height: 2.75rem; font-size: 1.2rem; }
.portalclean .pt__go { margin-top: 2rem; }
.portalclean .pt__go { text-align: left; }
body .portalclean .pt__go button {
  width: 100%;
  min-height: 3.5rem;
  background: var(--ink);
  color: var(--bg);
  border: 0;
  padding: 0.75rem 1rem;
}
body .portalclean .pt__go button:hover { background: var(--wine); color: var(--off); opacity: 1; }
.portalclean .pt__note { min-height: 1.2em; text-align: center; }
.portalclean__help { margin-top: 1.8rem; text-align: center; color: var(--greige); line-height: 1.55; }
.portalclean__help a { display: block; width: fit-content; margin: 0.35rem auto 0; color: var(--ink); }

@media (max-width: 48rem) {
  .portalclean { padding-inline: 1.25rem; }
  .portalclean__box { width: 100%; padding: 2rem 1.35rem; }
  .portalclean__label { margin-bottom: 1.4rem; }
  .portalclean__title { font-size: clamp(3.7rem, 18vw, 5rem); margin-bottom: 2.5rem; }
  .portalclean .pt__line { margin-bottom: 1.35rem; }
  .portalclean .pt__line input { min-height: 3rem; font-size: 1.1rem; }
  .portalclean .pt__go button { min-height: 3.75rem; font-size: 1.25rem; }
  .portalclean__help { margin-top: 1.5rem; }
  .portalclean__media::after { background: rgba(233, 226, 216, 0.74); }
  .portalclean__media img { object-position: 58% 50%; opacity: 0.24; }
}

/* ---------- a line at a time ----------
   Each rendered line sits in an overflow-hidden mask and plays a
   one-shot, time-based arrival when its block reaches the waypoint. */
.sl-mask {
  display: block;
  position: relative;
  overflow: hidden;
  width: 100%;
  padding-block: 0.08em 0.16em;
  margin-block: -0.08em -0.16em;
}
.sl {
  display: block;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(100%);
  transition: opacity var(--motion-enter), transform var(--motion-enter);
  transition-delay: calc(var(--i, 0) * var(--motion-stagger));
}
.is-split[data-reveal="left"] .sl { transform: translateX(-6.25rem); }
.is-in .sl,
.sl-mask.is-in .sl,
.is-split.is-in[data-reveal="left"] .sl { opacity: 1; transform: none; }

/* a block whose lines carry the arrival must not also fade as a block */
.is-split:not([data-scroll-text]) { opacity: 1 !important; transform: none !important; animation: none !important; }
.is-split[data-scroll-text] { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  .sl { opacity: 1; transform: none; transition: none; animation: none; }
}

/* ---------- rows (services, values) ---------- */
.rows { border-top: 1px solid var(--rule); }
.row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: clamp(1rem, 3vw, 2rem);
  padding: clamp(0.85rem, 2.2vh, 1.4rem) var(--pad);
  border-bottom: 1px solid var(--rule);
}
.row__name { font-family: var(--display); font-weight: 300; font-size: clamp(1.05rem, 1.9vw, 1.45rem); }
.row__lines { text-align: right; }
/* the tier's right column reads top down: who it is for, what it
   includes, what you are left holding */
.row__right { text-align: left; }
.row__right .row__lines { text-align: left; opacity: 0.8; }
.row__for {
  max-width: 44ch;
  margin-bottom: clamp(0.6rem, 1.6vh, 1rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1rem, 1.5vw, 1.25rem);
  line-height: 1.35;
}
.ptiers .row { padding-block: clamp(1.4rem, 3.5vh, 2.2rem); }

/* ---------- responsive ---------- */
@media (max-width: 60rem) {
  .idx { grid-template-columns: minmax(0, 1fr); }
  .idx__filters, .idx__clients { border-right: 0; border-bottom: 1px solid var(--rule); }
  .idx__aside { flex-direction: row; align-items: center; }
}

/* The wordmark must keep a real clear zone. The complete navigation is
   wider than a conventional tablet breakpoint—especially in German—so
   it changes to the compact menu while there is still enough room for
   the mark to remain optically centred instead of touching STUDIO. */
@media (max-width: 78rem) {
  .bar__links { display: none; }
  .bar__r > .langs { display: none; }
  .bar__burger { display: block; }
}

@media (max-width: 48rem) {
  /* A phone has no width to give away, so a long name breaks instead
     of shrinking to nothing: it is sized off its widest single word
     and takes as many lines as it needs. Nothing is ever cropped and
     nothing is ever illegible. */
  .plate__title {
    white-space: normal;
    line-height: 0.88;
    font-size: min(24vw, calc(100vw / var(--emw, 4)));
  }
  .say__body { font-size: clamp(1.25rem, 5.2vw, 1.8rem); }

  /* the six service labels ring the canvas on a desktop; on a phone
     there is no room for them without fouling the bar, and the
     services page carries the same list in full */
  .ring { display: grid; align-content: center; gap: 0.15rem; padding: var(--bar-h) var(--pad) 6rem; }
  .ring__lbl { display: none; }
  .ring__leaders { display: none; }
  .canvas { position: relative; height: 58vh; margin: 1rem 0; }
  .drag { position: static; margin-top: 1rem; }

  .grid { grid-template-columns: minmax(0, 1fr); }
  .cell:nth-child(odd) { border-right: 0; }

  .idx__row { grid-template-columns: minmax(6rem, 0.5fr) minmax(0, 1fr); }
  .idx__list { columns: 1; }

  .row { grid-template-columns: minmax(0, 1fr); }
  .row__lines { text-align: left; }

  .pjopen {
    grid-template-columns: 1fr;
    gap: 2.6rem;
    padding: 1.2rem var(--pad) 3.5rem;
  }
  .pjopen__eyebrow,
  .pjopen__lead,
  .pjopen__deck,
  .pjfacts { grid-column: 1; }
  .pjopen__lead { font-size: clamp(3.1rem, 15vw, 5rem); }
  .pjopen__deck { font-size: clamp(1.8rem, 8.5vw, 3rem); }
  .pjfacts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem 1rem; }

  .pjcollage { height: 145vw; margin: 0 0 5rem; }
  .pjcollage__frame--1 { left: -5%; top: 7%; width: 34%; height: 28%; }
  .pjcollage__frame--2 { left: 12%; top: 24%; width: 53%; height: 44%; }
  .pjcollage__frame--3 { left: 56%; top: 4%; width: 27%; height: 22%; }
  .pjcollage__frame--4 { left: 42%; top: 42%; width: 58%; height: 49%; }
  .pjcollage__frame--5 { left: 4%; top: 69%; width: 36%; height: 27%; }
  .pjcollage__frame--6 { right: -6%; top: 17%; width: 35%; height: 31%; }

  .pjessay { gap: 4.5rem; padding-bottom: 6rem; }
  .pjgallery__shot--wide img { aspect-ratio: 4 / 3; }
  .pjgallery__shot--wide,
  .pjgallery__shot--quiet { width: calc(100% - 2 * var(--pad)); margin-inline: var(--pad); }
  .pjgallery__pair,
  .pjgallery__pair--reverse { grid-template-columns: 1fr; gap: 2.5rem; }
  .pjgallery__pair--reverse > :first-child { order: 0; }
  .pjgallery__shot--portrait { width: 78%; }
  .pjgallery__shot--landscape { width: 86%; margin-left: auto; }
  .pjnote {
    grid-template-columns: 1fr;
    gap: 2rem;
    padding: 1.5rem var(--pad);
  }
  .pjnote__label,
  .pjnote--right .pjnote__label,
  .pjnote__copy,
  .pjnote--right .pjnote__copy { grid-column: 1; grid-row: auto; text-align: left; }
  .pjnote__copy { font-size: clamp(1.7rem, 7.5vw, 2.65rem); }

  .pjcontact { grid-template-columns: 1fr; gap: 2.2rem; padding: 5rem var(--pad); }
  .pjcontact > p,
  .pjcontact h2,
  .pjcontact a { grid-column: 1; }
  .pjcontact h2 { font-size: clamp(3.2rem, 14vw, 5rem); }
  .pjcontact a { justify-self: start; }
  .pjmore__title { display: block; font-size: clamp(4.3rem, 22vw, 7rem); }
  .pjmore__title span { display: block; }
  .pjmore__title span:last-child { text-align: right; }
  .pjmore__field { min-height: 210vw; margin-top: 1rem; }
  .pjmore__project--1 { grid-column: 1 / 9; margin-top: 10vw; }
  .pjmore__project--2 { grid-column: 5 / 13; margin-top: -7vw; }
  .pjmore__project--3 { grid-column: 1 / 9; margin-top: 9vw; }
  .ct__row { grid-template-columns: minmax(0, 1fr); gap: 1.4rem; }
  .ct__foot { grid-template-columns: minmax(0, 1fr); }
  .ct__foot > :last-child { text-align: left; }
}

/* =============================================================
   THE OPENING AND THE LANDING REEL
   ============================================================= */

/* Nothing on the landing page moves until the opening has finished.
   ALET holds its whole page for 2.3 seconds behind a fixed panel and
   every reveal on the page carries that delay; this is that clock. The
   moment the opening has played once, the hold drops to nothing, so a
   visitor never waits for it twice in one session. */
:root { --hold: 0s; }
/* the opening is playing on this load, so the page waits for it */
html.opening { --hold: 2.3s; }

/* While the opening is on screen, nothing underneath it can be
   pressed. This is done in CSS rather than by a class the script adds,
   because the script is deferred and the opening starts at first
   paint: a click in that gap used to fall straight through into a
   project the visitor could not even see. The lock lets itself out
   when the card has finished parting.

   pointer-events is a discrete property, so a zero-length animation on
   a delay is simply a timer that CSS can run on its own. */
@keyframes unlock { to { pointer-events: auto; } }
/* and if the script never runs, the card stops catching them anyway */
@keyframes fall-through { to { pointer-events: none; } }
html.opening .intro { animation: fall-through 0s linear 2.4s forwards; }
html.opening .slide__hit,
html.opening .reel__step,
html.opening .reel__arrows {
  pointer-events: none;
  animation: unlock 0s linear 3.75s forwards;
}


.sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- the brand pattern ----------
   The debossed field printed on the studio's card: hairline bars set in
   bands, every other band shifted half a pitch, each bar a dark stroke
   with a light one beside it so it reads as pressed into the paper
   rather than drawn on it. Two layers, no elements per bar. */
.deboss {
  position: absolute; inset: 0;
  overflow: hidden; pointer-events: none;
  --pitch: clamp(26px, 2.7vw, 46px);
  --band: calc(var(--pitch) * 1.8);
  --emb-lo: rgba(0, 0, 0, 0.26);
  --emb-hi: rgba(255, 255, 255, 0.09);
}
.deboss i {
  position: absolute; inset: 0; display: block;
  background-image: repeating-linear-gradient(
    90deg,
    transparent 0 calc(var(--pitch) - 4px),
    var(--emb-lo) calc(var(--pitch) - 4px) calc(var(--pitch) - 2px),
    var(--emb-hi) calc(var(--pitch) - 2px) calc(var(--pitch) - 1px),
    transparent calc(var(--pitch) - 1px) var(--pitch)
  );
  -webkit-mask-image: repeating-linear-gradient(
    180deg,
    #000 0 calc(var(--band) - 4px),
    transparent calc(var(--band) - 4px) calc(var(--band) * 2)
  );
  mask-image: repeating-linear-gradient(
    180deg,
    #000 0 calc(var(--band) - 4px),
    transparent calc(var(--band) - 4px) calc(var(--band) * 2)
  );
}
/* the shifted band */
.deboss i + i {
  background-position-x: calc(var(--pitch) / 2);
  -webkit-mask-position: 0 var(--band);
  mask-position: 0 var(--band);
}

/* ---------- the opening ---------- */
.intro {
  position: fixed; inset: 0; z-index: 90;
  -webkit-user-select: none;
  user-select: none;
  /* The card catches every click while it is up. Locking the things
     underneath it one by one depends on how a given browser hit-tests
     pointer-events, and that is not something to gamble a visitor's
     first three seconds on. Here the card simply is what you clicked,
     which is also the truth: it is the only thing you can see. */
  pointer-events: auto;
  color: var(--off);
  overflow: hidden;
}
html:not(.opening) .intro { display: none; }

/* The ground is the burgundy of the card, in two halves that part on
   the same axis the wordmark is split across. */
.intro__sheet {
  position: absolute; left: 0; width: 100%; height: 50.1%;
  background: var(--wine);
  overflow: hidden;
  will-change: transform;
}
.intro__sheet--t { top: 0; }
.intro__sheet--b { bottom: 0; }
.intro__sheet .deboss { height: 100svh; height: 100dvh; }
.intro__sheet--t .deboss { top: 0; bottom: auto; }
.intro__sheet--b .deboss { bottom: 0; top: auto; }

/* ---------- the opening's corners ----------
   The corners carry the manual's own page furniture and nothing else:
   the small tracked cells that sit at the foot of every page of it.
   The card is left otherwise bare so the parting sheets are the only
   move in the opening. */
.intro__cell {
  position: absolute; z-index: 1;
  color: var(--off);
  opacity: 0.55;
  font-size: 0.625rem;
  letter-spacing: 0.16em;
}
.intro__cell--tr { top: 1.5rem; right: 1.5rem; }
.intro__cell--bl { bottom: 1.5rem; left: 1.5rem; }

/* --- the opening's clock, kept to the reference's own beats --- */
@keyframes part-up { to { transform: translateY(-100%); } }
@keyframes part-down { to { transform: translateY(100%); } }
@keyframes fade-out { to { opacity: 0; } }

/* the move the whole opening is built around */


@keyframes cell-in { from { opacity: 0; } to { opacity: 0.55; } }

.intro__cell { animation: cell-in 0.8s var(--out) 0.45s both, fade-out 0.45s var(--in) 1.25s forwards; }

.intro__sheet--t { animation: part-up 0.8s var(--in-out) 1.35s forwards; }
.intro__sheet--b { animation: part-down 0.8s var(--in-out) 1.35s forwards; }

/* ---------- the landing reel ----------
   One project at a time, full bleed, advancing on its own. */
.reel {
  position: absolute; inset: 0; overflow: hidden;
  background: var(--noir);
  /* a photograph is not a paragraph: without this a stray drag selects
     the whole page, and every element picks up the selection colour */
  -webkit-user-select: none;
  user-select: none;
  /* the frames are turned by a horizontal drag, so the browser must
     not claim that gesture for its own back-swipe */
  touch-action: pan-y;
}
.reel__stage { position: absolute; inset: 0; }

.slide {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden;
  transition: opacity 1.2s var(--ease), visibility 0s linear 1.2s;
  --delay: 0s;
}
.slide[data-slide="0"] { --delay: var(--hold); }
html.cycled .slide[data-slide="0"] { --delay: 0s; }
.slide.is-on { opacity: 1; visibility: visible; transition: opacity 1.2s var(--ease), visibility 0s; }

.slide__hit { position: absolute; inset: 0; display: block; cursor: pointer; }
.slide__img { position: absolute; inset: 0; display: block; overflow: hidden; }
.slide__img img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: var(--crop, 50% 50%);
  transform: scale(1.04);
  pointer-events: none;
}
/* One frame dissolves into the next. The only movement is a slow, even
   drift across the whole hold, so the room is never still and the
   change of project is never an effect. */
@keyframes drift {
  from { transform: scale(1); }
  to { transform: scale(1.055); }
}
/* 5.5s, not 11s: it has to span the whole time a frame is up, which is
   the DWELL in app.js plus the crossfade. Both were halved together. */
.slide.is-on .slide__img img { animation: drift 5.5s linear both; animation-delay: var(--delay); }
/* type has to stay legible over a photograph */
.slide__img::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(to top,
      rgba(24, 18, 16, 0.78) 0%,
      rgba(24, 18, 16, 0.44) 22%,
      rgba(24, 18, 16, 0.16) 44%,
      rgba(24, 18, 16, 0) 66%),
    linear-gradient(to bottom, rgba(24, 18, 16, 0.4), rgba(24, 18, 16, 0) 22%);
}

/* ---------- the mark on the landing page ----------
   The index is the one screen where the studio should announce itself,
   so the wordmark comes off the bar and stands in the middle of the
   photograph. The bar's own copy steps aside while that chapter is
   showing, because the name has no business being on screen twice. */
.reel__mark {
  /* above the opening's card, because it is standing on it */
  position: absolute; inset: 0; z-index: 95;
  display: grid; place-content: center;
  pointer-events: none;
  color: var(--off);
  filter: drop-shadow(0 1px 16px rgba(24, 18, 16, 0.5));
}
/* small on purpose. A mark this size reads as confidence rather than
   announcement, and it leaves the room the photograph is of. */
:root {
  --hail-fs: clamp(0.95rem, 1.6vw, 1.4rem);
  /* The reference sets its tracked lines at two sizes above the small
     furniture: 23px for a statement's own label and 29.3px where the
     line is carrying the section on its own. Both measured off its DOM
     at a 2560 viewport. Our .lbl stays at 11px for nav, captions and
     page furniture; these are for the lines that are doing the talking. */
  --lbl-md: clamp(0.78rem, 0.9vw, 1.45rem);
  --lbl-lg: clamp(0.8rem, 1.145vw, 1.85rem);
  /* The mark is always laid out at its opening size and scaled down to
     its resting one. Animating the width instead re-ran layout on every
     frame, which is what the stutter was, and scaling *up* from the
     small size is what made it soft. Laid out large and scaled down,
     it is rasterised once at full detail and moved by the compositor:
     sharp at every moment and smooth all the way. */
  --mark-w: min(62vw, 58rem);
  --mark-k: 0.195;
}
.reel__mark .wm {
  width: var(--mark-w);
  transform: scale(var(--mark-k));
  transform-origin: 50% 50%;
}
.reel__mark .wm svg { width: 100%; height: auto; }
/* Arriving with the opening already over: it simply settles. */
@keyframes settle {
  from { opacity: 0; transform: scale(1.055); }
  to { opacity: 1; transform: none; }
}
.reel__mark { animation: settle 1.4s var(--out) 0.25s both; }

/* Arriving with the opening: the same mark, and there is only ever one
   of it. It appears large on the burgundy while the card is up, holds
   through the rotation, and shrinks into its resting size on the same
   beat the card parts. Nothing is drawn twice, so nothing can jump.

   The mark grows by laying out wider, not by being scaled: a CSS
   transform rasterises the artwork once at its small size and then
   stretches the bitmap, which is exactly how a vector logo ends up
   looking soft. Animating the width re-renders it at every size. */
@keyframes mark-land {
  0% { opacity: 0; transform: scale(1); animation-timing-function: var(--out); }
  11% { opacity: 1; transform: scale(1); animation-timing-function: linear; }
  61% { opacity: 1; transform: scale(1); animation-timing-function: var(--land); }
  100% { opacity: 1; transform: scale(var(--mark-k)); }
}
html.opening .reel__mark { animation: none; }
html.opening .reel__mark .wm { animation: mark-land 3.55s both; will-change: transform; }

body.p-home:has(.chapter[data-chapter="0"].is-on) .bar__mark {
  opacity: 0;
  pointer-events: none;
}
.bar__mark { transition: opacity 0.5s var(--ease); }

/* ---------- the sentence that holds the carousel together ----------
   The reference opens on a plain declarative sentence about itself,
   set in the light serif and centred. That is the register here too:
   who the studio is and what it does, no tagline, no claim. It does
   not change with the frames; the frames change under it. */
.hail {
  /* centred by margin rather than by a transform, because the entry
     animates transform and would otherwise knock it off centre */
  position: absolute; left: 0; right: 0;
  bottom: calc(clamp(1.6rem, 5vh, 3.4rem) + env(safe-area-inset-bottom));
  width: min(64rem, 84vw);
  margin: 0 auto;
  /* above the opening's card, because it is standing on it */
  z-index: 95; pointer-events: none;
  font-family: var(--display); font-weight: 300;
  font-size: var(--hail-fs);
  line-height: 1.24;
  text-align: center;
  color: var(--off);
  text-shadow: 0 1px 22px rgba(24, 18, 16, 0.45);
}
/* The break is authored and it holds at every size. Letting the line
   reflow between the opening and the resting state was the one thing
   in the whole handover that jumped: two lines on the card, one line
   on the photograph. Now it is two either way. */
.hail__line { display: block; }
.hail { animation: rise-line 1.2s var(--out) 0.4s both; }

/* The same sentence, on the same journey: it reads under the mark while
   the card is up and travels down to the foot as the card parts.

   Where it stands while the card is up is measured from the mark, not
   from the viewport. A plain -30vh lift put the sentence a comfortable
   distance under the wordmark on a laptop and half a screen away on a
   tall window, because the mark is centred and sized off the width
   while the lift was read off the height. The lift below cancels the
   height out: it starts at the centre line, comes back down past the
   half-height of the mark plus four tenths of it for air, and then
   past the sentence's own two lines and the foot it rests on. The gap
   under the wordmark is the same on every screen.

   0.0727 is the wordmark's own aspect (51.7 / 711.18), so
   --mark-w * 0.0727 is its height at the size it opens at; 0.0654 is
   that times 0.9, the half-height and the air in one number. */
.hail {
  --hail-h: calc(2 * 1.24em);
  --hail-lift: calc(
    -50vh + clamp(1.6rem, 5vh, 3.4rem) + env(safe-area-inset-bottom) +
    var(--hail-h) + var(--mark-w) * 0.0654
  );
}
@keyframes hail-land {
  0% { opacity: 0; transform: translateY(var(--hail-lift)); animation-timing-function: var(--out); }
  11% { opacity: 1; transform: translateY(var(--hail-lift)); animation-timing-function: linear; }
  58% { opacity: 1; transform: translateY(var(--hail-lift)); animation-timing-function: var(--land); }
  100% { opacity: 1; transform: none; }
}
/* it never changes size, only place: a sentence that is re-set larger
   and then shrunk has to re-lay-out on every frame, and it is the one
   thing on the screen small enough for that to show */
html.opening .hail { animation: hail-land 3.7s both; will-change: transform; }

/* the display line owns the foot of the landing page, so the chapter
   dots step aside there; the page still moves on scroll */
.p-home .hint { display: none; }

/* lines rise as a block */
@keyframes rise-line { from { opacity: 0; transform: translateY(2.2rem); } to { opacity: 1; transform: none; } }

/* the two edge strips, and the words for them */
.reel__step {
  position: absolute; top: 0; bottom: 0; width: 13%;
  z-index: 5; background: none;
}
.reel__step--prev { left: 0; cursor: w-resize; }
.reel__step--next { right: 0; cursor: e-resize; }
.reel__arrows {
  position: absolute; right: var(--pad); top: 50%; transform: translateY(-50%);
  z-index: 6; color: var(--off);
  display: grid; gap: 0.5rem; justify-items: end;
  opacity: 0; transition: opacity 0.4s var(--ease);
}
.reel:hover .reel__arrows { opacity: 0.9; }
.reel__arrows span { width: 1.6rem; height: 1px; background: currentColor; opacity: 0.4; }
.reel__arrows button { letter-spacing: 0.11em; text-transform: uppercase; font-size: 0.6875rem; }

@media (prefers-reduced-motion: reduce) {
  :root { --hold: 0s; }
  .intro { display: none; }
  html.opening .reel__mark .wm,
  html.opening .hail { animation: none; will-change: auto; }
  .slide.is-on .slide__img img,
  .reel__mark,
  .hail { animation: none; }
  .slide__img img { transform: none; }
}

@media (max-width: 48rem) {
  /* on a phone the sentence sets its own breaks; forcing the authored
     one would leave half a line hanging */
  .reel__mark {
    padding-top: calc(var(--bar-h) + env(safe-area-inset-top));
    padding-bottom: calc(6rem + env(safe-area-inset-bottom));
  }
  /* a phone gives the corner glyphs far too much of the screen at the
     desktop size, so they come down to a mark in the corner */
  .intro__cell--tr { top: 1.1rem; right: 1.1rem; }
  .intro__cell--bl { bottom: 1.1rem; left: 1.1rem; }
  /* a phone has far less room, so the mark grows by less and the
     sentence not at all, since any growth would cost it a line */
  :root {
    --mark-w: 88vw;
    --mark-k: 0.523;
  }
  /* on a phone the mark is centred inside its own padding and the
     sentence sets its own breaks, so neither of the measurements the
     desktop lift is built on holds; it goes back to a plain one. */
  /* A rough lift, and only ever the fallback: on a phone the sentence
     reflows, so how tall it is depends on the language and the width
     and cannot be known from a stylesheet. The script measures it and
     overwrites this the moment it runs. */
  .hail {
    width: 86vw;
    --hail-fs: clamp(0.9rem, 3.4vw, 1.1rem);
    --hail-lift: -30vh;
  }
  /* the statement's authored breaks are cut for a wide screen; on a
     phone they would leave three orphans, so the sentence reflows */
  .psay__line { display: inline; }
  .hail__line { display: inline; }
  .reel__arrows { display: none; }
}

/* =============================================================
   STUDIO — after the reference's About page
   A title plate, a statement with single words lifted into italic,
   then three numbered chapters: who the studio is, what it does, and
   who does it. Chapters alternate between the sand ground and the
   dark one, and the first opens with a sentence set enormous in caps
   over a hairline spine with the work scattered along it.
   ============================================================= */

/* ---------- the statement ---------- */
.p-studio main { overflow: clip; }
.lede {
  background: var(--bg);
  position: relative; z-index: 1;
  min-height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr auto;
  align-items: center;
  justify-items: center;
  gap: clamp(2rem, 6vh, 4rem);
  padding: calc(var(--bar-h) + 7vh) var(--pad) clamp(2.5rem, 7vh, 4.5rem);
  text-align: center;
}
.lede__eyebrow, .lede__hint {
  width: min(100%, 46rem);
  max-width: 46rem;
  opacity: 0.72;
}
.lede__line { display: block; }
.lede__body {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.5rem, 2.678vw, 3.6rem);
  line-height: 1.15;
  width: min(66.67vw, 53.35rem);
  max-width: 100%;
}
.lede__body em { font-style: normal; }

/* ---------- a chapter ---------- */
.ch {
  background: var(--noir);
  color: var(--off);
  padding: clamp(5rem, 14vh, 9rem) var(--pad) clamp(5rem, 14vh, 9rem);
  display: grid; justify-items: center;
  gap: clamp(2.4rem, 7vh, 5rem);
  text-align: center;
}
.p-studio section.ch {
  width: 100%;
  box-sizing: border-box;
  grid-template-columns: minmax(0, 1fr);
}
.ch--light { background: var(--bg); color: var(--ink); }
.ch__no { opacity: 0.55; letter-spacing: 0.2em; }

.ch__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.9rem, 3.67vw, 4.6rem);
  line-height: 0.96;
}
.ch__role { opacity: 0.6; margin-top: -1.4rem; }
.ch__para {
  max-width: 40rem;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.05rem, 1.9vw, 1.5rem);
  line-height: 1.4;
  opacity: 0.9;
}
.ch__foot {
  max-width: 44rem;
  opacity: 0.62;
  line-height: 1.8;
}

/* Studio opens on the same seam as a case study: the deck statement
   directly under the photograph, then the studio's own compact record,
   both on the dark ground. */
.ch--opening {
  display: block;
  padding: var(--seam-top) var(--pad) clamp(5rem, 12vh, 8rem);
  text-align: left;
}
.ch__intro {
  width: 100%;
  margin: 0;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
  text-align: left;
  color: var(--off);
}
.ch__intro em { font-style: normal; }
.ch--opening .pjfacts { margin-top: clamp(3rem, 7vh, 5rem); }

/* ---------- section heading ----------
   The shared numbered heading: label and serif title on the 1:3 grid,
   ranged left, the way every editorial transition on the site turns. */
.secthead-wrap {
  background: var(--bg); color: var(--ink);
  padding: var(--section-y) var(--pad) clamp(2rem, 6vh, 3.5rem);
}
.secthead {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) minmax(0, 3fr);
  align-items: end;
  gap: var(--grid-gap);
  text-align: left;
}
.secthead__no { opacity: 0.55; letter-spacing: 0.2em; }
.secthead__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3rem, 5vw, 5.5rem);
  line-height: 0.94;
  letter-spacing: -0.018em;
  text-wrap: balance;
}
@media (max-width: 48rem) {
  .secthead { grid-template-columns: 1fr; gap: 1.7rem; }
  .secthead__title { font-size: clamp(3.25rem, 14.5vw, 5rem); }
}

.studioessay {
  background: var(--bg); color: var(--ink);
  padding: clamp(5rem, 11vh, 9rem) var(--pad) clamp(6rem, 13vh, 10rem);
}
.studioessay__media {
  position: relative;
  min-height: clamp(34rem, 63vw, 65rem);
  margin-bottom: clamp(4rem, 10vh, 8rem);
}
.studioessay__media figure { margin: 0; overflow: hidden; background: var(--stone); }
.studioessay__media img { width: 100%; height: 100%; display: block; object-fit: cover; }
.studioessay__wide { position: absolute; left: 0; top: 0; width: 76%; height: 76%; }
.studioessay__portrait { position: absolute; right: 0; bottom: 0; z-index: 2; width: 31%; height: 58%; }
.studioessay__statement {
  width: 100%;
  margin-bottom: clamp(5rem, 11vh, 9rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.4rem, 4.1vw, 5rem);
  line-height: 0.98; letter-spacing: -0.028em;
  text-align: left;
}
.studioessay__statement em { font-style: normal; }
.studioessay .rows--ch {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(3rem, 7vw, 7rem);
  border: 0;
}
.studioessay .row {
  display: block;
  padding: 0;
  border: 0;
}
.studioessay .row__name { margin-bottom: 1rem; font-size: clamp(1.8rem, 2.7vw, 3rem); }
.studioessay .row__lines { max-width: 36rem; text-align: left; line-height: 1.65; }
.studioessay__foot { max-width: 44rem; margin-top: clamp(4rem, 9vh, 7rem); color: var(--greige); line-height: 1.7; }

/* ---------- the spine ----------
   The work is arranged around a hairline that draws down the page,
   then five, three and one portrait frames arrive around it. */
.spine {
  position: relative;
  width: 100%;
  display: grid;
  gap: clamp(2.5rem, 7vh, 5.5rem);
  justify-items: center;
  padding: clamp(2rem, 6vh, 4rem) 0;
}
.spine::before {
  content: "";
  position: absolute;
  z-index: 0;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: rgba(247, 244, 241, 0.32);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 1.5s var(--in-out);
}
.spine.is-in::before { transform: scaleY(1); }
.spine__row {
  position: relative; z-index: 1;
  width: 100%;
  display: grid;
  align-items: center;
  justify-items: center;
  gap: clamp(1rem, 4vw, 3.5rem);
}
.spine__row--five { grid-template-columns: repeat(5, 1fr); }
.spine__row--three { grid-template-columns: repeat(3, 1fr); width: min(72%, 60rem); }
.spine__f { margin: 0; width: 100%; aspect-ratio: 3 / 4; overflow: hidden; }
.spine__row--five .spine__f { max-width: 7.375rem; }
.spine__row--three .spine__f { max-width: 8.1875rem; }
/* the frames sit at their own heights, the way the reference staggers
   them, rather than lining up like a contact sheet */
.spine__row--five .spine__f:nth-child(2) { translate: 0 -1.6rem; }
.spine__row--five .spine__f:nth-child(4) { translate: 0 -1.6rem; }
.spine__row--five .spine__f:nth-child(3) { translate: 0 0.8rem; }
.spine__row--three .spine__f:nth-child(2) { translate: 0 1.4rem; }
.spine__f img, .spine__hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
.spine__hero {
  position: relative; z-index: 1;
  margin: 0; width: min(16.1875rem, 62vw); aspect-ratio: 3 / 4;
  max-height: 70svh; overflow: hidden;
}

/* ---------- the wall ----------
   A compact wall of six names. A contextual image opens on hover or
   keyboard focus on desktop; phones use the same card as an accordion. */
.wall {
  position: relative;
  background: var(--bg); color: var(--ink);
  padding: 0 var(--pad) clamp(4rem, 10vh, 7rem);
}
.wall__names {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  width: 100%;
}
.wall__item {
  position: relative;
  min-width: 0;
  min-height: clamp(3.2rem, 5.25vw, 6.6rem);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.wall__item:nth-child(even) { align-items: flex-end; }
.wall__item:nth-child(n + 2) { margin-top: -0.15rem; }
.wall__name {
  font-family: var(--display); font-weight: 300;
  text-transform: uppercase;
  font-size: clamp(3rem, 6.27vw, 8rem);
  line-height: 0.8;
  letter-spacing: -0.012em;
  color: var(--greige);
  opacity: 0.7;
  max-width: 100%;
  padding: 0;
  text-align: inherit;
  position: relative;
  z-index: 2;
  transition: opacity 0.35s var(--ease), color 0.35s var(--ease);
}
.wall__item:nth-child(even) .wall__name { text-align: right; }
.wall__name:hover,
.wall__name:focus-visible,
.wall__name.is-on { opacity: 1; color: var(--noir); }
.wall__card {
  position: fixed;
  z-index: 50;
  left: 48vw;
  top: 50%;
  width: min(46vw, 42rem);
  min-width: 0;
  background: var(--stone);
  color: var(--noir);
  padding: clamp(1rem, 2vw, 1.8rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(0.8rem, 2vh, 1.3rem);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  clip-path: inset(0 100% 0 0);
  transform: translate(1.5rem, -50%);
  transition:
    clip-path 1s cubic-bezier(0.16, 1, 0.3, 1),
    transform 1s cubic-bezier(0.16, 1, 0.3, 1),
    opacity 0.25s var(--ease),
    visibility 0s linear 1s;
}
.wall__card.is-on {
  opacity: 1;
  visibility: visible;
  clip-path: inset(0 0 0 0);
  transform: translate(0, -50%);
  transition-delay: 0s;
}
.wall__fig { margin: 0; width: 100%; min-width: 0; aspect-ratio: 16 / 9; overflow: hidden; }
.wall__fig img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wall__body {
  min-width: 0;
  font-size: var(--lbl-md);
  line-height: 1.6;
  opacity: 0.92;
  text-align: left;
  max-width: 62ch;
}

/* ---------- a full-bleed pair of photographs ---------- */
.band {
  display: grid;
  grid-template-columns: 58vw 58vw;
  width: 116vw;
  margin-left: -8vw;
  gap: 2px;
  background: var(--bg);
}
.band__f { margin: 0; aspect-ratio: 1.27 / 1; max-height: 82svh; overflow: hidden; }
.band__f img { width: 100%; height: 100%; object-fit: cover; display: block; filter: grayscale(1); }

/* the portrait that opens the last chapter */
.ch__portrait { margin: 0; width: min(46rem, 78vw); aspect-ratio: 3 / 2; overflow: hidden; }
.ch__portrait img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* a statement inside a chapter, set in the serif with a word or two
   lifted into italic, the way the reference stresses mid-sentence */
.ch__say {
  width: min(100%, 46rem);
  max-width: 46rem;
  box-sizing: border-box;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.25rem, 2.44vw, 3.1rem);
  line-height: 1.24;
}
.ch__say em { font-style: normal; }
.ch--tight { padding-bottom: clamp(2rem, 6vh, 4rem); }

/* ---------- everything arrives as it is scrolled to ----------
   The reference lifts each line into place as it enters, rather than
   having it simply be there. One rule, one observer. */
[data-rise] {
  opacity: 0;
  transform: translateY(2.5rem);
  transition: opacity var(--motion-enter), transform var(--motion-enter);
  /* --rise-i orders a group: a list arrives down its own length rather
     than all at once, which is what the reference does to every stack
     of lines on its pages */
  transition-delay: calc(var(--rise-i, 0) * 90ms);
}
[data-rise][data-reveal="left"] { transform: translateX(-6.25rem); }
[data-rise].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  [data-rise] { opacity: 1; transform: none; transition: none; }
}

/* ---------- what the studio does ---------- */
.expertise {
  width: min(64rem, 100%);
  display: grid;
  text-align: left;
  border-top: 1px solid var(--rule);
}
.expertise__item {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr) minmax(0, 1.4fr);
  align-items: baseline;
  gap: 1rem;
  padding: clamp(0.9rem, 2.2vh, 1.4rem) 0;
  border-bottom: 1px solid var(--rule);
}
.expertise__no { opacity: 0.5; }
.expertise__name {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.1rem, 2vw, 1.6rem);
  line-height: 1.1;
}
.expertise__line { opacity: 0.7; font-size: 0.8125rem; line-height: 1.5; }
.rows--ch { width: min(64rem, 100%); text-align: left; }

@media (max-width: 48rem) {
  .lede {
    gap: clamp(1.5rem, 5vh, 3rem);
    padding-top: calc(var(--bar-h) + 4rem);
  }
  .lede__body { width: 100%; font-size: clamp(1.45rem, 7.4vw, 2.45rem); }
  .spine__row--five { grid-template-columns: repeat(3, 1fr); }
  .spine__row--five .spine__f:nth-child(n + 4) { display: none; }
  .spine__row--three { width: 100%; }
  .spine__row--five .spine__f,
  .spine__row--three .spine__f { max-width: 6.5rem; }
  .expertise__item { grid-template-columns: 2.2rem minmax(0, 1fr); }
  .expertise__line { grid-column: 2; }

  .wall { padding-bottom: clamp(3rem, 8vh, 5rem); }
  .wall__item,
  .wall__item:nth-child(even) { align-items: stretch; min-height: 0; }
  .wall__item:nth-child(n + 2) { margin-top: 0.35rem; }
  .wall__name,
  .wall__item:nth-child(even) .wall__name {
    width: 100%;
    font-size: clamp(2.2rem, 10.5vw, 3.2rem);
    line-height: 0.86;
    text-align: left;
    padding: 0.12em 0;
  }
  .wall__card {
    position: relative;
    inset: auto;
    z-index: 1;
    width: 100%;
    box-sizing: border-box;
    max-height: 0;
    margin-top: 0;
    padding: 0 var(--pad);
    opacity: 0;
    visibility: visible;
    overflow: hidden;
    clip-path: none;
    transform: none;
    transition:
      max-height 0.8s var(--land),
      margin 0.8s var(--land),
      padding 0.8s var(--land),
      opacity 0.35s var(--ease);
  }
  .wall__card.is-on {
    max-height: 42rem;
    margin-top: 0.75rem;
    padding: var(--pad);
    opacity: 1;
    transform: none;
  }
  .band {
    grid-template-columns: 1fr;
    width: 100%;
    margin-left: 0;
  }
  .band__f { aspect-ratio: 4 / 5; max-height: none; }
  .ch__portrait { width: 100%; }
  .ch--opening { padding-top: 1.2rem; padding-bottom: 4.5rem; }
  .ch__intro { font-size: var(--type-deck-sm); line-height: 1; }
  .ch--opening .pjfacts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem 1rem; margin-top: 2.5rem; }
  .studioessay { padding: 4.5rem var(--pad) 6rem; }
  .studioessay__media { min-height: 128vw; margin-bottom: 4.5rem; }
  .studioessay__wide { width: 91%; height: 64%; }
  .studioessay__portrait { width: 58%; height: 53%; }
  .studioessay__statement { font-size: clamp(2.15rem, 10.5vw, 3.4rem); margin-bottom: 4.5rem; }
  .studioessay .rows--ch { grid-template-columns: 1fr; gap: 3.5rem; }
}


/* =============================================================
   WORK — one archive, three addressable views
   The opening plate above is deliberately untouched. This layer starts
   after it: a concise introduction, a sticky category control and an
   image-first archive. All, Residential and Commercial are views of
   the same data, so new projects only need to be added once.
   ============================================================= */
body.p-work { overflow-x: clip; }
.work { background: var(--bg); }

.workintro {
  min-height: min(72svh, 52rem);
  display: grid;
  grid-template-columns: minmax(10rem, 1fr) minmax(0, 2.35fr);
  grid-template-rows: auto 1fr;
  gap: clamp(2rem, 5vw, 5rem);
  padding: clamp(5rem, 12vh, 8rem) var(--pad) clamp(5rem, 12vh, 8rem);
}
.workintro__eyebrow { align-self: start; }
.workintro__statement {
  grid-column: 2;
  align-self: center;
  display: grid;
  grid-template-columns: minmax(0, 1.65fr) minmax(14rem, 0.65fr);
  gap: clamp(3rem, 7vw, 7rem);
  align-items: end;
}
.workintro__statement h2 {
  max-width: 16ch;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3rem, 5.65vw, 6rem);
  line-height: 0.94; letter-spacing: -0.022em;
}
.workintro__aside { padding-bottom: 0.35rem; }
.workintro__aside p { max-width: 27rem; line-height: 1.7; }

/* The selector behaves as quiet editorial navigation, not as a ruled
   dashboard. It remains available while the portfolio passes beneath. */
.workfilter {
  position: sticky; top: calc(var(--bar-h) + env(safe-area-inset-top));
  z-index: 38;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 4.5rem;
  padding: 0 var(--pad);
  background: color-mix(in srgb, var(--bg) 91%, transparent);
  backdrop-filter: blur(16px);
}
.workfilter__label { color: var(--greige); }
.workfilter__options {
  display: flex;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 4.5rem);
}
.workfilter__option {
  position: relative;
  display: block;
  padding: 0.6rem 0;
  color: var(--greige);
  text-transform: uppercase; letter-spacing: 0.08em;
  transition: color 0.35s var(--ease);
}
.workfilter__option:hover { color: var(--ink); }
.workfilter__option::after {
  content: "";
  position: absolute;
  left: 0; right: 100%; bottom: 0.25rem;
  height: 1px;
  background: currentColor;
  transition: right 0.45s var(--out);
}
.workfilter__option[aria-current="true"] { color: var(--ink); }
.workfilter__option[aria-current="true"]::after { right: 0; }

.workarchive {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  align-items: start;
  column-gap: clamp(0.75rem, 1.6vw, 1.5rem);
  row-gap: clamp(3.5rem, 7vh, 5.5rem);
  padding: clamp(2.5rem, 5vh, 4rem) var(--pad) clamp(5rem, 10vh, 7rem);
}
.workcard {
  grid-row: var(--work-row);
  min-width: 0;
  display: block;
  position: relative;
}
.workcard[hidden] { display: none; }
.workcard.is-lead {
  grid-column: 1 / -1;
  justify-self: start;
  width: min(100%, 145.78svh);
}
.workcard.is-west { grid-column: 1 / 8; }
.workcard.is-east { grid-column: 9 / 13; align-self: end; }
.workcard.is-pair-flip.is-west { grid-column: 1 / 5; margin-top: 0; }
.workcard.is-pair-flip.is-east { grid-column: 6 / 13; align-self: start; margin-top: 0; }
.workcard__figure {
  position: relative; overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--stone);
}
.workcard.is-east .workcard__figure,
.workcard.is-pair-flip.is-west .workcard__figure { aspect-ratio: 3 / 4; }
.workcard.is-pair-flip.is-east .workcard__figure { aspect-ratio: 4 / 3; }
.workcard.is-west .workcard__figure { z-index: 1; }
.workcard.is-east .workcard__figure { z-index: 2; }
.workcard.is-pair-flip.is-west .workcard__figure { z-index: 2; }
.workcard.is-pair-flip.is-east .workcard__figure { z-index: 1; }
.workcard.is-lead .workcard__figure {
  aspect-ratio: 16 / 9;
}
.workcard__img {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 1.1s var(--out), filter 0.6s var(--ease);
}
.workcard__img--portrait { display: none; }
.workcard.is-east:not(.is-pair-flip) .workcard__img--landscape,
.workcard.is-pair-flip.is-west .workcard__img--landscape { display: none; }
.workcard.is-east:not(.is-pair-flip) .workcard__img--portrait,
.workcard.is-pair-flip.is-west .workcard__img--portrait { display: block; }
.workcard__copy {
  position: relative;
  z-index: 3;
  width: 100%;
  padding-top: clamp(0.8rem, 1.7vh, 1.1rem);
  background: var(--bg);
}
.workcard.is-lead .workcard__copy {
  position: relative;
  inset: auto;
  width: 100%;
  padding-top: clamp(0.8rem, 1.7vh, 1.1rem);
  background: var(--bg);
  color: var(--ink);
  text-shadow: none;
}
.workcard__kind {
  display: flex; justify-content: space-between; gap: 1rem;
  color: var(--greige);
}
.workcard.is-lead .workcard__kind { justify-content: space-between; color: var(--greige); }
.workcard__title {
  max-width: none;
  padding: clamp(0.55rem, 1.3vh, 0.85rem) 0 0;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem, 3vw, 3.4rem);
  line-height: 0.92; letter-spacing: -0.022em;
}
.workcard.is-lead .workcard__title {
  max-width: none;
  font-size: clamp(3rem, 5vw, 5.6rem);
  line-height: 0.88;
}

.workdivider {
  grid-row: var(--work-row);
  grid-column: 1 / -1;
  min-height: clamp(30rem, 62svh, 48rem);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-content: center;
  padding-block: clamp(5rem, 11vh, 9rem);
}
.workdivider[hidden] { display: none; }
.workdivider__copy {
  display: none;
  grid-column: 4 / -1;
  max-width: 18ch;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3.4rem, 6.4vw, 7rem);
  line-height: 0.88; letter-spacing: -0.035em;
}
.workdivider--2 .workdivider__copy { grid-column: 1 / 10; justify-self: start; }
.work[data-filter="all"] .workdivider [data-copy-for="all"],
.work[data-filter="residential"] .workdivider [data-copy-for="residential"],
.work[data-filter="commercial"] .workdivider [data-copy-for="commercial"] { display: block; }
@media (hover: hover) and (pointer: fine) {
  .workcard:not(.workcard--archive):hover .workcard__figure img { transform: scale(1.012); }
}
.workcard--archive { cursor: default; }

.work[data-filtering] .workcard:not([hidden]) .workcard__figure,
.work[data-filtering] .workcard:not([hidden]) .workcard__copy {
  animation: workfilter-in 0.7s var(--out) both;
  animation-delay: min(calc(var(--view-i, 0) * 35ms), 175ms);
}
@keyframes workfilter-in {
  from { opacity: 0; transform: translateY(1.5rem); }
  to { opacity: 1; transform: none; }
}


@media (max-width: 64rem) {
  .workintro { grid-template-columns: minmax(8rem, 0.6fr) minmax(0, 2.4fr); }
  .workintro__statement { grid-template-columns: 1fr; }
  .workfilter__label { display: none; }
  .workfilter { justify-content: center; }
}

@media (max-width: 48rem) {
  .workintro {
    min-height: 0;
    grid-template-columns: 1fr; grid-template-rows: auto;
    gap: 3.5rem; padding: 5rem var(--pad) 5rem;
  }
  .workintro__statement { grid-column: 1; }
  .workintro__statement { gap: 1.5rem; }
  .workintro__statement h2 { font-size: clamp(2.85rem, 12.8vw, 4.35rem); }

  .workfilter {
    top: calc(var(--bar-h) + env(safe-area-inset-top));
    min-height: 3.8rem;
    padding: 0 0.7rem;
  }
  .workfilter__options { width: 100%; justify-content: space-around; gap: 0.4rem; }
  .workfilter__option {
    padding: 0.75rem 0.35rem; font-size: 0.65rem; letter-spacing: 0.05em;
  }
  .workarchive {
    grid-template-columns: 1fr;
    gap: 4rem;
    padding-top: 2.5rem;
  }
  .workcard,
  .workcard.is-lead,
  .workcard.is-west,
  .workcard.is-east,
  .workcard.is-pair-flip.is-west,
  .workcard.is-pair-flip.is-east {
    grid-column: 1;
    grid-row: auto;
    align-self: auto;
    width: 100%;
    margin-top: 0;
  }
  .workcard__figure,
  .workcard.is-east .workcard__figure,
  .workcard.is-pair-flip.is-west .workcard__figure,
  .workcard.is-pair-flip.is-east .workcard__figure { height: auto; }
  .workcard.is-lead .workcard__figure { height: auto; aspect-ratio: 4 / 3; }
  .workcard__title { font-size: clamp(2.2rem, 9.5vw, 3.25rem); }
  .workcard.is-lead .workcard__title { font-size: clamp(2.8rem, 12vw, 4rem); }
  .workcard__kind { flex-wrap: wrap; }

  .workdivider {
    grid-column: 1;
    min-height: 70svh;
    grid-template-columns: 1fr;
    gap: 2.5rem;
    padding-block: 5rem;
  }
  .workdivider__copy,
  .workdivider--2 .workdivider__copy {
    grid-column: 1;
    text-align: left;
  }
  .workdivider__copy { font-size: clamp(2.9rem, 13.5vw, 4.6rem); }

}

@media (prefers-reduced-motion: reduce) {
  .work[data-filtering] .workcard:not([hidden]) .workcard__figure,
  .work[data-filtering] .workcard:not([hidden]) .workcard__copy { animation: none; }
  .workcard__figure img { transition: none; }
}

@media (max-width: 48rem) {
  /* ---------- the header photograph is shown whole on a phone --------
     Pavel, 2026-09-20, opening About Us on a phone: "the header image
     must be seen full width." Filling a 100svh screen with
     `object-fit: cover` crops a landscape photograph down to a narrow
     vertical slice of itself, which is the opposite of the studio's own
     rule that a photograph is used in the format it was supplied in.
     So on a phone the plate stops being a screen and becomes the
     picture: full width, its own height, and the page name set
     underneath it on the sand rather than cropped over it. The veil
     goes with it, since it existed only to hold type on the photograph,
     and so does the settle animation, which was scaling the crop. */
  /* The composition is the one from the laptop, scaled — not a
     different layout (Pavel: "we need to keep the same composition on
     laptop, iPad and on iPhone ... we also need to scale the other
     elements, such as the text and the space between this section and
     the one under it"). The photograph keeps the format it was shot in
     and runs the full width; the plate is only as tall as that
     photograph; the name still sits over its foot with the same veil
     behind it, sized off its widest word so it fits the narrower box.
     `#main > .plate` carries an ID, so it outranks any class rule here:
     without naming it the plate stayed a full 100svh and left a screen
     of empty sand under the photograph. */
  /* every hero variant, by the same route the shared rule takes: that
     rule is `body :is(.plate, .pplate, .prhero).pagehero` (0,2,1), and a
     bare `.pagehero--image` lost to it, so Services, whose header is a
     `.pplate`, kept a full screen of height with its name at the foot of
     it, a screen away from the photograph */
  #main > .plate.pagehero--image,
  body :is(.plate, .pplate, .prhero).pagehero.pagehero--image {
    min-height: 0; height: auto;
    overflow: hidden;
  }
  .pagehero--image .plate__img { position: relative; inset: auto; }
  .pagehero--image .plate__img img {
    width: 100%; height: auto;
    object-fit: contain;
    object-position: 50% 50%;
    animation: none;
  }
  .pagehero--image .plate__title {
    font-size: min(24vw, calc(100vw / var(--emw, 4)));
  }
  .p-portal .pagehero .plate__img img { object-position: 56% 50%; }

  .pt { min-height: 0; padding: 5rem var(--pad) 6rem; }
  .pt__box { grid-template-columns: 1fr; gap: 1.8rem; }
  .pt__title,
  .pt__form,
  .pt__foot { grid-column: 1; }
  .pt__title { font-size: clamp(3.5rem, 15.5vw, 5.3rem); margin-bottom: 1rem; }
  .pt__foot { margin-top: 1.5rem; }
}

/* =============================================================
   SITE-WIDE EDITORIAL SYSTEM
   The page compositions remain individual, but their typography,
   arrivals, cards and utility states all speak the same language.
   ============================================================= */

/* Every photographic page opening now enters on the same clock. Titles
   make one short unmasked rise, then remain attached to their section;
   only photography is allowed to carry scroll depth. */
@keyframes pagehero-title-in {
  from { opacity: 0; transform: translate3d(0, 0.18em, 0); }
  to { opacity: 1; transform: none; }
}
@keyframes pagehero-media-in {
  from { opacity: 0.82; transform: scale(1.16); }
  to { opacity: 1; transform: none; }
}
@keyframes pagehero-label-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.pagehero {
  min-height: 100svh; min-height: 100dvh;
  overflow: hidden;
}
.pagehero__title {
  animation: pagehero-title-in var(--motion-title) 0.18s both;
  will-change: transform, opacity;
}
.pagehero__eyebrow {
  animation: pagehero-label-in 0.8s var(--out) 0.48s both;
}
.pagehero--image .plate__img img {
  animation: pagehero-media-in 1.6s var(--out) both;
  transform-origin: 50% 50%;
}

/* One hierarchy for the principal written moments. */
:where(.workintro__statement h2, .pjopen__lead) {
  font-size: var(--type-feature);
  text-wrap: balance;
}
:where(.prarchive__head h2, .praward__head h2) {
  font-size: var(--type-section);
  line-height: 0.88;
  letter-spacing: -0.018em;
  text-wrap: balance;
}
:where(.prarchive__head, .praward__head) {
  grid-template-columns: minmax(8rem, 1fr) minmax(0, 3fr);
  gap: var(--grid-gap);
}
:where(.prarchive__head, .praward__head) {
  margin-bottom: clamp(3.5rem, 8vh, 5rem);
}
:where(.pjnote__copy, .legal__copy) {
  font-size: var(--type-body);
  line-height: 1.72;
}

/* Studio is the benchmark for every top-level opening and editorial
   transition. Compositions may differ, but their scale, crop policy,
   spacing rhythm and interaction voice do not. */
:where(.p-work, .p-studio, .p-process, .p-press, .p-contact, .p-portal) .pagehero {
  height: 100svh;
  height: 100dvh;
  min-height: 100svh;
  min-height: 100dvh;
}
:where(.p-work, .p-studio, .p-process, .p-contact, .p-portal) .pagehero .plate__title {
  color: rgba(247, 244, 241, 0.82);
}
:where(.p-work, .p-studio, .p-process, .p-contact, .p-portal) .pagehero .plate__img img {
  object-position: 50% 50%;
}
:where(.workintro, .lede, .psay, .printro, .ctsay) {
  padding-left: var(--pad);
  padding-right: var(--pad);
}
:where(.workintro__eyebrow, .lede__eyebrow, .ctmail__lbl, .pt__lbl) {
  font-size: var(--type-label);
  letter-spacing: 0.11em;
  line-height: 1.5;
}

/* A stable landscape crop is used across editorial cards. Individual
   photographs can opt into a focal point through --crop. */
:where(.workcard__figure, .prcard__fig) img {
  object-fit: cover;
  object-position: var(--crop, 50% 50%);
}
.prcard:nth-child(2) .prcard__fig img { --crop: 50% 50%; }

/* Arrows and action marks share one motion and never change typographic
   style between archives. */
:where(.praward__read) [aria-hidden="true"] {
  display: inline-block;
  font-style: normal;
  transition: transform 0.35s var(--ease);
}

/* A card is an image, one aligned metadata row and a serif title. The
   complete surface is the link, so explanatory actions are unnecessary. */
.editorial-card { min-width: 0; }
.editorial-card :where(.workcard__figure, .prcard__fig) { background: var(--stone); }
.editorial-card :where(.workcard__figure img, .prcard__fig img) {
  transition: transform var(--motion-card), filter 0.65s var(--ease);
  transform-origin: 50% 50%;
}
.editorial-card:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 0.45rem;
}
@media (hover: hover) and (pointer: fine) {
}

/* The same focus language belongs to every form. The ruled field is
   the compound control, so it takes the focus emphasis as a unit. */
.ctform__line,
.pt__line { transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease); }
.ctform__line:focus-within,
.pt__line:focus-within {
  border-color: var(--ink);
  box-shadow: inset 0 -1px 0 var(--ink);
}
.ctform :is(input, textarea)[aria-invalid="true"],
.pt__line input[aria-invalid="true"] { color: var(--wine); }

/* Legal is a quiet editorial page, not an unstyled document and not a
   fake photographic portfolio page. It uses the same label, display
   type, grid and reveal rhythm as the rest of the site. */
.legal { background: var(--bg); }
.utilityhero {
  min-height: min(68svh, 48rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto 1fr;
  padding: calc(var(--bar-h) + clamp(2rem, 6vh, 4rem)) var(--pad) var(--section-y);
  border-bottom: 1px solid var(--rule);
}
.utilityhero__label { align-self: start; color: var(--greige); }
.utilityhero__title {
  align-self: end;
  justify-self: center;
  width: min(100%, 13ch);
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(4rem, 10vw, 10rem);
  line-height: 0.86;
  letter-spacing: -0.025em;
  text-align: center;
  text-wrap: balance;
}
.legal__body {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  padding: var(--section-y-lg) var(--pad);
}
.legal__lead {
  grid-column: 1 / 5;
  max-width: 30rem;
  font-family: var(--display);
  font-weight: 300;
  font-size: clamp(1.7rem, 2.8vw, 3rem);
  line-height: 1.12;
}
.legal__copy { grid-column: 6 / 11; max-width: var(--measure-copy); }
.legal__copy p + p { margin-top: 1.5rem; }
.legal__copy a { border-bottom: 1px solid currentColor; padding-bottom: 0.08em; }

/* Portal is the utility companion to Legal: smaller in scale, but
   anchored by the same label and reveal instead of a one-off title. */
.pt__box { width: min(34rem, 100%); }
.pt__title { font-size: clamp(2.8rem, 5.2vw, 4.8rem); text-wrap: balance; }

/* Touch and keyboard behaviour is shared rather than page-specific. */
:where(a, button, input, textarea) { touch-action: manipulation; }
:focus-visible { outline-width: 2px; }
@media (max-width: 78rem) {
  .bar__l a,
  .bar__mark {
    display: grid;
    align-items: center;
    min-height: 2.75rem;
  }
  .bar__burger {
    width: 2.75rem;
    height: 2.75rem;
    margin-right: -0.7rem;
  }
  .bar__burger span { left: 0.7rem; right: 0.7rem; }
  .bar__burger span:first-child { top: 1.05rem; }
  .bar__burger span:last-child { bottom: 1.05rem; }
}

@media (max-width: 48rem) {
  .psay { padding: 1.2rem var(--pad) 4rem; }
  .psay__body { font-size: var(--type-deck-sm); line-height: 1; }
  :where(.workintro__statement h2, .pjopen__lead) {
    font-size: clamp(2.7rem, 12.5vw, 4.4rem);
  }
  :where(.prarchive__head, .praward__head) {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.7rem;
  }
  :where(.prarchive__head h2, .praward__head h2) {
    font-size: clamp(3.25rem, 14.5vw, 5rem);
  }
  .prcard--wide .prcard__copy,
  .prcard--center .prcard__copy { grid-template-columns: minmax(0, 1fr); row-gap: 0.2rem; }
  .prcard--wide .prcard__meta,
  .prcard--center .prcard__meta { justify-content: flex-start; }
  .utilityhero { min-height: 62svh; padding-bottom: clamp(4rem, 12vh, 7rem); }
  .utilityhero__title { font-size: clamp(3.7rem, 17vw, 6rem); }
  .legal__body { grid-template-columns: minmax(0, 1fr); gap: 3.5rem; }
  .legal__lead,
  .legal__copy { grid-column: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .pagehero__title,
  .pagehero__eyebrow,
  .pagehero--image .plate__img img { animation: none; }
  .editorial-card :where(.workcard__figure img, .prcard__fig img) { transition: none; }
}

/* =============================================================
   EDITORIAL REBUILD — Studio, Services, Press, Contact (2026-09)
   The case-study grammar applied to the four pages that did not yet
   have it. One rule above all: a photograph is shown at the ratio it
   was delivered in. Frames take a width; their height is their own.
   ============================================================= */
:where(.disc__fig, .stfield__frame, .stfounders__fig, .svstep__fig, .prview__fig, .prrow__thumb, .ctvisit__wide, .ctvisit__portrait) { margin: 0; }
:where(.disc__fig, .stfield__frame, .stfounders__fig, .svstep__fig, .prview__fig, .prrow__thumb, .ctvisit__wide, .ctvisit__portrait) img {
  display: block; width: 100%; height: auto;
  background: var(--stone);
}
/* chapter headings on the editorial pages sit centred, the way the
   reference numbers its chapters, so they share the intro's axis */
.secthead--center {
  grid-template-columns: 1fr;
  justify-items: center;
  gap: clamp(1rem, 2.5vh, 1.6rem);
  text-align: center;
}
.secthead--center .secthead__title { font-size: clamp(2.4rem, 4vw, 4.6rem); }
.secthead--dark .secthead__no { opacity: 0.55; }
.secthead--dark .secthead__title { color: var(--off); }

/* The screen, not the grid, caps a photograph. A portrait frame given a
   column would grow as tall as the column is wide and leave a laptop
   screen empty beside it; here no frame is taller than about two thirds
   of the viewport, and its width follows from its own ratio. */
:where(.disc__fig, .svstep__fig, .stfounders__fig, .ctvisit__wide, .ctvisit__portrait) img {
  width: auto; max-width: 100%;
  max-height: 70svh;
}
.prview__fig img { width: auto; max-width: 100%; max-height: calc(100svh - var(--bar-h) - 5rem); }
.disc__fig img { margin-left: auto; }
.stdisc .disc { align-items: center; }
.stdisc .disc__no { align-self: start; }
.svstep__fig img { max-height: 62svh; }
.stfounders__fig img { max-height: 78svh; }
.ctvisit__wide img { max-height: 72svh; }
.ctvisit__portrait img { max-height: 58svh; }

/* ---------- studio ---------- */
/* Superseded 2026-09-22: 32% pulled the crop upwards, which suited the
   landscape group shot that used to be here. See the centring rule at
   the end of the file. */

/* what we do: three ruled rows, each with one photograph that shows it */
.stdisc { background: var(--bg); color: var(--ink); padding: 0 var(--pad) var(--section-y); }
.disc {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: start;
  padding: clamp(2.5rem, 6vh, 4rem) 0;
  border-top: 1px solid var(--rule);
}
.disc:last-child { border-bottom: 1px solid var(--rule); }
.disc__no { grid-column: 1 / 2; color: var(--greige); padding-top: 0.5rem; }
.disc__copy { grid-column: 2 / 8; }
.disc__name {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.2rem, 3.6vw, 4.4rem);
  line-height: 0.95; letter-spacing: -0.02em;
}
.disc__line { margin-top: 1rem; color: var(--greige); }
.disc__body { max-width: 34rem; margin-top: clamp(1.5rem, 3.5vh, 2.4rem); font-size: var(--type-body-lg); line-height: 1.6; }
.disc__fig { grid-column: 9 / 13; will-change: transform; }
.disc:nth-child(even) .disc__copy { grid-column: 2 / 7; }
.disc:nth-child(even) .disc__fig { grid-column: 8 / 12; }

/* the studio's own photographs, layered like a case study's first field */
.stfield {
  position: relative;
  height: clamp(34rem, 52vw, 62rem);
  margin: var(--section-y) 0 var(--section-y-lg);
}
.stfield__frame { position: absolute; will-change: transform; }
.stfield__frame--1 { left: -2%; top: 5%; width: 30%; z-index: 1; }
.stfield__frame--2 { left: 22%; top: 28%; width: 16%; z-index: 3; }
.stfield__frame--3 { left: 34%; top: 1%; width: 25%; z-index: 2; }
.stfield__frame--4 { left: 52%; top: 46%; width: 25%; z-index: 4; }
.stfield__frame--5 { left: 63%; top: 6%; width: 22%; z-index: 1; }
.stfield__frame--6 { right: -2%; top: 30%; width: 22%; z-index: 2; }

/* the method and the four principles */
.stmethod { background: var(--bg); color: var(--ink); padding: 0 var(--pad) var(--section-y-lg); }
.stmethod__statement {
  width: 100%;
  margin: 0 0 var(--section-y-lg);
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-deck);
  line-height: var(--deck-leading); letter-spacing: var(--deck-tracking);
}
.stmethod__statement em { font-style: normal; }
.stmethod__head { margin-bottom: clamp(2rem, 6vh, 3.5rem); }
.stvalues {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--grid-gap);
  border-top: 1px solid var(--rule);
}
.stvalue {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  gap: var(--grid-gap);
  padding: clamp(1.8rem, 4vh, 2.6rem) 0;
  border-bottom: 1px solid var(--rule);
}
.stvalue__no { color: var(--greige); padding-top: 0.35rem; }
.stvalue__name {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.6rem, 2.4vw, 2.6rem);
  line-height: 1;
}
.stvalue__body { max-width: 30rem; margin-top: 1rem; font-size: var(--type-body-lg); line-height: 1.6; }

/* the founders: two portraits lapped, the record beside them */
.stfounders {
  background: var(--noir); color: var(--off);
  padding: var(--section-y-lg) var(--pad);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
}
.stfounders .secthead { grid-column: 1 / -1; }
.stfounders__pair {
  grid-column: 1 / 8;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: end;
  margin-top: var(--section-y);
}
.stfounders__fig { position: relative; will-change: transform; }
/* one photograph of the two of them fills the pair's whole width */
.stfounders__pair > :only-child { grid-column: 1 / -1; }
.stfounders__fig--lift { z-index: 2; margin-left: -18%; margin-bottom: 14%; }
.stfounders__aside { grid-column: 9 / 13; align-self: end; margin-top: var(--section-y); }
.stfounders__role { opacity: 0.55; letter-spacing: 0.2em; }
.stfounders__copy { margin-top: clamp(1.5rem, 4vh, 2.5rem); }
.stfounders__copy p {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.2rem, 1.6vw, 1.7rem);
  line-height: 1.3;
}
.stfounders__copy p + p { margin-top: 1.4rem; }
.stfounders__copy em { font-style: normal; }
.stfounders__careers { margin-top: clamp(2rem, 5vh, 3rem); opacity: 0.6; line-height: 1.7; }
.stfounders__careers a { border-bottom: 1px solid currentColor; }

/* ---------- the centred intro, shortened for use mid-page ---------- */
.lede--short { min-height: 0; padding: var(--section-y) var(--pad); gap: clamp(1.4rem, 4vh, 2.4rem); }
.lede__body { text-wrap: balance; }

/* ---------- services ----------
   One step, one screen, four things, always in the same places: the
   step line across the top, the title in caps under it, the photograph
   bottom-left at its own ratio, the paragraph bottom-right. Steps
   alternate between the sand and the stone so each reads as a panel. */
.p-services { background: var(--bg); }
.svstep {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: auto auto 1fr;
  column-gap: var(--grid-gap);
  min-height: 100svh;
  padding: calc(var(--bar-h) + 0.6rem) var(--pad) clamp(1.5rem, 4vh, 2.5rem);
  background: var(--sand);
}
.svstep--alt { background: var(--stone); }
.svstep__bar {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--rule);
}
.svstep__bar span:last-child { grid-column: 2; }
.svstep__title {
  grid-column: 1 / -1;
  margin: clamp(1.2rem, 3vh, 2rem) 0 clamp(1.5rem, 4vh, 2.5rem);
  font-family: var(--display); font-weight: 300;
  text-transform: uppercase;
  font-size: clamp(3.2rem, 7.6vw, 8.6rem);
  line-height: 0.86; letter-spacing: -0.01em;
  max-width: 11ch;
}
.svstep__title em { font-style: normal; }
.svstep__fig { grid-column: 1 / 7; align-self: end; }
.svstep__fig--portrait { grid-column: 1 / 5; }
.svstep__copy { grid-column: 8 / 13; align-self: end; }
.svstep__body { max-width: 40rem; font-size: var(--type-body-lg); line-height: 1.6; }
.svstep__meta { margin-top: 1.4rem; color: var(--greige); line-height: 1.7; }

.svtiers { padding: var(--section-y) var(--pad) var(--section-y-lg); background: var(--bg); }
.svtiers__head { display: grid; justify-items: center; gap: clamp(1.2rem, 3vh, 2rem); text-align: center; }
.svtiers__title {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.5rem, 2.678vw, 3.6rem);
  line-height: 1.15;
}
.svtiers__lead { opacity: 0.72; }
.svtiers__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--grid-gap);
  margin-top: var(--section-y);
  border-top: 1px solid var(--rule);
}
.svtier { padding: clamp(2rem, 4vh, 3rem) 0 0 var(--grid-gap); border-left: 1px solid var(--rule); }
.svtier:first-child { padding-left: 0; border-left: 0; }
.svtier__no {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(3rem, 5vw, 5.5rem);
  line-height: 0.9; color: var(--greige);
}
.svtier__name {
  margin-top: clamp(1.4rem, 3vh, 2rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.6rem, 2.3vw, 2.5rem);
  line-height: 1;
}
.svtier__for {
  max-width: 24rem;
  margin-top: 1rem;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.05rem, 1.35vw, 1.3rem);
  line-height: 1.35; opacity: 0.8;
}
.svtier__items { list-style: none; margin: clamp(1.6rem, 4vh, 2.4rem) 0 0; padding: 0; }
.svtier__items li { padding: 0.6rem 0; border-top: 1px solid var(--rule); line-height: 1.5; }
.svtier__out {
  margin-top: clamp(1.6rem, 4vh, 2.4rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.15rem, 1.5vw, 1.5rem);
  line-height: 1.25;
}
.svtier__out .lbl { display: block; margin-bottom: 0.5rem; color: var(--greige); }

/* ---------- press ---------- */
.prlist {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: start;
  padding: 0 var(--pad) var(--section-y-lg);
}
.prlist__rows { grid-column: 1 / 8; border-top: 1px solid var(--rule); }
.prrow {
  display: grid;
  grid-template-columns: 7rem 8rem minmax(0, 1fr) 1.5rem;
  gap: var(--grid-gap);
  align-items: baseline;
  padding: clamp(1.4rem, 3vh, 2rem) 0;
  border-bottom: 1px solid var(--rule);
  transition: opacity 0.45s var(--ease);
}
.prrow__date { color: var(--greige); }
.prrow__mast { align-self: center; }
.prrow__mast .prmark svg { height: clamp(0.95rem, 1.1vw, 1.15rem); }
.prrow__mast .prmark--type { font-size: 0.68rem; }
.prrow__head {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.4rem, 2vw, 2.15rem);
  line-height: 1.05; letter-spacing: -0.012em;
  text-wrap: balance;
}
.prrow__src { display: block; margin-top: 0.6rem; color: var(--greige); }
.prrow__arrow { justify-self: end; transition: transform 0.35s var(--ease); }
.prrow__thumb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .prlist__rows:hover .prrow:not(:hover) { opacity: 0.4; }
  .prrow:hover .prrow__arrow { transform: translate(0.15em, -0.15em); }
}
.prview {
  grid-column: 9 / 13;
  position: sticky;
  top: calc(var(--bar-h) + 1.5rem);
  display: grid;
}
.prview__fig {
  grid-area: 1 / 1;
  opacity: 0;
  transition: opacity 0.7s var(--ease);
}
.prview__fig.is-on { opacity: 1; }
.prview__fig figcaption { margin-top: 0.65rem; color: var(--greige); }
/* ---------- press: the wide index and the travelling photograph ------
   Pavel, 2026-09-20, in three goes. First, pointing at a story near the
   foot of the list: "the image is up there, not going with me" — it was
   a sticky column, so it parked at the top of the screen while the
   reader was twelve rows down. A centred index was tried next and
   rejected: "now we're not using enough space ... only using the center
   composition, maybe it wasn't such a good idea after all."
   So the index has the width of the page back, left-ranged and ruled,
   and the photograph is solved properly rather than by centring: it is
   a fixed frame on the right whose vertical position FOLLOWS THE
   POINTER, eased, clamped to stay on screen. It appears only while a
   story is pointed at. Whatever row you are on, at the top of the list
   or the very bottom, the photograph is beside it. */
.prindex {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: start;
  padding: 0 var(--pad) var(--section-y-lg);
}
/* The photograph sits above the stories that have stepped back and
   below the one being pointed at: held under everything it showed the
   dimmed headlines through itself, which read as a printing fault
   rather than a photograph. So the layer takes z-index 1, the rows
   take the flow beneath it, and only the hovered row is lifted over
   it. Nothing else is on the screen, so the photograph can stand at
   full strength. */
/* The frame is fixed to the right margin and placed vertically by
   --pry, which app.js eases towards the pointer. It is never laid out
   by the grid: a fixed element cannot be, and tying it to the flow is
   what parked it at the top in the first place. */
.prindex__view {
  position: fixed;
  right: var(--pad);
  top: var(--pry, 50vh);
  width: min(26vw, 30rem);
  transform: translateY(-50%);
  display: grid;
  pointer-events: none;
  z-index: 1;
}
.prfig {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  transition: opacity 0.5s var(--ease);
}
.prfig img { display: block; width: 100%; height: auto; }
.prindex__view.is-live .prfig.is-on { opacity: 1; }

.prindex__rows {
  grid-column: 1 / 9;
  border-top: 1px solid var(--rule);
}
.prow {
  display: grid;
  grid-template-columns: 7rem 8rem minmax(0, 1fr) 1.5rem;
  gap: var(--grid-gap);
  align-items: baseline;
  padding: clamp(1.5rem, 3.4vh, 2.4rem) 0;
  border-bottom: 1px solid var(--rule);
  transition: background-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.prow__when { color: var(--greige); }
.prow__mast { align-self: center; }
.prow__mast .prmark svg { height: clamp(0.95rem, 1.1vw, 1.15rem); }
.prow__mast .prmark--type { font-size: 0.68rem; }
.prow__head {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.45rem, 2.1vw, 2.3rem);
  line-height: 1.05; letter-spacing: -0.012em;
  text-wrap: balance;
}
.prow__src { display: block; margin-top: 0.6rem; color: var(--greige); }
.prow__arrow { justify-self: end; transition: transform 0.35s var(--ease); }
/* Pavel, 2026-09-20: "a little bit confusing how the text is changing
   when I'm hovering over it, but the problem is that it's a bit too
   transparent for too long. Can we do a different effect?"
   It was the twelve stories you are NOT reading that changed: every
   other row faded to 0.4 over 0.45s, so the page washed out and the
   change read as the type itself altering. Nothing dims now. The row
   under the pointer is simply lit instead — a quiet off-white band,
   carried past the column's edges by two box shadows so it reads as a
   band rather than a box, the headline steps a quarter of an em in
   from its rule, and the arrow leans out. It settles in 0.2s, so it
   answers the pointer rather than trailing it. */
.prow__head { transition: transform 0.25s var(--ease); }
@media (hover: hover) and (pointer: fine) {
  .prow:hover {
    background-color: var(--off);
    box-shadow: -1.2rem 0 0 var(--off), 1.2rem 0 0 var(--off);
  }
  .prow:hover .prow__head { transform: translateX(0.25em); }
  .prow:hover .prow__arrow { transform: translate(0.15em, -0.15em); }
}
@media (max-width: 1100px) {
  .prindex__rows { grid-column: 1 / 13; }
  .prindex__view { display: none; }
}
@media (max-width: 860px) {
  .prow { grid-template-columns: 1fr; gap: 0.55rem; padding: 1.5rem 0; }
  .prow__arrow { display: none; }
  .prow__head { font-size: clamp(1.35rem, 6vw, 1.9rem); }
}

/* the masthead index stands on its own, on the page grid */
.prauthority { padding: 0 var(--pad) var(--section-y-lg); margin-top: 0; }
/* the close is the centred intro again, then the three ways out */
.prfoot { min-height: 0; display: block; padding: 0 var(--pad) clamp(2.5rem, 6vh, 4rem); }
.prfoot .lede { padding-left: 0; padding-right: 0; }

/* ---------- contact ---------- */
.ctfacts {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.6rem var(--grid-gap);
  margin-top: clamp(3rem, 8vh, 6rem);
}
.ctfacts dd { line-height: 1.6; }
.ctfacts a { border-bottom: 1px solid transparent; transition: border-color 0.3s var(--ease); }
.ctfacts a:hover { border-color: currentColor; }
.ctvisit {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: start;
  padding: 0 var(--pad) var(--section-y-lg);
}
.ctvisit__wide { grid-column: 1 / 9; grid-row: 1; will-change: transform; }
.ctvisit__portrait { grid-column: 7 / 10; grid-row: 1; margin-top: 62%; position: relative; z-index: 2; will-change: transform; }
.ctvisit__copy { grid-column: 10 / 13; grid-row: 1; align-self: end; }
.ctvisit__body {
  margin-top: 1rem;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.3rem, 1.8vw, 1.8rem);
  line-height: 1.3;
}

/* ---------- phones ---------- */
@media (max-width: 48rem) {
  .disc { grid-template-columns: 2.5rem minmax(0, 1fr); gap: 1rem var(--grid-gap); padding: 2.5rem 0; }
  .disc__no { grid-column: 1; }
  .disc__copy, .disc:nth-child(even) .disc__copy { grid-column: 2; }
  .disc__fig, .disc:nth-child(even) .disc__fig { grid-column: 2; width: 72%; margin-top: 1.5rem; }
  .stfield { height: 150vw; margin: 4rem 0 5rem; }
  .stfield__frame--1 { left: -4%; top: 3%; width: 60%; }
  .stfield__frame--2 { left: 48%; top: 14%; width: 34%; }
  .stfield__frame--3 { left: 6%; top: 34%; width: 50%; }
  .stfield__frame--4 { left: 40%; top: 58%; width: 56%; }
  .stfield__frame--5 { left: -4%; top: 78%; width: 52%; }
  .stfield__frame--6 { right: -4%; top: 86%; width: 46%; }
  .stmethod__statement { font-size: var(--type-deck-sm); line-height: 1; margin-bottom: 4.5rem; }
  .stvalues { grid-template-columns: 1fr; }
  .stfounders { grid-template-columns: 1fr; padding: 4.5rem var(--pad); }
  .stfounders__pair, .stfounders__aside { grid-column: 1; margin-top: 3rem; }
  .stfounders__fig--lift { margin-left: -12%; margin-bottom: 10%; }
  .svstep { grid-template-columns: 1fr; grid-template-rows: none; min-height: 0; padding: 4rem var(--pad) 3rem; }
  .svstep__bar { grid-template-columns: auto 1fr; gap: 1rem; }
  .svstep__bar span:last-child { grid-column: 2; }
  .svstep__title { font-size: clamp(2.8rem, 12vw, 4.2rem); max-width: none; }
  .svstep__fig, .svstep__fig--portrait { grid-column: 1; }
  .svstep__fig--portrait { width: 78%; }
  .svstep__copy { grid-column: 1; margin-top: 1.5rem; }
  .svtiers__grid { grid-template-columns: 1fr; gap: 0; }
  .svtier, .svtier:first-child { padding: 2.5rem 0; border-left: 0; border-bottom: 1px solid var(--rule); }
  .prlist { grid-template-columns: 1fr; padding-bottom: 5rem; }
  .prlist__rows { grid-column: 1; }
  .prview { display: none; }
  .prrow { grid-template-columns: minmax(0, 1fr) 1.5rem; gap: 0.6rem var(--grid-gap); align-items: start; padding: 1.8rem 0; }
  .prrow__thumb { display: block; grid-column: 1 / -1; grid-row: 1; width: 58%; margin-bottom: 0.8rem; }
  .prrow__date, .prrow__mast, .prrow__head { grid-column: 1; }
  .prrow__arrow { grid-column: 2; grid-row: 4; }
  .prrow__head { font-size: clamp(1.5rem, 7vw, 2.2rem); }
  .prfoot__line { font-size: var(--type-deck-sm); line-height: 1; }
  .ctfacts { grid-template-columns: 1fr; gap: 1.4rem; margin-top: 3rem; }
  .ctvisit { grid-template-columns: 1fr; padding-bottom: 5rem; }
  .ctvisit__wide { grid-column: 1; grid-row: auto; }
  .ctvisit__portrait { grid-column: 1; grid-row: auto; width: 60%; margin: -22% 0 0 auto; }
  .ctvisit__copy { grid-column: 1; grid-row: auto; margin-top: 2rem; }
}

/* =============================================================
   THE REFERENCE'S TWO REGISTERS, AND ITS MOTION (2026-09-14, pass 3)
   Read out of aletagency.com's own stylesheet and bundle. Its About
   page has no middle size at all: everything secondary is 14px caps,
   everything that matters is 58px serif or larger (69px caps thesis,
   135px caps discipline names, 203px chapter title, the page name at a
   quarter of the screen). Its motion: every section replays its
   arrival each time it enters; elements rise 90px over 1.4s on
   Power3.easeOut with 0.1s steps; the statement's lines rise 40px each,
   0.1s apart; the opening photograph settles from scale 1.65; a
   hairline draws down over 2s on Power4.easeInOut; every photograph
   drifts on its own parallax rate.
   ============================================================= */
:root {
  --type-cap: 0.8125rem;                       /* the small register */
  --type-note: clamp(1.5rem, 2.3vw, 3rem);     /* the reading register, serif */
}
.cap {
  font-family: var(--sans);
  font-size: var(--type-cap);
  letter-spacing: 0.08em; text-transform: uppercase;
  line-height: 1.55;
}

/* ---------- studio ---------- */
/* the row: a caps name at the size the reference gives a discipline,
   and its paragraph in the small caps register; nothing in between */
.disc__name {
  text-transform: uppercase;
  font-size: clamp(2.4rem, 5vw, 5.6rem);
  line-height: 0.86; letter-spacing: -0.01em;
  max-width: 10ch;
}
.disc__body {
  max-width: 30rem;
  margin-top: clamp(1.6rem, 3.5vh, 2.4rem);
  font-size: var(--type-cap);
  letter-spacing: 0.08em; text-transform: uppercase;
  line-height: 1.55; opacity: 0.85;
}
.stvalue__body {
  max-width: 28rem;
  font-size: var(--type-cap);
  letter-spacing: 0.08em; text-transform: uppercase;
  line-height: 1.55; opacity: 0.85;
}
/* the founders' story is set at the reading register, as the reference
   sets its founder's */
.stfounders__copy p { font-size: var(--type-note); line-height: 1.12; letter-spacing: -0.015em; }

/* the constellation */
.constellation {
  position: relative;
  display: grid;
  justify-items: center;
  gap: clamp(3rem, 9vh, 7rem);
  padding: var(--section-y) var(--pad) var(--section-y-lg);
}
.constellation::before {
  content: "";
  position: absolute; z-index: 0;
  left: 50%; top: 0; bottom: 0;
  width: 1px;
  background: var(--rule);
  transform: scaleY(0); transform-origin: top;
  transition: transform 2s var(--in-out) 0.2s;
}
.constellation.is-in::before { transform: scaleY(1); }
.constellation__row {
  position: relative; z-index: 1;
  width: 100%;
  display: flex; justify-content: space-between; align-items: center;
  gap: clamp(1rem, 3vw, 3rem);
}
.constellation__row--three { width: min(72%, 64rem); }
.constellation__f { position: relative; z-index: 1; margin: 0; }
.constellation__f img { display: block; width: 100%; height: auto; background: var(--stone); will-change: transform; }
.constellation__row--five .constellation__f { width: 11vw; max-width: 13rem; }
.constellation__row--three .constellation__f { width: 15vw; max-width: 17.5rem; }
.constellation__one { width: min(36vw, 36rem); }
.constellation__one img { max-height: 72svh; width: auto; max-width: 100%; margin-inline: auto; }
/* the frames sit at their own heights, never on one line */
.constellation__row--five .constellation__f:nth-child(2),
.constellation__row--five .constellation__f:nth-child(4) { translate: 0 -2.6rem; }
.constellation__row--five .constellation__f:nth-child(3) { translate: 0 1.8rem; }
.constellation__row--three .constellation__f:nth-child(2) { translate: 0 2.2rem; }

/* ---------- services and contact: the reading register ---------- */
.svstep__body {
  max-width: 30rem;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-note);
  line-height: 1.12; letter-spacing: -0.015em;
}
.svstep__meta { margin-top: clamp(1.4rem, 3vh, 2rem); }
.ctconversation__body {
  max-width: 28rem;
  font-family: var(--display); font-weight: 300;
  font-size: var(--type-note);
  line-height: 1.12; letter-spacing: -0.015em;
}

/* ---------- motion, to the reference's numbers ---------- */
[data-rise] {
  transform: translateY(5.6rem);
  transition: opacity 1.4s var(--out), transform 1.4s var(--out);
  transition-delay: calc(var(--rise-i, 0) * 100ms);
}
[data-rise].is-out,
.is-out .sl { transition: none !important; }
.sl { transform: translateY(2.5rem); transition: opacity 1s var(--out), transform 1s var(--out); }
.lede__body .sl { white-space: normal; }

@media (max-width: 48rem) {
  .disc__name { font-size: clamp(2.2rem, 11vw, 3.6rem); max-width: none; }
  .constellation { gap: 3rem; padding: 3rem var(--pad) 5rem; }
  .constellation__row { flex-wrap: wrap; justify-content: center; gap: 1.2rem; }
  .constellation__row--three { width: 100%; }
  .constellation__row--five .constellation__f { width: 26%; }
  .constellation__row--three .constellation__f { width: 30%; }
  .constellation__one { width: 82%; }
  .constellation__row--five .constellation__f:nth-child(n),
  .constellation__row--three .constellation__f:nth-child(n) { translate: none; }
  .constellation__row--five .constellation__f:nth-child(even) { translate: 0 1.4rem; }
}
@media (prefers-reduced-motion: reduce) {
  .constellation::before { transform: none; transition: none; }
}

/* =============================================================
   ABOUT — 1:1 to aletagency.com/about-us (2026-09-14, pass 4)
   Their root is font-size: 1.125vw above 1200px, so every serif size
   here is their rem value × 1.125vw. Their secondary text is 14px and
   never scales. Grounds and faces are ours; sections, order, widths,
   spacings and motion are theirs.
   ============================================================= */
.p-about { --ab-cap: 0.875rem; }
.p-about main { overflow: clip; }
.ab-cap {
  font-family: var(--sans);
  font-size: var(--ab-cap);
  line-height: 1.15; letter-spacing: 0;
  text-transform: uppercase;
}
.ab-line { display: block; }
.ab-ch { margin-bottom: clamp(1.5rem, 2.8vw, 3rem); }
.p-about em { font-style: normal; }
.p-about figure { margin: 0; }
.p-about figure img { display: block; width: 100%; height: auto; background: var(--stone); will-change: transform; }

/* 2 · header content: one screen, three things, centred */
.ab-lede {
  min-height: 100svh;
  display: grid; grid-template-rows: auto 1fr auto;
  justify-items: center; align-items: center;
  text-align: center;
  padding: clamp(1.5rem, 2.25vw, 2.5rem) var(--pad) clamp(3rem, 4.5vw, 4.5rem);
  background: var(--bg); color: var(--ink);
}
.ab-lede__mission { width: min(100%, 41.6vw); opacity: 0.85; }
.ab-lede__say {
  width: min(100%, 66.6vw);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.1rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: 0;
  text-wrap: balance;
}
.ab-lede__say .sl { white-space: normal; }
.ab-lede__hint { opacity: 0.85; }

/* 3 · chapter I on the dark ground */
.ab-one {
  display: grid; justify-items: center;
  padding: clamp(3rem, 4.9vw, 5.5rem) var(--pad) clamp(4rem, 7vw, 8rem);
  background: var(--noir); color: var(--greige);
  text-align: center;
}
.ab-one__thesis {
  width: min(100%, 83.3vw);
  font-family: var(--display); font-weight: 300;
  text-transform: uppercase;
  font-size: clamp(2.2rem, 4.82vw, 7.2rem);
  line-height: 0.94; letter-spacing: 0;
  color: var(--greige);
}
.ab-one__thesis .sl { white-space: normal; }
.ab-spine {
  position: relative; width: 100%;
  display: grid; justify-items: center;
  gap: 7.5vw;
  margin-top: clamp(2.5rem, 5.5vw, 6rem);
  padding-top: clamp(2rem, 4.9vw, 5rem);
}
.ab-spine::before {
  content: "";
  position: absolute; z-index: 0;
  left: 50%; top: 0; bottom: -2vw;
  width: 1px;
  background: rgba(247, 244, 241, 0.34);
  transform: scaleY(0); transform-origin: top;
  transition: transform 2s var(--in-out) 0.2s;
}
.ab-spine.is-in::before { transform: scaleY(1); }
.ab-spine__row {
  position: relative; z-index: 1;
  width: 100%;
  display: flex; justify-content: space-between; align-items: center;
  padding: 0 4.5vw;
}
.ab-spine__row--three { width: 72%; padding: 0; }
.ab-spine__f { position: relative; z-index: 1; }
.ab-spine__row--five .ab-spine__f { width: 9.2vw; }
.ab-spine__row--three .ab-spine__f { width: 10.2vw; }
.ab-spine__one { width: 20.3vw; }
.ab-one__scope { width: min(100%, 50vw); margin-top: 7.3vw; color: var(--off); opacity: 0.85; }
.ab-one__clients {
  width: min(100%, 83.3vw);
  margin-top: clamp(3rem, 6.5vw, 7rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.2rem, 4.82vw, 7.2rem);
  line-height: 0.94; letter-spacing: 0;
  color: var(--off);
  text-align: left;
}
.ab-one__clients .sl { white-space: normal; }

/* 4 · chapter II: Our Expertise and the wall */
.ab-two {
  background: var(--bg); color: var(--ink);
  padding: clamp(3rem, 3.4vw, 4rem) var(--pad) clamp(2rem, 2.25vw, 3rem);
}
.ab-two__head {
  display: grid; justify-items: center;
  text-align: center;
  margin-bottom: clamp(3rem, 5vw, 6rem);
}
.ab-two__head .ab-ch { margin-bottom: 1.1vw; color: var(--ink); }
.ab-two__line {
  display: block; width: 1px; height: 6vw;
  margin-bottom: 3.4vw;
  background: var(--ink);
  transform-origin: top;
}
.ab-two__line[data-rise] { transform: scaleY(0); transition: transform 1.5s var(--in-out), opacity 0.2s; }
.ab-two__line[data-rise].is-in { transform: scaleY(1); }
.ab-two__title {
  width: min(100%, 60vw);
  font-family: var(--display); font-weight: 300;
  /* their 12.57rem, unless the widest word would not fit the screen */
  font-size: min(14.14vw, calc((100vw - 2 * var(--pad)) / var(--emw, 5) * 0.96));
  line-height: 0.8; letter-spacing: 0;
}
.ab-two__title .sl { white-space: normal; }
/* the wall, to their measure: names at 8.357rem × 1.125vw, line-height .8 */
.p-about .wall { padding: 0 0 clamp(2rem, 3.4vw, 4rem); }
.p-about .wall__item { min-height: 0; }
.p-about .wall__item:nth-child(n + 2) { margin-top: clamp(0.8rem, 2.25vw, 2.5rem); }
.p-about .wall__name {
  color: var(--ink); opacity: 1;
  font-size: clamp(2.6rem, 9.4vw, 14rem);
  line-height: 0.8; letter-spacing: 0;
  transition: opacity 0.5s var(--ease);
}
.p-about .wall__name em { font-style: normal; }
@media (hover: hover) and (pointer: fine) {
  .p-about .wall__names:hover .wall__name:not(:hover):not(.is-on) { opacity: 0.35; }
}
.p-about .wall__card { background: var(--sand); width: min(40vw, 38rem); padding: clamp(1rem, 1.7vw, 1.8rem); }
.p-about .wall__fig { aspect-ratio: auto; }
.p-about .wall__fig img { width: auto; max-width: 100%; height: auto; max-height: 52svh; mix-blend-mode: multiply; }
.p-about .wall__body { font-size: var(--ab-cap); line-height: 1.15; letter-spacing: 0; max-width: none; }

/* 5 · text and image */
.ab-three {
  background: var(--bg); color: var(--ink);
  padding: clamp(3rem, 4.5vw, 5rem) var(--pad) 0;
}
.ab-three__pair {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.1vw;
  margin-bottom: clamp(2rem, 2.25vw, 3rem);
}
.ab-three__say {
  width: min(100%, 83.3vw);
  margin: 0 auto clamp(3rem, 4.5vw, 5rem);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.1rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: -0.015em;
  text-align: center; opacity: 0.8;
}
.ab-three__say .sl { white-space: normal; }
.ab-three__body {
  width: min(100%, 50vw);
  margin: 0 auto;
  padding-top: clamp(1rem, 5.6vw, 6rem);
  text-align: center; opacity: 0.85;
}
.ab-three__body p + p { margin-top: 1.15em; }

/* 6 · chapter III: the name on one ground, the founders on the next */
.ab-four { text-align: center; }
.ab-four__name {
  background: var(--stone); color: var(--ink);
  padding: clamp(3rem, 3.4vw, 4rem) var(--pad) 0;
  overflow: hidden;
}
.ab-four__name .ab-ch { margin-bottom: clamp(2rem, 5.6vw, 6rem); }
.ab-four__headline {
  font-family: var(--display); font-weight: 300;
  font-size: min(22vw, calc((100vw - 2 * var(--pad)) / var(--em, 8)));
  line-height: 0.9; letter-spacing: 0;
  white-space: nowrap;
  margin-bottom: -0.06em;
}
.ab-four__founder {
  background: var(--wine); color: var(--off);
  padding: clamp(3rem, 4.5vw, 5rem) var(--pad) clamp(4rem, 5.6vw, 6rem);
}
.ab-four__sub {
  width: min(100%, 33.3vw);
  margin: 0 auto 11vw;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: 0;
  text-wrap: balance;
}
.ab-four__sub .sl { white-space: normal; }
.ab-four__fig { width: min(100%, 50vw); margin: 0 auto; }
.ab-four__fig img { width: auto; max-width: 100%; max-height: 82svh; margin-inline: auto; }
.ab-four__copy {
  padding: clamp(2.5rem, 4.5vw, 5rem) 3.4vw 0;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: -0.015em;
}
.ab-four__copy .sl { white-space: normal; }
.ab-four__copy p + p { margin-top: 1em; }

/* 7 · footer */
.ab-foot {
  display: grid; gap: clamp(1.5rem, 2.25vw, 2.5rem);
  padding: clamp(1.5rem, 2.25vw, 2.5rem) var(--pad);
  background: var(--bg); color: var(--ink);
}
.ab-foot__row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ab-foot__row a, .ab-foot__copy {
  font-family: var(--sans); font-size: 1rem;
  line-height: 1.1; letter-spacing: 0; text-transform: uppercase;
}
.ab-foot__row a { border-bottom: 1px solid transparent; transition: border-color 0.3s var(--ease); width: max-content; }
.ab-foot__row a:hover { border-color: currentColor; }
.ab-foot__copy { opacity: 0.4; }

/* their sizes below 1200px are rem on a 2.85vw root: the same clamps
   bottom out at the phone values */
@media (max-width: 75rem) {
  .ab-lede__mission, .ab-one__scope, .ab-three__body { width: min(100%, 60vw); }
  .ab-lede__say, .ab-one__thesis, .ab-one__clients, .ab-three__say, .ab-two__title, .ab-four__sub { width: 100%; }
  .ab-spine__row { padding: 0 2vw; }
  .ab-spine__row--five .ab-spine__f { width: 12vw; }
  .ab-spine__row--three .ab-spine__f { width: 15vw; }
  .ab-spine__one { width: 28vw; }
  .ab-four__fig { width: min(100%, 70vw); }
}
@media (max-width: 48rem) {
  .ab-lede { padding-top: 4rem; }
  .ab-lede__mission, .ab-one__scope, .ab-three__body { width: 100%; }
  .ab-lede__say { font-size: clamp(1.9rem, 8.6vw, 3rem); }
  .ab-one__thesis, .ab-one__clients { font-size: clamp(2rem, 9.4vw, 3.2rem); }
  .ab-spine { gap: 3rem; }
  .ab-spine__row { flex-wrap: wrap; justify-content: center; gap: 1rem; }
  .ab-spine__row--three { width: 100%; }
  .ab-spine__row--five .ab-spine__f { width: 26%; }
  .ab-spine__row--three .ab-spine__f { width: 30%; }
  .ab-spine__one { width: 80%; }
  .ab-two__line { height: 3rem; margin-bottom: 1.5rem; }
  .ab-two__title { font-size: clamp(3.5rem, 22vw, 6rem); }
  .p-about .wall__name { font-size: clamp(2.2rem, 12vw, 3.6rem); }
  .ab-three__pair { grid-template-columns: 1fr; gap: 1rem; }
  .ab-three__say, .ab-four__sub, .ab-four__copy { font-size: clamp(1.7rem, 7.5vw, 2.6rem); }
  .ab-four__sub { margin-bottom: 3rem; }
  .ab-four__fig { width: 100%; }
  .ab-four__copy { padding: 2.5rem 0 0; }
  .ab-foot__row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
}

/* ---------- services: the roll-up is back (pass 4) ----------
   The centred intro is the pinned ground the first panel rolls over,
   the step paragraph is the reference's 14px caps, and no photograph
   is cropped inside its cell. */
.lede--pinned { position: sticky; top: 0; z-index: 0; }
.p-process .pstep { z-index: 1; }
.p-process .pstep__fig img { object-fit: contain; object-position: left bottom; }
.p-process .pstep--2 .pstep__fig img,
.p-process .pstep--3 .pstep__fig img,
.p-process .pstep--4 .pstep__fig img { object-position: center bottom; }
.p-process .pstep__body {
  font-family: var(--sans);
  font-size: 0.875rem; line-height: 1.15; letter-spacing: 0;
  text-transform: uppercase;
  max-width: 44rem;
}
.svtiers--after-steps { position: relative; z-index: 2; padding-top: var(--section-y-lg); }
.p-process .pjcontact { position: relative; z-index: 2; }
/* Panels stack the way the reference's do: each one stays pinned as the
   ground the next rolls over, so the intro never shows through between
   steps. The next section starts one screen early; its panel rolls up
   during exactly the stretch the previous one is still pinned. */
.p-process .pstep:not(:last-of-type) { margin-bottom: -100svh; }
/* Step 3 is the mirrored panel now, not the centred one: see the
   per-service layouts at the foot of this section. Its photograph
   stretches its column exactly as step 1's does, only on the other
   side, so it needs neither the height cap nor the top crop the
   centred version wanted. */

/* ---------- pass 4 fixes (Pavel's three screenshots) ----------
   1 · every step panel uses the reference's one template: photograph
       in the left column, copy at the foot of the right column. The
       centred photograph on steps 2 to 4 ran under the copy on wide
       windows.
   2 · the mixed-case hero title was clipped at the baseline: its line
       box was shorter than the glyphs and the plate clips overflow.
   3 · the founders' name was clipped at the foot of its band for the
       same reason; and the caps paragraphs on a wide window ran to
       140 characters a line. */
.p-process .pstep--2 .pstep__fig,
.p-process .pstep--3 .pstep__fig,
.p-process .pstep--4 .pstep__fig,
.p-process .pstep--5 .pstep__fig {
  grid-column: 1; grid-row: 3;
  justify-self: stretch; align-self: stretch;
  width: 100%; height: auto;
  margin: 0 0 0 var(--process-pad);
}
.p-process .pstep--2 .pstep__copy,
.p-process .pstep--3 .pstep__copy,
.p-process .pstep--4 .pstep__copy,
.p-process .pstep--5 .pstep__copy {
  grid-column: 2; grid-row: 3;
  justify-self: stretch; align-self: end;
  /* measure and placement come from the shared .p-process .pstep__copy
     rule below, so every step keeps one measure */
}
.p-process .pstep__fig img { object-fit: contain; object-position: left bottom; }
.p-process .pstep--2 .pstep__title,
.p-process .pstep--3 .pstep__title,
.p-process .pstep--5 .pstep__title { text-align: left; max-width: none; }

.plate__title--mix { line-height: 0.98; bottom: calc(var(--hero-title-bottom) - 0.04em); }

.ab-four__headline { line-height: 1.02; margin-bottom: 0; padding-bottom: 0.02em; }
.ab-lede__mission { width: min(41.6vw, 38rem); }
.ab-one__scope, .ab-three__body { width: min(50vw, 46rem); }
/* the italic word in the hero title is set at the same size as the rest
   of it; the whole title is measured so it still fits the screen */
.plate__title--mix { font-size: min(19.56vw, calc(100vw / var(--em, 6))); }
.plate__title--mix em { font-size: 1em; vertical-align: baseline; padding: 0 0.04em; }
/* press: no logo index; the list follows the statement directly */
.p-press .lede--short { padding-bottom: clamp(2rem, 5vh, 3.5rem); }
.p-press .prlist { padding-top: clamp(1rem, 3vh, 2rem); }

/* =============================================================
   CONTACT — one axis, two registers, nothing to hunt for (pass 5)
   The plate carries the free first meeting mid-photograph; then the
   invitation, the two direct ways to reach the studio at the same
   size as the invitation, the address, the form as ruled lines with
   the prompt centred in each, one large Send. All centred.
   ============================================================= */
.p-contact { --ab-cap: 0.875rem; }
.p-contact .plate__eyebrow {
  top: 48%; transform: none;
  font-family: var(--sans); font-size: 1rem;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--off); opacity: 0.92;
}
.p-contact .ab-cap {
  font-family: var(--sans); font-size: var(--ab-cap);
  line-height: 1.15; letter-spacing: 0; text-transform: uppercase;
}
.ct-say {
  min-height: 62svh;
  display: grid; place-items: center;
  padding: clamp(3rem, 6vw, 6rem) var(--pad);
  text-align: center; background: var(--bg); color: var(--ink);
}
.ct-say__body {
  width: min(100%, 66.6vw);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.1rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: 0;
  text-wrap: balance;
}
.ct-say__body .sl { white-space: normal; }
.ct-say__body em { font-style: normal; }

.ct-direct {
  display: grid; justify-items: center;
  gap: clamp(0.6rem, 1.2vw, 1.2rem);
  padding: 0 var(--pad) clamp(4rem, 8vw, 8rem);
  text-align: center; background: var(--bg); color: var(--ink);
}
.ct-direct__label { margin-bottom: clamp(1rem, 2vw, 2rem); opacity: 0.7; }
.ct-direct__line {
  display: inline-block;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: 0;
  border-bottom: 1px solid transparent;
  transition: border-color 0.35s var(--ease), opacity 0.35s var(--ease);
}
.ct-direct__line:hover { border-color: currentColor; }
.ct-direct__note { width: min(100%, 38rem); margin-top: clamp(1.5rem, 3vw, 3rem); opacity: 0.7; }

.ct-studio {
  display: grid; justify-items: center;
  gap: clamp(0.8rem, 1.5vw, 1.5rem);
  padding: clamp(3rem, 5vw, 5rem) var(--pad) clamp(4rem, 8vw, 8rem);
  text-align: center; background: var(--stone); color: var(--ink);
}
.ct-studio__label { opacity: 0.7; }
.ct-studio__line {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.6rem, 2.68vw, 4rem);
  line-height: 1.05;
}
.ct-studio__note { width: min(100%, 34rem); opacity: 0.7; }
.ct-studio__social { display: flex; gap: 2rem; margin-top: 0.5rem; }
.ct-studio__social a { border-bottom: 1px solid currentColor; padding-bottom: 0.15em; }

/* The invitation now has the screen to itself, as the shared `lede` the
   services page opens with (Pavel, 2026-09-20: "the main text should
   have space like this one"), and the form is the thing you scroll down
   INTO — so it stands on its own ground rather than continuing the
   sand, and arrives as a different surface. Stone is the next step of
   the manual's own ladder, and the off-white fields read cleanly on it
   without turning the page into a panel. */
.ct-form {
  padding: clamp(3rem, 6vw, 6rem) 0 clamp(3rem, 5vw, 5rem);
  text-align: center; background: var(--stone); color: var(--ink);
  position: relative; z-index: 1;
}
.ct-form__label { margin-bottom: clamp(2rem, 4vw, 4rem); opacity: 0.7; padding: 0 var(--pad); }
/* ---------- the form is a writing surface, not a set of rules --------
   Pavel, 2026-09-20: "these fully horizontal lines are not really
   pleasant to write into, can we design this so it's actually more
   pleasant for me as a customer to send a longer message."
   They were full-bleed rules carrying centred, uppercase, 0.1em-tracked
   text. That is the site's interface voice, which is right on a label
   and wrong on something a client has to write a paragraph into: on a
   wide screen the line ran the width of the page, the caret started in
   the middle of it and every character was pushed apart. The fields are
   now a contained column, ranged left, sentence case, untracked, on the
   off-white of the manual with a stone hairline, and the message is a
   deep field you can see the whole of what you have written in. */
.ct-form__form {
  width: min(100%, 54rem);
  margin: 0 auto;
  padding: 0 var(--pad);
  text-align: left;
  display: grid;
  gap: clamp(1.4rem, 2.4vh, 2.2rem);
}
.ct-form__pair { display: grid; grid-template-columns: 1fr 1fr; gap: inherit; }
.ct-form__line { margin: 0; border: 0; display: grid; gap: 0.55rem; }
.ct-form__cap { opacity: 0.6; }
.ct-form__line input,
.ct-form__line textarea {
  display: block; width: 100%;
  background: var(--off);
  border: 1px solid var(--stone);
  color: inherit;
  font-family: var(--sans);
  font-size: clamp(1rem, 1.02vw, 1.2rem);
  letter-spacing: 0; text-transform: none;
  text-align: left;
  line-height: 1.55;
  padding: clamp(0.85rem, 1.5vh, 1.15rem) clamp(1rem, 1.1vw, 1.3rem);
  transition: border-color 0.3s var(--ease), background 0.3s var(--ease);
}
.ct-form__line textarea {
  min-height: clamp(13rem, 30vh, 22rem);
  resize: vertical;
}
.ct-form__line input::placeholder,
.ct-form__line textarea::placeholder { color: currentColor; opacity: 0.4; }
.ct-form__line:focus-within .ct-form__cap { opacity: 1; }
.ct-form__line input:focus, .ct-form__line textarea:focus {
  outline: none;
  border-color: var(--ink);
  background: #fff;
}
@media (max-width: 720px) {
  .ct-form__pair { grid-template-columns: 1fr; }
}
.ct-form :is(input, textarea)[aria-invalid="true"] { color: var(--wine); }
.ct-form__go { margin: clamp(2.5rem, 4.5vw, 4.5rem) 0 0; padding: 0 var(--pad); }
.ct-form__go button {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.4rem, 4.82vw, 7rem);
  line-height: 1;
  border-bottom: 1px solid currentColor; padding-bottom: 0.04em;
  transition: opacity 0.35s var(--ease);
}
.ct-form__go button:hover { opacity: 0.6; }
/* the send sits with the column, not centred on the page, and the
   serif is brought down to the size of the field column so it reads as
   the end of the form rather than a second headline */
.ct-form__go {
  width: min(100%, 54rem);
  margin: clamp(1.4rem, 2.6vh, 2.4rem) auto 0;
  padding: 0 var(--pad);
  text-align: left;
}
.ct-form__go button { font-size: clamp(2rem, 3.1vw, 4rem); }
.ct-form__note { margin-top: clamp(1.2rem, 2vw, 2rem); padding: 0 var(--pad); opacity: 0.7; }
.ct-form__note:empty { display: none; }
.p-contact .ab-foot { padding-top: clamp(3rem, 5vw, 5rem); }

@media (max-width: 48rem) {
  .ct-say { min-height: 0; padding: 3.5rem var(--pad); }
  .ct-say__body { width: 100%; font-size: clamp(1.9rem, 8.6vw, 3rem); }
  .ct-direct__line { font-size: clamp(1.5rem, 7.4vw, 2.6rem); word-break: break-all; }
  .ct-studio__line { font-size: clamp(1.4rem, 6.5vw, 2.2rem); }
  .ct-form__go button { font-size: clamp(2.4rem, 12vw, 4rem); }
}

/* =============================================================
   PASS 6 — Anna's notes on the About, Services, Press and Contact
   One small register (the .lbl, 13px, 0.08em) for every small text,
   including the caps paragraphs; one edge distance for every section;
   no decorative lines; the sections she struck out are gone.
   ============================================================= */
:root { --edge: clamp(1.5rem, 2.25vw, 2.5rem); --gap: clamp(1.6rem, 2.8vw, 3rem); }
.ab-cap, .p-about .ab-cap, .p-contact .ab-cap {
  font-size: var(--type-label); letter-spacing: 0.08em; line-height: 1.5;
}
/* the intro: three things, one gap between them, one edge above and below */
.ab-lede {
  min-height: 0;
  grid-template-rows: auto auto auto;
  gap: var(--gap);
  padding: var(--edge) var(--pad);
}
.ab-lede__mission, .ab-lede__hint { opacity: 0.85; }
.ab-ch { margin-bottom: var(--gap); }
.ab-one { padding: var(--edge) var(--pad); }
.ab-spine { margin-top: var(--gap); padding-top: 0; gap: clamp(2.5rem, 5vw, 5rem); }
.ab-spine::before { display: none; }
.ab-one__scope { margin-top: clamp(2.5rem, 5vw, 5rem); }
.ab-two { padding: var(--edge) var(--pad) var(--edge); }
.ab-two .ab-ch { display: block; text-align: center; }
.p-about .wall { padding-bottom: 0; }
.p-about .wall__body { font-size: var(--type-label); letter-spacing: 0.08em; line-height: 1.5; }
.ab-four__name { padding: var(--edge) var(--pad) 0; }
.ab-four__name .ab-ch { margin-bottom: var(--gap); }
.ab-four__founder, .ab-four__team { padding: var(--edge) var(--pad); }
.ab-four__team { background: var(--noir); color: var(--off); display: grid; justify-items: center; gap: var(--gap); }
.ab-four__fig--wide { width: min(100%, 66vw); }
.ab-four__fig--wide img { max-height: 80svh; }
.ab-four__line { width: min(100%, 46rem); opacity: 0.85; }
.ab-four__careers { opacity: 0.6; }
.ab-four__careers a { border-bottom: 1px solid currentColor; }
.ab-four__copy { padding-top: var(--gap); }
.ab-foot { padding: var(--edge) var(--pad); }

/* services: the small register for the panel copy, the outcome in the
   same colour as the body, titles without italic */
/* The step sentence is set off the reference's own scale, taken from
   its stylesheet rather than guessed. Its root is fluid — 0.75vw from
   1200px, 0.729vw from 1500px — and the step paragraph is `1.571rem`
   of it, so the sentence GROWS with the window: 14.1px at 1200 and
   29.3px at 2560. Ours was a fixed label size that stayed at 13px at
   every width, which on a wide screen is less than half theirs, and
   Pavel's note was exactly that: "it's really easy to miss the text
   ... on the reference website the text is bigger."
   The clamp below tracks their curve within a fraction of a pixel
   (14.4 / 17.3 / 22.1 / 29.4 against their 14.1 / 17.2 / 22.0 / 29.3),
   and takes their leading of 1.1 and their letter-spacing of 0: at this
   size the tracked caps of the interface voice would fall apart, and
   this is reading copy now, not a label. */
.p-process .pstep__lead { margin-bottom: 1em; opacity: 0.7; }
.p-process .pstep__body {
  font-size: clamp(0.9rem, 1.15vw, 2.05rem);
  letter-spacing: 0.01em;
  line-height: 1.15;
  max-width: none;
}
.p-process .pstep__lead,
.p-process .pstep__meta {
  font-size: clamp(0.78rem, 0.84vw, 1.5rem);
  letter-spacing: 0.06em;
  line-height: 1.3;
}
.p-process .pstep__meta { margin-top: 1.2em; color: inherit; opacity: 0.7; display: block; }
.p-process .pstep__meta span { display: block; }
/* The copy is the second half of the panel, and on the reference it is
   not a column floating in that half: it starts one gutter clear of the
   photograph's right edge and runs out towards the page margin, so the
   measure grows with the window instead of being pinned to a ch cap.
   Measured off aletagency.com/process at 1200px: photograph ends at 554,
   the sentence sets 573 → 1130. Ours was capped at 52ch and centred, so
   it sat 125px clear of the photograph with 144px of air to its right
   and wrapped at ~28 characters. The photograph overhangs its own column
   by one --process-pad, which is why the text needs two of them on the
   left to clear it by a single gutter. */
.p-process .pstep__copy {
  gap: 0;
  justify-self: stretch;
  max-width: none;
  padding: 0 calc(var(--process-pad) * 3.5) 0 calc(var(--process-pad) * 2);
}
.p-process .pstep__title em { font-style: normal; }
.p-process .pstep--2 .pstep__title, .p-process .pstep--3 .pstep__title { text-align: left; }

/* ---------- the three services are three different pages ----------
   Pavel, 2026-09-20: "not all the pages have the same layout". They are
   not meant to be. Measured off aletagency.com/process at 1200px, whose
   five steps run photograph left (45%), left (45%), centred (57%),
   right (53%), right (52%): the page turns over halfway through. Ours
   has three services, so it makes the same turn in three — 01 keeps the
   photograph left with the sentence beside it, 02 centres both with the
   sentence beneath, 03 mirrors 01. Every service was otherwise the same
   page three times over, because the .p-process block above flattened
   the per-step variants the rules further up had defined.
   These come after the rules that set every step's title left, so they
   have to sit at the foot of the section to win the cascade. */

/* 02 — centred, the sentence under the photograph (their step 3) */
.p-process .pstep--2 .pstep__panel {
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "head"
    "title"
    "fig"
    "body";
}
.p-process .pstep--2 .pstep__title { text-align: center; max-width: none; }
.p-process .pstep--2 .pstep__fig {
  grid-area: fig;
  justify-self: stretch; align-self: stretch;
  width: 100%;
  margin: 0 var(--process-pad);
}
.p-process .pstep--2 .pstep__fig img { object-position: center bottom; }
.p-process .pstep--2 .pstep__copy {
  grid-area: body;
  justify-self: center; align-self: end;
  max-width: 55%;
  text-align: center;
  padding: clamp(1rem, 2.4vh, 1.8rem) 0 0;
}

/* 03 — mirrored: photograph right, sentence left (their step 5) */
.p-process .pstep--3 .pstep__panel {
  grid-template-columns: minmax(0, 1fr) minmax(0, 52%);
  grid-template-areas:
    "head head"
    "title title"
    "body fig";
}
/* stretch, not end: the major is absolutely positioned now, so an
   auto-height figure has nothing in flow to give it height and the
   whole pair collapsed to zero */
.p-process .pstep--3 .pstep__fig {
  grid-area: fig;
  justify-self: stretch; align-self: stretch;
  width: 100%;
  margin: 0 var(--process-pad) 0 0;
}
.p-process .pstep--3 .pstep__fig img { object-position: right bottom; }
.p-process .pstep--3 .pstep__copy {
  grid-area: body;
  justify-self: stretch; align-self: end;
  padding: 0 calc(var(--process-pad) * 2) 0 var(--process-pad);
}

/* ---------- the lapped pair ----------
   Pavel, 2026-09-20, pointing at the reference's work page: "what we
   really like is this layout of different images ... this should be
   used in the services too". Two frames set against each other, the
   larger one and a second crossing its far edge and standing proud of
   its top. Measured off that page: the second frame is 69% of the
   first's width, laps 8% of the box, and its foot lands two thirds of
   the way down the first. Both keep the format they were shot in, so
   neither is cropped to a ratio: the frames are width-led and the
   photograph's own height follows.
   The figure has to let the second frame escape, so the panel's
   overflow clip and the full-height image rules are undone here. */
/* The pair is sized by the HEIGHT the panel gives it, not by a share of
   the column's width. Pavel, 2026-09-20, on service 03: "my problem is
   how much space we use just for the colour, the images should be
   significantly bigger." Width-led, the pair's height was whatever the
   photograph's ratio happened to give, so it sat in the bottom corner
   and left most of the panel as bare wine. Filling the row makes it
   roughly twice the size on the same composition. */
.pstep__fig--pair {
  display: block;
  position: relative;
  overflow: visible;
  align-self: stretch;
  min-height: 0;
  height: auto;
}
.pstep__frame { display: block; margin: 0; }
.pstep__frame--major {
  position: absolute;
  bottom: 0; left: 0;
  height: 100%;
  width: max-content;
  max-width: 100%;
}
.pstep__fig--pair img {
  display: block;
  height: 100%; width: auto;
  max-width: 100%;
}
/* The second frame is sized by HEIGHT, not width, and now hangs off the
   major itself rather than the figure. Width-led sizing assumed both
   photographs share a ratio, the way the reference's two do; ours do
   not, and a portrait laid beside a landscape came out 864px tall
   against a 628px major, hanging into the sentence. Held to a share of
   the major's height it lands correctly whatever format it was shot in.
   Anchoring it to the figure then failed for the same reason in the
   other direction: once the major is sized by height its width is the
   photograph's business, so a fixed percentage of the figure no longer
   meets its edge. Nested inside the major, `left: 92%` laps the last
   8% of the photograph itself and holds at any size or ratio. */
.pstep__frame--minor {
  position: absolute; z-index: 2;
  height: 69%;
  left: 92%; right: auto;
  top: -3%;
}
/* 02 sets its pair in the middle, 03 mirrors 01 */
.p-process .pstep--2 .pstep__frame--major { left: 50%; transform: translateX(-50%); }
.p-process .pstep--3 .pstep__frame--major { left: auto; right: 0; }
.p-process .pstep--3 .pstep__frame--minor { left: auto; right: 92%; }

@media (max-width: 860px) {
  .pstep__frame--major { width: 78%; }
  .pstep__frame--minor { width: 46%; top: auto; bottom: -8%; }
}

/* press: the caps line alone, then the list */
.lede--line { padding: var(--edge) var(--pad); }
.p-press .prlist { padding-top: 0; }

/* contact: the form first */
.p-contact .plate__eyebrow { display: none; }
.ct-form { padding: var(--edge) 0 var(--edge); }
.ct-form__label { margin-bottom: var(--gap); opacity: 0.7; }
.ct-form__say {
  width: min(100%, 66.6vw);
  margin: 0 auto var(--gap);
  padding: 0 var(--pad);
  font-family: var(--display); font-weight: 300;
  font-size: clamp(2.1rem, 4.02vw, 6rem);
  line-height: 1; letter-spacing: 0;
  text-wrap: balance;
}
.ct-form__say .sl { white-space: normal; }
.ct-form__say em { font-style: normal; }
.ct-form__line select {
  display: block; width: 100%;
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; color: inherit; border-radius: 0;
  font-family: var(--sans); font-size: clamp(0.95rem, 1.24vw, 1.4rem);
  letter-spacing: 0.1em; text-transform: uppercase;
  text-align: center; text-align-last: center;
  padding: clamp(1.6rem, 2.8vw, 2.8rem) var(--pad);
  cursor: pointer;
}
.ct-form__line select:invalid, .ct-form__line select option[value=""] { color: inherit; }
.ct-form__line select:has(option[value=""]:checked) { opacity: 0.45; }
.ct-form__line select:focus { outline: none; }
.ct-direct { padding-top: var(--edge); padding-bottom: var(--edge); }
.ct-studio { padding: var(--edge) var(--pad); }
.ct-direct__note, .ct-studio__note { opacity: 0.7; }

@media (max-width: 48rem) {
  .ab-lede { padding-top: 2rem; }
  .ab-four__fig--wide { width: 100%; }
}
.ab-four__fig { display: flex; justify-content: center; }
.p-process .ab-foot, .p-process .pjcontact { position: relative; z-index: 2; background: var(--bg); }

/* ---------- pass 7: the reference's air, back ----------
   Pavel, with the reference beside ours: the intro is a full screen with
   the statement alone in the middle; chapter I opens 4.9vw below its
   edge; the spine sits 5.5vw under the thesis with 7.5vw between rows.
   These are the measured values from pass 4, restored over the tighter
   pass-6 spacing. Anna's structural deletions stay. */
.ab-lede {
  min-height: 100svh;
  grid-template-rows: auto 1fr auto;
  gap: clamp(2rem, 4.5vw, 5rem);
  padding: clamp(1.5rem, 2.25vw, 2.5rem) var(--pad) clamp(3rem, 4.5vw, 4.5rem);
}
.ab-one { padding: clamp(3rem, 4.9vw, 5.5rem) var(--pad) clamp(4rem, 7vw, 8rem); }
.ab-ch { margin-bottom: clamp(1.5rem, 2.8vw, 3rem); }
.ab-spine { margin-top: clamp(2.5rem, 5.5vw, 6rem); gap: 7.5vw; }
.ab-one__scope { margin-top: 7.3vw; }
.ab-two { padding: clamp(3rem, 4.9vw, 5.5rem) var(--pad) clamp(2rem, 3.4vw, 4rem); }
.ab-two .ab-ch { margin-bottom: clamp(3rem, 5vw, 6rem); }
.ab-four__name { padding: clamp(3rem, 3.4vw, 4rem) var(--pad) 0; }
.ab-four__name .ab-ch { margin-bottom: clamp(2rem, 5.6vw, 6rem); }
.ab-four__founder, .ab-four__team { padding: clamp(3rem, 4.5vw, 5rem) var(--pad) clamp(4rem, 5.6vw, 6rem); }
.ab-four__copy { padding-top: clamp(2.5rem, 4.5vw, 5rem); }
.ab-four__team { gap: clamp(2rem, 3.4vw, 3.5rem); }
.ab-foot { padding: clamp(1.5rem, 2.25vw, 2.5rem) var(--pad); }
.p-about .wall__name em { font-style: normal; }
/* the page was crowded against the other pages, which all open with a
   screen of room: these are roughly doubled (Pavel, 2026-09-20 —
   "should get a little more of the vertical space like the other
   pages, not as crowded as it is now") */
.ct-form { padding: clamp(5rem, 11vh, 10rem) 0 clamp(5rem, 9vh, 8rem); }
.ct-form__label { margin-bottom: clamp(2.5rem, 5vh, 4.5rem); }
.ct-form__say { margin-bottom: clamp(4rem, 8vh, 7.5rem); }
.ct-direct { padding: clamp(5rem, 10vh, 9rem) var(--pad) clamp(6rem, 12vh, 11rem); }
.ct-studio { padding: clamp(3rem, 5vw, 5rem) var(--pad) clamp(4rem, 8vw, 8rem); }

/* ---------- the team, one by one ----------
   Seven square portraits in a row of four then three, each with the
   name in the serif, the role and one line in the small register. */
.ab-members {
  list-style: none; margin: 0; padding: 0;
  width: 100%;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(2.5rem, 4.5vw, 5rem) var(--grid-gap);
  margin-top: clamp(1rem, 2.25vw, 2.5rem);
  text-align: center;
}
.ab-member { display: grid; justify-items: center; gap: 0.6rem; }
.ab-member__fig { width: min(100%, 14rem); margin-bottom: 0.8rem; }
.ab-member__fig img { width: 100%; height: auto; }
.ab-member__name {
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.3rem, 1.8vw, 2rem);
  line-height: 1.05;
}
.ab-member__role { opacity: 0.6; }
.ab-member__line { max-width: 22rem; opacity: 0.85; margin-top: 0.4rem; }
@media (max-width: 64rem) { .ab-members { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 40rem) { .ab-members { grid-template-columns: 1fr; } }
/* About carries the case study's own layered field on the dark ground */
.ab-collage { width: 100%; margin: clamp(2.5rem, 5.5vw, 6rem) 0 0; }
.p-about .ab-collage img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- chapter III as two colours ----------
   Anna & Tereza: everything on the beige, name, photograph and story.
   Team: everything on the wine, name, photograph and the people. */
.ab-four__founder { background: var(--stone); color: var(--ink); }
.ab-four__name + .ab-four__team, .ab-four__team { background: var(--wine); color: var(--off); }
.ab-four__name:nth-of-type(3) { background: var(--wine); color: var(--off); }
.ab-four__name:nth-of-type(3) .ab-four__headline { color: var(--off); }
.ab-four__name:nth-of-type(3) .ab-ch { color: var(--off); }

/* the people: one ruled list, name in the serif, role and line in the
   small register, and one portrait beside it that follows whichever
   row the reader is on (the press index's own mechanism) */
.ab-members { display: none; }
.ab-team {
  width: 100%;
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--grid-gap);
  align-items: start;
  margin-top: clamp(1rem, 2.25vw, 2.5rem);
  text-align: left;
}
.ab-team__rows { grid-column: 1 / 8; border-top: 1px solid rgba(247, 244, 241, 0.3); }
.ab-team__row {
  display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  column-gap: var(--grid-gap); row-gap: 0.7rem;
  padding: clamp(1.4rem, 2.8vh, 2rem) 0;
  border-bottom: 1px solid rgba(247, 244, 241, 0.3);
  transition: opacity 0.45s var(--ease);
  cursor: default;
}
.ab-team__row:focus-visible { outline: 1px solid rgba(247, 244, 241, 0.6); outline-offset: 0.4rem; }
.ab-team__name {
  grid-column: 1; grid-row: 1;
  font-family: var(--display); font-weight: 300;
  font-size: clamp(1.7rem, 2.6vw, 3rem);
  line-height: 1;
}
.ab-team__role { grid-column: 2; grid-row: 1; align-self: baseline; opacity: 0.7; }
.ab-team__line { grid-column: 1 / -1; grid-row: 2; max-width: 40rem; opacity: 0.85; }
.ab-team__thumb { display: none; }
@media (hover: hover) and (pointer: fine) {
  .ab-team__rows:hover .ab-team__row:not(:hover):not(.is-on) { opacity: 0.45; }
}
.ab-team__view {
  grid-column: 9 / 13;
  position: sticky; top: calc(var(--bar-h) + 1.5rem);
  display: grid;
}
.ab-team__view .prview__fig { grid-area: 1 / 1; opacity: 0; transition: opacity 0.7s var(--ease); margin: 0; }
.ab-team__view .prview__fig.is-on { opacity: 1; }
.ab-team__view img { width: 100%; height: auto; max-height: none; }
@media (max-width: 48rem) {
  .ab-team { grid-template-columns: 1fr; }
  .ab-team__rows { grid-column: 1; }
  .ab-team__view { display: none; }
  .ab-team__row { grid-template-columns: 1fr; }
  .ab-team__thumb { display: block; grid-row: 1; width: 46%; margin: 0 0 0.6rem; }
  .ab-team__name { grid-row: 2; } .ab-team__role { grid-column: 1; grid-row: 3; } .ab-team__line { grid-row: 4; }
}

/* ---------- the team as a layered field ----------
   The seven portraits in the case study's own field, a seventh frame
   added, each with only the name beneath it. */
.ab-team { display: none; }
.ab-teamfield { width: 100%; margin: clamp(2rem, 4.5vw, 5rem) 0 clamp(2rem, 3.4vw, 4rem); overflow: visible; }
.ab-teamfield .pjcollage__frame img { width: 100%; height: 100%; object-fit: cover; }
.ab-teamfield .pjcollage__frame figcaption {
  position: absolute; left: 0; top: 100%;
  margin-top: 0.7rem; white-space: nowrap;
  color: var(--off); opacity: 0.85;
}
.ab-teamfield .pjcollage__frame--7 { left: 50%; top: 64%; width: 15%; height: 30%; z-index: 4; }
@media (max-width: 48rem) {
  .ab-teamfield { height: 170vw; }
  .ab-teamfield .pjcollage__frame--7 { left: 30%; top: 84%; width: 34%; height: 14%; }
  .ab-teamfield .pjcollage__frame figcaption { white-space: normal; font-size: 0.7rem; }
}
/* names sit inside their frame, bottom left, so a lapping frame can
   never hide them */
.ab-teamfield .pjcollage__frame { overflow: hidden; }
.ab-teamfield .pjcollage__frame::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 42%;
  background: linear-gradient(180deg, rgba(51, 44, 40, 0) 0%, rgba(51, 44, 40, 0.55) 100%);
  pointer-events: none;
}
.ab-teamfield .pjcollage__frame figcaption {
  top: auto; bottom: 0.7rem; left: 0.8rem; right: 0.8rem;
  margin: 0; z-index: 1;
  color: var(--off); opacity: 1;
  white-space: normal; line-height: 1.3;
}
.ab-teamfield .pjcollage__frame figcaption { right: auto; max-width: 62%; }
.ab-teamfield .pjcollage__frame--7 { left: 57%; }
/* the team: one photograph, the names beneath it in the order they stand */
.ab-teamfield { display: none; }
.ab-four__photo { width: min(100%, 72vw); display: grid; gap: clamp(0.9rem, 1.4vw, 1.4rem); }
.ab-four__photo .ab-four__fig--wide { width: 100%; }
.ab-four__names {
  display: flex; justify-content: space-between; gap: 0.5rem 1rem;
  width: 100%; margin: 0; text-align: center;
}
.ab-four__names span { flex: 1 1 0; }
@media (max-width: 48rem) {
  .ab-four__photo { width: 100%; }
  .ab-four__names { display: grid; grid-template-columns: repeat(2, 1fr); text-align: left; }
}

/* ---------- the footer: the business card, full width ----------
   The wordmark across the whole width on the deep ground, off-white and
   debossed as it is on the card, then one row of links on the left and
   the copyright on the right, in the small register. On every page that
   ends, whatever colour the page before it was. Flat, as in Pavel's
   reference of 2026-09-28: the deboss filter came out. */
.ab-foot, .p-process .ab-foot, [data-dark] + .ab-foot {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: end; column-gap: var(--grid-gap);
  row-gap: clamp(4.5rem, 13vw, 15rem);
  padding: clamp(3.5rem, 6.5vw, 8rem) max(var(--pad), 4.2vw) clamp(1.75rem, 2.4vw, 2.75rem);
  background: var(--deep); color: var(--off);
}
.ab-foot__mark { grid-column: 1 / -1; }
.ab-foot__mark .wm svg {
  width: 100%; height: auto;
}
.ab-foot__links { display: flex; flex-wrap: wrap; gap: 0.75rem clamp(2rem, 5vw, 5rem); }
.ab-foot__links a, .ab-foot__copy {
  font-family: var(--sans); font-size: clamp(0.8125rem, 1vw, 1.0625rem);
  letter-spacing: 0.01em; text-transform: uppercase; line-height: 1.5;
}
.ab-foot__links a { border-bottom: 1px solid transparent; transition: border-color 0.3s var(--ease); }
.ab-foot__links a:hover { border-color: currentColor; }
.ab-foot__copy { text-align: right; margin: 0; opacity: 1; }
.ab-foot__row { display: none; }
@media (max-width: 48rem) {
  .ab-foot, .p-process .ab-foot, [data-dark] + .ab-foot { grid-template-columns: 1fr; row-gap: 3rem; }
  .ab-foot__links { display: grid; grid-template-columns: repeat(2, max-content); column-gap: 3rem; }
  .ab-foot__copy { text-align: left; margin-top: -1.5rem; }
}
/* the clip belongs to the section with the lapping frames, not to
   main: a clipped main hides the footer from the intersection observer */
.p-about main, .p-studio main { overflow: visible; }
.ab-one { overflow: clip; }
/* contact, after the reference: three ruled lines and a full-width
   black send bar */
.ct-form__line--message textarea { min-height: 7rem; }
.ct-form__go { margin: 0; padding: 0; }
.ct-form__go button {
  display: block; width: 100%;
  padding: clamp(1.8rem, 3.4vw, 3.2rem) var(--pad);
  background: var(--noir); color: var(--off);
  font-family: var(--sans); font-size: var(--type-label);
  letter-spacing: 0.08em; text-transform: uppercase; line-height: 1.5;
  border: 0; border-radius: 0;
  transition: background 0.35s var(--ease);
}
.ct-form__go button:hover { background: var(--deep); opacity: 1; }
/* the footer's bottom line: links in a row on the left, copyright on
   the right (the layout itself is in "the business card" block above) */
.ab-foot__copy { white-space: nowrap; }
@media (max-width: 48rem) { .ab-foot__copy { white-space: normal; } }
/* fail safe: the arrival styles only apply while the reveal observer is
   running (html.rise, set by app.js once it is built). No script, no
   hiding. */
html:not(.rise) [data-rise], html:not(.rise) .sl { opacity: 1 !important; transform: none !important; }

/* ---------- not found ----------
   The utility hero, plus the one sentence and the two ways out. */
.nf .utilityhero { min-height: 100svh; display: grid; align-content: center; }
.nf__lead { margin-top: clamp(1.2rem, 3vh, 2rem); max-width: 34rem; font-size: var(--type-body-lg, 1.1rem); line-height: 1.55; }
.nf__ways { display: flex; flex-wrap: wrap; gap: 0.6rem 2rem; margin-top: clamp(2rem, 5vh, 3.5rem); }
.nf__ways a { padding: 0.9rem 0; border-bottom: 1px solid currentColor; }

/* =================================================================
   PHONE PASS, 2026-09-21
   Everything below is the phone. It sits at the very end of the file
   on purpose: the desktop rules above are scattered across passes and
   several are more specific than they need to be, and the mistake this
   pass exists to correct was exactly that — desktop rules written with
   no `min-width` guard, later in the file and heavier than the phone
   rules they sat after, quietly overriding them. Anything for a phone
   goes here, and `[data-step]` is on the selectors only to outweigh
   the `.p-process .pstep--N …` rules (0,3,0) without an !important.

   Read off the reference on a real phone profile (iPhone 14, 390x844),
   not a narrowed desktop window: see research/alet/mobile-study.
   ================================================================= */

/* ---------- services: the steps stop being a spectacle ----------
   On a laptop each step is a pinned panel rolling up out of a stack of
   bars, and the three are laid out left, centred and mirrored. The
   reference keeps none of that on a phone: no pinning, no bar stack,
   one layout for every step. Each becomes a plain section on its own
   ground, a screen tall, with a small centred label at the head, air,
   and then the name sitting tight on the photograph with the sentence
   under it, all centred.
   Ours had been left with the laptop's two-column mirror on a 390px
   screen: service 03 set its sentence in a 134px column, 21 lines of 12
   characters; service 02 ran its second photograph off the edge; and
   service 01 showed no photographs at all, because an absolutely
   positioned frame in an auto-height figure has no height to fill. */
@media (max-width: 64rem) {
  .p-process .lede--pinned { position: relative; }
  .p-process .pstack { display: none; }
  .p-process .pstep[data-step] { height: auto; margin-bottom: 0; }
  .p-process .pstep[data-step] .pstep__pin { position: static; height: auto; overflow: visible; }
  .p-process .pstep[data-step] .pstep__panel {
    position: relative; inset: auto;
    transform: none; will-change: auto;
    min-height: 100svh;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(3rem, 1fr) auto auto auto;
    grid-template-areas: "head" "." "title" "fig" "body";
    padding: 0 0 clamp(2.5rem, 7vh, 4rem);
  }
  /* the label at the head of the section, in two centred lines */
  .p-process .pstep[data-step] .pbar--head {
    grid-area: head;
    display: grid; grid-template-columns: minmax(0, 1fr);
    justify-items: center; row-gap: 0.15rem;
    text-align: center;
    padding: 1.4rem var(--pad) 0;
  }
  .p-process .pstep[data-step] .pbar--head > span { grid-column: 1; justify-self: center; text-align: center; }
  .p-process .pstep[data-step] .pstep__title {
    grid-area: title;
    text-align: center; max-width: none;
    font-size: clamp(2.2rem, 10.4vw, 3.2rem);
    line-height: 0.9;
    padding: 0 var(--pad);
    margin-bottom: 0.9rem;
    text-wrap: balance;
  }
  /* The pair fills the width of the screen exactly. The second frame is
     69% of the first's height and starts 92% of the way across it, so
     in units of the first frame's width the pair is
       0.92 + 0.69 * (its ratio / the first's ratio)
     wide; the build hands over both ratios, and dividing the figure by
     that lands the pair edge to edge whatever formats were shot. */
  /* `grid-area` alone: a `grid-row: auto` after it quietly undoes the
     placement and the photograph auto-flowed above its own title */
  .p-process .pstep[data-step] .pstep__fig {
    grid-area: fig;
    justify-self: stretch; align-self: end;
    width: auto; height: auto;
    margin: 0.6rem var(--pad) 0;
    overflow: visible;
  }
  .p-process .pstep[data-step] .pstep__frame--major {
    position: relative; inset: auto;
    left: auto; right: auto; bottom: auto;
    transform: none;
    display: block;
    height: auto; max-width: none;
    width: calc(100% / (0.92 + 0.69 * var(--nr, 1.5) / var(--mr, 1.5)));
    margin: 0;
  }
  /* `aspect-ratio: auto` undoes the older phone rule that forced every
     step photograph to 4:3. It distorted the portraits, which breaks the
     studio's rule that a photograph keeps the format it was shot in, and
     it made every frame the wrong width, so the second one ran off the
     screen: and a phone answers sideways overflow by zooming the whole
     page out to fit it (innerWidth read 465 on a 390 screen), so one
     stray frame was shrinking the entire page by a sixth. */
  .p-process .pstep[data-step] .pstep__frame--major img { width: 100%; height: auto; max-width: none; aspect-ratio: auto; }
  .p-process .pstep[data-step] .pstep__frame--minor {
    left: 92%; right: auto; top: -3%;
    height: 69%;
  }
  .p-process .pstep[data-step] .pstep__frame--minor img { height: 100%; width: auto; max-width: none; aspect-ratio: auto; }
  .p-process .pstep[data-step] .pstep__copy {
    grid-area: body;
    justify-self: stretch; align-self: start;
    max-width: none;
    margin: 1.4rem 0 0;
    padding: 0 var(--pad);
    text-align: center;
  }
  .p-process .pstep[data-step] .pstep__body { font-size: 0.84rem; line-height: 1.22; text-align: center; }
  .p-process .pstep[data-step] .pstep__lead,
  .p-process .pstep[data-step] .pstep__meta { font-size: 0.72rem; line-height: 1.35; }
  /* the reveal was written for a panel rolling up; in plain flow a
     section has simply arrived */
  .p-process .pstep[data-step] .pstep__fig,
  .p-process .pstep[data-step] .pstep__copy { opacity: 1; transform: none; }
}

/* ---------- studio: three paragraphs set in a sliver ----------
   The phone block higher up already gives these `width: 100%`. Two
   unguarded desktop rules after it (`width: min(41.6vw, 38rem)` and
   `min(50vw, 46rem)`) put the viewport share back, and 41.6vw of a
   390px screen is 162px: the intro set as nine lines of two words.
   The wall's card is the same story, `min(40vw, 38rem)` leaving the
   accordion 156px wide and its paragraph 19 lines of 11 characters. */
@media (max-width: 48rem) {
  .p-about .ab-lede__mission,
  .p-about .ab-one__scope,
  .p-about .ab-three__body { width: 100%; }
  .p-about .wall__card { width: 100%; }
}

/* ---------- things a thumb has to hit ----------
   44px is the smallest target a finger lands on reliably. These were
   set as lines of type and measured 20 to 28px tall: the footer's three
   links on 45 pages, the "Let's talk" that closes 33 pages, the studio's
   own address on Contact. The type does not move or grow; the hit area
   around it does, with the padding taken back out of the flow so the
   layout is unchanged. */
@media (max-width: 48rem) {
  .ab-foot__row a,
  .pjcontact a,
  .ct-direct__line {
    display: inline-flex; align-items: center;
    min-height: 44px;
  }
  .ab-foot__row a { padding-block: 0.55rem; margin-block: -0.55rem; }
  .workfilter__option { min-height: 44px; display: inline-flex; align-items: center; }
  /* the record under a case study: 10.9px is under the 11pt floor */
  .pjfacts dt, .pjfacts dd, .prmark--type { font-size: max(0.72rem, 11.5px); }
}

/* ---------- the page name over a phone-sized photograph ----------
   The older phone rule sized a name off its widest single word and let
   it wrap, which suited a photograph cropped to fill the whole screen.
   The plate is now only as tall as the photograph in its own format,
   260px for a 3:2 picture, and a name wrapped to two 88px lines covered
   most of it and ran up under the bar ("Barrandov / Residence"). The
   laptop sets every name on ONE line, edge to edge over the foot of the
   picture, and that is the composition to keep: the same formula, so a
   short name still reaches 24vw and a long one simply comes down to
   whatever fits the line. */
@media (max-width: 48rem) {
  .pagehero--image .plate__title {
    white-space: nowrap;
    font-size: min(24vw, calc(96vw / var(--em, 6)));
  }
  /* the filter on Work: 10.4px, and something a thumb has to hit */
  .workfilter__option span, .workfilter__option { font-size: max(0.72rem, 11.5px); }
}

/* the footer's links live in .ab-foot__links (the rule above named
   .ab-foot__row, which is a different, older footer, and so changed
   nothing: the audit still read 21px on all 45 pages) */
@media (max-width: 48rem) {
  .ab-foot__links a {
    display: inline-flex; align-items: center;
    min-height: 44px;
    margin-block: -0.6rem;
  }
  .ab-foot__links { row-gap: 0.2rem; }
  .legal__copy a { display: inline-flex; align-items: center; min-height: 44px; }
  /* outweighs `.prow__mast .prmark--type { font-size: .68rem }` */
  .prow__mast .prmark--type { font-size: max(0.72rem, 11.5px); }
}

/* ---------- the menu, on a phone ----------
   Opening it was the only way to see these: the sweep audits a page with
   the menu shut. The language switch is the one control the whole
   language-by-country arrangement leans on, because on a phone it is the
   only way to overrule it, and it was 17 x 17px set in 10px type, a third
   of what a thumb needs. The type comes up to a legible 12.5px and each
   language takes a 44px square around itself; the row is pulled back in
   by the same amount so nothing in the menu moves. */
html.am-menu-open, html.am-menu-open body { overflow: hidden; }
.menu { overscroll-behavior: contain; }
@media (max-width: 48rem) {
  .menu .langs { gap: 0; margin-right: -0.9rem; }
  .menu .langs a {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 44px; min-height: 44px;
    font-size: 0.78rem; padding-bottom: 0;
  }
  .menu .langs span { font-size: 0.78rem; }
  .menu__foot a[href^="mailto"] { display: inline-flex; align-items: center; min-height: 44px; }
  .menu__foot { bottom: max(calc(var(--pad) - 0.6rem), env(safe-area-inset-bottom)); }
}

@media (max-width: 48rem) {
  /* the last two a thumb could miss: the portal's support address (20px
     tall) and the shortest filter word, tall enough but 33px wide */
  .p-portal a[href^="mailto"] { display: inline-flex; align-items: center; min-height: 44px; }
  .workfilter__option { min-width: 44px; justify-content: center; }
}
/* not found: ranged left with its label and sentence, at every width */
.nf .utilityhero__title { text-align: left; }

/* =================================================================
   TABLET, 2026-09-21
   An iPad held upright is 820 x 1180: above the phone's 48rem, so it was
   handed the laptop's layout on a portrait screen. Two things broke on
   it, and Pavel had named the device ("the same composition on laptop,
   iPad and iPhone"). The reference's own rule is that the stacked
   process layout serves everything under 1200px, not only phones; ours
   stops at 64rem so a large iPad on its side still gets the laptop.
   ================================================================= */

/* Services between a phone and a laptop: the same stacked, centred
   sections (the block above now runs to 64rem), with the measure held
   in, because a sentence centred across 780px runs to 100 characters. */
@media (min-width: 48.0625rem) and (max-width: 64rem) {
  .p-process .pstep[data-step] .pstep__title { font-size: clamp(3.2rem, 9.6vw, 5.2rem); }
  .p-process .pstep[data-step] .pstep__fig { justify-self: center; width: min(100% - 2 * var(--pad), 42rem); margin-inline: 0; }
  .p-process .pstep[data-step] .pstep__copy { justify-self: center; width: min(100% - 2 * var(--pad), 36rem); padding-inline: 0; }
  .p-process .pstep[data-step] .pstep__body { font-size: 0.95rem; }
  .p-process .pstep[data-step] .pstep__lead,
  .p-process .pstep[data-step] .pstep__meta { font-size: 0.78rem; }
}

/* The header photograph, whole, on any upright screen up to a tablet.
   A full-screen `cover` crop of a 3:2 photograph on an 820 x 1180 screen
   keeps barely 45% of its width: the studio's team of three showed two.
   Landscape tablets keep the full-screen plate, where the crop is mild. */
@media (min-width: 48.0625rem) and (max-width: 64rem) and (orientation: portrait) {
  /* every hero variant, by the same route the shared rule takes: that
     rule is `body :is(.plate, .pplate, .prhero).pagehero` (0,2,1), and a
     bare `.pagehero--image` lost to it, so Services, whose header is a
     `.pplate`, kept a full screen of height with its name at the foot of
     it, a screen away from the photograph */
  #main > .plate.pagehero--image,
  body :is(.plate, .pplate, .prhero).pagehero.pagehero--image { min-height: 0; height: auto; overflow: hidden; }
  .pagehero--image .plate__img { position: relative; inset: auto; }
  .pagehero--image .plate__img img {
    width: 100%; height: auto;
    object-fit: contain; object-position: 50% 50%;
    animation: none;
  }
  .pagehero--image .plate__title { white-space: nowrap; font-size: min(24vw, calc(96vw / var(--em, 6))); }
}

/* the 11.5px floor holds on a tablet too: it is about legibility at arm's
   length, not about the width of the screen */
@media (min-width: 48.0625rem) and (max-width: 64rem) {
  .pjfacts dt, .pjfacts dd, .prow__mast .prmark--type, .prmark--type { font-size: max(0.72rem, 11.5px); }
}

/* ---------- the statement screen, on a phone ----------
   Pavel, on a phone: "I have to scroll down too much in Contact to
   actually reach the contact form." The invitation takes a full screen
   on a laptop, which he asked for there; on a phone that is 844px of
   air in front of the one thing the page is for. The reference's own
   statement panel on a phone is 505px of an 844px screen, about 60%,
   never a whole one, so every `.lede` comes down to that here.
   Contact goes further, because its statement is an invitation to the
   form directly under it: it takes only the room its words need, and
   the "scroll down to write to us" line goes, since on a phone the
   form is already arriving at the foot of the same screen. */
@media (max-width: 48rem) {
  .lede { min-height: 60svh; padding-top: clamp(2.5rem, 7vh, 4rem); }
  .p-contact .lede {
    min-height: 0;
    grid-template-rows: auto auto;
    gap: 1.6rem;
    padding: 2.6rem var(--pad) 2.8rem;
  }
  .p-contact .lede .lede__hint { display: none; }
  .p-contact .ct-form { padding-top: 2.6rem; }
}

/* ---------- a name that could never arrive ----------
   "ANNA & TEREZA" and "TEAM" did not exist on a phone. While a
   `[data-rise]` element waits it is translated 5.6rem down. These two
   sit in `.ab-four__name`, which clips its overflow, and on a phone the
   name is 47px tall in a 147px box: pushed down 90px it lay wholly
   outside the clip. An IntersectionObserver counts a target clipped away
   by an ancestor as not intersecting, so it never fired, and the name is
   only un-pushed once it fires. Hidden because never seen, never seen
   because hidden. On a laptop the name is set at 22vw and the box has
   room for the travel, which is why it only failed small.
   Below a laptop these fade in where they stand. */
@media (max-width: 64rem) {
  .ab-four__name [data-rise]:not(.is-in) { transform: none; }
}

/* ---------- the second frame is exactly as wide as its photograph ----
   It was sized by `height: 69%` with its width left to shrink-wrap the
   picture. A browser cannot shrink-wrap a box around an image whose size
   comes from a percentage height, and resolves the box as a SQUARE: a
   portrait 95px wide sat in a box 127px wide. The photograph itself was
   placed correctly, so nothing looked wrong, but the 32px of empty box
   ran past the edge of a phone and widened the page to 402px on a 390px
   screen, which a phone answers by zooming the whole page out. On a
   laptop the panel clips it, but the mirrored pair anchors by the box's
   RIGHT edge, so there the same surplus shifted the visible lap.
   With both ratios to hand the frame needs no shrink-wrapping at all:
   69% of the first frame's height is `69% * nr / mr` of its width. The
   first frame takes its own ratio too, so its room is held before the
   file arrives instead of collapsing to nothing and jumping. */
/* Height-led as before, with `aspect-ratio` supplying the width. A first
   version derived the width from the first frame's WIDTH instead
   (`69% * nr / mr`), which is only the same thing when that frame's box
   has the photograph's own ratio. On a laptop it does not: the box is
   the full height of the row and the photograph is letterboxed inside
   it, so steps 1 and 3 came out 12% smaller than the layout Pavel had
   approved the day before. A box with a definite height and an
   aspect-ratio has an exact width and nothing to shrink-wrap. */
.p-process .pstep[data-step] .pstep__frame--minor {
  height: 69%;
  width: auto;
  aspect-ratio: var(--nr, 1.5);
}
.p-process .pstep[data-step] .pstep__frame--minor img {
  width: 100%; height: 100%; max-width: none;
  aspect-ratio: auto; object-fit: cover;
}
@media (max-width: 64rem) {
  .p-process .pstep[data-step] .pstep__frame--major img { aspect-ratio: var(--mr, 1.5); }
}

/* ---------- a title that is one long word ----------
   "Kundenportal" is a single 12-letter word, and at the phone's 18vw it
   is 378px wide in a box with 307px of room. A word cannot break, so it
   pushed its box out to 423px and the German portal to 443px on a 390px
   screen; "Client Portal" and "Klientský portál" are two words and never
   showed it. The build already knows the width of a title's widest word
   (`--emw`, from the font's own metrics), which is how the page names
   are fitted; this one had simply never been given it. */
@media (max-width: 48rem) {
  .portalclean__title {
    font-size: min(clamp(3.7rem, 18vw, 5rem), calc((100vw - 2 * var(--pad) - 2.8rem) / var(--emw, 6)));
    overflow-wrap: anywhere;
  }
}

/* =================================================================
   What the copy review of 2026-09-21 did to the layout.
   Deleting text is not only a change of words: two of the studio's
   deletions left a layout built for what used to be there.
   ================================================================= */

/* A case study has three facts now (Place, Type, Realization): the
   fourth, Scope, was deleted in the review. Three cells in a grid of
   four ranged left and left the last column empty. The rule is about
   the count, not the page, so the Studio and Press records, which still
   have four, are untouched. */
.pjfacts:has(> div:nth-child(3):last-child) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 48rem) {
  .pjfacts:has(> div:nth-child(3):last-child) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Contact's statement went from a three-line paragraph ("Have you got a
   space in mind? Write to us to hear how we would approach it…") to six
   words: "Got a space? Tell us everything." At the size set for a
   paragraph a single line looked lost in the screen it has to itself.
   It is a headline now, so it takes a headline's size; every other
   page's statement is still a paragraph and keeps the shared one. */
.p-contact .lede__body {
  font-size: clamp(2.5rem, 5.4vw, 6.75rem);
  line-height: 1.02;
  letter-spacing: -0.015em;
}

/* a line of a statement that the writer broke by hand */
.lede__part { display: block; }

/* the bar over a dark section of text: white type as over a photograph,
   but on that section's own ground, so copy scrolls under it, not through it */
/* It is a gradient, not a hard band: solid behind the links, then
   fading out below them so the copy slips under instead of being cut. */
.bar::before {
  content: ""; position: absolute; inset: 0 0 auto 0; z-index: -1;
  height: calc(100% + 2.75rem);
  background: linear-gradient(180deg, var(--bar-ground) 0%, var(--bar-ground) calc(100% - 2.75rem), transparent 100%);
  opacity: 0; pointer-events: none;
  transition: opacity 0.4s var(--ease);
}
.bar.bar--over.bar--grounded { background: transparent; }
.bar.bar--over.bar--grounded::before { opacity: 1; }

/* ---------- contact form: the parts added for sending ---------- */
/* off screen, not display:none: a script skips a field it can tell is hidden */
.ct-form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.ct-form__privacy {
  margin: 0;
  font-size: 0.78rem; line-height: 1.5;
  color: var(--ink); opacity: 0.62;
  text-align: left;
}
.ct-form__privacy a { border-bottom: 1px solid currentColor; }
.ct-form__go button:disabled { opacity: 0.5; cursor: progress; }

/* ---------- the team row: "Role / Name", six across, on one line ------
   Pavel, 2026-09-22: the names with their positions, on one line, and
   smaller type if that is what it takes. Six items of role and name run
   to about 160 characters, which at the label size would need 1,500px:
   more than a laptop. So the row takes the full width of the page
   rather than the photograph's 72vw, sets in a size that follows the
   window (11.2px at 1440, 13px from 1660) and never wraps; the role is
   quiet, the name is not. Under 64rem one line is not possible at any
   readable size, so the row becomes a grid of two columns with the role
   standing over the name. */
.ab-four__names {
  width: 100%;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: 0 1.2rem;
  font-size: clamp(0.62rem, 0.78vw, 0.8125rem);
}
.ab-four__names span { flex: 0 1 auto; white-space: nowrap; text-align: center; }
.ab-four__names em { font-style: normal; opacity: 0.55; }
.ab-four__photo { width: 100%; }
.ab-four__photo .ab-four__fig--wide { width: min(100%, 72vw); justify-self: center; }
@media (max-width: 64rem) {
  .ab-four__names {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.9rem 1.5rem; font-size: 0.75rem; text-align: left;
  }
  .ab-four__names span { white-space: normal; text-align: left; }
  .ab-four__names em { display: block; font-size: max(0.72rem, 11.5px); margin-bottom: 0.15rem; }
  .ab-four__names span::after { content: none; }
}

/* =================================================================
   SERVICES, 2026-09-22: one photograph per step, the same page for all
   three. The studio's sketch (Pavel's screenshot): a single large picture
   filling the left, the sentence in a block to its right at the foot,
   "a všude stejně i u těch dalších záložek". This retires the lapped
   pair and the left / centred / mirrored rhythm from 2026-09-20 on this
   page; both are still in the stylesheet above and unused. The picture
   keeps its own format: it fills the width of its column and takes the
   height that gives it, never a crop. This block sits last on purpose.
   ================================================================= */
@media (min-width: 64.0625rem) {
  .p-process .pstep[data-step] .pstep__panel {
    grid-template-columns: minmax(0, 56%) minmax(0, 1fr);
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas: "head head" "title title" "fig body";
  }
  .p-process .pstep[data-step] .pstep__title { text-align: left; max-width: none; }
  .p-process .pstep[data-step] .pstep__fig {
    grid-area: fig;
    justify-self: stretch; align-self: end;
    width: auto; height: auto; max-height: 100%;
    margin: 0 0 0 var(--process-pad);
    overflow: hidden;
  }
  .p-process .pstep[data-step] .pstep__fig img {
    display: block; width: 100%; height: auto;
    max-height: 100%; object-fit: contain; object-position: left bottom;
    aspect-ratio: auto; animation: none;
  }
  .p-process .pstep[data-step] .pstep__copy {
    grid-area: body;
    justify-self: stretch; align-self: end;
    max-width: none; text-align: left;
    padding: 0 calc(var(--process-pad) * 3) 0 calc(var(--process-pad) * 2.5);
  }
  .p-process .pstep[data-step] .pstep__body,
  .p-process .pstep[data-step] .pstep__lead,
  .p-process .pstep[data-step] .pstep__meta { text-align: left; }
}
/* the phone and tablet blocks above still stack the step; only the
   picture changes, from a pair to one photograph at full width */
@media (max-width: 64rem) {
  .p-process .pstep[data-step] .pstep__fig--one img { width: 100%; height: auto; aspect-ratio: auto; max-width: none; }
}

/* "Working worldwide" on its own line under the first sentence (the
   studio, 2026-09-22). An authored break as a block, never a <br>: the
   line-split reveal leaves a <br> standing as an empty row. */
.ab-lede__line { display: block; }

/* =================================================================
   ONE SPACE UNDER EVERY HERO (2026-09-22). `--seam-top` is defined once
   in :root. The first section after the photograph on each page takes
   it as its top padding here, last in the file so nothing above wins:
   Work (.workintro), case studies (.pjopen), Studio (.ab-lede), Services
   and Contact (.lede), Press (.prindex). Change the token, never these.
   ================================================================= */
.workintro, .pjopen, .ab-lede, .lede, .prindex { padding-top: var(--seam-top); }
@media (max-width: 48rem) {
  .p-contact .lede { padding-top: var(--seam-top); }
}

/* ---------- the founders, one portrait each, side by side ----------
   The studio, 2026-09-22: two photographs of Anna and Tereza, "next to
   each other, not over each other, and they should be central. There
   should be a gap between them."
   So: two equal columns, a gap, the pair centred in the band. Both
   negatives are 1891x2800 from the same roll, so equal widths give
   equal heights and the two portraits sit on one line at top and
   bottom without any measurement. (An earlier version lapped them; it
   read as one picture, which is not what was wanted.)
   The figure spans the whole band and `justify-content` centres the
   two frames inside it. Centring the figure itself with an auto margin
   looked equivalent and was not: it left the pair flush against the
   left edge, because `.ab-four__fig` is a flex box and the width cap
   made the auto margins collapse. Sizing the frames and letting the
   flex box do the centring has no such trap. */
.ab-four__fig--pair {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(1rem, 2.4vw, 2.5rem);
}
.ab-four__frame { display: block; flex: 0 0 auto; width: min(25vw, 42%); margin: 0; }
.ab-four__frame img { width: 100%; height: auto; max-width: none; max-height: none; margin: 0; }
@media (max-width: 64rem) { .ab-four__frame { width: min(36vw, 44%); } }
@media (max-width: 48rem) {
  .ab-four__fig--pair { gap: 1rem; }
  .ab-four__frame { width: 47%; }
}

/* ---------- a portrait photograph as a full-screen header ----------
   The studio, 2026-09-22: "the header images that are vertical
   portraits, when viewed on a laptop, should be centred vertically as
   well as horizontally." Their new headers (About, Contact, Services)
   are 5464x8192 portraits, and a laptop screen is landscape, so `cover`
   has to throw away most of the height. Where it throws it away from
   was tuned page by page for the landscape shots that used to be here,
   which on a portrait reads as a crop slipping off one edge. Centre is
   the honest default for both axes, and it is the whole rule now.
   Phones show these photographs whole, so this only concerns a laptop. */
@media (min-width: 48.0625rem) {
  .pagehero .plate__img img,
  .pagehero--image .plate__img img { object-position: var(--crop, 50% 50%); }
}

/* ---------- a step that plays ----------
   The studio sent a clip for Build rather than a photograph
   (2026-09-22). It sits in the step's figure exactly where the
   photograph did, so it takes the same box and the same crop; only the
   element is different. Its poster is its own first frame, so nothing
   moves until the video is ready and nothing jumps when it is. */
.clip { display: block; width: 100%; height: 100%; object-fit: cover; background: var(--stone); }

/* The clip was shot upright, and the studio wants it kept that way
   (2026-09-22: "the video ... is funny as a portrait, and we should put
   it as a portrait"). Sized to the figure's height rather than its
   width, so the whole frame is visible instead of a band cut out of the
   middle, and held to the left of the column: the space beside it is
   where the photographs they are sending next will lap over it, in the
   same arrangement the work pages use. */
/* `[data-step]` is in the selector because the laptop rules for a step
   figure carry it, and a rule without it loses to them. */
.p-process .pstep[data-step] .pstep__fig--clip {
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  overflow: visible;
}
/* A height in viewport units, not a percentage: the figure takes its
   height from what is inside it, so a percentage there is circular and
   the browser falls back to the clip's own 9:16, which is what put a
   1392px frame in a 582px box. The studio, 2026-09-22: it "should be
   as tall as the original image, so scale it so it ends under the
   build text" — so the height is the panel minus the title, and the
   frame runs from just under BUILD to the foot of the step. */
.p-process .pstep[data-step] .pstep__fig--clip .clip {
  width: auto; height: 76svh;   /* a plain viewport height: `min(76svh, 100%)`
                                   reintroduced the percentage and with it the
                                   indefinite-height fallback this rule exists
                                   to avoid */
  max-width: 100%;
  object-fit: contain; object-position: left bottom;
}
@media (max-width: 64rem) {
  .p-process .pstep[data-step] .pstep__fig--clip { justify-content: center; }
  .p-process .pstep[data-step] .pstep__fig--clip .clip {
    width: auto; height: auto;
    max-width: 100%; max-height: 62svh;
    object-fit: contain; object-position: center bottom; aspect-ratio: auto;
  }
}

/* =================================================================
   VERTICAL RHYTHM
   The studio, 2026-09-22: "the actual gaps amongst the texts are
   different on the entire website. We should establish a couple of
   rules from the pages that we like. The pages should be light and
   full of air." And, pointing at the team photograph: "the gap between
   the text TEAM and the image is very different than the gap between
   the image and the names of the team under the image", and "the names
   are full width while the image is not. It's not really clear that
   these names under the image are actually the names of the people
   that are in the image."

   So there are five distances on this site and no others. Each is a
   clamp, so the whole rhythm opens as the window widens and closes on
   a phone without a single media query.

     --sp-caption  a picture and the words that belong TO it. The
                   smallest distance on the site, and deliberately much
                   smaller than the one above the picture: that
                   difference is the only thing that says the words
                   underneath are a caption and not the next paragraph.
     --sp-close    lines of one thought: a label over its sentence.
     --sp-group    one block to the next inside a band.
     --sp-band     a band of one colour to the next.
     --sp-page     the page's own top and bottom seams.

   The ratio between them is roughly 1 : 1.7 : 3.4 : 6.5 : 11, so any
   two distances that meet are obviously different rather than nearly
   the same, which is what made the page look accidental.
   ================================================================= */
:root {
  --sp-caption: clamp(0.6rem, 0.85vw, 0.95rem);
  --sp-close: clamp(1rem, 1.5vw, 1.6rem);
  --sp-group: clamp(2rem, 3.4vw, 3.25rem);
  --sp-band: clamp(3.75rem, 6vw, 6rem);
  --sp-page: clamp(6rem, 9.5vw, 10.5rem);
  /* the old name for a block gap, kept so every rule that already used
     it moves onto the scale instead of being rewritten one by one */
  --gap: var(--sp-group);
}

/* ---------- the team, and its caption ----------
   The photograph is held to 72vw and the names underneath were held to
   the full width of the band, so they read as a new paragraph that
   happened to contain names. They are a caption: same width as the
   picture, and close under it. */
.ab-four__photo {
  width: min(100%, 72vw);
  margin-inline: auto;
  gap: var(--sp-caption);
  /* the row of names cannot wrap, so its max-content width was sizing
     the grid column and the photograph followed it out past the band.
     minmax(0, 1fr) says the column is the wrapper and nothing wider. */
  grid-template-columns: minmax(0, 1fr);
}
.ab-four__photo .ab-four__fig--wide { width: 100%; justify-self: stretch; }
.ab-four__names {
  width: 100%;
  /* held to the picture's width now, so it is allowed a second line
     rather than being pushed off the edge */
  flex-wrap: wrap;
  row-gap: var(--sp-close);
}
.ab-four__team { gap: var(--sp-group); }
@media (max-width: 64rem) {
  .ab-four__photo { width: 100%; }
}

/* ---------- one seam for every band ----------
   The page sections butt against each other, so all the air on this
   site is the sections' own padding, and every section had invented
   its own: at 1440 the tops ran 41, 71, 90, 99, 126 and the bottoms
   32, 49, 63, 81, 101, 108, 126. Nothing about those numbers was a
   decision; they were each arrived at separately, which is exactly
   what the studio saw. One number now, top and bottom, for every band
   on every page.

   The body class is in the selector because the per-page rules that
   set these paddings carry one, and a rule without it loses to them.
   It is `body.p-studio`, not `body .p-studio`: the class is ON the
   body, so the descendant form matched nothing at all.
   Read this as: nothing below chooses a distance, it only points the
   existing bands at the scale. */
html body:is(.p-studio, .p-process, .p-contact, .p-press, .p-work, .p-project)
  :is(.ab-lede, .ab-one, .ab-two, .lede, .prindex, .ct-form, .ct-direct, .workintro,
      .pjcontact, .pjopen, .pjessay, .pjmore, .workarchive) {
  padding-top: var(--sp-band);
  padding-bottom: var(--sp-band);
}

/* A headline band and the picture under it are one thing, so the
   distance between them is the small one and the air goes around the
   pair. The studio, at the team photograph: "the gap between the text
   TEAM and the image is very different than the gap between the image
   and the names". It still is, and now on purpose: band, group,
   caption, in that order, each obviously smaller than the last. */
html body.p-studio .ab-four__name { padding-top: var(--sp-band); padding-bottom: 0; }
html body.p-studio .ab-four__founder,
html body.p-studio .ab-four__team { padding-top: var(--sp-group); padding-bottom: var(--sp-band); }

/* the first band under a full-screen header used its own smaller seam;
   it is on the scale like everything else now */
:root { --seam-top: var(--sp-band); }

/* the footer is small type and gets the group distance, not a band's:
   it closes the page rather than being another section of it. It was
   49 above on every page and 72 on Contact alone, for no reason. */
/* Since the footer became the card (wordmark on the deep ground) it
   needs air above the mark instead: the same value as in the card
   block, repeated here because this selector outranks that one on
   pages whose footer does not follow a dark section. */
html body .ab-foot { padding-top: clamp(3.5rem, 6.5vw, 8rem); }

/* ---------- a step that stacks two photographs ----------
   The studio, 2026-09-22, sending a second picture for Interior
   Documentation: "we can use a similar way to how we display multiple
   images over each other ... the layout that we use at the top of the
   detail of the individual works."

   That layout is `.pstep__fig--pair`: the major frame is absolutely
   positioned and sized by height, the minor hangs off its edge. An
   absolutely positioned child gives its parent no height, so the figure
   has to be stretched by the grid or the whole pair collapses to zero
   — which is exactly what it did, because the laptop rule for a step
   figure carries `[data-step]` and sets `align-self: end`. Same
   specificity here, and the pair stands up. */
html body.p-process .pstep[data-step] .pstep__fig--pair {
  align-self: stretch;
  height: auto;
  overflow: visible;
}

/* The studio, 2026-09-22, on Interior Documentation: the second picture
   "should be stuck on top of the other one next to it ... slightly
   smaller but on top of the reference image that we already have there
   on the right side."
   The shared geometry only kisses the major's edge (`left: 92%`, so the
   lap is the last 8% of it). Here the minor sits ON the right of the
   photograph: smaller, and overlapping it properly rather than standing
   beside it.
   `[data-step]` is in the selector because the laptop rule that sizes
   this frame carries it, and a rule without it loses on height alone:
   the first version moved the frame and left it the old size. */
html body.p-process .pstep--2[data-step] .pstep__frame--minor {
  height: 58%;
  left: 58%;
  top: 14%;
}
@media (max-width: 860px) {
  html body.p-process .pstep--2[data-step] .pstep__frame--minor {
    height: 54%;
    left: 52%;
    top: 16%;
    bottom: auto;
    width: auto;
  }
}

/* the Impressum heading on the German legal page: the same small
   register as the rest of that page, just set apart with air above so
   the block reads as its own thing rather than another paragraph */
.legal__head {
  margin-top: var(--sp-band);
  margin-bottom: var(--sp-close);
  font-size: var(--type-label);
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

/* ---------- the contact form's confirmation ----------
   The studio asked twice for this, and the second time was the useful
   one: "it needs to be communicated a little better, so I'm sure that
   the message really gets left."

   So it takes the whole band the form stood in rather than sitting
   politely inside it, which is the honest version of the pop-up they
   described: unmistakable, but no modal, nothing to dismiss, nothing
   that traps focus or breaks on a phone. The order of the page is the
   order of the reassurance: the label states the fact, the serif line
   names the person, the sentence names the address the answer goes to.
   The way back is there but quiet, because most people are done. */
.ct-ok {
  display: grid;
  justify-items: center;
  align-content: center;
  text-align: center;
  gap: var(--sp-close);
  min-height: min(60svh, 34rem);
  padding: var(--sp-band) var(--pad);
  outline: none;
  animation: ct-ok-in 0.7s var(--out, ease) both;
}
@keyframes ct-ok-in {
  from { opacity: 0; transform: translateY(0.9rem); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .ct-ok { animation: none; }
}
.ct-ok__label {
  font-size: var(--type-label);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.55;
}
.ct-ok__title {
  font-family: var(--display);
  font-size: clamp(2.2rem, 5.4vw, 4rem);
  line-height: 1.04;
  max-width: 16ch;
}
.ct-ok__body {
  font-size: clamp(1.05rem, 1.5vw, 1.35rem);
  line-height: 1.55;
  max-width: 34ch;
}
.ct-ok__urgent {
  font-size: var(--type-label);
  letter-spacing: 0.02em;
  line-height: 1.6;
  max-width: 44ch;
  opacity: 0.6;
}
.ct-ok__urgent a { border-bottom: 1px solid currentColor; }
.ct-ok__again {
  margin-top: var(--sp-close);
  padding: 0 0 0.35rem;
  background: none;
  border: 0;
  border-bottom: 1px solid currentColor;
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: var(--type-label);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  opacity: 0.5;
  transition: opacity 0.3s var(--out, ease);
}
.ct-ok__again:hover { opacity: 1; }

/* ---------- how long the opening holds the visitor ----------
   The studio, 2026-09-23: "the website is not loading for a long
   time." It was not loading slowly at all: the server answers in 43ms
   and the page is painted in under half a second. What they were
   watching was this card, which held the site for 3.75 seconds on
   every arrival from outside and on every reload.

   Two changes, and the first is the one that matters. The opening now
   plays ONCE per visit (sessionStorage, decided in the head before
   first paint), so a visitor who arrives from Google, looks at the
   work, and comes back to the home page is not made to watch it
   again. Second, the whole sequence is shortened from 3.75s to 2.4s,
   which is still a moment and no longer a wait.

   Kept rather than cut, because a boutique studio arriving with a
   deliberate opening is a different thing from a page that simply
   appears, and that difference is the point of it. */

/* ---------- hidden means hidden ----------
   The confirmation appeared UNDER the form instead of replacing it,
   so a visitor saw both at once and could not tell whether anything
   had happened. `form.hidden = true` was being set correctly and lost
   the argument: the browser's own `[hidden] { display: none }` has
   almost no weight, and any rule that gives the element a `display`
   of its own beats it. `.ct-form__form` is a grid, so it stayed a
   grid.

   This is the general fix rather than a patch for one form, because
   the trap catches every element the site ever hides this way. */
[hidden] { display: none !important; }

/* ---------- the outward arrow ----------
   Drawn, not typed. As the character U+2197 it was one of the glyphs an
   operating system may set either as type or as a colour emoji, and it
   chose by what it could find: a Mac has it, an iPhone has it in neither
   of our faces and reached for Apple Color Emoji. The line that asks for
   the work ended, on a phone, in a blue rounded square.

   Sized in em so it follows whatever it sits beside, and stroked in
   currentColor so it inherits the colour of that line, including over a
   dark footer. */
.arr {
  width: .68em;
  height: .68em;
  margin-left: .42em;
  vertical-align: -.02em;
  flex: none;
  overflow: visible;
}
/* in the press index the arrow is its own grid cell, already placed */
.prow__arrow .arr { margin-left: 0; vertical-align: middle; }

/* ---------- emphasis is not drawn ----------
   The copy marks certain words as emphasised and the markup still
   carries <em>, which is what a screen reader announces. It is simply
   not drawn, and here is why.

   Royals Serif Light is the only cut the studio licensed, and it has no
   italic. Asked for one, a browser makes its own by tilting the upright,
   which on a serif of this class reads as a mistake rather than as
   emphasis. The family does have real italics, twelve fonts across six
   weights, so this is a purchase away from being right. Until someone
   buys it, a slanted counterfeit is worse than nothing.

   Two alternatives were set and looked at before choosing this. The
   brand wine turns three emphasised words in one sentence into what
   looks like three links. A hairline under the word disappears at
   display sizes. The sentence loses nothing by standing plain. */
