/* =========================================================================
   South Desert Studio — Mar de Plástico
   Night over the greenhouse sea of Almería. The plastic is what glows.
   ========================================================================= */

/* --- faces ------------------------------------------------------------- */

@font-face {
  font-family: "General Sans";
  src: url("../fonts/general-sans-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "General Sans";
  src: url("../fonts/general-sans-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("../fonts/satoshi-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("../fonts/satoshi-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Satoshi";
  src: url("../fonts/satoshi-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* --- tokens ------------------------------------------------------------ */

:root {
  /* ground: night over the field */
  --ground: #14100e;
  --ground-raised: #1f1815;
  --ground-sunk: #0d0a09;

  /* ink — every value verified against --ground at 4.5:1 or better */
  --ink: #ede7e1; /* 15.3:1 */
  --ink-dim: #9a8f86; /*  6.0:1 */
  --ink-faint: #8a8079; /*  4.9:1 */

  /* the accent is terracotta, and it is only ever an action */
  --accent: #c97b4a; /*  5.8:1 */
  --accent-lit: #e29a66;
  --accent-sunk: #8a4f2c;

  /* the material: polytunnel plastic catching an eastern sun */
  --plastic: #f2ede6;

  /* hairlines — this world is drawn, so rules do the work cards would */
  --rule: rgba(237, 231, 225, 0.11);
  --rule-strong: rgba(237, 231, 225, 0.2);

  /* type */
  --display: "General Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --text: "Satoshi", "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* spacing — one rhythm for the whole page */
  --s1: 0.5rem;
  --s2: 0.875rem;
  --s3: 1.5rem;
  --s4: 2.5rem;
  --s5: 4rem;
  --s6: 6.5rem;
  --s7: 10rem;

  --measure: 68ch;
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --page: 1320px;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --quick: 180ms var(--ease);
  --slow: 620ms var(--ease);
}

/* --- reset ------------------------------------------------------------- */

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--text);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: "tnum" 0;
  /* `clip` contains the field without creating a scroll container, so the
     fixed masthead, cursor mark and consent bar are not clipped. */
  overflow-x: clip;
}

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

h1,
h2,
h3,
h4 {
  font-family: var(--display);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.03em;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

ul {
  margin: 0;
  padding: 0;
  list-style: none;
}

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

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/* --- browser surfaces --------------------------------------------------
   The parts we did not draw still carry the design. */

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

:focus-visible {
  outline: 2px solid var(--accent-lit);
  outline-offset: 3px;
  border-radius: 2px;
}

html {
  scrollbar-color: var(--accent-sunk) var(--ground-sunk);
  scrollbar-width: thin;
  caret-color: var(--accent);
  accent-color: var(--accent);
}

::-webkit-scrollbar {
  width: 11px;
  height: 11px;
}
::-webkit-scrollbar-track {
  background: var(--ground-sunk);
}
::-webkit-scrollbar-thumb {
  background: var(--accent-sunk);
  border: 3px solid var(--ground-sunk);
  border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--accent);
}

/* --- layout ------------------------------------------------------------ */

.page {
  width: min(100% - var(--gutter) * 2, var(--page));
  margin-inline: auto;
}

.band {
  padding-block: clamp(var(--s5), 11vw, var(--s7));
  border-top: 1px solid var(--rule);
}

.band--tight {
  padding-block: clamp(var(--s4), 7vw, var(--s6));
}

.prose {
  max-width: var(--measure);
  color: var(--ink-dim);
  font-size: 1.0625rem;
  line-height: 1.7;
}

.prose + .prose {
  margin-top: var(--s3);
}

.prose--small {
  font-size: 0.9375rem;
}

.minor-title {
  font-size: 1.125rem;
  letter-spacing: -0.02em;
}

.prose strong {
  color: var(--ink);
  font-weight: 500;
}

.lede {
  max-width: 30ch;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(1.75rem, 1.1rem + 2.6vw, 3rem);
  line-height: 1.14;
  letter-spacing: -0.032em;
  color: var(--ink);
  /* it is the section heading, but the rhythm below it is the stance's own */
  margin-bottom: 0;
}

/* section headings: the heading carries its own weight, no label above it */
.band > .page > h2,
.band-title {
  font-size: clamp(1.6rem, 1.1rem + 2vw, 2.6rem);
  margin-bottom: var(--s4);
}

/* --- annotation --------------------------------------------------------
   Small tracked type is for reading measurements off the plan — a URL, a
   platform, a place. It is never a label parked above a heading. */

.annot {
  font-family: var(--text);
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-feature-settings: "tnum" 1;
}

/* --- actions ----------------------------------------------------------- */

.action {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--display);
  font-weight: 500;
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
  color: var(--accent);
  padding-block: 0.35em;
  transition: color var(--quick);
}

.action .arrow {
  width: 1em;
  height: 1em;
  flex: none;
  transition: transform var(--quick);
}

.action:hover,
.action:focus-visible {
  color: var(--accent-lit);
}

.action:hover .arrow,
.action:focus-visible .arrow {
  transform: translateX(0.28em);
}

.action--solid {
  background: var(--accent);
  color: var(--ground);
  padding: 0.72em 1.35em;
  border-radius: 2px;
  box-shadow: 0 2px 14px -4px rgba(0, 0, 0, 0.75);
  transition: background var(--quick), transform var(--quick),
    box-shadow var(--quick);
}

.action--solid:hover,
.action--solid:focus-visible {
  background: var(--accent-lit);
  color: var(--ground);
  transform: translateY(-1px);
  box-shadow: 0 6px 22px -6px rgba(0, 0, 0, 0.85);
}

/* inline links inside prose */
.prose a,
.link {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent-sunk);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  transition: text-decoration-color var(--quick), color var(--quick);
}

.prose a:hover,
.link:hover {
  color: var(--accent-lit);
  text-decoration-color: var(--accent-lit);
}

/* =========================================================================
   Navigation
   ========================================================================= */

.masthead {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  transition: background var(--slow), border-color var(--slow),
    backdrop-filter var(--slow);
  border-bottom: 1px solid transparent;
}

.masthead.is-lifted {
  background: rgba(20, 16, 14, 0.82);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border-bottom-color: var(--rule);
}

.masthead__inner {
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: 72px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-right: auto;
  padding-block: 0.4rem;
}

.brand img {
  width: 30px;
  height: 30px;
  border-radius: 50%;
}

.brand__name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(0.85rem, 1.6vw, 1.4rem);
}

