/* Submatter splash — tokens first; everything below reads from these.
   Re-skin by changing this block when the new palette and type land. */
:root {
  --bg: #070808;
  --paper: #f5f5f7;
  --signal: #2ea6b5;
  --grid-ink: rgba(245, 245, 247, 0.18);
  --grid-size: 32px;
  --dot: 1.1px;
  --mark-width: clamp(200px, 46vw, 680px);
  --mark-optical-offset: -4.5vh; /* lift above geometric center; negative = up */
  --band-height: 22%;
  --scrim-alpha: 0.30;        /* uniform veil over the whole frame */
  --scrim-focus-alpha: 0.30;  /* extra darkening centered behind the mark */
  --sweep-duration: 11s;
  --settle-duration: 600ms;
  --ease-instrument: cubic-bezier(0.2, 0.7, 0.2, 1);
  --font-sans: "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  min-height: 100%;
  background: var(--bg);
  color: var(--paper);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

/* The field: a fixed, full-viewport measurement surface. */
.field {
  position: fixed;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  isolation: isolate;
  background: var(--bg);
}

/* Dot grid. Shared geometry for the substrate and the signal layer so they align. */
.field__grid,
.field__signal {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle, var(--grid-ink) var(--dot), transparent calc(var(--dot) + 0.6px));
  background-size: var(--grid-size) var(--grid-size);
  background-position: center;
  /* Clear a quiet zone around the mark; fade the field toward the viewport edge. */
  -webkit-mask-image:
    radial-gradient(ellipse 60% 48% at 50% 50%, transparent 0 34%, #000 72%),
    radial-gradient(ellipse 100% 100% at 50% 50%, #000 55%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(ellipse 60% 48% at 50% 50%, transparent 0 34%, #000 72%),
    radial-gradient(ellipse 100% 100% at 50% 50%, #000 55%, transparent 100%);
  mask-composite: intersect;
}

/* Signal: the same dots in the accent color, revealed only inside a hard-edged
   band that sweeps the field, rests, and sweeps again. */
.field__signal {
  --grid-ink: var(--signal);
  opacity: 0.85;
  clip-path: inset(-25% 0 100% 0);
  animation: sweep var(--sweep-duration) linear infinite;
  will-change: clip-path;
}

@keyframes sweep {
  0%   { clip-path: inset(-25% 0 100% 0); }
  62%  { clip-path: inset(100% 0 -25% 0); }
  100% { clip-path: inset(100% 0 -25% 0); }
}

/* Background video. Covers the viewport, loops, muted. The poster paints first. */
.field__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  background: var(--bg);
}

/* Still frame used when the video is hidden (reduced motion, or autoplay blocked). */
.field__still {
  position: absolute;
  inset: 0;
  display: none;
  background: var(--bg) url("/assets/submatter-splash-poster.jpg") center / cover no-repeat;
}

/* Scrim so the white logo reads over bright footage: a light uniform veil plus a
   centered focus behind the mark. Set either alpha to 0 to remove that layer. */
.field--video::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(ellipse 58% 42% at 50% calc(50% + var(--mark-optical-offset)), rgba(7, 8, 8, var(--scrim-focus-alpha)) 0%, rgba(7, 8, 8, 0) 100%),
    rgba(7, 8, 8, var(--scrim-alpha));
}

/* Archival grain. Static. */
.field__grain {
  position: absolute;
  inset: 0;
  opacity: 0.07;
  z-index: 1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.95' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.7 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
}

/* The mark. One weighted settle on arrival, then stillness. */
.mark {
  position: relative;
  z-index: 2;
  margin: 0;
  width: var(--mark-width);
  padding: 0 16px;
  transform: translateY(var(--mark-optical-offset));
  animation: settle var(--settle-duration) var(--ease-instrument) both;
}

.mark__img {
  display: block;
  width: 100%;
  height: auto;
}

@keyframes settle {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* 404 and any other static state: the field holds still. */
.field--static .field__signal {
  display: none;
}

.notice {
  position: relative;
  z-index: 1;
  max-width: 34rem;
  padding: 0 24px;
  text-align: center;
}

.notice__code {
  margin: 0 0 24px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--signal);
}

.notice__title {
  margin: 0 0 16px;
  font-size: clamp(22px, 3.6vw, 32px);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.2;
  text-transform: uppercase;
}

.notice__body {
  margin: 0 0 32px;
  font-size: 17px;
  line-height: 1.55;
  color: rgba(245, 245, 247, 0.72);
}

.notice__link {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.02em;
  color: var(--paper);
  text-decoration: underline;
  text-underline-offset: 0.25em;
  transition: color 180ms ease-out;
}

.notice__link:hover,
.notice__link:focus-visible {
  color: var(--signal);
  outline: none;
}

.notice__link:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 4px;
}

