@charset "utf-8";

/* ==========================================================================
   Two inks on ash stock.

   The whole design is one printer's idea: every title is printed twice, a
   fluorescent-pink plate slightly out of register behind a federal-blue plate.
   Hover, focus or load snaps the plates together. Nothing else is decorated.
   ========================================================================== */

:root {
  --paper:      #dfe1db;
  --paper-2:    #d7dad2;
  --text:       #14161a;
  --muted:      #55585c;
  --pink:       #ff3d8b;
  /* Fluorescent pink is only 2.5:1 on this stock, so anything a reader has to
     read — errors, the current section, focus rings — uses the ink overprinted
     to 5.2:1 instead. The bright ink stays for plates and ornament. */
  --pink-text:  #b00a5e;
  --blue:       #17255e;
  --rule:       rgba(23, 37, 94, .22);
  --rule-hover: rgba(23, 37, 94, .55);

  /* Overlapping inks darken on white stock and lighten on dark stock. */
  --plate-blend: multiply;
  --screen-ink: rgba(0, 0, 0, .5);

  --display: "Zilla Slab", Superclarendon, "Bookman Old Style", Georgia, serif;
  --body:    Archivo, "Helvetica Neue", Helvetica, system-ui, sans-serif;
  --mono:    "Fragment Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --pad:     clamp(1.35rem, 3.6vw, 3.25rem);
  --measure: 60ch;
  --reg-x:   0.1875rem;   /* how far out of register an unhovered plate sits */
  --reg-y:   0.15rem;
  --ease:    cubic-bezier(.2, .85, .2, 1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper:      #101216;
    --paper-2:    #171a20;
    --text:       #e7e8e2;
    --muted:      #9a9ea6;
    --pink:       #ff5f9f;
    /* On dark stock the bright ink already clears 6:1, so it needs no help. */
    --pink-text:  #ff5f9f;
    --blue:       #97abff;
    --rule:       rgba(231, 232, 226, .18);
    --rule-hover: rgba(231, 232, 226, .5);
    --plate-blend: screen;
    --screen-ink: rgba(0, 0, 0, .62);
  }
}

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

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

body {
  margin: 0;
  background-color: var(--paper);
  color: var(--text);
  font-family: var(--body);
  font-size: clamp(1rem, .96rem + .18vw, 1.075rem);
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

/* Paper grain: the stock, not an effect. Barely visible on purpose. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 100;
  pointer-events: none;
  opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

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

a { color: var(--blue); text-decoration-thickness: 1px; text-underline-offset: .18em; }

:focus-visible {
  outline: 2px solid var(--pink-text);
  outline-offset: 3px;
  border-radius: 1px;
}

::selection { background: var(--pink-text); color: #fff; }

.skip {
  position: absolute;
  left: -9999px;
  top: .5rem;
  z-index: 200;
  padding: .6rem 1rem;
  background: var(--blue);
  color: var(--paper);
  font-family: var(--mono);
  font-size: .8rem;
  text-decoration: none;
}
.skip:focus { left: .5rem; }

/* --------------------------------------------------------------- structure */

.sheet {
  display: grid;
  /* Stated rather than implied: a minmax(0, …) track cannot be widened past the
     container by an unbreakable string, which an implicit auto track can. */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 3.5rem);
  max-width: 84rem;
  margin: 0 auto;
  padding: var(--pad);
}

@media (min-width: 60rem) {
  .sheet {
    grid-template-columns: 17.5rem minmax(0, 1fr);
    gap: clamp(3rem, 6vw, 6rem);
    align-items: start;
    padding-block: clamp(3rem, 6vw, 5.5rem);
  }
  .rail {
    position: sticky;
    top: clamp(3rem, 6vw, 5.5rem);
  }
}

/* -------------------------------------------------------------------- rail */

.rail { view-transition-name: rail; }

.inks { position: absolute; width: 0; height: 0; }

