/* Landark Studio — variant 2
   Image-first. Ground colour from Gustafson Porter + Bowman (#ecece9, #4d4d4d).
   Layout from studioilse. Category split from Vincent Van Duysen.
   Written fresh — shares nothing with the live site's stylesheet. */

:root {
  --bg:        #ecece9;
  --ink:       #4d4d4d;
  --ink-deep:  #343431;
  --meta:      #5f5f5a;
  --line:      #d8d8d3;
  --on-image:  #ffffff;

  /* Carried over deliberately. These three are the practice's discipline
     colours — they carry meaning, not decoration — and all three clear 3:1
     against the ground, which is the bar for a dot. The cell also holds a
     visually-hidden label, so nothing depends on colour alone. */
  --d-landscape:    #2c7030;
  --d-architecture: #a85434;
  --d-interiors:    #8a5d00;

  --serif: Spectral, Georgia, "Times New Roman", serif;
  --sans:  "IBM Plex Sans", system-ui, -apple-system, Segoe UI, sans-serif;

  --gut:   clamp(20px, 4vw, 56px);
  --head-h: 74px;
  --ease: cubic-bezier(.4, 0, .2, 1);
  /* the one picture frame phones use for home slides, page heroes, discipline rows and project cards */
  --phone-frame: 1.6953;
  /* the height a long section keeps on narrow screens, where it scrolls sideways */
  --pan-h: 200px;
}

