/* Tokens: Arbiter design system (grounds, ink, accents, 4px space grid). */
@font-face {
  font-family: "Departure Mono";
  src: url("assets/fonts/DepartureMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* One scale unit drives every size on the page (hairlines and hard shadows
     excepted). Sizes below are written in design pixels × --u.
     Stacked layout: 1px on phones, growing with tablets and tall windows (by
     whichever side is tighter, so landscape phones don't balloon). The
     two-column layout redefines it further down. */
  --u: clamp(1px, min(100vw / 560, 100dvh / 700), 2px);

  --void: #08080a;
  --pit: #111113;
  --stone-raised: #292930;
  --line: #3a3a42;

  --bone: #f7f0e0;
  --ink: #e8e3d8;
  --ash: #c2c2ca;
  --dust: #a6a6ae;
  --slate: #6a6a72;

  --blue: #3399da;
  --blue-lit: #86cbf0;
  --blue-deep: #1c5f8c;
  --blue-abyss: #10303f;
  --gold: #ebbb2d;
  --venom: #7fb83f;

  --sp-1: calc(4 * var(--u));
  --sp-2: calc(8 * var(--u));
  --sp-3: calc(12 * var(--u));
  --sp-4: calc(18 * var(--u));
  --sp-5: calc(28 * var(--u));
  --sp-6: calc(44 * var(--u));
  --sp-7: calc(88 * var(--u));

  --t-meta: calc(11 * var(--u));
  --t-body: calc(13 * var(--u));
  --t-title: calc(15 * var(--u));
  --t-name: calc(44 * var(--u));
  --avatar: calc(208 * var(--u));
  --logo: calc(36 * var(--u));

  --f-mono: "Departure Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --halo: 0 0 0 1px var(--blue), 0 0 10px rgba(51, 153, 218, .6), 0 0 26px rgba(51, 153, 218, .3);

  color-scheme: dark;
}

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

body {
  margin: 0;
  background: var(--void);
  color: var(--ink);
  font: 400 var(--t-body)/1.7 var(--f-mono);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); text-decoration: none; }
a:hover { color: var(--blue-lit); }
a:focus-visible { outline: none; box-shadow: var(--halo); }

::selection { background: var(--blue-deep); color: var(--bone); }

.sep { color: var(--slate); }

/* ---------- background dither ---------- */
.bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--void);
}
.bg::after {
  /* Quiet the field under the reading column. */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(8, 8, 10, .7) 30%, rgba(8, 8, 10, .7) 70%, transparent);
  pointer-events: none;
}
.bg canvas { display: block; }

/* Hidden probe main.js measures to scale the dither grids with --u. */
.u-probe {
  position: absolute;
  width: calc(1000 * var(--u));
  height: 0;
  visibility: hidden;
  pointer-events: none;
}

/* ---------- layout ---------- */
.wrap {
  max-width: calc(520 * var(--u));
  margin: 0 auto;
  padding: var(--sp-6) 16px;
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  text-align: center;
}
/* Narrow: the column wrappers step aside and everything stacks, links last. */
.side, .content { display: contents; }
.hero { order: 0; }
.content > section { order: 1; }
.side > section { order: 2; }

/* ---------- hero ---------- */
.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.avatar {
  position: relative;
  width: var(--avatar);
  height: var(--avatar);
  margin-bottom: var(--sp-3);
  /* The artwork's near-black ground takes the field's colour, so no square edge shows. */
  mix-blend-mode: lighten;
}
.avatar img, .avatar canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.avatar canvas { display: block; }
/* The img is the no-WebGL fallback; the shader canvas replaces it once live. */
.avatar.is-live img { visibility: hidden; }

.name {
  margin: 0;
  font: 400 var(--t-name)/1 var(--f-mono);
  letter-spacing: -.01em;
  color: var(--bone);
  text-shadow:
    0 .07em 0 var(--blue),
    0 .14em 0 var(--blue-abyss),
    0 0 .4em rgba(51, 153, 218, .6),
    0 0 .9em rgba(51, 153, 218, .3);
}
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
.tagline {
  margin: var(--sp-3) 0 0;
  font-size: var(--t-body);
  color: var(--dust);
}

/* ---------- sections ---------- */
section { display: flex; flex-direction: column; gap: var(--sp-4); }

.label {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  margin: 0;
  font: 400 var(--t-meta)/1 var(--f-mono);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--dust);
}
.label::before {
  content: "";
  width: calc(6 * var(--u));
  height: calc(6 * var(--u));
  background: var(--blue);
  box-shadow: 0 0 7px var(--blue);
}

.list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
}
.list li { display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); }
.list .body { display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); }
.list p { margin: 0; max-width: 60ch; color: var(--ash); text-wrap: pretty; }

.title { font-size: var(--t-title); color: var(--bone); }
.title.step { margin-top: var(--sp-2); font-size: var(--t-body); color: var(--ink); }