.nav__link {
  position: relative;
  display: inline-block;
  padding: 0.55rem 0.2rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-dim);
  transition: color var(--quick);
}

.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.2rem;
  height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--quick);
}

.nav__link:hover,
.nav__link:focus-visible,
.nav__link[aria-current="true"] {
  color: var(--ink);
}

.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="true"]::after {
  transform: scaleX(1);
}

/* --- Proyectos dropdown ------------------------------------------------ */

.nav__group {
  position: relative;
}

.nav__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}

.nav__caret {
  width: 0.6em;
  height: 0.6em;
  transition: transform var(--quick);
}

.nav__trigger[aria-expanded="true"] .nav__caret {
  transform: rotate(180deg);
}

.nav__trigger[aria-expanded="true"] {
  color: var(--ink);
}

.nav__trigger[aria-expanded="true"]::after {
  transform: scaleX(1);
}

.menu {
  position: absolute;
  top: calc(100% + 0.6rem);
  left: 50%;
  width: min(23rem, calc(100vw - 2rem));
  padding: var(--s1);
  background: rgba(31, 24, 21, 0.96);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  border: 1px solid var(--rule-strong);
  border-radius: 6px;
  box-shadow: 0 20px 50px -18px rgba(0, 0, 0, 0.9);

  opacity: 0;
  visibility: hidden;
  transform: translate(-50%, -6px);
  transition: opacity var(--quick), transform var(--quick),
    visibility 0s linear 180ms;
}

.nav__group.is-open .menu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
  transition: opacity var(--quick), transform var(--quick), visibility 0s;
}

.menu__item {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.85rem;
  row-gap: 0.15rem;
  align-items: center;
  padding: 0.8rem 0.85rem;
  border-radius: 4px;
  transition: background var(--quick);
}

.menu__item:hover,
.menu__item:focus-visible {
  background: rgba(237, 231, 225, 0.06);
}

.menu__mark {
  grid-row: 1 / span 2;
  width: 26px;
  height: 26px;
  color: var(--accent);
}

.menu__name {
  font-family: var(--display);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: -0.015em;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 0.45em;
}

.menu__name .ext {
  width: 0.7em;
  height: 0.7em;
  color: var(--ink-faint);
  transition: color var(--quick);
}

.menu__item:hover .ext {
  color: var(--accent);
}

.menu__what {
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--ink-dim);
}

/* --- hamburger --------------------------------------------------------- */

.burger {
  display: none;
  width: 42px;
  height: 42px;
  padding: 0;
  place-items: center;
}

.burger__box {
  position: relative;
  width: 19px;
  height: 12px;
}

.burger__box span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform var(--quick), opacity var(--quick);
}

.burger__box span:nth-child(1) {
  top: 0;
}
.burger__box span:nth-child(2) {
  top: 5.25px;
}
.burger__box span:nth-child(3) {
  top: 10.5px;
}

.burger[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(5.25px) rotate(45deg);
}
.burger[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.burger[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-5.25px) rotate(-45deg);
}

/* --- reading progress -------------------------------------------------- */

.progress {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 1px;
  width: 100%;
  transform: scaleX(var(--p, 0));
  transform-origin: left;
  background: var(--accent);
  opacity: 0.85;
}

/* =========================================================================
   Hero — the field
   ========================================================================= */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: 8rem 4rem;
  overflow: hidden;
}

.field {
  position: absolute;
  inset: 0;
  /* Above .hero-3d, because ::before below is the scrim the headline reads
     against and it has to cover the canvas as well as the SVG. */
  z-index: 1;
  pointer-events: none;
}

.field-svg {
  width: 100%;
  height: 100%;
}

/* The 3D field. Progressive enhancement over .field, never a replacement for
   it: the SVG above is the resting state and stays rendered until a real WebGL
   frame exists, so no-JS, no-WebGL, reduced-motion, save-data and print all
   keep the hero they were always going to get. */
.hero-3d {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
}

.hero-3d__canvas {
  display: block;
  width: 100%;
  height: 100%;
}

/* No transition. The canvas is opaque and its first frame is the page's own
   --ground with nothing lit yet, so it can be switched on outright; the entrance
   is animated inside the scene, not by fading the element. */
.hero--3d-live .hero-3d {
  opacity: 1;
}