.plate {
  position: relative;
  display: block;
  width: min(100%, 12.5rem);
  aspect-ratio: 1;
  margin-bottom: 1.35rem;
  background: var(--blue);
  isolation: isolate;
}

/* The misregistered plate: an ink edge peeking out from behind the image. */
.plate::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--pink);
  transform: translate(.5rem, .4375rem);
  animation: register 1.1s .35s var(--ease) both;
}

/* Two inks, mapped across the tonal range by the SVG filter in the page. */
.plate__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: url("#duotone") contrast(1.04);
}

/* Halftone screen, 4px pitch, as if it came off a duplicator. */
.plate__screen {
  position: absolute;
  inset: 0;
  z-index: 3;
  opacity: .3;
  mix-blend-mode: multiply;
  background-image: radial-gradient(circle at center, var(--screen-ink) 0 32%, transparent 34%);
  background-size: 4px 4px;
}

.plate:hover::before,
.plate:focus-visible::before { transform: translate(0, 0); }

@keyframes register {
  from { transform: translate(.5rem, .4375rem); }
  to   { transform: translate(0, 0); }
}

.wordmark {
  margin: 0;
  font-family: var(--display);
  font-size: 1.75rem;
  font-weight: 400;
  line-height: 1;
  letter-spacing: -.01em;
}

.rail__strapline {
  margin: .6rem 0 0;
  max-width: 22ch;
  color: var(--muted);
  font-size: .92rem;
  line-height: 1.45;
}

