/* randart.hu — static styles.
   The Game of Life keyframes, the loop duration (--run) and the bolt geometry
   (--bolt) all live in life.css, generated by build.py. */

:root {
  --bg:      #000000;
  --dead:    #123d1e;  /* resting glyph — the grid you always half-see */
  --live:    #00ff41;  /* phosphor green */
  --glow:    #00ff4180;
  --ink:     #b8ffcb;
  --muted:   #4c9d68;
  --rule:    #00ff4126;
  --panel:   #000000c9;
}

/* Subset to the five characters of ランダート and nothing else, so the file is
   under 3 KB. Mincho at its heaviest: the stroke entries and exits are cut
   rather than drawn, which is where the sharpness comes from. */
@font-face {
  font-family: "ShipporiMinchoB1";
  src: url("ShipporiMinchoB1.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
}

body {
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 2rem 1.25rem;
  color: var(--ink);
  font: 400 16px/1.6 ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
        "Liberation Mono", monospace;
  overflow-x: hidden;
}

/* ---------------------------------------------------------------- the grid */

.matrix {
  --cell: max(100vw / 64, 100svh / 36);
  --fw: calc(var(--cell) * 64);
  --fh: calc(var(--cell) * 36);

  position: fixed;
  inset: 0;
  overflow: hidden;
  z-index: 0;
}

/* The bolt shares the grid's box so its clip-path lands on the same cells the
   simulation had burned. The grid is scaled to cover, so this box overflows
   the viewport — sizing the bolt to the viewport instead would misalign it. */
.grid,
.bolt {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: var(--fw);
  height: var(--fh);
}

.grid {
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(64, var(--cell));
  grid-auto-rows: var(--cell);
  font-size: calc(var(--cell) * 0.78);
  line-height: 1;
  user-select: none;
}

/* Every cell paints twice: ::before is the resting glyph, ::after is the same
   glyph lit up. Only ::after is animated, and only its opacity — the cheapest
   property there is, on 2000-odd elements. */
.grid i {
  position: relative;
  display: block;
}

.grid i::before,
.grid i::after {
  content: attr(data-g);
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

.grid i::before { color: var(--dead); }

.grid i::after {
  opacity: 0;
  color: var(--live);
  text-shadow: 0 0 0.3em var(--live), 0 0 0.9em var(--glow);
  animation-timing-function: step-end;   /* hold each generation */
  animation-iteration-count: infinite;
}

/* Scanlines + vignette: a CRT sitting in a dark room. */
.matrix::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    repeating-linear-gradient(to bottom, #0000 0 2px, #00000059 2px 4px),
    radial-gradient(ellipse 80% 70% at 50% 45%, #0000 0%, #000000a6 70%, #000 100%);
}

/* ----------------------------------------------------------- the lightning */

/* Both layers sit above the vignette — lightning is in front of the glass. */
.flash,
.bolt {
  pointer-events: none;
  opacity: 0;
  will-change: opacity;
  animation-duration: var(--run, 360s);
  animation-iteration-count: infinite;
  animation-timing-function: ease-out;
}

.flash {
  position: absolute;
  inset: 0;
  z-index: 3;
  mix-blend-mode: screen;
}

/* Each .bolt is clipped to the jagged path that was burned into the field at
   its own generation; life.css carries the geometry and the gradient. */
.bolt {
  z-index: 4;
  filter: drop-shadow(0 0 5px #c7ffd9)
          drop-shadow(0 0 16px #00ff41)
          drop-shadow(0 0 46px #00ff41cc);
}

/* ------------------------------------------------------------- the content */

main {
  position: relative;
  z-index: 1;
  /* Shrink to the wordmark rather than holding a fixed column. */
  width: fit-content;
  max-width: 100%;
  padding: clamp(1.75rem, 5vw, 3.25rem);
  background: var(--panel);
  border: 1px solid var(--rule);
  backdrop-filter: blur(3px);
  box-shadow: 0 0 0 1px #000, 0 0 60px #00ff4114, 0 30px 80px #000000b3;
}

h1 {
  margin: 0;
  font-family: "ShipporiMinchoB1", serif;
  font-weight: 800;
  font-synthesis: none;
  font-size: clamp(2.4rem, 10vw, 4.2rem);
  letter-spacing: 0.16em;
  /* letter-spacing hangs after the last glyph; pull the line back flush */
  margin-right: -0.16em;
  color: var(--live);
  text-shadow: 0 0 0.35em var(--glow);
}

h1 a {
  color: inherit;
  text-decoration: none;
}

h1 a:hover,
h1 a:focus-visible {
  outline: none;
  text-shadow: 0 0 0.25em var(--live), 0 0 0.7em var(--live);
}

/* --------------------------------------------------------------- a11y bits */

@media (prefers-reduced-motion: reduce) {
  .flash,
  .bolt,
  .grid i::after {
    animation: none !important;
  }
  /* Freeze on generation 0 rather than an empty grid. */
  .grid i.g0::after { opacity: 1; }
}
