/* ==========================================================================
   Earthlight site.css

   Direction: EARTHSHINE (seed 869d1fc3). The observatory plate room where the
   ashen light on the Moon's dark limb is actually measured. The reading field
   is achromatic; the ONLY luminance on the page is at the limb. That is the
   colour rule and it is not negotiable: an accent scattered through the
   interface is the failure mode this direction was chosen to avoid.

   Committed single-world dark. There is no light theme and no toggle: a plate
   is black, and a photographic negative rendered on white is not the same
   object. Every colour is painted explicitly so the page never borrows a host
   background.
   ========================================================================== */

/* ------------------------------------------------------------------ font --
   Two variable faces, self-hosted, latin subset. Archivo carries a width axis,
   which is what lets the display type sit at the logo's tracking without
   faking it with letter-spacing alone. Martian Mono is the measurement
   register: ledger rows, statuses, plate numbers, annotation.
   font-display: swap, because the headline is the first paint and a blank hero is
   worse than a reflow. */
@font-face {
  font-family: "Archivo";
  src: url("/assets/fonts/archivo-latin.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Martian Mono";
  src: url("/assets/fonts/martianmono-latin.woff2") format("woff2-variations");
  font-weight: 100 800;
  font-stretch: 75% 112.5%;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------------- tokens -- */
:root {
  /* Ground and its two lifts. Not pure black: #0A0C0F carries a faint blue
     bias, which is what a plate looks like and what stops the page reading as
     an OLED void. */
  --plate:      #0A0C0F;
  --sleeve:     #12161B;
  --sleeve-hi:  #171C22;

  /* Ink. Silver-gelatin greys. --body is the reading colour and clears 7:1 on
     --plate; --silver is for labels and clears 4.5:1. */
  --silver:     #8A9199;
  --body:       #A7ADB5;
  --ash:        #F4F2EC;

  /* The one warm material: the manila sleeve. Used for plate tabs, ledger
     numbers and annotation: physical labels, never a UI accent. */
  --manila:     #C9BDA4;

  --rule:        rgba(138,145,153,.19);
  --rule-strong: rgba(138,145,153,.40);

  /* Type scale. Fluid, and every step is used. */
  --t-mono:  .76rem;
  --t-body:  clamp(.98rem, .3vw + .9rem, 1.08rem);
  --t-lede:  clamp(1.08rem, .55vw + .95rem, 1.28rem);
  --t-h3:    clamp(1.05rem, .5vw + .92rem, 1.28rem);
  --t-h2:    clamp(1.35rem, 1.9vw + .6rem, 2.25rem);
  --t-h1:    clamp(1.5rem, 2.9vw + .35rem, 3.35rem);

  --measure: 66ch;
  --gut:     clamp(1.15rem, 4vw, 3.25rem);
  --rail:    19rem;      /* the ledger rail on desktop */
  --shell:   88rem;

  --ease: cubic-bezier(.22,.68,.28,1);
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--plate);
  color: var(--body);
  font-family: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  font-variation-settings: "wdth" 100;
  font-size: var(--t-body);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;   /* the limb arc deliberately overhangs the viewport */
}

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

/* Skip link. Visible the moment it takes focus, never before. */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ash); color: var(--plate);
  padding: .7rem 1.1rem; font-weight: 600;
}
.skip:focus { left: 0; }

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

/* ------------------------------------------------------------------ type -- */
h1, h2, h3, h4 {
  color: var(--ash);
  margin: 0;
  font-weight: 600;
  text-wrap: balance;
  letter-spacing: .015em;
}
/* The display register sits WIDE. That is the logo's own proportion, and the
   width axis does the work rather than letter-spacing, which would open the
   counters without widening the letterforms. */
h1 { font-size: var(--t-h1); line-height: 1.06; font-weight: 300; font-variation-settings: "wdth" 112; text-transform: uppercase; letter-spacing: .15em; }
h2 { font-size: var(--t-h2); line-height: 1.12; font-weight: 400; font-variation-settings: "wdth" 108; text-transform: uppercase; letter-spacing: .085em; }
h3 { font-size: var(--t-h3); line-height: 1.25; font-variation-settings: "wdth" 104; }

p { margin: 0; max-width: var(--measure); }
a { color: var(--ash); text-decoration-color: var(--rule-strong); text-underline-offset: .22em; }
a:hover { text-decoration-color: var(--manila); }
strong { color: var(--ash); font-weight: 600; }
em { color: var(--ash); font-style: italic; }

.mono {
  font-family: "Martian Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--t-mono);
  font-variation-settings: "wdth" 100;
  letter-spacing: .11em;
  text-transform: uppercase;
  font-weight: 400;
  color: var(--silver);
  line-height: 1.5;
}
.mono--manila { color: var(--manila); }
.mono--ash    { color: var(--ash); }

