@font-face {
  font-display: swap;
  font-family: "Imbue";
  font-style: normal;
  font-weight: 100 900;
  src: url("fonts/imbue-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Imbue Fallback";
  size-adjust: 53%;
  src: local("Georgia"), local("Times New Roman");
}

@font-face {
  font-display: swap;
  font-family: "Onest";
  font-style: normal;
  font-weight: 100 900;
  src: url("fonts/onest-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Onest Fallback";
  size-adjust: 104%;
  src: local("Arial"), local("Helvetica");
}

:root {
  --color-accent: #ff6a3d;
  --color-alive: #b9ff5c;
  --color-bg: #0f0e12;
  --color-blood: #ff3d5a;
  --color-bruise: #a77bff;
  --color-dim: #847e96;
  --color-ectoplasm: #7ff3e1;
  --color-focus: #ffd166;
  --color-ink: #efe9df;
  --color-line: #2d2937;
  --color-muted: #a8a2b4;
  --color-surface: #1a1820;
  --color-witch: #ff5ce1;
  --font-sans: "Onest", "Onest Fallback", system-ui, sans-serif;
  --font-serif: "Imbue", "Imbue Fallback", Georgia, serif;
  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

blockquote,
dd,
dl,
dt,
h1,
h2,
p {
  margin: 0;
}

body {
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  line-height: 1.6;
  margin: 0;
  -webkit-text-size-adjust: 100%;
}

html {
  scroll-behavior: var(--scroll-behavior, auto);
}

@media (prefers-reduced-motion: no-preference) {
  html {
    --scroll-behavior: smooth;
  }
}

.collateral {
  background: var(--color-surface);
  border-radius: 40px;
  corner-shape: squircle;
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  margin-block: 3rem;
  padding: clamp(1.5rem, 4vw, 3rem);
}

.collateral__dd {
  --focus-in-end: cover 32%;
  --focus-in-start: cover 6%;
  color: var(--color-muted);
}

.collateral__dt {
  color: var(--color-ink);
  font: 400 1.625rem/1.1 var(--font-serif);
  margin-bottom: 0.25rem;
}

.collateral__list {
  display: grid;
  gap: 1.5rem 2.5rem;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.collateral__title {
  font: 300 clamp(2.5rem, 6vw, 4.5rem)/0.95 var(--font-serif);
}

.dead-title {
  display: contents;
}

/* Rises, holds for a few seconds, then dies again. The death only fills forwards so it can't override the rise while it waits */
.dead-title--alive {
  --hero-a-animation: hero-a-rises 1.6s linear both, hero-a-dies 2.4s 4.6s linear forwards;
  --hero-end-animation: hero-end-opens 0.5s cubic-bezier(0.3, 0, 0.2, 1) both, hero-end-closes 0.7s 6.6s cubic-bezier(0.3, 0, 0.2, 1) forwards;
}

/* Killed from the alive hold: the same death and "d." closing as on page load, starting now */
.dead-title--buried {
  --hero-a-animation: hero-a-dies 2.4s linear both;
  --hero-end-animation: hero-end-closes 0.7s 2s cubic-bezier(0.3, 0, 0.2, 1) both;
}

/* No CSS animations: for one style pass between cycles, so the next starts fresh rather than reusing the finished death,
   and while a rewind plays from dev-is-dead.js */
.dead-title--reset {
  --hero-a-animation: none;
  --hero-end-animation: none;
}

/* After a rewind the letter is already in place, so it only holds and dies again, on the same timing as --alive */
.dead-title--revived {
  --hero-a-animation: hero-a-dies 2.4s 3s linear forwards;
  --hero-end-animation: hero-end-closes 0.7s 5s cubic-bezier(0.3, 0, 0.2, 1) forwards;
}

/* Each resurrection moves "(again)" on a colour; hover previews the next one. DeadTitle in dev-is-dead.js counts these */
.dead-title--tone-1 {
  --again-color: var(--color-alive);
  --again-hover: var(--color-bruise);
}

.dead-title--tone-2 {
  --again-color: var(--color-bruise);
  --again-hover: var(--color-ectoplasm);
}

.dead-title--tone-3 {
  --again-color: var(--color-ectoplasm);
  --again-hover: var(--color-blood);
}

.dead-title--tone-4 {
  --again-color: var(--color-blood);
  --again-hover: var(--color-witch);
}

.dead-title--tone-5 {
  --again-color: var(--color-witch);
  --again-hover: var(--color-alive);
}

/* On <html> until the graveyard's monument surges up and knocks the "a" out (DeadTitle in dev-is-dead.js) */
.death-hold {
  --death-play: paused;
}

.entry {
  --entry-content-column: 2;
  --entry-content-row: 2;
  --entry-marker-column: 1;
  --entry-year-column: 2;
  --entry-year-size: clamp(2.25rem, 4.5vw, 3.25rem);
  display: grid;
  gap: 1rem 0.75rem;
  grid-template-columns: var(--entry-columns, 2.5rem minmax(0, 1fr));
  padding-block: clamp(2.5rem, 6vw, 4.5rem);
}

@media (min-width: 48em) {
  .entry {
    --entry-columns: minmax(0, 1fr) var(--spine-gap, 5rem) minmax(0, 1fr);
    --entry-content-column: 1;
    --entry-content-justify: end;
    --entry-content-row: 1;
    --entry-marker-column: 2;
    --entry-year-column: 3;
  }
}

.entry::before {
  align-self: start;
  background: var(--color-bg);
  border: 3px solid var(--color-accent);
  border-radius: 50%;
  content: "";
  grid-column: var(--entry-marker-column);
  grid-row: 1;
  height: 1rem;
  justify-self: center;
  margin-top: calc(var(--entry-year-size) / 2 - 0.5rem);
  width: 1rem;
}

@media (min-width: 48em) {
  .entry:nth-child(even) {
    --entry-content-column: 3;
    --entry-content-justify: start;
    --entry-year-align: end;
    --entry-year-column: 1;
    --entry-year-justify: end;
  }
}

.entry__body {
  color: var(--color-muted);
  font-weight: 200;
  max-width: 62ch;
}

.entry__content {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  grid-column: var(--entry-content-column);
  grid-row: var(--entry-content-row);
  justify-self: var(--entry-content-justify, start);
}

.entry__headline {
  font: 300 clamp(2rem, 2.8vw, 2.4rem)/1.15 var(--font-serif);
  max-width: 34ch;
  text-wrap: balance;
}

.entry__title {
  font: 300 clamp(2.75rem, 7vw, 5.5rem)/0.92 var(--font-serif);
  line-height: 1.1;
  text-wrap: balance;
}

.entry__year {
  align-self: start;
  color: var(--color-accent);
  font: 400 var(--entry-year-size)/1 var(--font-serif);
  grid-column: var(--entry-year-column);
  grid-row: 1;
  justify-self: var(--entry-year-justify, start);
  position: var(--entry-position, static);
  text-align: var(--entry-year-align, start);
  top: 1.5rem;
}

.focus-in {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .focus-in {
      animation: focus-in cubic-bezier(0.2, 0.7, 0.3, 1) both;
      animation-range: var(--focus-in-start, entry 100%) var(--focus-in-end, cover 26%);
      animation-timeline: view();
    }

    @keyframes focus-in {
      from {
        filter: blur(8px);
        opacity: 0;
        transform: translateY(1.5em);
      }

      to {
        filter: blur(0);
        opacity: 1;
        transform: none;
      }
    }
  }
}

.footer {
  border-top: 1px solid var(--color-line);
  padding-top: clamp(4rem, 10vw, 8rem);
}

.footer__note {
  color: var(--color-muted);
  font-size: clamp(1.5rem, 2.6vw, 2.8rem);
  font-weight: 100;
  letter-spacing: -0.015em;
  line-height: 1.25;
  text-wrap: balance;
}

.footer__title {
  font: 300 clamp(3rem, 9vw, 8.5rem)/0.9 var(--font-serif);
  letter-spacing: -0.005em;
  text-wrap: balance;
}

.grave {
  justify-content: end;
  min-height: 100svh;
  padding-bottom: clamp(1.5rem, 4vh, 3rem);
}

.hero {
  display: flex;
  min-height: 100svh;
  padding-block: clamp(3rem, 10vh, 6rem) 2rem;
}

.hero__a {
  display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
  .hero__a {
    animation: var(--hero-a-animation, hero-a-dies 2.4s 2.2s linear both);
    animation-play-state: var(--death-play, running);
    transform-origin: 50% 100%;
  }

  @keyframes hero-a-dies {
    0% {
      animation-timing-function: ease-in-out;
      transform: none;
    }

    16% {
      animation-timing-function: ease-in-out;
      transform: translateY(0.02em) rotate(5deg) scaleY(0.96);
    }

    24% {
      animation-timing-function: ease-in-out;
      transform: rotate(-2deg);
    }

    34% {
      animation-timing-function: ease-in;
      transform: translateY(0.03em) rotate(8deg) scaleY(0.94);
    }

    42% {
      animation-timing-function: ease-out;
      transform: translateY(0.02em) rotate(4deg) scaleY(0.95);
    }

    58% {
      animation-timing-function: ease-out;
      transform: translateY(0.05em) rotate(22deg) scaleY(0.92);
    }

    64% {
      animation-timing-function: cubic-bezier(0.55, 0, 0.9, 0.45);
      opacity: 1;
      transform: translateY(0.04em) rotate(17deg) scaleY(0.92);
    }

    88% {
      opacity: 1;
    }

    /* Falls through the copy below; scatter-text in dev-is-dead.js times the words to this drop */
    100% {
      opacity: 0;
      transform: translate(0.12em, 75svh) rotate(100deg) scaleY(0.92);
    }
  }

  /* Climbs back up from where hero-a-dies left it; scatter-text times the words to this too */
  @keyframes hero-a-rises {
    0% {
      animation-timing-function: cubic-bezier(0.15, 0.6, 0.3, 1);
      opacity: 0;
      transform: translate(0.12em, 75svh) rotate(100deg) scaleY(0.92);
    }

    8% {
      opacity: 1;
    }

    50% {
      animation-timing-function: ease-in-out;
      transform: translateY(-0.12em) rotate(-8deg) scaleY(1.06);
    }

    62% {
      animation-timing-function: ease-in-out;
      transform: translateY(0.03em) rotate(4deg) scaleY(0.94);
    }

    72% {
      animation-timing-function: ease-in-out;
      transform: rotate(-3deg);
    }

    84% {
      animation-timing-function: ease-in-out;
      transform: rotate(1.5deg);
    }

    100% {
      opacity: 1;
      transform: none;
    }
  }
}

.hero__end {
  display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
  .hero__end {
    animation: var(--hero-end-animation, hero-end-closes 0.7s 4.2s cubic-bezier(0.3, 0, 0.2, 1) both);
    animation-play-state: var(--death-play, running);
  }

  @keyframes hero-end-closes {
    from {
      transform: none;
    }

    /* Advance of the "a" at this weight and size, less the title's letter-spacing */
    to {
      transform: translateX(-0.284em);
    }
  }

  @keyframes hero-end-opens {
    from {
      transform: translateX(-0.284em);
    }

    to {
      transform: none;
    }
  }
}

.hero__hint {
  --hint-margin: auto;
  align-self: start;
}

.hero__layout {
  align-items: end;
  display: grid;
  gap: clamp(3rem, 6vw, 5rem) 7rem;
  grid-template-areas: var(--hero-areas, "title" "lede" "record");
  grid-template-columns: var(--hero-columns, minmax(0, 1fr));
}

@media (min-width: 64em) {
  .hero__layout {
    --hero-areas: "title title" "lede record";
    --hero-columns: minmax(0, 1fr) auto;
  }
}

.hero__lede {
  font-size: clamp(1.125rem, 1.6vw, 1.375rem);
  font-weight: 100;
  grid-area: lede;
  max-width: 50ch;
}

.hero__record {
  grid-area: record;
}

.hero__sub {
  background: none;
  border: 0;
  color: var(--again-color, var(--color-accent));
  font: inherit;
  font-size: 0.24em;
  font-weight: 300;
  letter-spacing: 0;
  line-height: 1;
  padding: 0;
}

.hero__sub:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 4px;
}

.hero__sub:hover {
  color: var(--again-hover, var(--color-alive));
  cursor: pointer;
}

.hero__sub[aria-disabled="true"] {
  cursor: default;
}

.hero__title {
  align-items: last baseline;
  display: flex;
  flex-wrap: wrap;
  font: 200 clamp(5rem, 21vw, 21rem)/0.82 var(--font-serif);
  gap: 0 1rem;
  grid-area: title;
  justify-content: space-between;
  letter-spacing: -0.01em;
  margin-left: -0.05em;
}

.hint {
  color: var(--color-dim);
  font-size: 0.9375rem;
  margin-top: var(--hint-margin, 2rem);
  text-align: center;
  text-decoration: none;
}

.hint:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 4px;
}

.hint:hover {
  color: var(--color-muted);
}

/* On <html> until the graves start rising, so the tally draws in alongside them. Released by dev-is-dead.js */
.intro-hold {
  --intro-play: paused;
}

.record {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.record__row {
  align-items: center;
  display: grid;
  gap: 1.5rem;
  grid-template-columns: 8.5rem auto;
}

.record__term {
  color: var(--color-muted);
  font-size: 0.9375rem;
}

.record__value {
  color: var(--color-ink);
  font: 300 clamp(2rem, 3vw, 2.5rem)/1 var(--font-serif);
}

.reveal {
  opacity: 1;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .reveal {
      animation: reveal linear both;
      animation-range: entry 0% entry 45%;
      animation-timeline: view();
    }

    @keyframes reveal {
      from {
        opacity: 0;
        transform: translateY(2.5rem);
      }

      to {
        opacity: 1;
        transform: translateY(0);
      }
    }
  }
}

.scatter-text__word {
  display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
  .scatter-text__word {
    animation: scatter 1.1s var(--scatter-delay, 0ms) both;
  }

  @keyframes scatter {
    0% {
      animation-timing-function: cubic-bezier(0.2, 0.8, 0.3, 1);
      transform: none;
    }

    18% {
      animation-timing-function: ease-in-out;
      transform: translate(var(--scatter-x, 0), var(--scatter-y, 0)) rotate(var(--scatter-rotate, 0deg));
    }

    48% {
      animation-timing-function: ease-in-out;
      transform: translate(calc(var(--scatter-x, 0) * -0.2), calc(var(--scatter-y, 0) * -0.35)) rotate(calc(var(--scatter-rotate, 0deg) * -0.3));
    }

    72% {
      animation-timing-function: ease-in-out;
      transform: translate(calc(var(--scatter-x, 0) * 0.06), calc(var(--scatter-y, 0) * 0.12)) rotate(calc(var(--scatter-rotate, 0deg) * 0.1));
    }

    100% {
      transform: none;
    }
  }
}

.scene {
  display: block;
  /* lvh, not dvh: the largest viewport height doesn't change as a phone's URL bar slides in and out, so the graveyard
     doesn't resize and jump on scroll; it just runs under the bar while it's showing */
  height: 100lvh;
  inset: 0 0 auto;
  position: fixed;
  z-index: -1;
}

.scene__canvas {
  display: block;
  height: 100%;
  width: 100%;
}

@media (prefers-reduced-motion: no-preference) {
  .scene__canvas {
    animation: scene-in 1s ease-out both;
  }

  @keyframes scene-in {
    from {
      opacity: 0;
    }

    to {
      opacity: 1;
    }
  }
}

.stamp {
  border: 3px solid var(--stamp-color, var(--color-alive));
  color: var(--stamp-color, var(--color-alive));
  font-size: 0.8125rem;
  font-weight: 800;
  letter-spacing: 0.18em;
  line-height: 1;
  padding: 0.6rem 0.8rem 0.5rem;
  rotate: -3deg;
  text-transform: uppercase;
  width: fit-content;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .entry {
      view-timeline: --entry block;
    }

    /* Stamp lands as its entry's top edge reaches the top of the viewport */
    .stamp {
      animation: stamp linear both;
      animation-range: cover 95vh cover 110vh;
      animation-timeline: --entry;
    }

    @keyframes stamp {
      0% {
        opacity: 0;
        rotate: -8deg;
        scale: 1.4;
      }

      55% {
        opacity: 1;
        rotate: -2deg;
        scale: 0.96;
      }

      72% {
        scale: 1.02;
      }

      100% {
        opacity: 1;
        rotate: -3deg;
        scale: 1;
      }
    }
  }
}