/* Company marks: one square tile each, same size whatever the source. */
.logo {
  display: grid;
  place-items: center;
  width: var(--logo);
  height: var(--logo);
  margin-bottom: var(--sp-1);
  overflow: hidden;
  background: var(--pit);
  border: 1px solid var(--line);
  box-shadow: 3px 3px 0 #000;
}
.logo img { width: 100%; height: 100%; object-fit: cover; }
.logo-mark img { width: 72%; height: 72%; object-fit: contain; }
.logo-unknown {
  /* Company not shown. */
  font-size: calc(18 * var(--u));
  line-height: 1;
  color: var(--blue);
  text-shadow: 0 0 8px rgba(51, 153, 218, .7);
}
.list li:hover .logo { border-color: var(--blue); box-shadow: 3px 3px 0 #000, 0 0 10px rgba(51, 153, 218, .5); }
a.title { color: var(--bone); }
a.title span { color: var(--blue); }
a.title:hover { color: var(--blue-lit); }
.at { color: var(--gold); white-space: nowrap; }
.title, .meta { text-wrap: balance; }
.meta { font-size: var(--t-meta); color: var(--dust); }
.now { color: var(--venom); }
/* Game credits: a small labelled list, set like a credits roll. */
.credits {
  margin: var(--sp-2) 0 0;
  font-size: var(--t-meta);
  line-height: 1.6;
}
.credits dt {
  margin-bottom: var(--sp-1);
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--slate);
}
.credits dd { margin: 0; }
.credits .game { color: var(--bone); }
.credits .role { color: var(--dust); }
.credits .role::before { content: "— "; color: var(--slate); }
.nw { white-space: nowrap; }

.live {
  display: inline-flex;
  align-items: center;
  gap: calc(6 * var(--u));
  margin-left: var(--sp-1);
  font-size: var(--t-meta);
  color: var(--venom);
  vertical-align: .1em;
}
.live::before {
  content: "";
  width: calc(6 * var(--u));
  height: calc(6 * var(--u));
  background: var(--venom);
  box-shadow: 0 0 7px var(--venom);
  animation: blink 1.6s steps(1, end) infinite;
}

.links { display: flex; justify-content: center; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); }
.links a { padding: var(--sp-2) 0; font-size: var(--t-title); }
.links a::before { content: "→ "; color: var(--slate); }
.links a:hover::before { color: var(--blue); }

@media (max-width: 640px) {
  :root {
    --avatar: calc(176 * var(--u));
    --t-name: calc(36 * var(--u));
  }
  .wrap { padding-top: var(--sp-5); gap: var(--sp-5); }
  .bg::after { background: rgba(8, 8, 10, .6); }
}

/* Wide, landscape or square: identity and links in a sticky left column, the
   record on the right. The composition is about 1150×900 design pixels and
   scales by whichever viewport side is tighter, so it fills the window at any
   size or zoom. Clamped: it never drops below 0.8× (so zooming in past that
   still enlarges it) or grows past 2.4×. Portrait windows keep the stack. */
@media (min-width: 900px) and (min-aspect-ratio: 1/1) {
  :root {
    --u: clamp(.8px, min(100vw / 1150, 100dvh / 900), 2.4px);
    --avatar: calc(240 * var(--u));
  }
  .wrap {
    max-width: calc(1000 * var(--u) + 2 * var(--sp-5));
    min-height: 100dvh;
    display: grid;
    grid-template-columns: calc(280 * var(--u)) minmax(0, 1fr);
    column-gap: var(--sp-7);
    align-items: start;
    align-content: center;
    padding: var(--sp-6) var(--sp-5);
  }
  .side {
    position: sticky;
    top: var(--sp-6);
    display: flex;
    flex-direction: column;
    gap: var(--sp-5);
    /* Sticky makes its own stacking context, which would cut the portrait's blend
       off from the field; blending the whole column carries it through. Text is
       lighter than the field, so it is unaffected. */
    mix-blend-mode: lighten;
  }
  /* The links sit right under the name here, so their heading divides nothing.
     Hidden visually, kept for screen readers. */
  .side .label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .content {
    display: flex;
    flex-direction: column;
    gap: var(--sp-6);
    text-align: left;
  }
  .content .label { justify-content: flex-start; }
  .content .list li { flex-direction: row; align-items: flex-start; gap: var(--sp-4); }
  .content .logo { flex: none; margin: calc(2 * var(--u)) 0 0; }
  .content .body { align-items: flex-start; }
  /* No logo: keep the text on the same column as the entries above. */
  .content .list li > .body:only-child { padding-left: calc(var(--logo) + var(--sp-4)); }
  .bg::after {
    background: linear-gradient(90deg, transparent, rgba(8, 8, 10, .7) 15%, rgba(8, 8, 10, .7) 85%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .live::before { animation: none; }
}