.lede { font-size: var(--t-lede); color: var(--body); max-width: 54ch; line-height: 1.55; }

/* ---------------------------------------------------------------- layout -- */
.shell { max-width: var(--shell); margin-inline: auto; padding-inline: var(--gut); }
.stack { display: flex; flex-direction: column; gap: 1.15rem; }
.stack--lg { gap: 2.5rem; }
.stack--sm { gap: .55rem; }

/* --------------------------------------------------------------- the limb --
   Two elements. .limb__plate is a photographic asset, and it has to be one:
   an earlier build drew it as a single stroked circle and flat vector where
   the world is photographic is exactly what reads as templated. .limb__arc is
   the far hairline of atmosphere, still authored, because at that opacity it
   is one stroke and an image would be 30KB of almost nothing.

   Both are decorative in the accessibility sense and sit inside an
   aria-hidden wrapper, but the plate is the single most load-bearing element
   in the direction. It deliberately overhangs the viewport: a limb that fits
   inside the frame reads as a circle, and a circle reads as a logo, not a
   horizon. */
.limb { position: absolute; inset: 0; pointer-events: none; overflow: hidden; }

/* The photographic plate. Positioned by where its LIT RIM has to land, not by
   its own box: in the file the rim's leftmost point sits at x=0.27 of the
   image, so with width W and right offset R the rim lands at
   (100 + R - W) + 0.27W of the viewport. 62vw is the gap between the headline
   and the ledger rail, which is where the comp puts it. */
.limb__plate {
  position: absolute;
  right: -46vw; top: 50%;
  width: 118vw; max-width: none; height: auto;
  transform: translateY(-50%) rotate(var(--limb-turn, 0deg));
  transform-origin: 50% 50%;
  mix-blend-mode: screen;
}
/* The far arc sits outside the plate, up and to the left. */
.limb__arc {
  position: absolute;
  right: 4vw; top: 50%;
  width: 118vw; max-width: none; height: auto;
  transform: translateY(-54%) rotate(calc(var(--limb-turn, 0deg) * -0.4));
  transform-origin: 50% 50%;
}

@media (max-width: 900px) {
  /* Further out and quieter: at this width the plate would otherwise sit
     under the headline rather than beside it. */
  .limb__plate { right: -88vw; width: 158vw; opacity: .3; }
  .limb__arc { right: -20vw; width: 150vw; opacity: .35; }
}

/* ------------------------------------------------------------------ nav -- */
.masthead {
  position: relative; z-index: 3;
  display: flex; align-items: center; gap: 1.15rem 2rem; flex-wrap: wrap;
  padding-block: clamp(1.25rem, 2.6vw, 2.1rem);
}
.masthead__logo { flex: none; display: block; width: clamp(132px, 15vw, 186px); }
.masthead__logo svg, .masthead__logo img { width: 100%; height: auto; }
.masthead__slug { display: none; }
@media (min-width: 900px) { .masthead__slug { display: block; } }

.nav { margin-left: auto; display: flex; gap: clamp(1rem, 2.4vw, 2.1rem); flex-wrap: wrap; }
.nav a {
  font-family: "Martian Mono", ui-monospace, monospace;
  font-size: var(--t-mono); letter-spacing: .12em; text-transform: uppercase;
  color: var(--silver); text-decoration: none; padding-block: .3rem;
  border-bottom: 1px solid transparent;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.nav a:hover { color: var(--ash); border-bottom-color: var(--rule-strong); }
.nav a[aria-current="page"] { color: var(--ash); border-bottom-color: var(--manila); }

/* ----------------------------------------------------------------- hero -- */
.hero { position: relative; background: var(--plate); border-bottom: 1px solid var(--rule); }
/* The masthead's ground. Without it the limb decides whether the nav is
   readable, and on the inner pages it decided no. */
.hero::before {
  content: ""; position: absolute; inset: 0 0 auto 0; z-index: 1;
  height: clamp(92px, 15vh, 164px); pointer-events: none;
  background: linear-gradient(to bottom,
    var(--plate) 0%, rgba(10,12,15,.92) 46%, rgba(10,12,15,0) 100%);
}
.hero__inner {
  position: relative; z-index: 2;
  display: grid;
  grid-template-columns: minmax(0,1fr);
  gap: clamp(2.5rem, 6vw, 4rem);
  padding-block: clamp(2.5rem, 8vh, 6rem) clamp(3rem, 9vh, 6.5rem);
  min-height: min(76svh, 44rem);
  align-content: center;
  align-items: start;
}
@media (min-width: 1040px) {
  .hero__inner { grid-template-columns: minmax(0,1fr) var(--rail); gap: clamp(2.5rem,4vw,4.5rem); }
}
.hero h1 { margin-bottom: clamp(1.4rem, 2.6vw, 2.1rem); }
.hero__sub { margin-bottom: clamp(1.9rem, 3.4vw, 2.6rem); }

/* --------------------------------------------------------------- actions -- */
.actions { display: flex; flex-wrap: wrap; gap: .8rem; }
.btn {
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: "Martian Mono", ui-monospace, monospace;
  font-size: var(--t-mono); letter-spacing: .13em; text-transform: uppercase;
  padding: .95rem 1.5rem .88rem; text-decoration: none; border: 1px solid transparent;
  transition: background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease);
}
/* The primary action is the lit edge of the page. It is the only solid ash
   field in the whole design, which is what makes it unmissable without an
   accent colour. */
