/* ---------------------------------------------------------------
   created.games — introductory page
   --------------------------------------------------------------- */

:root {
  --paper: #f7f7f7;
  --ink:   #0a0a0a;
  --mark:  var(--paper);          /* the light squares on the cube */
  --muted: #5b5b5b;

  --cube: clamp(76px, 9vw, 92px);

  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #0a0a0a;
    --ink:   #f2f2f2;
    --muted: #9a9a9a;
  }
}

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

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

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;

  /* Centred on a roomy screen, top-aligned when the page is taller
     than the window. Browsers without `safe` simply top-align. */
  display: grid;
  align-content: safe center;

  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.page {
  max-width: 42em;
  margin: 0 auto;
  padding: clamp(2.5rem, 10vh, 5rem) clamp(1.5rem, 6vw, 2.5rem);
}

/* --- copy ------------------------------------------------------ */

.prose { max-width: 34em; }

.prose p {
  margin: 0 0 0.5em;
  text-wrap: pretty;
}

.prose a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.prose a:hover { text-decoration-thickness: 2px; }

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

.games {
  max-width: 34em;
  margin-top: 2.75em;
}

.games h2 {
  margin: 0 0 1em;
  font-size: inherit;
  font-weight: inherit;
  color: var(--muted);
}

.game-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.game-list li {
  padding: 0.55em 0;
  border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
}

.game-list li:last-child {
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
}

.game-row {
  display: flex;
  justify-content: space-between;
  gap: 1em;
  color: inherit;
  text-decoration: none;
}

a.game-row:hover .game-title {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.game-meta { color: var(--muted); }

.game-list p {
  margin: 0.1em 0 0;
  color: var(--muted);
}

/* The note shows only while the list is empty. */
.game-list:not(:empty) + .empty { display: none; }

.empty {
  margin: 0;
  color: var(--muted);
}

/* --- the cube -------------------------------------------------- */

.stage {
  /* Room for the cube's bounding sphere (side x sqrt(3)) so no
     orientation ever clips, plus slack for a comfortable grab. */
  width: calc(var(--cube) * 1.85);
  height: calc(var(--cube) * 1.85);

  /* Pull the slack back in so the resting cube optically aligns with
     the text: the hexagon is 0.218 x side in from the left of that box
     and 0.108 x side down from the top. */
  margin: calc(var(--cube) * -0.108)
          0
          clamp(2rem, 5vh, 3rem)
          calc(var(--cube) * -0.218);

  display: grid;
  place-items: center;

  perspective: calc(var(--cube) * 18);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
  outline: none;
}

.stage:active { cursor: grabbing; }

.stage:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -2px;
  border-radius: 4px;
}

.cube {
  position: relative;
  width: var(--cube);
  height: var(--cube);
  transform-style: preserve-3d;
  /* The resting pose: looking straight down a body diagonal, which is
     exactly the isometric view the flat logo is drawn in. */
  transform: rotateX(-35.264deg) rotateY(-45deg);
  will-change: transform;
}

.face {
  position: absolute;
  inset: 0;
  background-color: var(--ink);
  backface-visibility: hidden;

  /* Four squares, each a quarter of the face, centred at 25/50/75%
     in a diamond — the same geometry as assets/favicon.svg. The
     pattern is identical on all six faces and unchanged by 90-degree
     turns, so the mark reads correctly from every corner. */
  background-image:
    linear-gradient(var(--mark), var(--mark)),
    linear-gradient(var(--mark), var(--mark)),
    linear-gradient(var(--mark), var(--mark)),
    linear-gradient(var(--mark), var(--mark));
  background-repeat: no-repeat;
  background-size: 25% 25%;
  background-position:
    16.667% 50%,
    50% 16.667%,
    50% 83.333%,
    83.333% 50%;

  /* Hides the hairline seams where two faces meet. */
  outline: 1px solid var(--ink);
}

.face--front  { transform: translateZ(calc(var(--cube) / 2)); }
.face--back   { transform: rotateY(180deg) translateZ(calc(var(--cube) / 2)); }
.face--right  { transform: rotateY(90deg)  translateZ(calc(var(--cube) / 2)); }
.face--left   { transform: rotateY(-90deg) translateZ(calc(var(--cube) / 2)); }
.face--top    { transform: rotateX(90deg)  translateZ(calc(var(--cube) / 2)); }
.face--bottom { transform: rotateX(-90deg) translateZ(calc(var(--cube) / 2)); }

/* --- game pages ------------------------------------------------- */

/* Each game page can bring one colour of its own. Ghost Boy's is the
   purple of its night sky: the deep violet on paper, the lavender from
   the same scene on dark. */
.game-page {
  --accent: #532e7a;
  --screen: #231530;              /* video backdrop: the game's plum */
}