.nav {
  display: flex;
  flex-wrap: wrap;
  gap: .35rem 1.1rem;
  margin-top: 1.6rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.nav__link {
  color: var(--text);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}
.nav__link:hover { border-bottom-color: var(--pink-text); }
.nav__link.is-here { color: var(--pink-text); }
.nav__link--out::after { content: " \2197"; color: var(--muted); }

.colophon {
  margin: 1.6rem 0 0;
  max-width: 26ch;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .7rem;
  line-height: 1.55;
}

/* -------------------------------------------------------------------- pane */

.pane { view-transition-name: pane; }
.pane__inner { max-width: 46rem; }

/* ------------------------------------------------------------------- titles */

/* Both plates of a printed title. The pseudo-element carries the pink plate;
   `/ ""` gives it empty alt text so it is never announced twice. */
.hero__line,
.row__title,
.subject {
  position: relative;
  display: inline-block;
  font-family: var(--display);
  /* Medium, not regular: two plates of a heavier letterform read as two inks
     rather than one blurred impression. */
  font-weight: 500;
  color: var(--blue);
}

.hero__line::before,
.row__title::before,
.subject::before {
  content: attr(data-plate) / "";
  position: absolute;
  inset: 0;
  z-index: -1;
  color: var(--pink);
  mix-blend-mode: var(--plate-blend);
  transform: translate(var(--reg-x), var(--reg-y));
  transition: transform .3s var(--ease);
}

.hero {
  margin: 0 0 1.6rem;
  font-size: clamp(1.9rem, 4.6vw, 3.35rem);
  font-weight: 500;
  line-height: 1.06;
  letter-spacing: -.016em;
}

.hero__line {
  display: block;
  animation: register-text 1s var(--ease) both;
}
.hero__line:first-child { animation-delay: .1s; }
.hero__line:last-child  { animation-delay: .22s; }

@keyframes register-text {
  from { opacity: 0; transform: translateY(.5rem); }
  to   { opacity: 1; transform: translateY(0); }
}

.subject {
  view-transition-name: subject;
  margin: 0 0 1.1rem;
  font-size: clamp(2.35rem, 7vw, 4.4rem);
  line-height: .98;
  letter-spacing: -.02em;
}

.lede {
  max-width: var(--measure);
  margin: 0 0 2.6rem;
  font-size: clamp(1.05rem, 1.02rem + .35vw, 1.25rem);
  line-height: 1.5;
  color: var(--text);
  text-wrap: pretty;
}

.eyebrow {
  margin: 0 0 .7rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.eyebrow__sep { margin: 0 .5em; color: var(--pink-text); }

.section-label {
  display: flex;
  align-items: baseline;
  gap: .6rem;
  margin: 0 0 .2rem;
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}
.section-label__count { color: var(--pink-text); }

/* -------------------------------------------------------------------- index */

.index {
  list-style: none;
  margin: 0;
  padding: 0;
  border-bottom: 1px solid var(--rule);
}

.row {
  display: grid;
  grid-template-columns: 3.75rem minmax(0, 1fr);
  gap: .1rem 1.25rem;
  padding: 1.15rem 0 1.25rem;
  border-top: 1px solid var(--rule);
  color: inherit;
  text-decoration: none;
  transition: border-color .3s var(--ease);
}

@media (min-width: 46rem) {
  .row {
    grid-template-columns: 3.75rem minmax(0, 1fr) minmax(0, 11rem);
    align-items: start;
  }
}

.row:hover,
.row:focus-visible { border-top-color: var(--rule-hover); }

.row__year {
  padding-top: .45rem;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .04em;
}

.row__title {
  font-size: clamp(1.4rem, 1.15rem + 1.1vw, 2rem);
  line-height: 1.05;
  letter-spacing: -.012em;
}

.row:hover .row__title::before,
.row:focus-visible .row__title::before { transform: translate(0, 0); }

.row__summary {
  display: block;
  max-width: 46ch;
  margin-top: .35rem;
  color: var(--muted);
  font-size: .95rem;
  line-height: 1.5;
  transition: color .3s var(--ease);
}
.row:hover .row__summary { color: var(--text); }

.row__kicker {
  grid-column: 2;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}

@media (min-width: 46rem) {
  .row__kicker {
    grid-column: 3;
    grid-row: 1;
    padding-top: .55rem;
    text-align: right;
    transition: color .3s var(--ease);
  }
  .row:hover .row__kicker { color: var(--pink-text); }
}

.empty {
  padding: 2rem 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .85rem;
}

/* -------------------------------------------------------- project detail */

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  list-style: none;
  margin: -1.8rem 0 2.4rem;
  padding: 0;
}

.tag {
  padding: .22rem .6rem .28rem;
  border: 1px solid var(--rule);
  color: var(--muted);
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .07em;
  text-transform: uppercase;
}

.prose { max-width: var(--measure); }
.prose p { margin: 0 0 1.15em; line-height: 1.65; text-wrap: pretty; }
.prose strong { font-weight: 600; }
.prose code {
  padding: .1em .35em;
  background: var(--paper-2);
  font-family: var(--mono);
  font-size: .86em;
}
.prose a { color: var(--blue); text-decoration-color: var(--pink-text); }

.prose__h {
  margin: 2.2rem 0 .8rem;
  font-family: var(--mono);
  font-size: .74rem;
  font-weight: 400;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
}

.prose__list {
  margin: 0 0 1.15em;
  padding-left: 1.6rem;
  list-style: none;
}
.prose__list li { position: relative; margin-bottom: .5em; line-height: 1.6; }
.prose__list li::before {
  content: "\2014";
  position: absolute;
  left: -1.6rem;
  color: var(--pink);
}

.links {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
  list-style: none;
  margin: 2.2rem 0 0;
  padding: 0;
}

.link-out {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--blue);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 2px;
}
.link-out:hover { border-bottom-color: var(--pink-text); color: var(--pink-text); }
.link-out__arrow { margin-left: .3em; }

.pager {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 1.25rem;
  margin-top: clamp(3rem, 7vw, 4.5rem);
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule);
}

.pager__back {
  font-family: var(--mono);
  font-size: .76rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
}
.pager__back:hover { color: var(--pink-text); }