/* The hand-over is a wipe, not a cross-fade.
   --hero-wipe is written by the scene every frame of the reveal and carries the
   same front the shader uses, so the SVG is erased exactly where and when the
   3D world takes over. Above the front: 3D only. Below it: SVG only, untouched.
   Neither layer is ever half-visible, which is what stopped the two fields from
   appearing at once.

   clip-path rather than mask-image, and that is a measured choice: masking this
   SVG re-rasterises 1900 polygons every frame of the wipe and cost 3fps against
   19fps steady on a software rasteriser. Clipping the same element holds 14fps.
   The trade is a hard edge instead of a feathered one, which is why the shader's
   softness band is narrow — the blend now happens on the 3D side of the line.

   Only the <svg> is clipped: .field also carries the ::before scrim the headline
   is read against, and that has to survive the swap or the name and the
   terracotta action end up sitting on lit plastic. */
.hero--3d-live .field-svg {
  clip-path: inset(var(--hero-wipe, 0%) 0 0 0);
}

/* Once the front has run off the bottom there is nothing left of the SVG to
   show, so it stops being composited altogether. */
.hero--3d-swept .field-svg {
  display: none;
}

.field-cells polygon {
  fill: var(--plastic);
  stroke: var(--ground);
  stroke-width: 1.1;
  vector-effect: non-scaling-stroke;
  /* resting state is lit: the field is visible with or without motion */
  opacity: var(--o);
}

/* Low sun from the east, and night closing the top and bottom edges.
   The middle of the field is left alone: the plastic is what glows. */
.field::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(
      95% 70% at 92% 72%,
      rgba(201, 123, 74, 0.22),
      transparent 58%
    ),
    linear-gradient(
      to bottom,
      var(--ground) 0%,
      rgba(20, 16, 14, 0.55) 12%,
      transparent 32%,
      transparent 70%,
      rgba(20, 16, 14, 0.72) 90%,
      var(--ground) 100%
    );
}

/* the wordmark needs its own ground, and the rambla alone is not enough
   once the field is this bright */
.field::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    100deg,
    rgba(13, 10, 9, 0.92) 0%,
    rgba(13, 10, 9, 0.72) 28%,
    rgba(13, 10, 9, 0.12) 52%,
    transparent 68%
  );
}

.hero__inner {
  position: relative;
  z-index: 2;
}

.hero__name {
  font-size: clamp(2.6rem, 1rem + 6.6vw, 6rem);
  line-height: 0.94;
  letter-spacing: -0.038em;
  max-width: 13ch;
  text-shadow: 0 2px 40px rgba(13, 10, 9, 0.9);
}

.hero__line {
  margin-top: var(--s3);
  max-width: 46ch;
  font-size: clamp(1.0625rem, 1rem + 0.4vw, 1.25rem);
  line-height: 1.55;
  color: var(--ink-dim);
  text-shadow: 0 1px 24px rgba(13, 10, 9, 0.9);
}

.hero__line strong {
  color: var(--ink);
  font-weight: 500;
}

.hero__actions {
  margin-top: var(--s4);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3);
}

.hero__where {
  position: absolute;
  z-index: 2;
  left: var(--gutter);
  bottom: 2.25rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.hero__where svg {
  width: 13px;
  height: 13px;
  color: var(--accent);
}

/* scroll cue */
.cue {
  position: absolute;
  z-index: 2;
  right: var(--gutter);
  bottom: 2.25rem;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  color: var(--ink-faint);
  border: 1px solid var(--rule-strong);
  border-radius: 50%;
  transition: color var(--quick), border-color var(--quick), opacity var(--slow);
}

.cue svg {
  width: 14px;
  height: 14px;
}

.cue:hover,
.cue:focus-visible {
  color: var(--accent);
  border-color: var(--accent-sunk);
}

.cue.is-gone {
  opacity: 0;
  pointer-events: none;
}

/* =========================================================================
   Positioning — what the studio is
   ========================================================================= */

.stance {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s5) var(--s5);
  align-items: start;
}

.stance__half > h3 {
  font-size: clamp(1.15rem, 1rem + 0.6vw, 1.4rem);
  margin-bottom: var(--s2);
}

.stance__half > .prose {
  max-width: 46ch;
}

.stance__rule {
  height: 1px;
  background: var(--rule);
  margin-bottom: var(--s3);
}

/* =========================================================================
   Products — each one a plot in the field
   ========================================================================= */

.plot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--s5);
  align-items: center;
  padding-block: clamp(var(--s4), 6vw, var(--s6));
  border-top: 1px solid var(--rule);
}

.plot:first-of-type {
  border-top: 0;
  padding-top: 0;
}

.plot--flip .plot__figure {
  order: -1;
}

.plot__name {
  font-size: clamp(2rem, 1.3rem + 2.6vw, 3.25rem);
  letter-spacing: -0.035em;
}

.plot__what {
  margin-top: var(--s3);
  max-width: 44ch;
  color: var(--ink-dim);
  font-size: 1.0625rem;
  line-height: 1.7;
}

.plot__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.75rem;
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
}

.plot__fact {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.plot__fact b {
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.9375rem;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.plot__go {
  margin-top: var(--s4);
}

.plot__figure {
  position: relative;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--ground-sunk);
  overflow: hidden;
  display: grid;
  place-items: center;
  padding: var(--s3);
}

.plot__figure--diagram {
  aspect-ratio: 364 / 184;
}

.plot__figure svg.diagram {
  width: 100%;
  height: 100%;
}

.plot__figure img {
  max-height: 78%;
  width: auto;
  object-fit: contain;
  filter: drop-shadow(0 18px 40px rgba(0, 0, 0, 0.7));
}

/* The FIELDS composition arrives with its own ground (#050303, a shade off
   --ground-sunk) and its own studio shadow. Floating it — padding, contain, a
   second drop-shadow — would seat one dark rectangle inside another and put a
   seam between them. It runs to the edges instead. */
.plot__figure--shot {
  padding: 0;
}

.plot__figure--shot img {
  max-height: none;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: none;
}

/* All the scrim has left to do is carry the frame edge back into the ground.
   The warm wash is gone: the photograph already supplies its own amber. */
.plot__figure--shot::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(
    78% 68% at 50% 50%,
    transparent 42%,
    rgba(13, 10, 9, 0.55) 100%
  );
}