@font-face {
  font-family: Spectral;
  src: url("../fonts/spectral-latin-400-normal.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Sans";
  src: url("../fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}

/* Two candidate display faces, local to this variant. Switch with data-display
   on <body>: "spectral-300" or "cormorant". Omit it for Spectral 400. */
@font-face {
  font-family: "Spectral Light";
  src: url("fonts/spectral-latin-300-normal.woff2") format("woff2");
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("fonts/cormorant-garamond-latin-300-normal.woff2") format("woff2");
  font-weight: 300; font-style: normal; font-display: swap;
}

body[data-display="spectral-300"] {
  --serif: "Spectral Light", Georgia, serif;
  --serif-w: 300;
}
body[data-display="cormorant"] {
  --serif: "Cormorant Garamond", Georgia, serif;
  --serif-w: 300;
  /* Cormorant sits on a small x-height, so it needs more size to hold the
     same optical weight as Spectral at the same px value. */
  --serif-scale: 1.16;
}

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

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

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

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

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--bg); color: var(--ink);
  padding: 12px 18px; font-size: 13px;
}
.skip:focus { left: 12px; top: 12px; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

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

/* Sits above the overlay so the wordmark stays put while the menu is open. */
.site-head {
  position: fixed; inset: 0 0 auto 0; z-index: 160;
  height: var(--head-h);
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  padding: 0 var(--gut);
  color: var(--ink);
  transition: color .4s var(--ease);
}
.site-head.over-image { color: var(--on-image); }

.mark { grid-column: 2; justify-self: center; display: block; }
.mark svg { width: 132px; height: auto; display: block; }

.menu-btn {
  grid-column: 3; justify-self: end;
  appearance: none; background: none; border: 0; padding: 8px 0; margin: 0;
  color: inherit; cursor: pointer;
  font-family: var(--sans); font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase;
}

/* ---------- overlay menu ---------- */

.menu {
  position: fixed; inset: 0; z-index: 150;
  background: var(--bg);
  padding: var(--head-h) var(--gut) var(--gut);
  display: flex; align-items: center;
  opacity: 0; visibility: hidden;
  transition: opacity .42s var(--ease), visibility .42s;
}
.menu[data-open="true"] { opacity: 1; visibility: visible; }

.menu-cols {
  display: grid; gap: clamp(36px, 6vw, 96px);
  grid-template-columns: 1fr;
  width: 100%; max-width: 1100px; margin: 0 auto;
}
@media (min-width: 760px) { .menu-cols { grid-template-columns: 1fr 1fr; } }

.menu-group h2 {
  margin: 0 0 18px;
  font-family: var(--sans); font-size: 11px; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.menu-group ul { list-style: none; margin: 0; padding: 0; }
.menu-group li + li { margin-top: 2px; }
.menu-group a {
  display: block;
  font-family: var(--serif);
  font-weight: var(--serif-w, 400);
  font-size: calc(clamp(1.6rem, 4.2vw, 2.6rem) * var(--serif-scale, 1));
  line-height: 1.25;
  color: var(--ink);
  transition: opacity .2s var(--ease);
}
.menu-group a:hover { opacity: .55; }
/* Van Duysen's nested type level, held but not shown: four or five projects per
   discipline is too few to sort. Delete this one rule to switch it on, and
   confirm the type names first — they are a placeholder, not Landark's taxonomy. */
.menu-group .sub { display: none; }

.menu-group .sub.shown {
  display: block;
  font-family: var(--sans); font-size: 12px; letter-spacing: .04em;
  color: var(--meta); margin: 2px 0 14px;
}

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

.hero {
  position: relative;
  height: 100svh; min-height: 520px;
  overflow: hidden;
  background: #c9c9c4;
}

.slide {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
}
.slide[data-active="true"] { opacity: 1; }
.slide img { width: 100%; height: 100%; object-fit: cover; object-position: var(--wide-position, var(--portrait-position, center)); }

/* Two scrims. The radial one is load-bearing: these renders are sunlit white
   walls and pale sky, so a centred white line has nothing to sit on without it.
   The linear one only keeps the header and the caption legible. */
.slide::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(116% 50% at 50% 50%,
      rgba(0,0,0,.44) 0%, rgba(0,0,0,.28) 46%, rgba(0,0,0,0) 78%),
    linear-gradient(180deg,
      rgba(0,0,0,.30) 0%, rgba(0,0,0,0) 22%,
      rgba(0,0,0,0) 54%, rgba(0,0,0,.46) 100%);
}

.slide-line {
  position: absolute; z-index: 2;
  left: var(--gut); right: var(--gut); top: 50%;
  transform: translateY(-50%);
  /* em-based, so the measure holds as the line scales */
  max-width: 16em; margin: 0 auto; text-align: center;
  /* a line that wraps splits evenly instead of leaving a scrap on the second line */
  text-wrap: balance;
  font-family: var(--serif);
  font-weight: var(--serif-w, 400);
  font-size: calc(clamp(1.5rem, 3.4vw, 2.9rem) * var(--serif-scale, 1));
  line-height: 1.3;
  color: var(--on-image);
  text-shadow: 0 1px 24px rgba(0,0,0,.32);
}

.slide-id {
  position: absolute; z-index: 2;
  left: var(--gut); bottom: calc(var(--gut) + 26px);
  margin: 0;
  font-size: 12px; letter-spacing: .04em;
  color: rgba(255,255,255,.88);
  text-shadow: 0 1px 16px rgba(0,0,0,.45);
}

.dots {
  position: absolute; z-index: 3;
  left: 0; right: 0; bottom: calc(var(--gut) - 4px);
  display: flex; gap: 9px; justify-content: center;
}
.dots button {
  appearance: none; padding: 0; border: 0; cursor: pointer;
  width: 7px; height: 7px; border-radius: 50%;
  background: rgba(255,255,255,.42);
  transition: background .3s var(--ease);
}
.dots button[aria-current="true"] { background: rgba(255,255,255,.95); }

/* Captions follow their photograph in, as on studioilse: the slide fades up, then about a
   second later its line rises 30px into place and the project name follows. The script
   switches this on, so without it, or with reduced motion, the text simply shows. */
.hero[data-captions] .slide-line,
.hero[data-captions] .slide-id {
  opacity: 0;
  transition: opacity .35s var(--ease), transform .35s var(--ease);
}
.hero[data-captions] .slide-line { transform: translateY(calc(-50% + 30px)); }
.hero[data-captions] .slide-id   { transform: translateY(12px); }
.hero[data-captions] .slide[data-captioned] .slide-line,
.hero[data-captions] .slide[data-captioned] .slide-id {
  opacity: 1;
  transition: opacity .8s ease-out, transform .8s ease-out;
}
.hero[data-captions] .slide[data-captioned] .slide-line { transform: translateY(-50%); }
.hero[data-captions] .slide[data-captioned] .slide-id   { transform: none; transition-delay: .15s; }

@media (prefers-reduced-motion: reduce) {
  .slide, .dots { transition: none; }
}

/* ---------- disciplines (home) ---------- */

/* After studioilse's category rows: one row per discipline, a tall photograph beside a
   serif name and one sentence, the photograph changing sides from row to row. Each row is
   one link, to that discipline's page. On a phone the photograph sits above the text. */
.disciplines { padding: clamp(56px, 8vw, 120px) 0 clamp(24px, 4vw, 60px); }

.discipline { display: block; color: inherit; margin-bottom: clamp(56px, 9vw, 90px); }
.discipline-img { padding: 0 var(--gut); }
.discipline-img img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.discipline-text { padding: clamp(22px, 5vw, 34px) var(--gut) 0; }
.discipline-inner { max-width: 27em; }
.discipline h2 {
  margin: 0 0 16px;
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(clamp(2.1rem, 3.1vw, 2.9rem) * var(--serif-scale, 1));
  line-height: 1.15;
  transition: opacity .2s var(--ease);
}
.discipline p { margin: 0; font-size: 16px; line-height: 1.6; }
.discipline:hover h2 { opacity: .6; }

@media (min-width: 860px) {
  .discipline { display: flex; align-items: center; margin-bottom: 50px; }
  .discipline-img { width: 50%; height: min(90vh, 62vw); padding: 0; }
  .discipline-img img { height: 100%; aspect-ratio: auto; }
  .discipline-text { width: 50%; padding: 50px; }
  .discipline:nth-child(1) .discipline-img  { width: 60%; }
  .discipline:nth-child(1) .discipline-text { width: 40%; }
  .discipline:nth-child(2) .discipline-img  { order: 2; }
  .discipline:nth-child(2) .discipline-inner { margin-left: auto; }
  /* the third row tucks up under the second, whose photograph is on the other side. Its interior
     shows whole at its own 3:2, because a tall crop kept only the middle half of the room; at half
     the page wide it stays clear of the second row's photograph. The 3 / 2 holds the row's height
     until the picture loads, so the page below it does not jump. */
  .discipline:nth-child(3) { margin-top: -10%; }
  .discipline:nth-child(3) .discipline-img { width: 50%; height: auto; margin-right: 5%; }
  .discipline:nth-child(3) .discipline-img img { height: auto; aspect-ratio: auto 3 / 2; }
  .discipline:nth-child(3) .discipline-text { width: 45%; }
}

/* Rows rise into place as they come up the screen, as studioilse's do. The script turns
   this on; without it, or with reduced motion, the rows are simply there. */
.disciplines[data-reveal] .discipline {
  opacity: .2; transform: translateY(30px);
  transition: opacity .8s ease-out, transform .8s ease-out;
}
.disciplines[data-reveal] .discipline-img  { transform: translateY(50px); transition: transform 1.2s ease-out; }
.disciplines[data-reveal] .discipline-text { transform: translateY(50px); transition: transform .8s ease-out; }
.disciplines[data-reveal] .discipline.in-view { opacity: 1; transform: none; }
.disciplines[data-reveal] .discipline.in-view .discipline-img,
.disciplines[data-reveal] .discipline.in-view .discipline-text { transform: none; }

/* ---------- inner pages ---------- */

/* Transparent while it sits over a hero, solid the moment it doesn't. Keyed to
   the class rather than the page, because the project page switches mid-scroll. */
.site-head:not(.over-image) { background: var(--bg); }

.sheet { padding-top: var(--head-h); }

.intro {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(52px, 7vw, 112px) var(--gut) clamp(32px, 4vw, 56px);
  display: grid; gap: clamp(20px, 3vw, 64px);
  grid-template-columns: 1fr;
}
@media (min-width: 860px) {
  .intro { grid-template-columns: 1.1fr 1fr; align-items: end; }
}

.intro h1 {
  margin: 0;
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(clamp(2.4rem, 6vw, 4.2rem) * var(--serif-scale, 1));
  line-height: 1.04; letter-spacing: -.01em;
}
.intro p { margin: 0; max-width: 44ch; font-size: 15px; line-height: 1.6; }

/* ---------- project grid ---------- */

.grid {
  max-width: 1400px; margin: 0 auto;
  padding: 0 var(--gut) clamp(72px, 9vw, 132px);
  display: grid;
  gap: clamp(28px, 3.4vw, 52px) clamp(18px, 2.4vw, 32px);
  grid-template-columns: 1fr;
}
@media (min-width: 620px)  { .grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .grid { grid-template-columns: repeat(3, 1fr); } }

.card { display: block; }
.card img {
  width: 100%; aspect-ratio: 3 / 2; object-fit: cover; object-position: var(--wide-position, var(--portrait-position, center));
  background: #dededa;
  transition: opacity .35s var(--ease);
}
.card:hover img, .card:focus-visible img { opacity: .82; }

.card h2 {
  margin: 15px 0 3px;
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(1.3rem * var(--serif-scale, 1)); line-height: 1.25;
}
.card .where { margin: 0; font-size: 12px; color: var(--meta); }
/* Only on projects that run into another discipline — the reason a house turns
   up on the landscape page at all. */
.card .also {
  margin: 4px 0 0; font-size: 11px; letter-spacing: .04em; color: var(--meta);
}

/* ---------- project page ---------- */

.phero {
  position: relative; overflow: hidden;
  height: 82svh; min-height: 440px;
  background: #c9c9c4;
}
/* Where a cropped picture holds. On wide screens a slide, hero or card holds where its img's
   --wide-position says, or else its --portrait-position; phones read --portrait-position alone (the
   portrait rules further down). So the Onyx and St. Luke street views keep their roofs on every
   screen, and Where Generations Unite keeps the wheelchair user and the group on the right on wide
   screens and the girl with the balloon on phones, as Hans chose. */
.phero img { width: 100%; height: 100%; object-fit: cover; object-position: var(--wide-position, var(--portrait-position, center)); }
.phero::after {
  content: ""; position: absolute; inset: 0;
  background:
    radial-gradient(116% 50% at 50% 50%,
      rgba(0,0,0,.44) 0%, rgba(0,0,0,.28) 46%, rgba(0,0,0,0) 78%),
    linear-gradient(180deg,
      rgba(0,0,0,.30) 0%, rgba(0,0,0,0) 22%,
      rgba(0,0,0,0) 54%, rgba(0,0,0,.40) 100%);
}
.phero .titles {
  position: absolute; inset: 0; z-index: 2;
  display: grid; place-content: center; align-content: center;
  text-align: center; padding: 0 var(--gut); color: var(--on-image);
}
.phero h1 {
  margin: 0;
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(clamp(2.1rem, 5.4vw, 4rem) * var(--serif-scale, 1));
  line-height: 1.08;
  text-shadow: 0 1px 24px rgba(0,0,0,.32);
}
.phero .titles p {
  margin: 12px 0 0; font-size: 13px; letter-spacing: .04em;
  color: rgba(255,255,255,.9); text-shadow: 0 1px 16px rgba(0,0,0,.4);
}

/* A project that opens on a drawing rather than a photograph. The title sits on
   the page ground instead of over the image, because a masterplan cropped to a
   hero band stops being readable as a plan — and because a locator rectangle
   placed in per cent only tracks the drawing while the image keeps its own
   aspect ratio, which object-fit: cover destroys. */
.plan-title {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(34px, 5vw, 72px) var(--gut) clamp(18px, 2.5vw, 30px);
}
.plan-title h1 {
  margin: 0;
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(clamp(2.1rem, 5.4vw, 4rem) * var(--serif-scale, 1));
  line-height: 1.04; letter-spacing: -.01em;
}
.plan-title p {
  margin: 10px 0 0;
  font-size: 13px; letter-spacing: .04em; color: var(--meta);
}

/* standfirst left, the spec block right */
.brief {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(46px, 6vw, 96px) var(--gut) clamp(26px, 3.5vw, 48px);
  display: grid; gap: clamp(26px, 4vw, 72px);
  grid-template-columns: 1fr;
}
@media (min-width: 860px) { .brief { grid-template-columns: 1.35fr 1fr; } }

.brief .lede p {
  margin: 0 0 14px; max-width: 52ch;
  font-size: clamp(15px, 1.5vw, 17px); line-height: 1.62;
}
.brief .lede p:last-child { margin-bottom: 0; }

.facts { margin: 0; font-size: 13px; line-height: 1.55; }
.facts div {
  display: grid; grid-template-columns: 8.5em 1fr; gap: 14px;
  padding: 9px 0; border-top: 1px solid var(--line);
}
.facts div:last-child { border-bottom: 1px solid var(--line); }
.facts dt { color: var(--meta); }
.facts dd { margin: 0; }
.facts a { border-bottom: 1px solid var(--line); }
.facts a:hover { border-bottom-color: var(--meta); }

/* ---------- image mosaic ---------- */

.mosaic, .plate {
  max-width: 1400px; margin: 0 auto;
  padding: 0 var(--gut);
}
.mosaic {
  display: grid; gap: clamp(30px, 4vw, 64px) clamp(18px, 2.4vw, 40px);
  grid-template-columns: 1fr;
  padding-bottom: clamp(30px, 4vw, 64px);
}
/* The offset on the second column is what stops this reading as a table of
   pictures. It only earns its keep once there are two columns to stagger. */
@media (min-width: 760px) {
  .mosaic { grid-template-columns: 1fr 1fr; }
  .mosaic figure:nth-child(even) { margin-top: clamp(34px, 6vw, 104px); }
}
.plate { padding-bottom: clamp(30px, 4vw, 64px); }

.mosaic figure, .plate figure { margin: 0; }
.mosaic img, .plate img { width: 100%; height: auto; background: #dededa; }
.mosaic figcaption, .plate figcaption {
  margin-top: 11px; font-size: 12px; line-height: 1.5;
  color: var(--meta); max-width: 46ch;
}

/* Drawings open at full size. A plan or a section is drawn to be read, and at
   472px on a phone the grid references and dimensions are visible but not
   legible — so the linework stays in the page and the numbers stay reachable.
   The badge is always shown rather than revealed on hover, because hover does
   not exist on the devices where this matters most. */
.drawing a { position: relative; display: block; }
.drawing .full {
  position: absolute; right: 10px; bottom: 10px;
  background: rgba(236, 236, 233, .93);
  border: 1px solid var(--line);
  padding: 5px 9px;
  font-size: 10px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--meta);
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.drawing a:hover .full,
.drawing a:focus-visible .full { color: var(--ink); border-color: var(--meta); }

/* Long sections on narrow screens. Across a phone a section is a strip 40 to 90px tall, too thin
   to read, so below 860px it keeps the --pan-h height and scrolls sideways in its own frame, with a
   line under it saying so. Each of those imgs gives its width at that height in its sizes, so the
   phone fetches a picture sharp enough to scroll along. The planting schedule is a table, so on
   narrow screens its Full size badge sits under the table instead of over the plant names. */
.pan-hint { display: none; }
@media (max-width: 859px) {
  .pan { overflow-x: auto; overscroll-behavior-x: contain; }
  .plate .pan img { width: auto; max-width: none; height: var(--pan-h); }
  .pan-hint { display: block; margin: 8px 0 0; font-size: 11px; letter-spacing: .04em; color: var(--meta); }
  .drawing.schedule .full { position: static; display: table; margin: 8px 0 0 auto; }
}

/* Section labels. The CAD export has its text stripped, leaving only the dashed
   leader lines along the top edge, so the words go back in as HTML at the per
   cent where each leader falls: a strip directly above the image, each label
   centred on its line. The first is left-aligned so it cannot run off the edge.
   The labels stop clearing each other below about 980px of image — measured on
   the live site — which in this wider column arrives at a 1066px viewport; below
   that a one-line legend reads them out left to right instead. */
.legend {
  margin: 0 0 12px;
  font-size: 12px; line-height: 1.6; color: var(--meta);
}
.seclabels { display: none; }
@media (min-width: 1080px) {
  .seclabels {
    display: block; position: relative;
    height: 18px; line-height: 18px; margin: 0 0 8px;
    font-size: 12px; color: var(--meta);
  }
  .seclabels span {
    position: absolute; bottom: 0;
    white-space: nowrap; transform: translateX(-50%);
  }
  .seclabels span.l0 { transform: none; }
  .seclabels + .legend { display: none; }
}

/* Locator on a drawing: a dashed rectangle over the part of a bigger plan that
   this page is actually about. An SVG rather than a CSS border, because the
   browser chooses its own dash length for `dashed` and these need to stay short.
   viewBox 0 0 100 100 with preserveAspectRatio="none" makes the rect
   co-ordinates read as percentages; non-scaling-stroke then keeps the line and
   the dashes a constant thickness on screen however far the plan is scaled. */
.locator {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
}
.locator rect {
  fill: none;
  stroke: #d62828;
  stroke-width: 2;
  stroke-dasharray: 6 4;
  vector-effect: non-scaling-stroke;
}

/* ---------- studio: the record ---------- */

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

.record {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(24px, 3vw, 44px) var(--gut) clamp(10px, 2vw, 22px);
}
.record h2 {
  margin: 0 0 16px; font-family: var(--sans); font-size: 11px; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.record-note { margin: 0; max-width: 62ch; font-size: 15px; line-height: 1.62; }
.record-note + .record-note { margin-top: 14px; }

/* Safety net: if the four columns still will not fit, the table scrolls inside
   its own box rather than pushing the page sideways. */
.matrix-wrap { overflow-x: auto; margin: 24px 0 18px; }

.matrix { width: 100%; border-collapse: collapse; font-size: 13px; }
.matrix th, .matrix td {
  padding: 13px 10px 13px 0;
  border-bottom: 1px solid var(--line);
  text-align: left; font-weight: 400;
}
.matrix thead th {
  font-family: var(--sans); font-size: 10px; font-weight: 400;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--meta); vertical-align: bottom; white-space: nowrap;
}
.matrix tbody th {
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(1.05rem * var(--serif-scale, 1));
  text-align: left; white-space: nowrap;
}
.matrix tbody th a { border-bottom: 1px solid transparent; }
.matrix tbody th a:hover { border-bottom-color: var(--meta); }
.matrix th + th, .matrix td { text-align: center; }

.dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; }
.dot.l { background: var(--d-landscape); }
.dot.a { background: var(--d-architecture); }
.dot.i { background: var(--d-interiors); }

.matrix tfoot th, .matrix tfoot td {
  border-bottom: 0; padding-top: 14px;
  font-family: var(--sans); font-size: 12px; color: var(--meta);
}

/* Narrow: the column heads become initials. `.full` is hidden visually rather
   than with display:none, so each column keeps its real accessible name. */
.matrix .abbr { display: none; }
@media (max-width: 619px) {
  .matrix thead .full {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .matrix .abbr { display: inline; }
  .matrix tbody th { white-space: normal; }
}

/* ---------- studio: the five stages ---------- */

.stages {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(24px, 3vw, 44px) var(--gut) clamp(24px, 3vw, 44px);
}
.stages h2 {
  margin: 0 0 16px; font-family: var(--sans); font-size: 11px; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.stages-note { margin: 0 0 26px; max-width: 62ch; font-size: 15px; line-height: 1.62; }
.stages ol { list-style: none; margin: 0 0 26px; padding: 0; counter-reset: stage; }
.stages li {
  counter-increment: stage;
  display: grid; gap: 4px 20px; grid-template-columns: 1fr;
  padding: 16px 0; border-top: 1px solid var(--line);
}
.stages li:last-child { border-bottom: 1px solid var(--line); }
@media (min-width: 760px) { .stages li { grid-template-columns: 15em 1fr; } }
.stages li strong {
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(1.15rem * var(--serif-scale, 1));
}
.stages li strong::before {
  content: counter(stage) " ";
  font-family: var(--sans); font-size: 11px; color: var(--meta);
  letter-spacing: .16em; margin-right: 8px;
}
.stages li span { font-size: 14px; line-height: 1.6; color: var(--ink); max-width: 56ch; }

/* ---------- notes ---------- */

.notelist {
  list-style: none; max-width: 1400px; margin: 0 auto;
  padding: 0 var(--gut) clamp(60px, 8vw, 110px);
}
.notelist li { border-top: 1px solid var(--line); padding: 20px 0; }
.notelist li:last-child { border-bottom: 1px solid var(--line); }
.notelist a {
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(clamp(1.35rem, 2.6vw, 1.9rem) * var(--serif-scale, 1));
  line-height: 1.25;
}
.notelist a:hover { opacity: .6; }
.notelist p { margin: 5px 0 0; font-size: 12px; color: var(--meta); }

/* A note is the one place on this site where the text is the object, so it
   gets a reading measure rather than a column of a grid. */
.note .intro { grid-template-columns: 1fr; }
@media (min-width: 860px) { .note .intro { grid-template-columns: 1.35fr 1fr; } }
.prose {
  max-width: 1400px; margin: 0 auto;
  padding: 0 var(--gut) clamp(20px, 3vw, 40px);
}
.prose p {
  margin: 0 0 1.15em; max-width: 34em;
  font-size: clamp(15px, 1.55vw, 17px); line-height: 1.68;
}

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

.contact {
  max-width: 1400px; margin: 0 auto;
  padding: 0 var(--gut) clamp(60px, 8vw, 110px);
  display: grid; gap: clamp(26px, 4vw, 56px);
  grid-template-columns: 1fr;
  font-size: 15px; line-height: 1.6;
}
@media (min-width: 760px) { .contact { grid-template-columns: repeat(3, 1fr); } }
.contact h2 {
  margin: 0 0 8px; font-family: var(--sans); font-size: 11px; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.contact p + h2 { margin-top: 22px; }
.contact p { margin: 0 0 12px; }
.contact a { border-bottom: 1px solid var(--line); }
.contact a:hover { border-bottom-color: var(--meta); }

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

.next {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(30px, 4vw, 56px) var(--gut) clamp(56px, 7vw, 96px);
  border-top: 1px solid var(--line);
}
.next span {
  display: block; font-size: 11px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.next a {
  display: inline-block; margin-top: 8px;
  font-family: var(--serif); font-weight: var(--serif-w, 400);
  font-size: calc(clamp(1.6rem, 3.4vw, 2.4rem) * var(--serif-scale, 1));
  line-height: 1.2;
}
.next a:hover { opacity: .6; }

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

.foot {
  border-top: 1px solid var(--line);
  max-width: 1400px; margin: 0 auto;
  padding: clamp(30px, 4vw, 52px) var(--gut) clamp(44px, 6vw, 76px);
  display: grid; gap: 22px; grid-template-columns: 1fr;
  font-size: 13px; line-height: 1.6; color: var(--meta);
}
@media (min-width: 760px) { .foot { grid-template-columns: 1fr 1fr 1fr; } }
/* Under the full-bleed carousel the footer runs full width too, so its left
   edge lines up with the slide caption instead of a centred 1400px column. */
body[data-page="home"] .foot { max-width: none; }
.foot a { text-decoration: none; border-bottom: 1px solid var(--line); }
.foot a:hover { border-bottom-color: var(--meta); }
.foot h2 {
  margin: 0 0 8px; font-size: 11px; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}

/* ---------- project text between the pictures ---------- */

/* What to notice, and where the claim stops holding: short passages in the same
   column and measure as the standfirst, set beside the pictures they are about. */
.textblock {
  max-width: 1400px; margin: 0 auto;
  padding: clamp(10px, 2vw, 28px) var(--gut) clamp(44px, 5vw, 76px);
}
.textblock h2, .prose h2 {
  margin: 0 0 14px; font-family: var(--sans); font-size: 11px; font-weight: 400;
  letter-spacing: .16em; text-transform: uppercase; color: var(--meta);
}
.prose h2 { margin: 2.6rem 0 .9rem; }
.textblock p {
  margin: 0 0 14px; max-width: 52ch;
  font-size: clamp(15px, 1.5vw, 17px); line-height: 1.62;
}
.textblock p:last-child { margin-bottom: 0; }
.textblock a, .brief .lede a { border-bottom: 1px solid var(--line); }
.textblock a:hover, .brief .lede a:hover { border-bottom-color: var(--meta); }

/* the reason for two dates, under the studio facts */
.facts-note { margin: 14px 0 0; max-width: 46ch; font-size: 13px; line-height: 1.6; color: var(--meta); }

/* ---------- running text ---------- */

/* Paragraphs set flush on both sides, the last line of each left as it falls.
   Hyphenation keeps the word gaps even in a phone-width column. Lines set on the
   pictures and one-line labels keep their own alignment and never hyphenate. */
main p, main figcaption, .stages li span {
  text-align: justify;
  -webkit-hyphens: auto; hyphens: auto;
}
.slide-line, .slide-id, .phero .titles p, .plan-title p, .card p, .notelist p, .legend, .pan-hint {
  -webkit-hyphens: manual; hyphens: manual;
}
.slide-id, .plan-title p, .card p, .notelist p, .legend, .pan-hint { text-align: left; }
.phero .titles p { text-align: center; }

/* ---------- portrait screens: whole pictures ---------- */

/* On a portrait screen a landscape render cropped to fill the frame loses most of its width.
   Measured on the live site at 390 x 844: 24 to 31 per cent of each home slide survived, and 29
   to 38 per cent of each page hero. So on any portrait screen the pictures keep their own
   proportions, the header stops floating over them, and the words that were set on the picture
   move onto the ground beneath it. Landscape screens keep the full-bleed pictures. */
@media (orientation: portrait) {
  .site-head.over-image { color: var(--ink); background: var(--bg); }

  /* Home: every slide at the full width of the screen and one shared height, the --phone-frame
     (1.6953:1). That is the geometric mean of the 3:2 and the 1.92:1 renders the site uses, so
     either shape loses the same 11.5 per cent: a 3:2 picture at the top and bottom, a 1.92:1 one at
     the sides. A 16:9 picture loses 4.6 per cent at the sides. Page heroes, the discipline rows and
     the project cards use the same frame, and any picture can move its own crop with
     --portrait-position on its img.
     The dots sit 16px under the pictures (the page script sets the same figure), then the line and
     the project name. The space under the picture holds three lines at the line's own size: 176px
     on phones, more on portrait tablets, where the line grows with the screen. 82.4px is the 44px
     above the line, the 10px gap and 19px project name below it, and 9px to spare, so three lines
     at 24px (3.9 times 24px) make the 176px. With a fixed 176px, the fourth slide's project name
     was cut off on portrait iPads. */
  .hero {
    /* the line's size: 24px on most phones; smaller under 348px wide (6.9vw is 24px at 348px), so
       the fourth slide's "all within the same practice." fits across a 320px phone; larger on
       tablets (3.4vw) */
    --line-size: calc(min(clamp(1.5rem, 3.4vw, 2.9rem), 6.9vw) * var(--serif-scale, 1));
    height: calc(100vw / var(--phone-frame) + max(176px, 82.4px + 3.9 * var(--line-size)));
    min-height: 0; margin-top: var(--head-h); background: var(--bg);
  }
  .slide img { height: auto; aspect-ratio: var(--phone-frame); object-fit: cover; object-position: var(--portrait-position, center); }
  .slide::after { display: none; }
  .slide-line {
    position: static; transform: none;
    max-width: none; margin: 44px var(--gut) 0;
    font-size: var(--line-size);
    color: var(--ink); text-shadow: none;
  }
  .slide-id {
    position: static; margin: 10px var(--gut) 0;
    text-align: center; color: var(--meta); text-shadow: none;
  }
  .hero[data-captions] .slide-line { transform: translateY(30px); }
  .hero[data-captions] .slide-id { transform: translateY(12px); }
  .hero[data-captions] .slide[data-captioned] .slide-line,
  .hero[data-captions] .slide[data-captioned] .slide-id { transform: none; }
  .dots { top: calc(100vw / var(--phone-frame) + 16px); bottom: auto; transition: top .6s var(--ease); }
  .dots button { background: rgba(77, 77, 77, .28); }
  .dots button[aria-current="true"] { background: var(--ink); }
  .disciplines { padding-top: 28px; }

  /* Project and studio pages: the picture in the phone frame, the title and place on the ground beneath it. */
  .phero { height: auto; min-height: 0; margin-top: var(--head-h); background: none; }
  .phero img { height: auto; aspect-ratio: var(--phone-frame); object-position: var(--portrait-position, center); }
  .phero::after { display: none; }
  .phero .titles { position: static; display: block; padding: 22px var(--gut) 0; text-align: left; color: var(--ink); }
  .phero h1 { text-shadow: none; }
  .phero .titles p { color: var(--meta); text-shadow: none; text-align: left; }
}

/* In a single column the project cards and the home discipline rows take the phone frame, so a
   list of pictures reads as one set. */
@media (max-width: 619px) { .card img { aspect-ratio: var(--phone-frame); object-position: var(--portrait-position, center); } }
@media (max-width: 859px) { .discipline-img img { aspect-ratio: var(--phone-frame); object-position: var(--portrait-position, center); } }

/* The Bridge City street view was drawn from a roof terrace, and the top of the terrace wall runs
   across the bottom 16 per cent of the render. On a landscape screen the cover crop is anchored 35
   per cent down, which keeps most of the wall out of sight. Portrait screens show the whole render,
   wall included. */
.slide img.trim-foot { object-position: center 35%; }