.btn--primary { background: var(--ash); color: var(--plate); font-weight: 600; }
.btn--primary:hover { background: #fff; }
.btn--ghost { color: var(--ash); border-color: var(--rule-strong); }
.btn--ghost:hover { border-color: var(--ash); background: rgba(244,242,236,.05); }


/* ---------------------------------------------------------------- ledger --
   The exposure log. Rows are observations: number, subject, status. This is
   where the slate's withheld state becomes visible rather than absent: a
   sleeved plate that exists and has not been printed. */
.ledger { border-top: 1px solid var(--rule-strong); }
.ledger__cap { display: grid; grid-template-columns: 2.9rem 1fr; gap: .9rem; }
.ledger__cap { padding-block: .8rem; border-bottom: 1px solid var(--rule); }
.ledger__row {
  display: grid; grid-template-columns: 2.9rem 1fr auto; gap: .35rem .9rem;
  align-items: baseline; padding-block: .78rem;
  border-bottom: 1px solid var(--rule);
}
.ledger__no {
  justify-self: start; align-self: start;
  background: var(--manila); color: #17140F;
  font-family: "Martian Mono", ui-monospace, monospace; font-size: .64rem;
  font-weight: 700; letter-spacing: .08em; font-variant-numeric: tabular-nums;
  padding: .26rem .42rem .22rem;
  /* the notched corner of a sleeve index tab */
  clip-path: polygon(0 0, 100% 0, 100% 62%, 78% 100%, 0 100%);
}
.ledger__subject {
  color: var(--ash); font-size: .93rem; font-weight: 500; line-height: 1.35;
  border-left: 1px solid var(--rule); padding-left: .95rem;
}
.ledger__cap span { display: block; }
.ledger__status {
  font-family: "Martian Mono", ui-monospace, monospace; font-size: .68rem;
  letter-spacing: .11em; text-transform: uppercase; color: var(--silver); white-space: nowrap;
}
/* A withheld row is dimmer but still ranked and still counted. It never
   collapses and it is never removed. */
.ledger__row--withheld .ledger__subject {
  color: var(--silver);
  /* the sleeved plate: present, numbered, unread */
  background: repeating-linear-gradient(
    -45deg, rgba(138,145,153,.16) 0 3px, transparent 3px 7px);
  padding: .1rem .45rem; border-radius: 1px;
}
.ledger__row--withheld .ledger__status { color: var(--manila); }

/* --------------------------------------------------------------- section -- */
.band { border-bottom: 1px solid var(--rule); padding-block: clamp(3.2rem, 8vw, 6.5rem); position: relative; }
.band--tight { padding-block: clamp(2.4rem, 5vw, 4rem); }

/* The manila sleeve tab. It marks a PLATE, an actual numbered item in the
   archive, and nothing else. It is not a section eyebrow: an earlier build
   used it above every heading, which turned the numbers into a per-page
   counter that contradicted itself across pages. */
.tab {
  flex: none; background: var(--manila); color: #17140F;
  font-family: "Martian Mono", ui-monospace, monospace; font-weight: 700;
  font-size: .6rem; letter-spacing: .12em; text-transform: uppercase;
  padding: .3rem .58rem .25rem;
}

/* ------------------------------------------------------------ measure row --
   Fletcher's donation: every band opens on one figure that lands its point
   before a sentence is read. */
/* A measurement strip, read across. Four cells divided by hairlines rather
   than four floating tiles: the tile version is the stat-block every site
   ships, and this world reads instruments, not dashboards. Label above,
   figure below, tabular figures so the digits line up between cells.

   The dividers are drawn with border-left and dropped on the first cell of
   each row, which is why the nth-child rules change per breakpoint: a wrapped
   grid would otherwise leave a rule hanging at the start of the second row. */
.record {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--rule-strong);
  border-bottom: 1px solid var(--rule);
}
.record__row {
  display: block;
  padding: 1.15rem 1.3rem 1.25rem 0;
  border-bottom: 1px solid var(--rule);
}
.record__row:last-child { border-bottom: none; }

