@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url(/fonts/schibsted-grotesk-latin.woff2) format('woff2');
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(/fonts/instrument-sans-latin.woff2) format('woff2');
}

:root {
  /* Colours are named for their job, not their hue, because dark mode swaps
     them: --bg is paper in light mode and near-black in dark. */
  --bg: #F3EEE5;
  --fg: #1B1916;
  --fg-2: #3E3A34;
  --fg-3: #5F5950;
  --slash: #B3AA9C;
  --accent: #2E48FF;
  --rule: rgba(27, 25, 22, .14);
  --display: 'Schibsted Grotesk', system-ui, sans-serif;
  --gutter: clamp(20px, 4vw, 56px);
  /* Wordmark size: ~6.4em wide on one line; the min() keeps it inside the
     gutters. Also used to size the first screen below it. */
  --wm: clamp(36px, min(14.4vw, calc((100vw - 40px) / 6.4)), 210px);
  --header-top: clamp(20px, 3vw, 40px);
  color-scheme: light dark;
}

/* Dark mode follows the visitor's system setting. Palette "A, Electric",
   chosen by James 2026-09-27 over the designer's own dark treatment, which
   read as washed out: its periwinkle #8C9BFF got contrast by mixing in white,
   and the beige greys made everything sepia. Here the brand blue stays
   saturated, lifted only as far as needed (#2E48FF -> #5570FF), on a deeper
   near-black. Contrast, all AA: text 16.7:1, lede 12.5, footer 7.0,
   accent 4.7 (light mode: 15.2 / 9.8 / 6.0 / 5.2). */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0F0E0C;
    --fg: #F3EEE5;
    --fg-2: #D6CFC4;
    --fg-3: #A39B8F;
    --slash: #4A453F;
    --accent: #5570FF;
    --rule: rgba(243, 238, 229, .14);
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: 'Instrument Sans', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; text-underline-offset: 3px; }
a:hover { color: var(--accent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.wrap {
  max-width: 1440px;
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}
.blue { color: var(--accent); }

/* ---------------------------------------------------------------- hero */

.site-header { padding-top: var(--header-top); }

/* The wordmark, sawn in half: each word's top half in ink, a blue copy's
   bottom half nudged right, with a sliver of paper between them. On load
   the halves start flush and the saw goes through. */
.wordmark {
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: var(--wm);
  letter-spacing: -.045em;
  line-height: 1;
  white-space: nowrap;
}
.word {
  position: relative;
  display: inline-block;
  padding-right: .07em;
}
.word .top { display: block; clip-path: inset(0 0 50% 0); }
.word .bottom {
  position: absolute;
  top: 0;
  left: .07em;
  color: var(--accent);
  clip-path: inset(54% 0 0 0);
  animation: saw 1.1s cubic-bezier(.2, .8, .2, 1) .25s both;
  transition: transform .5s cubic-bezier(.2, .8, .2, 1);
}
.word + .word .bottom { animation-delay: .4s; }
.wordmark:hover .bottom { transform: translateX(.035em); }

@keyframes saw {
  from { transform: translateX(-.07em); clip-path: inset(50% 0 0 0); }
  to   { transform: none;               clip-path: inset(54% 0 0 0); }
}

/* Phones: stack the two words so the mark can be twice the size. */
@media (max-width: 600px) {
  :root { --wm: calc((100vw - 40px) / 3.45); }
  .wordmark { line-height: .92; }
  .word { display: block; width: max-content; }
}

/* The first screen is a poster: wordmark at the top, statement at the
   bottom, with the list just peeking in below the fold. */
.intro {
  min-height: calc(92vh - var(--header-top) - var(--wm));
  min-height: calc(92svh - var(--header-top) - var(--wm));
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
  gap: 28px clamp(40px, 7vw, 120px);
  align-content: end;
  align-items: end;
  /* Vertical only: .wrap supplies the side gutters. */
  padding-top: clamp(56px, 9vw, 120px);
  padding-bottom: clamp(48px, 6vw, 88px);
}
/* No poster-height first screen on a phone: it only opens a gap. */
@media (max-width: 600px) { .intro { min-height: 0; } }

h1 {
  margin: 0;
  max-width: 21ch;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(30px, 3.6vw, 54px);
  line-height: 1.06;
  letter-spacing: -.03em;
  text-wrap: balance;
}

.lede {
  margin: 0;
  max-width: 40ch;
  font-size: clamp(17px, 1.35vw, 19px);
  line-height: 1.55;
  color: var(--fg-2);
  text-wrap: pretty;
}

/* ---------------------------------------------------------------- games */

.games {
  padding-top: clamp(40px, 5vw, 64px);
  padding-bottom: clamp(72px, 10vw, 150px);
  position: relative;
}
/* A rule inside the gutters rather than a border across them. */
.games::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  border-top: 1px solid var(--rule);
}


.list {
  margin: 0;
  padding: 0;
  list-style: none;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(34px, 6.6vw, 104px);
  line-height: 1.02;
  letter-spacing: -.04em;
  /* Deliberately not text-wrap: balance -- balancing evens the lines out by
     shortening all of them, which left a wide empty band on the right. */
}
.list li { display: inline; }
/* The slashes are decoration: the second content value is the (empty) text
   alternative, so screen readers announce a plain list of seven items. */
.list li:not(:last-child)::after {
  content: "\00a0/";
  content: "\00a0/" / "";
  color: var(--slash);
}
/* Keep each activity whole where there is room: the longest ("argue an
   absurd position") is ~11.2em, and fits a line from 900px up to the size cap. */
@media (min-width: 900px) { .list li { white-space: nowrap; } }

/* One activity at a time lights up blue, in a fixed shuffled order: 14 steps
   of 1.6s, each activity twice, never the same one twice running and never
   bouncing back to the one before -- so it reads as random. Generated; the
   order is 3, 6, 1, 5, 2, 7, 4, 1, 6, 3, 7, 2, 5, 4. */
.list li:nth-child(1) { animation: pick1 22.4s infinite; }
.list li:nth-child(2) { animation: pick2 22.4s infinite; }
.list li:nth-child(3) { animation: pick3 22.4s infinite; }
.list li:nth-child(4) { animation: pick4 22.4s infinite; }
.list li:nth-child(5) { animation: pick5 22.4s infinite; }
.list li:nth-child(6) { animation: pick6 22.4s infinite; }
.list li:nth-child(7) { animation: pick7 22.4s infinite; }
@keyframes pick1 {
  0%, 100% { color: var(--fg); }
  14.29% { color: var(--fg); }
  15.49%, 20.23% { color: var(--accent); }
  21.43% { color: var(--fg); }
  50% { color: var(--fg); }
  51.2%, 55.94% { color: var(--accent); }
  57.14% { color: var(--fg); }
}
@keyframes pick2 {
  0%, 100% { color: var(--fg); }
  28.57% { color: var(--fg); }
  29.77%, 34.51% { color: var(--accent); }
  35.71% { color: var(--fg); }
  78.57% { color: var(--fg); }
  79.77%, 84.51% { color: var(--accent); }
  85.71% { color: var(--fg); }
}
@keyframes pick3 {
  0%, 100% { color: var(--fg); }
  1.2%, 5.94% { color: var(--accent); }
  7.14% { color: var(--fg); }
  64.29% { color: var(--fg); }
  65.49%, 70.23% { color: var(--accent); }
  71.43% { color: var(--fg); }
}
@keyframes pick4 {
  0%, 100% { color: var(--fg); }
  42.86% { color: var(--fg); }
  44.06%, 48.8% { color: var(--accent); }
  50% { color: var(--fg); }
  92.86% { color: var(--fg); }
  94.06%, 98.8% { color: var(--accent); }
  100% { color: var(--fg); }
}
@keyframes pick5 {
  0%, 100% { color: var(--fg); }
  21.43% { color: var(--fg); }
  22.63%, 27.37% { color: var(--accent); }
  28.57% { color: var(--fg); }
  85.71% { color: var(--fg); }
  86.91%, 91.66% { color: var(--accent); }
  92.86% { color: var(--fg); }
}
@keyframes pick6 {
  0%, 100% { color: var(--fg); }
  7.14% { color: var(--fg); }
  8.34%, 13.09% { color: var(--accent); }
  14.29% { color: var(--fg); }
  57.14% { color: var(--fg); }
  58.34%, 63.09% { color: var(--accent); }
  64.29% { color: var(--fg); }
}
@keyframes pick7 {
  0%, 100% { color: var(--fg); }
  35.71% { color: var(--fg); }
  36.91%, 41.66% { color: var(--accent); }
  42.86% { color: var(--fg); }
  71.43% { color: var(--fg); }
  72.63%, 77.37% { color: var(--accent); }
  78.57% { color: var(--fg); }
}

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

footer {
  padding-top: 20px;
  padding-bottom: clamp(16px, 2vw, 28px);
  position: relative;
}
footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  border-top: 1px solid var(--rule);
}
footer p {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--fg-3);
}