.stamp--pending {
  --stamp-color: var(--color-accent);
}

.stamp--twist {
  --stamp-color: var(--color-focus);
}

.tally {
  display: inline-flex;
  gap: 0.75rem;
  height: 1.75rem;
  vertical-align: middle;
}

.tally__group {
  display: inline-flex;
  gap: 0.3rem;
  position: relative;
}

.tally__group:nth-child(2) {
  --group: 1;
}

.tally__group:nth-child(3) {
  --group: 2;
}

.tally__group:nth-child(4) {
  --group: 3;
}

.tally__group--struck::after {
  background: var(--color-accent);
  content: "";
  height: 2px;
  inset-inline: -0.4rem;
  position: absolute;
  top: calc(50% - 1px);
  transform: rotate(-28deg);
}

@media (prefers-reduced-motion: no-preference) {
  .tally__group--struck::after {
    animation: tally-strike 0.25s ease-out both;
    animation-delay: calc((var(--group, 0) * 5 + 4) * 70ms + 400ms);
    animation-play-state: var(--intro-play, running);
  }

  @keyframes tally-strike {
    from {
      transform: rotate(-28deg) scaleX(0);
    }

    to {
      transform: rotate(-28deg) scaleX(1);
    }
  }
}

.tally__mark {
  background: var(--color-ink);
  border-radius: 1px;
  height: 100%;
  transform: rotate(var(--mark-tilt, 3deg));
  width: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  .tally__mark {
    animation: tally-mark 0.18s ease-out both;
    animation-delay: calc((var(--group, 0) * 5 + var(--mark, 0)) * 70ms + 400ms);
    animation-play-state: var(--intro-play, running);
    transform-origin: top;
  }

  @keyframes tally-mark {
    from {
      transform: rotate(var(--mark-tilt, 3deg)) scaleY(0);
    }

    to {
      transform: rotate(var(--mark-tilt, 3deg)) scaleY(1);
    }
  }
}