.record__row dt {
  color: var(--silver);
  font-family: "Martian Mono", ui-monospace, monospace;
  font-size: var(--t-mono); letter-spacing: .11em; text-transform: uppercase;
  margin-bottom: .55rem;
}
.record__row dd {
  margin: 0; color: var(--ash); font-variation-settings: "wdth" 116;
  font-size: clamp(1.9rem, 3.4vw, 2.9rem); line-height: 1; font-weight: 500;
  font-variant-numeric: tabular-nums; letter-spacing: .01em;
}
.record__unit {
  color: var(--silver); font-size: .72rem; font-weight: 400;
  font-variation-settings: "wdth" 100; margin-left: .5rem;
  letter-spacing: 0;
}

@media (min-width: 560px) {
  .record { grid-template-columns: repeat(2, 1fr); }
  .record__row { border-bottom: none; padding-left: 1.5rem; border-left: 1px solid var(--rule); }
  .record__row:nth-child(2n+1) { padding-left: 0; border-left: none; }
  .record__row:nth-child(-n+2) { padding-bottom: 1.9rem; }
  .record__row:nth-last-child(-n+2) { padding-top: 1.9rem; border-top: 1px solid var(--rule); }
}
@media (min-width: 900px) {
  .record { grid-template-columns: repeat(4, 1fr); }
  .record__row,
  .record__row:nth-child(-n+2),
  .record__row:nth-last-child(-n+2) {
    padding: 1.4rem 1.4rem 1.5rem 1.6rem;
    border-left: 1px solid var(--rule);
    border-top: none;
  }
  .record__row:first-child { padding-left: 0; border-left: none; }
}

/* ----------------------------------------------------------------- cols -- */
.cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); gap: clamp(1.8rem,3.5vw,3rem); }
.cols--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 24rem), 1fr)); }
.cols--wide { align-items: start; }

/* ------------------------------------------------------------ instrument --
   The automata donation: Development → Production → Finance as one linked
   instrument rather than three parallel columns. The connecting rule is drawn,
   so the reading order is a mechanism, not a list. */
.instrument { display: grid; gap: 0; }
.stage {
  display: grid; grid-template-columns: minmax(0,1fr);
  gap: 1rem; padding-block: clamp(1.9rem, 3.6vw, 2.9rem);
  border-top: 1px solid var(--rule);
}
.stage:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 860px) {
  .stage { grid-template-columns: 4.5rem minmax(0, 20rem) minmax(0, 1fr); gap: 2.4rem; align-items: start; }
}
.stage__no { font-family: "Martian Mono", ui-monospace, monospace; font-size: .72rem; letter-spacing: .1em; color: var(--manila); font-variant-numeric: tabular-nums; }
.stage__services { list-style: none; margin: 1rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: .45rem; }
.stage__services li {
  font-family: "Martian Mono", ui-monospace, monospace; font-size: .66rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--silver);
  border: 1px solid var(--rule); padding: .32rem .55rem .28rem;
}

/* --------------------------------------------------------------- beliefs -- */
.belief { padding-block: clamp(1.5rem,3vw,2.2rem); border-top: 1px solid var(--rule); display: grid; gap: .7rem; }
.belief:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 780px) { .belief { grid-template-columns: 3.2rem minmax(0,18rem) minmax(0,1fr); gap: 2rem; align-items: baseline; } }
.belief__no { font-family: "Martian Mono", ui-monospace, monospace; font-size: .66rem; color: var(--manila); letter-spacing: .1em; }

/* ----------------------------------------------------------------- plate --
   A slate entry. Rendered from data/slate.json by tools/sync.py. The Massin
   donation lives here: scale carries status before any label does. */
.plates { display: grid; gap: 0; }
.plate {
  display: grid; gap: .7rem;
  padding-block: clamp(1.8rem, 3.4vw, 2.6rem);
  border-top: 1px solid var(--rule);
  align-items: start;
}
.plate:last-of-type { border-bottom: 1px solid var(--rule); }
@media (min-width: 880px) {
  .plate { grid-template-columns: 4.5rem minmax(0,1fr) 9.5rem 10rem; gap: 2rem; align-items: baseline; }
  .plate--bare { grid-template-columns: 4.5rem minmax(0,1fr); }
}
.plate__no { font-family: "Martian Mono", ui-monospace, monospace; font-size: .72rem; color: var(--manila); letter-spacing: .09em; font-variant-numeric: tabular-nums; }
.plate__title {
  color: var(--ash); font-variation-settings: "wdth" 110; font-weight: 600;
  font-size: clamp(1.3rem, 2.4vw, 2rem); line-height: 1.1; letter-spacing: .015em;
  text-transform: uppercase; margin: 0;
}
/* Released titles carry more optical weight than development titles. Status is
   legible with every word removed. */
.plate--mid .plate__title { font-size: clamp(1.15rem, 2vw, 1.62rem); font-variation-settings: "wdth" 105; }
.plate--development .plate__title { font-size: clamp(1.05rem, 1.6vw, 1.35rem); color: var(--body); font-variation-settings: "wdth" 100; }
.plate__meta { display: flex; flex-wrap: wrap; gap: .3rem .9rem; }
.plate__status { justify-self: start; text-wrap: balance; }
@media (min-width: 880px) { .plate__status { justify-self: end; text-align: right; } }