/* the authored diagrams share one line grammar */
.diagram .d-rule {
  stroke: var(--rule-strong);
  stroke-width: 1;
  fill: none;
}
.diagram .d-line {
  stroke: var(--accent);
  stroke-width: 1.5;
  fill: none;
  stroke-linecap: round;
}
.diagram .d-node {
  fill: var(--accent);
}
.diagram .d-plot {
  fill: var(--plastic);
  opacity: 0.16;
}
.diagram .d-plot.is-on {
  opacity: 0.72;
}
.diagram .d-label {
  fill: var(--ink-faint);
  font-family: var(--text);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* =========================================================================
   Place — Almería
   ========================================================================= */

.place {
  position: relative;
  border-top: 1px solid var(--rule);
}

.place__frame {
  position: relative;
  aspect-ratio: 21 / 9;
  /* Never let the block size transfer back into an inline minimum. A box with
     an aspect-ratio and width:auto turns a min-height into an effective
     min-width of `min-height x ratio` — a min-height of 320px here computed a
     746px floor, which overflowed the 350px column on a phone and dragged the
     whole document into horizontal scroll. The frame's width comes from its
     column, always; the height follows from the ratio. */
  min-width: 0;
  background: var(--ground-sunk);
  border-radius: 4px;
  overflow: hidden;
  display: grid;
  place-items: center;
}

/* <picture> is an inline box with no height of its own, so the img's height:100%
   below was resolving against nothing and falling back to the photo's intrinsic
   21:9 — it sat centred in the frame with bands of ground above and below. That
   went unnoticed while the frame was also 21:9 and the two happened to match;
   any other frame ratio exposes it. */
.place__frame picture {
  display: block;
  width: 100%;
  height: 100%;
}

.place__frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.place__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(13, 10, 9, 0.92),
    rgba(13, 10, 9, 0.15) 55%,
    rgba(13, 10, 9, 0.4)
  );
  pointer-events: none;
}

.place__caption {
  position: absolute;
  z-index: 3;
  left: var(--s4);
  bottom: var(--s4);
  right: var(--s4);
}

.place__text {
  margin-top: var(--s5);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s5);
  align-items: start;
}

/* =========================================================================
   Team — three people, no hover theatre
   ========================================================================= */

.crew {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s4);
  border-top: 1px solid var(--rule);
}

.person {
  position: relative;
  padding-top: var(--s4);
}

/* The divider sits in the grid gap, so every column is the same width and the
   last portrait still reaches the margin the section hairline reaches. */
.person:not(:last-child)::after {
  content: "";
  position: absolute;
  top: var(--s4);
  bottom: 0;
  right: calc(var(--s4) / -2);
  width: 1px;
  background: var(--rule);
}

/* The supplied photographs have the studio badge composited into them, so the
   frame clips and the image is scaled past the badge's arch. Replace the
   source photographs and this scale drops back to 1. */
.person__frame picture {
  display: block;
  width: 100%;
  height: 100%;
}

.plot__figure picture {
  display: contents;
}

.person__frame {
  overflow: hidden;
  border-radius: 3px;
  aspect-ratio: 4 / 5;
  background: var(--ground-sunk);
}

.person__portrait {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center var(--eye, 30%);
  transform: scale(var(--zoom, 1.18));
  /* sepia after grayscale: a warm monochrome that belongs to this ground,
     rather than a neutral #AAA plate sitting on warm black */
  filter: grayscale(1) sepia(0.34) saturate(1.15) contrast(1.06)
    brightness(0.92);
  transition: filter var(--slow), transform var(--slow);
}

.person:hover .person__portrait,
.person:focus-within .person__portrait {
  filter: grayscale(0.25) sepia(0.12) saturate(1.05) contrast(1)
    brightness(1);
  transform: scale(calc(var(--zoom, 1.18) * 1.035));
}

.person__name {
  margin-top: var(--s3);
  font-size: 1.125rem;
  letter-spacing: -0.02em;
}

.person__role {
  margin-top: 0.3rem;
  color: var(--ink-dim);
  font-size: 0.9375rem;
}

/* =========================================================================
   Contact + footer
   ========================================================================= */

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

.contact__open {
  max-width: var(--measure);
  margin-bottom: var(--s5);
}

.contact__open .band-title {
  margin-bottom: var(--s3);
}

/* Three columns of comparable weight, so the page's last screen closes level
   instead of trailing one long column past a short one. */
.contact {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 0.55fr);
  gap: var(--s5);
  align-items: start;
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
}

.reach {
  display: grid;
  gap: var(--s2);
  align-content: start;
}

.reach__row {
  display: grid;
  grid-template-columns: 20px 1fr;
  gap: 0.9rem;
  align-items: start;
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--rule);
}

.reach__row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.reach__row svg {
  width: 16px;
  height: 16px;
  margin-top: 0.28rem;
  color: var(--accent);
}