/* Reduced motion: the sweep stops, the mark is simply present. */
@media (prefers-reduced-motion: reduce) {
  .field__signal,
  .field__video {
    display: none;
  }
  .field__still {
    display: block;
  }
  .mark {
    animation: none;
  }
}

/* ---- Dither pass ------------------------------------------------------- */
/* The canvas paints over the video once the first dithered frame is drawn.
   Until then it is invisible so the poster and video show. If WebGL2 is
   unavailable or the context is lost, the script removes it. */
.field__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: var(--bg);
  opacity: 0;
}

.field__canvas.is-live {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .field__canvas {
    display: none;
  }
}

/* ---- Tuning panel (Escape) --------------------------------------------- */
.tune {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 10;
  width: min(320px, calc(100vw - 32px));
  max-height: calc(100vh - 32px);
  overflow: auto;
  padding: 12px 14px 14px;
  background: rgba(7, 8, 8, 0.92);
  border: 1px solid rgba(245, 245, 247, 0.16);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.4;
}

.tune[hidden] {
  display: none;
}

.tune__head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}

.tune__title {
  letter-spacing: 0.08em;
  color: var(--signal);
}

.tune__meta {
  margin-left: auto;
  color: rgba(245, 245, 247, 0.6);
  font-size: 11px;
}

.tune__status {
  margin: 0 0 10px;
  font-size: 11px;
  color: rgba(245, 245, 247, 0.55);
}

.tune__controls {
  display: grid;
  gap: 6px;
}

.tune__row {
  display: grid;
  grid-template-columns: 64px 1fr 44px;
  align-items: center;
  gap: 8px;
}

.tune__name {
  color: rgba(245, 245, 247, 0.8);
}

.tune__val {
  text-align: right;
  color: rgba(245, 245, 247, 0.6);
  font-variant-numeric: tabular-nums;
}

.tune__input {
  width: 100%;
  min-width: 0;
  accent-color: var(--signal);
  color: var(--paper);
  background: rgba(245, 245, 247, 0.06);
  border: 1px solid rgba(245, 245, 247, 0.16);
  font: inherit;
}

.tune__input--range {
  background: transparent;
  border: 0;
  padding: 0;
  height: 20px;
}

.tune__input--select {
  padding: 2px 4px;
}

.tune__input--color {
  height: 22px;
  padding: 0;
}

.tune__input--checkbox {
  width: 16px;
  height: 16px;
  justify-self: start;
}

.tune__input:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 2px;
}

.tune__actions {
  display: flex;
  gap: 8px;
  margin: 12px 0 8px;
}

.tune__btn {
  font: inherit;
  letter-spacing: 0.04em;
  color: var(--paper);
  background: transparent;
  border: 1px solid rgba(245, 245, 247, 0.3);
  padding: 4px 10px;
  cursor: pointer;
  transition: border-color 180ms ease-out, color 180ms ease-out;
}

.tune__btn:hover,
.tune__btn:focus-visible {
  border-color: var(--signal);
  color: var(--signal);
  outline: none;
}

.tune__btn--close {
  padding: 2px 6px;
  font-size: 10px;
}

.tune__readout {
  margin: 0;
  padding: 8px;
  max-height: 160px;
  overflow: auto;
  font-size: 11px;
  background: rgba(245, 245, 247, 0.04);
  border: 1px solid rgba(245, 245, 247, 0.1);
  user-select: all;
}