.plate--withheld .plate__title {
  color: var(--silver);
  background: repeating-linear-gradient(-45deg, rgba(138,145,153,.15) 0 4px, transparent 4px 9px);
  padding: .15rem .5rem;
}

/* --------------------------------------------------------------- credits --
   Delivered work. The slate is thin and half of it is under non-disclosure,
   so on its own it does not answer the only question a financier is asking.
   These do, and they belong to the people, which the copy states. */
.credits { display: grid; border-top: 1px solid var(--rule-strong); }
.credit {
  display: grid; gap: .3rem .9rem; align-items: baseline;
  grid-template-columns: minmax(0,1fr);
  padding-block: .95rem; border-bottom: 1px solid var(--rule);
}
@media (min-width: 720px) {
  .credit { grid-template-columns: minmax(0,1.3fr) minmax(0,.7fr) minmax(0,1fr); gap: 1.6rem; }
}
.credit__title {
  color: var(--ash); font-variation-settings: "wdth" 106; font-weight: 500;
  font-size: clamp(1.02rem, 1.2vw, 1.2rem); line-height: 1.25;
}
.credit__note { color: var(--silver); }

/* ------------------------------------------------------------------ team -- */
.people { display: grid; gap: 0; }
.person { padding-block: clamp(1.9rem,3.6vw,2.8rem); border-top: 1px solid var(--rule); display: grid; gap: .9rem; }
.person:last-child { border-bottom: 1px solid var(--rule); }
@media (min-width: 860px) { .person { grid-template-columns: 4.5rem minmax(0,16rem) minmax(0,1fr); gap: 2.4rem; align-items: start; } }
/* Portraits. None exist yet; data/team.json says so and says not to source
   stand-ins. The slot is real so that adding one is a data edit, not a design
   task. Grayscale because a colour headshot on this ground is the only place
   the achromatic rule could break. */
.person__portrait {
  width: 100%; max-width: 13rem; aspect-ratio: 4 / 5; object-fit: cover;
  border: 1px solid var(--rule-strong);
  filter: grayscale(1) contrast(1.04);
  margin-bottom: .9rem;
}

.person__name { color: var(--ash); font-variation-settings: "wdth" 108; font-size: clamp(1.15rem,1.9vw,1.5rem); font-weight: 600; line-height: 1.15; margin: 0; }
.person__pending { color: var(--silver); font-style: italic; }

/* ---------------------------------------------------------------- routes -- */
.route { padding-block: clamp(1.9rem,3.6vw,2.8rem); border-top: 1px solid var(--rule); display: grid; gap: .9rem; }
.route:last-of-type { border-bottom: 1px solid var(--rule); }
@media (min-width: 860px) { .route { grid-template-columns: 4.5rem minmax(0,17rem) minmax(0,1fr); gap: 2.4rem; align-items: start; } }

/* ----------------------------------------------------------------- form -- */
.form { display: grid; gap: 1.4rem; max-width: 38rem; }
.field { display: grid; gap: .5rem; }
.field label { color: var(--silver); }
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%23C9BDA4' stroke-width='1.4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: .7rem;
  padding-right: 2.6rem;
  text-overflow: ellipsis;
}
.field input, .field textarea, .field select {
  background: var(--sleeve); color: var(--ash);
  border: 1px solid var(--rule-strong); border-radius: 0;
  padding: .85rem 1rem; font: inherit; font-size: .98rem; width: 100%;
  transition: border-color .2s var(--ease), background-color .2s var(--ease);
}
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none; border-color: var(--manila); background: var(--sleeve-hi);
}
.field textarea { min-height: 9.5rem; resize: vertical; }
.form__note { color: var(--silver); }

/* --------------------------------------------------------------- contact -- */
.contact-block { display: grid; gap: 1.5rem; align-content: start; }
.contact-item { display: grid; gap: .3rem; padding-block: 1rem; border-top: 1px solid var(--rule); }

/* ------------------------------------------------------------------ crumb -- */
.crumb { display: flex; gap: .6rem; align-items: center; padding-block: clamp(1.5rem,3vw,2.4rem); }

/* ---------------------------------------------------------------- footer -- */
.foot { padding-block: clamp(2.8rem,6vw,4.5rem) clamp(2rem,4vw,3rem); }
.foot__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%,11rem),1fr)); gap: 2.2rem 2rem; padding-bottom: clamp(2rem,4vw,3rem); }
.foot__col { display: grid; gap: .55rem; align-content: start; }
.foot__col a { color: var(--body); text-decoration: none; font-size: .93rem; }
.foot__col a:hover { color: var(--ash); text-decoration: underline; text-decoration-color: var(--manila); }
.foot__legal { display: flex; flex-wrap: wrap; gap: .5rem 1.6rem; padding-top: 1.5rem; border-top: 1px solid var(--rule); }
.foot__credit { flex-basis: 100%; margin-top: .35rem; }
.foot__credit a { color: var(--silver); text-decoration-color: var(--rule-strong); }
.foot__credit a:hover { color: var(--ash); text-decoration-color: var(--manila); }
.foot__logo { width: 128px; opacity: .7; margin-bottom: 1rem; }