.tally__mark:nth-child(2) {
  --mark: 1;
}

.tally__mark:nth-child(3) {
  --mark: 2;
}

.tally__mark:nth-child(4) {
  --mark: 3;
}

.tally__mark:nth-child(even) {
  --mark-tilt: -2deg;
}

.timeline {
  --spine-x: 1.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

@media (min-width: 48em) {
  .timeline {
    --spine-x: 50%;
  }
}

.timeline::after {
  background: var(--color-accent);
  content: "";
  inset-block: 0;
  left: var(--spine-x);
  position: absolute;
  transform: translateX(-50%) scaleY(1);
  transform-origin: top;
  width: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .timeline::after {
      animation: spine linear both;
      animation-range: cover 0% cover 100%;
      animation-timeline: view();
    }

    @keyframes spine {
      from {
        transform: translateX(-50%) scaleY(0);
      }

      to {
        transform: translateX(-50%) scaleY(1);
      }
    }
  }
}

.timeline::before {
  background: var(--color-line);
  content: "";
  inset-block: 0;
  left: var(--spine-x);
  position: absolute;
  transform: translateX(-50%);
  width: 2px;
}

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

.wrap {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  margin-inline: auto;
  max-width: 70rem;
  padding-inline: clamp(1.25rem, 4vw, 3rem);
  width: 100%;
}