@media (prefers-reduced-motion: reduce) {
  .word .bottom, .list li:nth-child(n) { animation: none; transition: none; }
  .list li:nth-child(3) { color: var(--accent); }
}

.home { display: block; text-decoration: none; color: inherit; }

/* ---------------------------------------------------------------- 404 */

/* The wordmark's saw trick, gone wrong: "404" is cut in half, the lower half
   teeters for a beat, then falls out of the bottom of the page. "This page
   didn't make the cut." It falls behind the text, not across it. */
.err-page {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  padding-top: clamp(20px, 3vw, 40px);
  padding-bottom: clamp(20px, 3vw, 40px);
  overflow: hidden;
}
.err-home .wordmark { font-size: clamp(28px, 3.2vw, 44px); }
.err-home .word { display: inline-block; }   /* no phone stacking up here */

.err-page main {
  flex: 1;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr));
  gap: 24px clamp(40px, 7vw, 120px);
  align-content: center;
  align-items: center;
  padding: clamp(32px, 6vw, 80px) 0;
}

.err-code {
  position: relative;
  margin: 0;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(140px, 26vw, 360px);
  letter-spacing: -.05em;
  line-height: 1;
  width: max-content;
  max-width: 100%;
}
.err-code .top { display: block; clip-path: inset(0 0 50% 0); }
.err-code .bottom {
  position: absolute;
  top: 0;
  left: 0;
  color: var(--accent);
  clip-path: inset(54% 0 0 0);
  transform-origin: 90% 60%;
  animation: fall 2.6s .4s both;
}
@keyframes fall {
  0%   { transform: none; clip-path: inset(50% 0 0 0); animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
  18%  { transform: none; clip-path: inset(54% 0 0 0); animation-timing-function: ease-out; }
  34%  { transform: translate(.04em, .02em) rotate(-3deg); }
  44%  { transform: translate(.04em, .02em) rotate(-2deg); }
  52%  { transform: translate(.05em, .03em) rotate(-4deg); animation-timing-function: cubic-bezier(.55, 0, .9, .4); }
  100% { transform: translate(.3em, 140vh) rotate(-28deg); clip-path: inset(54% 0 0 0); }
}

.err-text { display: flex; flex-direction: column; gap: 20px; position: relative; z-index: 1; }
.err-text .lede a { color: var(--accent); }
.err-text .lede a:hover { color: var(--fg); }

@media (prefers-reduced-motion: reduce) {
  .err-code .bottom { animation: none; visibility: hidden; }
}