/* ================================================================ motion ==
   There is one authored moment on this site and it is the limb: it turns with
   the scroll, so the lit edge travels as the page moves.

   There is deliberately no per-section reveal. An earlier build faded every
   band in on the same curve: one identical entrance on fifteen elements,
   which is scattered effect dressed as choreography, and it meant real content
   sat at a third opacity whenever the observer missed it. Removing it also
   removes any question about content depending on script.
   ========================================================================= */
@media (prefers-reduced-motion: reduce) {
  .limb__plate, .limb__arc { --limb-turn: 0deg !important; }
}

/* --------------------------------------------------------------- utility -- */
.scroll-x { overflow-x: auto; }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }
.dim { color: var(--silver); }
.sep { color: var(--rule-strong); }

/* ------------------------------------------------------------- page hero --
   Inner pages carry the same limb and the same masthead, at a lower height.
   The arc is not a homepage ornament. It is the page's horizon, and dropping
   it on the inner pages would make them read as a different site. */
.hero--page .hero__inner {
  min-height: auto;
  grid-template-columns: minmax(0,1fr);
  padding-block: clamp(1rem,3vh,2rem) clamp(2.6rem,7vh,4.5rem);
}
.hero--page h1 { font-size: clamp(1.5rem, 2.7vw + .35rem, 3.05rem); }
.hero--page .limb__plate { width: 62vw; right: -16vw; top: 58%; }
.hero--page .limb__arc { width: 78vw; right: 10vw; top: 57%; }

@media (max-width: 900px) {
  .hero--page .limb__plate { width: 132vw; right: -66vw; opacity: .3; }
  .hero--page .limb__arc { width: 128vw; right: -22vw; opacity: .3; }
}


/* ============================================================== narrow ====
   Phone. Two things break at this width if left alone, and both were caught
   in a 390px capture rather than by inspection:

   1. The hero headline is set as three forced lines. At the desktop display
      size "THIRTY PRODUCTIONS." does not fit 390px, and because the break is
      in the markup the line cannot reflow. It runs past the edge and is
      clipped by the overflow guard on <body>, which reads as truncated copy.
      The fix is the reduced --t-h1 below, which makes all three lines fit;
      the breaks are kept, because dropping them removes the only word
      boundary in the markup and fuses "YEARS.THIRTY".

   2. The nav is a single flex item next to the logo, so it will not shrink
      below its own content width. Given the whole row it wraps instead.
   ========================================================================= */
@media (max-width: 720px) {
  .masthead { gap: .85rem 1.2rem; padding-block: 1.1rem; }
  .nav { margin-left: 0; width: 100%; gap: .85rem 1.15rem; }
}

@media (max-width: 640px) {
  :root { --t-h1: clamp(1.3rem, 5.1vw, 1.95rem); }
  .hero h1 { font-variation-settings: "wdth" 104; letter-spacing: .11em; }
  /* The rail becomes a block under the hero copy rather than a column. */
  .hero__inner { gap: 2.4rem; }
}


/* ------------------------------------------------------- browser surfaces --
   The parts not drawn here still carry the design. Left alone, the selection
   highlight is system blue, which on this ground is the single loudest thing
   on the page and the only colour that never came from the palette. */