.reach__row b {
  display: block;
  font-family: var(--display);
  font-weight: 500;
  font-size: 1rem;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.reach__row span {
  display: block;
  margin-top: 0.1rem;
  color: var(--ink-dim);
  font-size: 0.9375rem;
}

.reach__row a:hover span {
  color: var(--accent-lit);
}

/* newsletter */
.subscribe .prose {
  margin-top: 0.4rem;
}

.subscribe__field {
  display: flex;
  gap: 0.5rem;
  margin-top: var(--s3);
}

.subscribe__icon {
  width: 16px;
  height: 16px;
}

.subscribe input {
  flex: 1;
  min-width: 0;
  padding: 0.78rem 0.95rem;
  font: inherit;
  font-size: 0.9375rem;
  color: var(--ink);
  background: var(--ground-sunk);
  border: 1px solid var(--rule-strong);
  border-radius: 3px;
  transition: border-color var(--quick);
}

.subscribe input::placeholder {
  color: var(--ink-faint);
}

.subscribe input:focus {
  outline: none;
  border-color: var(--accent);
}

.subscribe button {
  flex: none;
  padding: 0.78rem 1.1rem;
  background: var(--accent);
  color: var(--ground);
  border-radius: 3px;
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.9375rem;
  transition: background var(--quick);
}

.subscribe button {
  display: grid;
  place-items: center;
}

.subscribe button:hover:not(:disabled) {
  background: var(--accent-lit);
}

.subscribe button:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* Every outcome of the form is named in the page, rather than handing the
   visitor to the form host and off the site. */
.form__note {
  margin-top: var(--s2);
  min-height: 1.25rem;
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-dim);
}

.form__note[data-state="ok"] {
  color: var(--accent-lit);
}

.form__note[data-state="error"] {
  color: #e8836f;
}

.subscribe input[aria-invalid="true"] {
  border-color: #e8836f;
}

.elsewhere .social {
  margin-top: var(--s3);
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s2);
}

.elsewhere .social a {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.3rem 0;
  font-size: 0.9375rem;
  color: var(--ink-dim);
}

.elsewhere .social a:hover,
.elsewhere .social a:focus-visible {
  transform: none;
  color: var(--accent-lit);
}

.elsewhere .social svg {
  flex: none;
}

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

.colophon {
  border-top: 1px solid var(--rule);
  padding-block: var(--s4);
}

.colophon__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s3) var(--s4);
}

.colophon__legal {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-left: auto;
}

.colophon a {
  color: var(--ink-faint);
  font-size: 0.8125rem;
  transition: color var(--quick);
}

.colophon a:hover {
  color: var(--ink);
}

.colophon__copy {
  font-size: 0.8125rem;
  color: var(--ink-faint);
  font-feature-settings: "tnum" 1;
}

/* --- public funding ------------------------------------------------------
   The RETECH publicity obligation, and the page's last movement. It sits in
   the footer rather than in the colophon row because it is a statement, not a
   link. The emblems are supplied as one official composite and may not be
   recoloured or recut, so the sheet beneath them is not ornament: it is the
   only ground they are legible on — and lit plastic on desert black is the
   material this whole page is made of. */

.colophon:has(.funding) {
  padding-top: 0;
}

.funding {
  padding-block: clamp(var(--s4), 7vw, var(--s6));
}

/* The frame is the lit room the emblems stand in. Its border carries the
   pointer-tracked glow from sds-dev-governance (frontend-patterns/ui-animations/
   border-glow): --gx/--gy are written by app.js and move the bright arc of the
   ring. The defaults below place that arc top-right, so the frame reads the
   same on touch, where there is no pointer to track. */
.funding__frame {
  --gx: 76%;
  --gy: -8%;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding: clamp(1rem, 2.6vw, var(--s4));
  border: 1px solid rgba(201, 123, 74, 0.46);
  border-radius: 6px;
  background:
    radial-gradient(
      140% 115% at 80% -14%,
      rgba(226, 154, 102, 0.2),
      transparent 60%
    ),
    var(--ground-sunk);
  /* The halo has a downward offset: the light in this world comes from above
     and to the right, the same place the hero's sun sits. */
  box-shadow: 0 18px 90px -42px rgba(226, 154, 102, 0.55);
}

/* The ring: a one-pixel band cut out of a radial gradient with mask-composite,
   exactly the technique the governance pattern uses for its dock. */
.funding__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  padding: 1px;
  border-radius: inherit;
  background: radial-gradient(
    900px 420px at var(--gx) var(--gy),
    var(--accent-lit),
    rgba(226, 154, 102, 0.55) 30%,
    rgba(201, 123, 74, 0.22) 58%,
    transparent 82%
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
  pointer-events: none;
  transition: background 420ms var(--ease);
}

/* The field of plates: the hero's greenhouse sea, drawn by the compositor
   instead of by WebGL. A plane laid flat under a real CSS perspective, so the
   rows converge the way the Three.js floor converges — not a sheared grid
   pretending to. No bytes, no canvas, no frame loop. */
.funding__field {
  position: absolute;
  inset: 0;
  z-index: 0;
  perspective: 520px;
  perspective-origin: 84% 0%;
  pointer-events: none;
  /* The falloff is masked on the frame-sized box, not on the plane: the plane
     is deliberately oversized so its yaw never shows a corner, and a mask on
     it would drift with that size. */
  -webkit-mask-image: radial-gradient(
    76% 132% at 82% 116%,
    #000 0%,
    rgba(0, 0, 0, 0.58) 42%,
    transparent 76%
  );
  mask-image: radial-gradient(
    76% 132% at 82% 116%,
    #000 0%,
    rgba(0, 0, 0, 0.58) 42%,
    transparent 76%
  );
}