@media (prefers-color-scheme: dark) {
  .game-page { --accent: #977ec1; }
}

/* Naval Zone: the game's Agent cyan, deepened on paper so it stays
   readable, and its near-black field behind the screenshots. */
.game-page.naval-zone {
  --accent: #0f6a70;
  --screen: #0c1515;
}

@media (prefers-color-scheme: dark) {
  .game-page.naval-zone { --accent: #72f5fd; }
}

.back {
  display: inline-block;
  margin-bottom: 2.5em;
  color: var(--muted);
  text-decoration: none;
}

.back:hover { color: var(--ink); }

.game-head { max-width: 34em; }

.game-head h1 {
  margin: 0 0 0.6em;
  font-size: inherit;
  font-weight: inherit;
  color: var(--accent);
}

.game-head p {
  margin: 0 0 0.5em;
  text-wrap: pretty;
}

.game-head .game-facts { color: var(--muted); }

.devlog { margin-top: 2.75em; }

.devlog h2 {
  margin: 0 0 1em;
  font-size: inherit;
  font-weight: inherit;
  color: var(--muted);
}

.entries {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* A vertical timeline: a rail down the left, one dot per entry level
   with its date. The newest dot is filled in the game's accent. */
.entries {
  --dot: 9px;
  --rail: color-mix(in srgb, var(--ink) 18%, transparent);
  --mid: 0.775em;                 /* half a line: the date's centre */
}

.entries > li {
  position: relative;
  padding: 0 0 2.25em 1.75em;
}

/* the rail, from this dot down to the next one */
.entries > li::before {
  content: "";
  position: absolute;
  left: calc(var(--dot) / 2 - 0.5px);
  top: var(--mid);
  bottom: calc(var(--mid) * -1);
  width: 1px;
  background: var(--rail);
}

.entries > li:last-child::before { display: none; }

/* the dot */
.entries > li::after {
  content: "";
  position: absolute;
  left: 0;
  top: calc(var(--mid) - var(--dot) / 2);
  width: var(--dot);
  height: var(--dot);
  box-sizing: border-box;
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--ink) 35%, transparent);
  background: var(--paper);
}

.entries > li:first-child::after {
  border-color: var(--accent);
  background: var(--accent);
}

.entry time {
  display: block;
  color: var(--muted);
}

.entry h3 {
  margin: 0 0 0.75em;
  font-size: inherit;
  font-weight: inherit;
}

.entry video,
.entry img {
  display: block;
  width: 100%;
  height: auto;
  margin-bottom: 0.9em;
  background: var(--screen);
}

.entry video.square,
.entry img.square { max-width: 22em; }

/* --- theme switcher (Naval Zone) -------------------------------- */

/* One shot, re-taken in each of the game's themes. The shot itself is a
   button that steps to the next theme; the swatches below jump straight
   to one. Each swatch is the theme's field with its highlight centred on
   it, the same square-in-square as the mark. */
.theme-switch {
  max-width: 22em;
  margin: 0 0 0.9em;
}

.theme-shot {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.theme-shot img { margin-bottom: 0; }

.theme-shot:focus-visible,
.theme-swatches button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.theme-picker { margin-top: 0.75em; }

.theme-swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4em;
}

.theme-swatches button {
  position: relative;
  width: 1.75em;
  height: 1.75em;
  padding: 0;
  border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent);
  background: var(--field);
  cursor: pointer;
}

.theme-swatches button::after {
  content: "";
  position: absolute;
  inset: 32%;
  background: var(--light);
}

.theme-swatches button[aria-pressed="true"] {
  outline: 1px solid var(--ink);
  outline-offset: 2px;
}

/* Each theme's background and highlight, from the game's tokens. */
[data-theme="cyan"]     { --field: #0c1515; --light: #72f5fd; }
[data-theme="magenta"]  { --field: #150c15; --light: #f572fd; }
[data-theme="indigo"]   { --field: #0b0a1f; --light: #8fb0ff; }
[data-theme="amber"]    { --field: #140e06; --light: #ffb000; }
[data-theme="void"]     { --field: #000000; --light: #ffffff; }
[data-theme="chrome"]   { --field: #23272c; --light: #e6ebf0; }
[data-theme="ordnance"] { --field: #e8e5dd; --light: #1b1b19; }
[data-theme="arctic"]   { --field: #eaf3f3; --light: #0a5560; }

/* Two lines are kept for the caption whether it needs them or not, so
   switching between a short and a long one doesn't move the page.
   Scoped under .entry so it outranks `.entry p`'s zero margin. */
.entry .theme-name {
  min-height: calc(2em * 1.55);
  margin: 1.1em 0 0;
  color: var(--muted);
}

.theme-name span { color: var(--ink); }

.game-head a,
.entry a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.game-head a:hover,
.entry a:hover { text-decoration-thickness: 2px; }

.entry p {
  max-width: 34em;
  margin: 0;
  color: var(--muted);
  text-wrap: pretty;
}

.follow {
  margin: 0;
  padding-top: 1.25em;
  border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  color: var(--muted);
}

.follow a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

/* --- hover effects on the games list (fx.js) -------------------- */

.game-list li {
  position: relative;
  isolation: isolate;               /* keeps the effects behind the text */
}

.fx {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  overflow: visible;

  --ghost:       #b4a2e0;
  --ghost-shade: #8f79c9;
  --ghost-eye:   #231530;
  --agent:       #0f6a70;
  --nemesis:     #e0532b;
  --blast:       #f2b83c;
  --blast-core:  #f05930;
  --smoke:       color-mix(in srgb, var(--ink) 35%, transparent);
}

@media (prefers-color-scheme: dark) {
  .fx {
    --ghost:       #e3d9fe;
    --ghost-shade: #8879ac;
    --ghost-eye:   #22152f;
    --agent:       #72f5fd;
    --nemesis:     #f05930;
  }
}

/* Every sprite sits at the layer's corner and is moved by transform. */
.fx > * {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
  will-change: transform, opacity;
}

.px { overflow: visible; }

.px-g  { fill: var(--ghost); }
.px-gs { fill: var(--ghost-shade); }
.px-ge { fill: var(--ghost-eye); }

.fx-agent   .px-h { fill: var(--agent); }
.fx-nemesis .px-h { fill: var(--nemesis); }
.px-w { fill: var(--paper); }       /* portholes */

.px-y { fill: var(--blast); }
.px-r { fill: var(--blast-core); }
.px-smoke { fill: var(--smoke); }

/* Square blocks: shells, spray, smoke. */
.px-block.fx-agent   { background: var(--agent); }
.px-block.fx-nemesis { background: var(--nemesis); }
.px-block.px-smoke   { background: var(--smoke); }