::selection { background: var(--manila); color: #17140F; }
::-moz-selection { background: var(--manila); color: #17140F; }

input, textarea { caret-color: var(--manila); accent-color: var(--manila); }

/* Firefox */
html { scrollbar-color: var(--rule-strong) var(--plate); scrollbar-width: thin; }
/* WebKit */
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: var(--plate); }
::-webkit-scrollbar-thumb { background: #232930; border: 3px solid var(--plate); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: #313941; }


/* The form's in-flight state. Set by site.js on submit; without script the
   form posts exactly as before and this never applies. */
.btn[aria-disabled="true"] { opacity: .6; pointer-events: none; }

/* ============================================================== project ==
   A page per title, generated from data/slate.json by tools/sync.py. Two
   templates: a delivered title gets synopsis, credits and specifications; a
   title still in development gets a still, a line, and an honest statement
   that the rest is not published yet.
   ========================================================================= */
.hero--project .hero__inner { padding-block: clamp(1rem,3vh,2rem) clamp(2rem,5vh,3.5rem); }
.proj__meta { margin-bottom: 1.1rem; }
.hero--project h1 { font-size: clamp(1.8rem, 3.6vw + .4rem, 4rem); }
.proj__status {
  margin-top: 1.1rem; display: inline-block;
  border-top: 1px solid var(--manila); padding-top: .5rem;
}
.proj__logline { margin-top: 1.6rem; max-width: 46ch; }

/* Demo content says so. An invented line that is not marked is how a
   placeholder quietly becomes a claim. */
.proj__demo {
  margin-top: 1.8rem; color: var(--manila);
  border-top: 1px solid var(--rule); padding-top: .9rem; max-width: 46ch;
}

.proj__still { margin: 0; }
.proj__still img {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--rule-strong);
}
.proj__still figcaption { margin-top: .7rem; color: var(--silver); }

/* Credits and specifications share one ruled list. An unfilled seat reads
   "To be confirmed" rather than a name that does not exist. */
.specs { margin: 0; border-top: 1px solid var(--rule-strong); }
.spec {
  display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.2fr);
  gap: .4rem 1.5rem; align-items: baseline;
  padding-block: .85rem; border-bottom: 1px solid var(--rule);
}
.spec dt { color: var(--silver); }
.spec dd { margin: 0; color: var(--ash); }
.spec dd.spec--tbc { color: var(--silver); font-style: italic; }

.proj__nav {
  display: flex; flex-wrap: wrap; gap: 1.5rem 2.5rem;
  margin-top: clamp(2rem,4vw,3rem); padding-top: 1.4rem;
  border-top: 1px solid var(--rule);
}
.proj__nav-item { display: grid; gap: .35rem; text-decoration: none; }
.proj__nav-item--next { margin-left: auto; text-align: right; }
.proj__nav-title {
  color: var(--ash); font-variation-settings: "wdth" 106; font-weight: 500;
  font-size: 1.05rem;
}
.proj__nav-item:hover .proj__nav-title { text-decoration: underline; text-decoration-color: var(--manila); }

/* The slate's titles are links now. Keep the plate's type, add only the
   affordance. */
/* ------------------------------------------------------- row-wide links --
   The whole row is the target, not just the title.

   Done with a stretched pseudo-element rather than by wrapping the row in an
   anchor: the link text stays "Cry Havoc" for a screen reader instead of
   becoming the plate number, the title, the director, the form, the genre and
   the status read out as one link. Each row contains exactly one link, so the
   overlay covers nothing it should not.

   Trade-off worth knowing: the overlay sits above the row, so dragging to
   select a row's text no longer works. On a list whose job is to be clicked
   through, that is the right way round. */
.plate,
.ledger__row { position: relative; }

.plate__title a,
.ledger__subject a { color: inherit; text-decoration: none; }

.plate__title a::after,
.ledger__subject a::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
}

/* Hover and keyboard focus light the whole row, so the target and the
   feedback are the same shape. */
.plate:has(a:hover) .plate__title,
.plate:focus-within .plate__title,
.ledger__row:has(a:hover) .ledger__subject,
.ledger__row:focus-within .ledger__subject {
  text-decoration: underline;
  text-decoration-color: var(--manila);
  text-underline-offset: .18em;
}
.plate:has(a:hover),
.ledger__row:has(a:hover) { background: rgba(244,242,236,.028); }

/* Without :has() the title still underlines on its own hover, so the row is
   simply less lit rather than broken. */
.plate__title a:hover,
.ledger__subject a:hover {
  text-decoration: underline; text-decoration-color: var(--manila);
  text-underline-offset: .18em;
}

/* --------------------------------------------------------- project cover --
   Cover artwork beside the title rather than above it, so the first viewport
   carries the film and the facts at the same time. The limb sits to the right
   of both, which is why the text column stops short of it. */
.hero--project .hero__inner { align-items: start; }
.proj__cover { margin: 0 0 .4rem; max-width: 12rem; }
.proj__cover img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 2 / 3; object-fit: cover;
  border: 1px solid var(--rule-strong);
}
@media (min-width: 800px) {
  .hero--project .hero__inner {
    grid-template-columns: clamp(10rem, 17vw, 15rem) minmax(0, 1fr);
    gap: clamp(1.8rem, 3.5vw, 3.2rem);
  }
  .proj__cover { max-width: none; margin-bottom: 0; }
}

/* ---------------------------------------------------------- sealed plate --
   The bar under the heading on the non-disclosure page: the same diagonal
   hatch the withheld rows carry, at full width, so the page reads as the same
   object the slate row promised rather than as a generic error screen. */
.sealed__bar {
  margin-top: 1.5rem;
  height: clamp(2.6rem, 5vw, 3.6rem);
  max-width: 34rem;
  border: 1px solid var(--rule-strong);
  background: repeating-linear-gradient(
    -45deg, rgba(138,145,153,.20) 0 4px, transparent 4px 10px);
}

/* The film's own words: the tagline off the key art, and the sub-line under
   the title. Set quiet, because the artwork already says it loudly. */