.funding__field::before {
  content: "";
  position: absolute;
  /* Oversized on every side: the yaw below swings the plane in its own plane,
     and a tighter box would show its corners inside the frame. */
  left: -110%;
  right: -110%;
  bottom: -55%;
  height: 300%;
  /* Read right to left: the plots are first turned off-square in the ground
     plane, then the ground is laid down under the perspective. That yaw is
     what turns a printed grid into a field seen from the side.

     One yaw for the whole plane, deliberately. The hero gives every plot its
     own FIELD.jitterYaw of 5.5deg and gets away with it because the scene
     moves: the eye reads the scatter as hand-laid ground. This floor never
     moves, and per-plate scatter in a still frame stops being character and
     becomes noise. So the plates here are all square to each other, and the
     only thing that changes across the field is the convergence — which is
     perspective doing its job, not jitter. */
  transform: rotateX(70deg) rotateZ(24deg);
  transform-origin: 50% 100%;
  background-color: rgba(226, 154, 102, 0.5);
  background-image:
    linear-gradient(90deg, rgba(13, 10, 9, 0.96) 4px, transparent 4px),
    linear-gradient(0deg, rgba(13, 10, 9, 0.96) 4px, transparent 4px);
  background-size: 68px 46px;
  opacity: 0.72;
}

.funding__sheet {
  /* The supplied composite carries its own opaque white ground, so the sheet
     is that same white: any warmer tone would draw a second frame inside the
     first. The padding is white too — it only gives the emblems air. */
  position: relative;
  z-index: 1;
  padding: clamp(0.75rem, 1.7vw, 1.15rem) clamp(0.9rem, 2.2vw, 1.6rem);
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 20px 50px -18px rgba(0, 0, 0, 0.9);
}

.funding__sheet picture {
  display: block;
}

.funding__emblems {
  width: 100%;
  height: auto;
}

.funding__body {
  margin-top: clamp(var(--s4), 4vw, var(--s5));
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: var(--s5);
  align-items: start;
}

/* The mandated wording is a citation, so it keeps its own measure and its own
   line height rather than borrowing the prose scale of the sections above. */
.funding__statement {
  max-width: 60ch;
  color: var(--ink-dim);
  font-size: 0.9375rem;
  line-height: 1.75;
}

.funding__note {
  max-width: 60ch;
  margin-top: var(--s3);
  color: var(--ink-faint);
  font-size: 0.875rem;
  line-height: 1.7;
}

.funding__record {
  display: grid;
  gap: var(--s2);
  align-content: start;
  margin: 0;
  padding-top: 0.15rem;
}

.funding__row {
  display: grid;
  gap: 0.28rem;
  padding-bottom: var(--s2);
  border-bottom: 1px solid var(--rule);
}

.funding__row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.funding__row dd {
  margin: 0;
  color: var(--ink);
  font-size: 0.9375rem;
  line-height: 1.4;
}

.funding + .colophon__inner {
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
}

.social {
  display: flex;
  gap: 0.35rem;
}

.social {
  gap: var(--s3);
}

.social a {
  display: grid;
  place-items: center;
  color: var(--ink-dim);
  padding: 0.35rem 0;
  transition: color var(--quick), transform var(--quick);
}

.social a:hover,
.social a:focus-visible {
  color: var(--accent-lit);
  transform: translateY(-1px);
}

.social svg {
  width: 18px;
  height: 18px;
}

/* =========================================================================
   Cookie consent
   ========================================================================= */

/* A bar along the foot of the page: it never lands on the hero's own action. */
.consent {
  position: fixed;
  z-index: 200;
  inset: auto 0 0 0;
  padding: var(--s3) 0;
  background: rgba(31, 24, 21, 0.97);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border-top: 1px solid var(--rule-strong);
  box-shadow: 0 -18px 50px -24px rgba(0, 0, 0, 0.9);
  transform: translateY(102%);
  transition: transform var(--slow);
}

.consent.is-shown {
  transform: translateY(0);
}

.consent__inner {
  display: flex;
  align-items: center;
  gap: var(--s3) var(--s4);
}

.consent__text {
  flex: 1 1 26rem;
  min-width: 0;
}

.consent h2 {
  font-size: 1rem;
  letter-spacing: -0.02em;
}

.consent p {
  margin-top: 0.2rem;
  max-width: 74ch;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ink-dim);
}

.consent__buttons {
  flex: none;
  display: flex;
  gap: 0.5rem;
}

.consent__buttons button {
  padding: 0.65rem 1.35rem;
  border-radius: 3px;
  font-family: var(--display);
  font-weight: 500;
  font-size: 0.875rem;
  white-space: nowrap;
  transition: background var(--quick), border-color var(--quick),
    color var(--quick);
}

@media (max-width: 720px) {
  .consent__inner {
    flex-wrap: wrap;
  }

  .consent__buttons {
    width: 100%;
  }

  .consent__buttons button {
    flex: 1;
  }
}

.btn-accept {
  background: var(--accent);
  color: var(--ground);
}
.btn-accept:hover {
  background: var(--accent-lit);
}

.btn-reject {
  border: 1px solid var(--rule-strong);
  color: var(--ink-dim);
}
.btn-reject:hover {
  border-color: var(--ink-faint);
  color: var(--ink);
}

/* =========================================================================
   Back to top
   ========================================================================= */