.pager__next {
  text-align: right;
  text-decoration: none;
  color: inherit;
}
.pager__label {
  display: block;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.pager__title {
  font-family: var(--display);
  font-size: 1.4rem;
  color: var(--blue);
}
.pager__next:hover .pager__title { color: var(--pink-text); }

/* -------------------------------------------------------------------- form */

.form { max-width: 34rem; }

.field { margin-bottom: 1.5rem; }

.field__label {
  display: block;
  margin-bottom: .4rem;
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
}
.field__hint { text-transform: none; letter-spacing: .02em; opacity: .8; }

.field__input {
  width: 100%;
  /* Whole pixels: a fractional height lands the 1px rule on a subpixel
     boundary, and some fields then print heavier than their neighbours. */
  padding: 10px 2px;
  border: 0;
  border-bottom: 1px solid var(--rule-hover);
  background: transparent;
  color: var(--text);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.5;
  border-radius: 0;
  transition: border-color .2s var(--ease);
}
.field__input:hover { border-bottom-color: var(--blue); }
.field__input:focus {
  outline: none;
  border-bottom: 2px solid var(--pink-text);
  padding-bottom: 9px;
}
.field__input--area { resize: vertical; min-height: 9rem; }
.field__input--short { max-width: 6rem; }
.field__input[aria-invalid="true"] { border-bottom-color: var(--pink-text); }

.field__error {
  margin: .45rem 0 0;
  color: var(--pink-text);
  font-size: .87rem;
  line-height: 1.45;
}

/* Off-canvas rather than display:none, which is easier for a bot to spot. */
.decoy {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-top: 2.2rem;
}

/* The button reuses the register motif: pink plate behind, snapping in.
   Both plates are pseudo-elements. A negative z-index child paints above its
   parent's own background, so the blue has to be a layer of its own rather than
   the button's background, or the pink would cover it. */
.button {
  position: relative;
  isolation: isolate;
  padding: .78rem 1.6rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--paper);
  font-family: var(--mono);
  font-size: .8rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  cursor: pointer;
}
.button::before,
.button::after {
  content: "";
  position: absolute;
  inset: 0;
}
.button::after {
  z-index: -1;
  background: var(--blue);
}
.button::before {
  z-index: -2;
  background: var(--pink);
  transform: translate(.3125rem, .25rem);
  transition: transform .25s var(--ease);
}
.button:hover::before,
.button:focus-visible::before { transform: translate(0, 0); }
.button[disabled] { cursor: progress; opacity: .75; }
.button[disabled]::before { transform: translate(0, 0); }

.form__status {
  margin: 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .06em;
}

.notice {
  max-width: 34rem;
  margin: 0 0 2rem;
  padding: .85rem 1rem;
  border-left: 3px solid var(--pink-text);
  background: var(--paper-2);
  font-size: .95rem;
  line-height: 1.5;
}

.receipt { max-width: 34rem; }
.receipt__head {
  margin: 0 0 .6rem;
  font-family: var(--display);
  font-size: 1.6rem;
  color: var(--blue);
}
.receipt p { line-height: 1.6; }

/* -------------------------------------------------------- view transitions */

@view-transition { navigation: auto; }

::view-transition-group(pane) {
  animation-duration: .4s;
  animation-timing-function: cubic-bezier(.2, .85, .2, 1);
}
::view-transition-old(pane) { animation-name: pane-out; }
::view-transition-new(pane) { animation-name: pane-in; }

@keyframes pane-out {
  to { opacity: 0; transform: translateY(-.6rem); }
}
@keyframes pane-in {
  from { opacity: 0; transform: translateY(1rem); }
}

/* The clicked project title morphs into the page title it becomes. */
::view-transition-group(subject) {
  animation-duration: .48s;
  animation-timing-function: cubic-bezier(.22, .9, .2, 1);
}

/* ------------------------------------------------------------ less motion */

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }

  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-delay: 0ms !important;
    transition-duration: .001ms !important;
  }

  /* Print everything in register when motion is unwelcome. */
  .hero__line::before,
  .row__title::before,
  .subject::before,
  .plate::before,
  .button::before { transform: translate(0, 0); }
}

@media print {
  body::before, .plate__screen { display: none; }
  .sheet { display: block; }
}