.proj__tagline {
  color: var(--manila); margin-bottom: .8rem;
  font-size: clamp(.92rem, 1.1vw, 1.05rem); letter-spacing: .02em;
  max-width: 40ch;
}
.proj__note { margin-top: 1.1rem; max-width: 46ch; }

/* Artwork is the one place colour enters this site. The interface stays
   achromatic; the films do not have to. */
.proj__cover img, .proj__still img { filter: none; }

/* Cast reads as a column of names rather than a two-column table: the role
   label is short and the name is the thing being looked for. */
@media (min-width: 720px) {
  .specs--cast { max-width: 42rem; }
  .specs--cast .spec { grid-template-columns: minmax(0,10rem) minmax(0,1fr); }
}

/* ---------------------------------------------------------------- gallery --
   Stills from the shoot, three across and two down. The stills are shot 3:2
   and the asset is cut to 16:9, so the crop is made once where it can be
   judged by eye. The frame here matches the asset, so object-fit has nothing
   left to trim. A caption is optional and is usually left off.

   The frame is a link to the full image. With no JavaScript that link opens
   the image on its own, which is a working gallery; site.js upgrades it to
   the lightbox below. */
.gallery {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem;
  grid-template-columns: repeat(2, minmax(0,1fr));
}
@media (min-width: 720px) {
  .gallery { grid-template-columns: repeat(3, minmax(0,1fr)); gap: 1.25rem; }
}
.gallery__fig { margin: 0; display: grid; gap: .5rem; }
.gallery__fig img {
  display: block; width: 100%; height: auto; aspect-ratio: 16 / 9;
  object-fit: cover; background: var(--rule);
}
.gallery__cap { color: var(--silver); }

.gallery__link { display: block; }
.gallery__link:focus-visible { outline: 2px solid var(--manila); outline-offset: 3px; }

/* --------------------------------------------------------------- lightbox --
   Built by site.js on first open and reused after that, so a visitor who
   never opens a still never pays for the markup. Hidden by default here
   rather than inline, so the overlay cannot flash before the script runs. */
.lightbox {
  position: fixed; inset: 0; z-index: 90; display: none;
  background: rgba(8, 9, 11, .95);
  padding: clamp(.75rem, 3vw, 2.5rem);
}
.lightbox.is-open { display: grid; grid-template-rows: 1fr auto; justify-items: center; align-items: center; }
html.has-lightbox { overflow: hidden; }
.lightbox__img {
  display: block; max-width: 100%; max-height: 82vh;
  width: auto; height: auto; object-fit: contain;
}
.lightbox__bar { display: flex; gap: 1.25rem; align-items: center; padding-top: 1rem; }
.lightbox__btn {
  appearance: none; background: none; border: 1px solid var(--rule-strong);
  color: var(--ash); font: inherit; font-size: .95rem; line-height: 1;
  padding: .55rem .9rem; cursor: pointer;
}
.lightbox__btn:hover { border-color: var(--manila); color: var(--manila); }
.lightbox__btn:focus-visible { outline: 2px solid var(--manila); outline-offset: 2px; }
.lightbox__btn[disabled] { opacity: .35; cursor: default; }
.lightbox__btn[disabled]:hover { border-color: var(--rule-strong); color: var(--ash); }
.lightbox__count { color: var(--silver); }

/* ------------------------------------------------------------------ press --
   Coverage, as a ruled list. Outlet first, because on a delivered title the
   masthead is the proof and the headline is the detail. */
.press { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-strong); }
.press__item {
  display: grid; gap: .35rem 1.5rem; align-items: baseline;
  grid-template-columns: minmax(0,1fr);
  padding-block: 1rem; border-bottom: 1px solid var(--rule);
}
@media (min-width: 720px) {
  .press__item { grid-template-columns: minmax(0,1fr) auto; }
}
.press__link { display: grid; gap: .3rem; text-decoration: none; }
.press__outlet { color: var(--manila); }
.press__title { color: var(--ash); font-size: 1.02rem; line-height: 1.35; max-width: 52ch; }
.press__link:hover .press__title { text-decoration: underline; text-decoration-color: var(--manila); text-underline-offset: .18em; }
.press__date { color: var(--silver); }
@media (min-width: 720px) { .press__date { text-align: right; } }

/* Cast: names, in billing order. A character is shown only where the credit
   card gives one, which on most films is almost nobody. */
.cast { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule-strong); max-width: 42rem; }
.cast__item {
  display: flex; flex-wrap: wrap; gap: .25rem 1.2rem; align-items: baseline;
  padding-block: .8rem; border-bottom: 1px solid var(--rule);
}
.cast__name {
  color: var(--ash); font-variation-settings: "wdth" 106; font-weight: 500;
  font-size: clamp(1.02rem, 1.2vw, 1.18rem);
}
.cast__as { color: var(--silver); }
