/* ------------------------------------------------------------------
   Peter Rod — typographic landing page
   Geometry is expressed in the units of the source design (a 1728px
   wide MacBook Pro 16" frame). `--u` is one design pixel, so every
   value below can be read straight off the design file.
   ------------------------------------------------------------------ */

@font-face {
  font-family: "HN Black";
  src: url("../fonts/HelveticaNeue-Black.woff2") format("woff2");
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

/* The design is set in Menlo, which ships with macOS. Roboto Mono
   (Apache 2.0) is carried for everyone else: at the same 0.6em advance
   it breaks the body copy into exactly the same lines. */
@font-face {
  font-family: "Body Mono";
  src: url("../fonts/RobotoMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Body Mono";
  src: url("../fonts/RobotoMono-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

:root {
  --u: min(calc(100vw / 1728), 1px);

  --paper: #fdf6ed;
  --ink: #000;
  --display-ink: #383634;
  --accent: #ff0c50;
  --muted: #7f7b77;
  --card-ink: #323130;
  --colophon-ink: #4c4c4c;

  /* The design's own faces come first — Helvetica Neue and Menlo, both
     native on macOS. The bundled webfonts are only for machines without
     them. "HelveticaNeue-CondensedBlack" is a PostScript name, which
     macOS resolves; typeface.js notices when it lands and drops the
     geometric condensing below. */
  --body-face: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --mono-face: Menlo, "SF Mono", SFMono-Regular, ui-monospace, "Body Mono", monospace;
  --display-face: "HelveticaNeue-CondensedBlack", "HN Black",
                  "Helvetica Neue", Helvetica, Arial, sans-serif;

  /* Fallback geometry: the bundled Black is normal width, so it is
     condensed to the design's proportions and tracked in to match. */
  --display-xscale: 0.752;
  --display-track: -0.023em;

  /* Nominal design sizes are multiplied by 1.0354: this cut of Black has
     a shorter cap height than the one the design was drawn in, and cap
     height is what the eye measures. */
  --h-large: calc(85.9 * var(--u));
  --h-small: calc(43.5 * var(--u));

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --trigger-width: calc(1140 * var(--u));
  --pace: 420ms;
}

/* Set by typeface.js when macOS has supplied the real condensed Black.
   That face is already the width the design expects, so the geometric
   condensing comes off and the design's own sizes apply — the bundled
   Black needs them scaled up because its cap height is shorter. */
:root[data-native-condensed] {
  --display-xscale: 1;
  --display-track: 0;
  --h-large: calc(83 * var(--u));
  --h-small: calc(42 * var(--u));
  --trigger-width: calc(857 * var(--u));
}

:root[data-native-condensed] .name { font-size: calc(96 * var(--u)); }
:root[data-native-condensed] .page-title { font-size: calc(76 * var(--u)); }

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* The longest headline is drawn to bleed toward the right edge; clip the
     empty tail of its layout box so it cannot raise a scrollbar. */
  overflow-x: clip;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body-face);
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.canvas {
  width: calc(1728 * var(--u));
  margin-inline: auto;
  padding: 0 calc(64 * var(--u)) calc(60 * var(--u)) calc(54 * var(--u));
}

/* ---------- outlined display type ---------------------------------- */

.display {
  font-family: var(--display-face);
  font-weight: 900;
  text-transform: uppercase;
  margin: 0;
}

.display .tx {
  display: block;
  transform: scaleX(var(--display-xscale));
  transform-origin: 0 50%;
  letter-spacing: var(--display-track);
  color: var(--display-ink);
}

/* The domain headlines carry the condensing on the button instead, so the
   pointer target matches the glyphs the visitor can actually see. */
.domain-title .trigger {
  width: var(--trigger-width);
  transform: scaleX(var(--display-xscale));
  transform-origin: 0 50%;
}

.domain-title .tx { transform: none; }

/* Without text-stroke support the glyphs would be invisible, so the
   transparent fill is only applied where the stroke can be painted. */
/* ---------- masthead ------------------------------------------------ */

.masthead {
  background: var(--paper);
}

.masthead-inner {
  width: calc(1728 * var(--u));
  margin-inline: auto;
  /* The space under the block matches the space above the name. */
  padding: calc(52 * var(--u)) calc(64 * var(--u))
           calc(67 * var(--u)) calc(54 * var(--u));
  display: grid;
  grid-template-columns: calc(900 * var(--u)) 1fr;
  align-items: start;
}

.name {
  --display-track: -0.0167em;
  font-size: calc(99.4 * var(--u));
  line-height: 1;
  margin-top: calc(2 * var(--u));
}

.name .tx { white-space: nowrap; }

.tagline {
  margin: calc(8 * var(--u)) 0 0;
  font-size: calc(17 * var(--u));
  line-height: calc(21 / 17);
  text-transform: lowercase;
}

.nav {
  justify-self: end;
  display: flex;
  gap: calc(38.2 * var(--u));
  font-size: calc(17 * var(--u));
  line-height: 1;
  margin-top: calc(18 * var(--u));
}

.nav a { text-transform: lowercase; }

/* ---------- stage: portrait + domain column ------------------------- */

.stage {
  margin-left: calc(-54 * var(--u));
  margin-top: calc(43 * var(--u));
  display: grid;
  grid-template-columns: calc(665 * var(--u)) calc(205 * var(--u)) minmax(0, 1fr);
}

.portrait {
  grid-column: 1;
  height: calc(1156.6 * var(--u));
  overflow: hidden;
}

.portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The design crops the frame off the left, holding the right edge. */
  object-position: 100% 50%;
  display: block;
}

.column {
  grid-column: 3;
  display: flex;
  flex-direction: column;
  min-height: calc(1156.6 * var(--u));
  padding-top: calc(71 * var(--u));
}

/* ---------- domains ------------------------------------------------- */

.domain + .domain { margin-top: calc(48.8 * var(--u)); }

/* The design closes the gap ahead of an open domain and after its card
   row; only the run of closed headlines keeps the full 86px pitch. */
.has-focus .domain + .domain.is-active { margin-top: calc(35.3 * var(--u)); }

/* An open domain ends on its card row, which needs less air after it. */
.has-focus .domain.is-active + .domain { margin-top: calc(31.5 * var(--u)); }

.domain-title {
  font-size: var(--h-large);
  /* The design leads its two-line headlines at 78px in one place and 69px
     in the others; this sits between them. */
  line-height: 0.856;
  transition: font-size var(--pace) var(--ease);
}

.domain-title .trigger {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
}

.has-focus .domain:not(.is-active) .domain-title { font-size: var(--h-small); }

/* ---------- the detail that opens ----------------------------------- */

.domain-detail {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows var(--pace) var(--ease),
              opacity calc(var(--pace) * 0.7) var(--ease);
}

.domain.is-active .domain-detail { grid-template-rows: 1fr; opacity: 1; }

.domain-detail > .reveal { overflow: hidden; min-height: 0; }

.domain-desc {
  margin: calc(26 * var(--u)) 0 0 calc(44 * var(--u));
  /* Wide enough for the 77 monospace characters the design puts on its
     longest line, and too narrow for the next word, at both Menlo's
     0.602em advance and Roboto Mono's 0.600em. */
  max-width: calc(655 * var(--u));
  font-family: var(--mono-face);
  font-size: calc(14 * var(--u));
  line-height: calc(20 / 14);
}

.examples-label {
  margin: calc(23 * var(--u)) 0 0 calc(44 * var(--u));
  font-family: var(--mono-face);
  font-size: calc(14 * var(--u));
  font-style: italic;
  line-height: 1;
  color: var(--muted);
}

/* ---------- project cards ------------------------------------------- */

.cards {
  display: flex;
  gap: calc(19 * var(--u));
  margin: calc(15 * var(--u)) 0 0 calc(43 * var(--u));
  padding: 0;
  list-style: none;
}

.cards > li { display: flex; width: calc(151 * var(--u)); }

.card {
  position: relative;
  display: block;
  width: 100%;
  height: calc(140 * var(--u));
  padding: calc(15.5 * var(--u)) calc(9 * var(--u));
  border: calc(1 * var(--u)) solid var(--display-ink);
  font-size: calc(14 * var(--u));
  font-style: italic;
  line-height: calc(20 / 14);
  color: var(--card-ink);
  overflow: hidden;
  transition: color 240ms var(--ease);
}

/* The fill wipes down from the top edge rather than simply appearing. */
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: 0 0;
  transition: transform 260ms var(--ease);
}

.card .label { position: relative; }

/* Colour is the whole response — these are not links, and nothing here
   should suggest otherwise. */
.card:hover { color: #fff; }

.card:hover::before { transform: scaleY(1); }

/* ---------- colophon ------------------------------------------------ */

.colophon {
  margin-top: auto;
  margin-bottom: calc(4 * var(--u));
  margin-left: calc(-6 * var(--u));
  padding-top: calc(40 * var(--u));
  font-size: calc(14 * var(--u));
  font-style: italic;
  line-height: 1;
  color: var(--colophon-ink);
}

/* ---------- links --------------------------------------------------- */

a { color: inherit; text-decoration: none; }

a.underlined {
  text-decoration: underline;
  text-decoration-thickness: calc(1 * var(--u));
  text-underline-offset: calc(2.5 * var(--u));
}

.nav a:hover { color: var(--accent); }

:focus-visible {
  outline: calc(2 * var(--u)) solid var(--accent);
  outline-offset: calc(3 * var(--u));
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 1ms !important; }
}

/* ---------- interior pages ------------------------------------------ */

.page {
  margin-top: calc(165 * var(--u));
  max-width: calc(1000 * var(--u));
}

.page-title {
  font-size: calc(78.6 * var(--u));
  line-height: 1;
}

.page-title .tx { white-space: nowrap; }

.page-body {
  margin-top: calc(28 * var(--u));
  max-width: calc(655 * var(--u));
  font-family: var(--mono-face);
  font-size: calc(14 * var(--u));
  line-height: calc(20 / 14);
}

.page-body p { margin: 0 0 calc(14 * var(--u)); }
.page-body p:last-child { margin-bottom: 0; }

/* ---------- password gate ------------------------------------------- */

/* Gated content stays hidden until gate.js clears the flag, so it never
   flashes on screen — and stays hidden entirely without JavaScript. */
body[data-gated] .gated-content { display: none; }
body:not([data-gated]) .gate { display: none; }

.gate { margin-top: calc(165 * var(--u)); }

.gate-form {
  display: flex;
  gap: calc(10 * var(--u));
  margin-top: calc(24 * var(--u));
  align-items: stretch;
}

.gate-form input {
  font: inherit;
  font-size: calc(14 * var(--u));
  width: calc(280 * var(--u));
  padding: calc(9 * var(--u)) calc(11 * var(--u));
  color: var(--ink);
  background: var(--paper);
  border: calc(1 * var(--u)) solid var(--ink);
  border-radius: 0;
}

.gate-form input::placeholder { color: #999; }

.gate-form button {
  font: inherit;
  font-size: calc(14 * var(--u));
  padding: calc(9 * var(--u)) calc(20 * var(--u));
  color: var(--paper);
  background: var(--ink);
  border: calc(1 * var(--u)) solid var(--ink);
  border-radius: 0;
  cursor: pointer;
}

.gate-form button:hover { background: var(--accent); border-color: var(--accent); }

.page-body .gate-note {
  margin-top: calc(22 * var(--u));
  font-size: calc(14 * var(--u));
  line-height: calc(20 / 14);
}

.page-body .gate-error {
  margin-top: calc(12 * var(--u));
  font-size: calc(14 * var(--u));
  color: var(--accent);
}

.gate-error[hidden] { display: none; }

/* ------------------------------------------------------------------
   Below the design width the two-column composition stops working —
   proportional scaling would take the body copy under 10px. From here
   down the same type system is re-set as a single column. The source
   design covers desktop only; these values are a reading of it, not a
   specification, and should be replaced when a small-screen design
   exists.
   ------------------------------------------------------------------ */

@media (max-width: 1279px) {
  :root {
    --u: 1px;
    --h-large: clamp(30px, 8.4vw, 62px);
    --h-small: clamp(19px, 5vw, 34px);
  }

  .canvas {
    width: 100%;
    max-width: 860px;
    padding: 28px 24px 40px;
  }

  .masthead-inner {
    display: block;
    width: 100%;
    padding: 28px 24px 24px;
  }

  .name { font-size: clamp(44px, 12vw, 92px); margin-top: 0; }
  .tagline { margin-top: 10px; font-size: 15px; line-height: 1.35; }

  .nav {
    justify-self: start;
    flex-wrap: wrap;
    gap: 22px;
    margin-top: 24px;
    font-size: 15px;
  }

  /* One column: the portrait leads, the domains follow. */
  .stage {
    display: block;
    margin-left: -24px;
    margin-right: -24px;
    margin-top: 32px;
  }

  .portrait { height: clamp(320px, 52vh, 460px); }
  .portrait img { object-position: 50% 28%; }

  .column {
    min-height: 0;
    padding: 36px 24px 0;
  }

  .domain-title { line-height: 0.95; }
  .domain-title .trigger { width: 100%; transform: none; }
  .domain-title .tx {
    transform: scaleX(var(--display-xscale));
    transform-origin: 0 50%;
    width: calc(100% / var(--display-xscale));
  }

  .domain + .domain { margin-top: 30px; }
  .has-focus .domain.is-active + .domain { margin-top: 26px; }

  .domain-desc {
    margin: 18px 0 0;
    max-width: none;
    font-size: 15px;
    line-height: 1.45;
  }

  .examples-label { margin: 20px 0 0; font-size: 15px; }

  .cards {
    flex-wrap: wrap;
    gap: 12px;
    margin: 12px 0 0;
  }

  .cards > li { width: calc(50% - 6px); }

  .card {
    height: auto;
    min-height: 116px;
    padding: 13px 12px;
    font-size: 14px;
    line-height: 1.4;
  }

  .colophon {
    margin: 48px 0 0;
    padding-top: 0;
    font-size: 14px;
  }

  .page, .gate { margin-top: 56px; }
  .page-title { font-size: clamp(30px, 8.4vw, 62px); }
  .page-title .tx { white-space: normal; }
  .page-body { max-width: none; font-size: 15px; line-height: 1.45; }

  .gate-form { flex-wrap: wrap; }
  .gate-form input { flex: 1 1 200px; width: auto; font-size: 16px; }
  .gate-form button { font-size: 16px; }
}

