/* legacynote.app holding page: the LgcY Note wordmark on its grid, in the house's night.
   Colours, easing and the blur-in come from the app (src/styles/tokens.css, src/lib/motion.ts).

   The grid is built from the wordmark: one cell is its cap height, and the wordmark spans
   exactly seven cells (website/tools/wordmark.py), so its cap line and baseline lie on grid lines
   and the ends of its ink on others. Both are centred on the same point of the same box, so
   the grid stays symmetric about the wordmark at every size. */

:root {
  color-scheme: dark;
  --bg: #09090b;
  --line: rgb(255 255 255 / 0.06);
  --violet: 168 85 247;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  /* 34px on a 390px phone, 64px at 1440px, held between 30px and 72px */
  --cell: clamp(30px, 2.857vw + 22.86px, 72px);
}

html {
  background: var(--bg);
}

body {
  margin: 0;
}

.stage {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  overflow: hidden;
}

/* Whole, even pixels where the browser can round: half a cell is then a whole pixel, so every
   line lies a whole number of pixels from the centre. An odd window would put the centre between
   two pixels; Chrome then draws the wordmark on the next whole pixel but the grid on the half,
   a device pixel apart (measured at 2x). The stage drops the odd last pixel instead, so the
   centre, the ink and the lines all land on whole pixels, half a pixel from the window's centre. */
@supports (width: round(down, 100%, 2px)) {
  :root {
    --cell: round(clamp(30px, 2.857vw + 22.86px, 72px), 2px);
  }

  .stage {
    width: round(down, 100%, 2px);
    height: round(down, 100%, 2px);
  }
}

/* The field: grid lines through the centre of the stage at every cell, over a violet light
   sized to the wordmark, fading out toward the edges. A tile's middle sits on the centre, so
   its leading edge, where the line is drawn, lies half a cell from it: on the wordmark's cap
   line, baseline and ink edges. */
.stage::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, var(--line) 1px, transparent 1px) 50% 50% / var(--cell) var(--cell),
    linear-gradient(to bottom, var(--line) 1px, transparent 1px) 50% 50% / var(--cell) var(--cell),
    radial-gradient(
      calc(var(--cell) * 7) calc(var(--cell) * 3.5) at 50% 50%,
      rgb(var(--violet) / 0.09),
      transparent
    );
  --fade: radial-gradient(
    calc(var(--cell) * 12) calc(var(--cell) * 7) at 50% 50%,
    #000,
    rgb(0 0 0 / 0.55) 50%,
    transparent
  );
  /* prefixed for Chrome before 120 and Safari before 15.4 */
  -webkit-mask-image: var(--fade);
  mask-image: var(--fade);
}

/* A faint, fixed noise over the field dithers the light, which would otherwise show its 8-bit
   steps as rings on a dark screen. It moves no pixel by more than three levels. */
.stage::after {
  content: '';
  position: absolute;
  inset: 0;
  background: url('/grain.png') 0 0 / 128px 128px;
  image-rendering: pixelated;
  pointer-events: none;
}

h1 {
  position: relative;
  z-index: 1;
  margin: 0;
}

/* The box runs from cap line to baseline and from ink edge to ink edge; the g's descender and
   the round letters' overshoot draw outside it, as type does below its baseline. */
.wordmark {
  display: block;
  width: calc(var(--cell) * 7);
  height: var(--cell);
  overflow: visible;
}

/* Arriving: the field comes up while the wordmark condenses out of a soft blur of light, as
   words do in the app, only slower, since it is the whole page. Then nothing moves. */
@media (prefers-reduced-motion: no-preference) {
  .stage::before {
    animation: field-in 1600ms var(--ease-out) both;
  }

  .wordmark {
    animation:
      condense 1100ms var(--ease-out) 100ms both,
      appear 360ms var(--ease-out) 100ms both;
  }
}

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

@keyframes condense {
  from {
    filter: blur(calc(var(--cell) * 0.12)) brightness(1.6);
  }
}

@keyframes appear {
  from {
    opacity: 0;
  }
}

/* With forced colours the wordmark takes the system's text colour and the decoration goes. */
@media (forced-colors: active) {
  .stage::before,
  .stage::after {
    display: none;
  }

  .wordmark path {
    fill: CanvasText;
  }
}