.totop {
  position: fixed;
  z-index: 55;
  right: var(--gutter);
  bottom: var(--gutter);
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  color: var(--ink-dim);
  background: rgba(31, 24, 21, 0.86);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--rule-strong);
  border-radius: 50%;
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  transition: opacity var(--quick), transform var(--quick), color var(--quick),
    border-color var(--quick);
}

.totop.is-shown {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.totop:hover {
  color: var(--accent-lit);
  border-color: var(--accent-sunk);
}

.totop svg {
  width: 15px;
  height: 15px;
}

/* =========================================================================
   Cursor — a surveyor's registration mark
   Fine pointers only. The native cursor is never taken away from anyone else.
   ========================================================================= */

@media (pointer: fine) {
  html.has-mark,
  html.has-mark a,
  html.has-mark button,
  html.has-mark input,
  html.has-mark [tabindex] {
    cursor: none;
  }

  .mark {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -17px;
    pointer-events: none;
    opacity: 0;
    transition: opacity 200ms var(--ease);
    will-change: transform;
  }

  .mark.is-live {
    opacity: 1;
  }

  .mark__ring,
  .mark__cross {
    position: absolute;
    inset: 0;
    transition: transform 260ms var(--ease), opacity 260ms var(--ease);
  }

  /* The ring: the registration circle. Three states scale one 34px box —
     at rest, pressed, and open over a target. Resting was 0.42 (~14px) and
     read as a speck on a large display; it is 1.5x that now (~21px), which
     still leaves a clear opening gesture up to 1.0. */
  .mark__ring {
    /* One point heavier than it was, in both states: at rest the ring is drawn
       at scale 0.63, so a hairline border was rendering thinner than a hairline
       and disappearing on dense displays. */
    border: 2px solid var(--ink-dim);
    border-radius: 50%;
    transform: scale(0.63);
    opacity: 0.85;
  }

  /* the crosshair ticks, drawn only when the mark opens over a target */
  .mark__cross::before,
  .mark__cross::after {
    content: "";
    position: absolute;
    background: var(--accent);
    opacity: 0;
    transition: opacity 200ms var(--ease);
  }

  .mark__cross::before {
    left: 50%;
    top: 0;
    bottom: 0;
    width: 2px;
    margin-left: -1px;
  }

  .mark__cross::after {
    top: 50%;
    left: 0;
    right: 0;
    height: 2px;
    margin-top: -1px;
  }

  .mark__dot {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 4px;
    height: 4px;
    margin: -2px 0 0 -2px;
    background: var(--ink);
    border-radius: 50%;
    transition: opacity 200ms var(--ease);
  }

  /* over a target: the mark opens, the ticks come in, the dot steps aside */
  .mark.is-open .mark__ring {
    transform: scale(1);
    border-color: var(--accent);
    opacity: 1;
  }

  .mark.is-open .mark__cross::before,
  .mark.is-open .mark__cross::after {
    opacity: 0.7;
  }

  .mark.is-open .mark__dot {
    opacity: 0;
  }

  /* pressed */
  .mark.is-down .mark__ring {
    transform: scale(0.78);
  }
}

/* =========================================================================
   Reveal — content is visible by default; motion is the enhancement
   ========================================================================= */

@media (prefers-reduced-motion: no-preference) {
  /* The one authored moment: light crosses the field from the east, and the
     name surfaces out of the rambla as it arrives. One gesture, one curve.
     `backwards` keeps the resting state visible, so nothing here is load-bearing. */
  .field-cells polygon {
    animation: ignite 820ms var(--ease) backwards;
    animation-delay: calc(var(--d) * 1500ms);
  }

  @keyframes ignite {
    from {
      opacity: 0;
    }
  }

  .hero__name,
  .hero__line,
  .hero__actions,
  .hero__where {
    animation: surface 1000ms var(--ease) backwards;
  }

  .hero__name {
    animation-delay: 120ms;
  }
  .hero__line {
    animation-delay: 300ms;
  }
  .hero__actions {
    animation-delay: 440ms;
  }
  .hero__where {
    animation-delay: 620ms;
  }

  @keyframes surface {
    from {
      opacity: 0;
      transform: translateY(14px);
      filter: blur(6px);
    }
  }
}

/* =========================================================================
   Legal pages
   ========================================================================= */

.doc {
  padding-top: 8rem;
}

.doc__title {
  font-size: clamp(1.9rem, 1.2rem + 2.6vw, 3rem);
  margin-bottom: var(--s4);
}

.doc__viewer {
  width: 100%;
  height: min(78vh, 900px);
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--ground-sunk);
}

.doc__back {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  margin-top: var(--s4);
  color: var(--accent);
  font-family: var(--display);
  font-weight: 500;
  transition: color var(--quick);
}

.doc__back:hover {
  color: var(--accent-lit);
}

.doc__back svg {
  width: 1em;
  height: 1em;
}

/* =========================================================================
   Responsive
   ========================================================================= */

@media (max-width: 1100px) {
  .contact {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .elsewhere {
    grid-column: 1 / -1;
    padding-top: var(--s3);
    border-top: 1px solid var(--rule);
  }

  .elsewhere .social {
    flex-direction: row;
    gap: var(--s4);
  }
}

@media (max-width: 900px) {
  .stance,
  .plot,
  .place__text,
  .contact {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s4);
  }

  .funding__body {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s4);
  }

  .funding__record {
    padding-top: var(--s3);
    border-top: 1px solid var(--rule);
  }

  /* 21:9 is a horizon on a desktop and a letterbox slit on a phone. The frame
     takes a taller crop as the column narrows instead of the old min-height
     floor — which is what that floor was reaching for before it started
     dictating the width instead of the height. */
  .place__frame {
    aspect-ratio: 16 / 9;
  }

  .plot--flip .plot__figure {
    order: 0;
  }

  /* the crew keeps three columns further down; portraits are narrow and a
     two-column grid strands the third on its own row */
}

@media (max-width: 780px) {
  .burger {
    display: grid;
  }

  .nav {
    position: fixed;
    inset: 0 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 5.5rem var(--gutter) var(--s4);
    background: rgba(20, 16, 14, 0.98);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-bottom: 1px solid var(--rule);
    transform: translateY(-101%);
    transition: transform 420ms var(--ease);
    max-height: 100svh;
    overflow-y: auto;
  }

  .nav.is-open {
    transform: translateY(0);
  }

  .nav__link {
    padding: 0.85rem 0;
    font-size: 1.0625rem;
    border-bottom: 1px solid var(--rule);
  }

  .nav__link::after {
    display: none;
  }

  .nav__group {
    position: static;
  }

  .menu {
    position: static;
    width: 100%;
    transform: none;
    opacity: 1;
    visibility: visible;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: 0;
    border-bottom: 1px solid var(--rule);
    border-radius: 0;
    box-shadow: none;
    padding: 0 0 var(--s2) 0;
    display: none;
  }

  .nav__group.is-open .menu {
    display: block;
    transform: none;
  }

  .hero__where {
    display: none;
  }

  /* The rambla void carries the wordmark on wide screens. At this width the
     text runs the full frame, so the scrim has to as well or the name and the
     terracotta action end up sitting on lit plastic. */
  .field::before {
    background: linear-gradient(
      180deg,
      rgba(13, 10, 9, 0.34) 0%,
      rgba(13, 10, 9, 0.46) 18%,
      rgba(13, 10, 9, 0.92) 33%,
      rgba(13, 10, 9, 0.93) 74%,
      rgba(13, 10, 9, 0.5) 88%,
      rgba(13, 10, 9, 0.34) 100%
    );
  }
}

@media (max-width: 700px) {
  /* A 10:1 strip of five emblems has nowhere to go on a phone but wider, so
     the sheet takes the page gutter back and runs edge to edge. Every pixel
     the viewport can give the emblems, they get — the strip is never recut. */
  /* The frame takes the page gutter so the emblems inside it keep every pixel
     the viewport has. The composite already carries its own side margins, so
     the sheet adds only vertical air. */
  .funding__frame {
    margin-inline: calc(var(--gutter) * -1);
    /* Deeper at the foot than at the head: that is where the field of plates
       has to read, and a 14px strip of it reads as an artefact, not a floor. */
    padding: 0.9rem 0 1.6rem;
    border-radius: 0;
    border-left: 0;
    border-right: 0;
  }

  .funding__sheet {
    padding: 0.6rem 0;
    border-radius: 0;
  }

  .funding__field {
    perspective-origin: 88% 0%;
  }

  .funding__field::before {
    opacity: 0.58;
  }

  .place__frame {
    aspect-ratio: 3 / 2;
  }

  .crew {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* the divider of the last item on each row would land on the grid edge */
  .person:nth-child(2n)::after {
    display: none;
  }
}

@media (max-width: 520px) {
  .crew {
    grid-template-columns: minmax(0, 1fr);
  }

  .person::after {
    display: none;
  }

  .person {
    border-top: 1px solid var(--rule);
  }

  .person:first-child {
    border-top: 0;
  }

  .person:first-child {
    border-top: 0;
  }

  .person__frame {
    aspect-ratio: 3 / 2;
  }

  .person__portrait {
    object-position: center var(--eye-wide, 26%);
  }

  .colophon__legal {
    margin-left: 0;
  }

  .place__caption {
    left: var(--s3);
    right: var(--s3);
    bottom: var(--s3);
  }
}

/* =========================================================================
   Preferences
   ========================================================================= */

@media (prefers-reduced-motion: reduce) {
  /* The boot gate declines the scene under reduced motion; this is the belt to
     that braces, in case the class is ever applied by other means. */
  .hero-3d {
    display: none;
  }

  /* The ring keeps its authored arc and stops chasing the pointer. app.js
     never attaches the listener here either; this is the belt to that brace. */
  .funding__frame::after {
    transition: none;
  }

  .hero--3d-live .field-svg,
  .hero--3d-swept .field-svg {
    display: block;
    clip-path: none;
  }

  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

@media (prefers-contrast: more) {
  :root {
    --ink-dim: #d3cbc3;
    --ink-faint: #bdb3ab;
    --rule: rgba(237, 231, 225, 0.26);
    --rule-strong: rgba(237, 231, 225, 0.42);
    --accent: #e8a271;
  }
}

@media print {
  :root {
    --ground: #ffffff;
    --ground-raised: #ffffff;
    --ground-sunk: #ffffff;
    --ink: #101010;
    --ink-dim: #3a3a3a;
    --ink-faint: #555555;
    --accent: #8a4f2c;
    --accent-lit: #8a4f2c;
    --rule: rgba(0, 0, 0, 0.2);
    --rule-strong: rgba(0, 0, 0, 0.35);
  }

  .masthead,
  .field,
  .hero-3d,
  .cue,
  .totop,
  .consent,
  .mark,
  .social {
    display: none !important;
  }

  body {
    background: #fff;
    color: var(--ink);
  }
}
