/* Retro Room — phase 9c: the CRT filter.
 *
 * Three levels on one button: off, soft, full. See src/crt.js for the geometry
 * and for an honest list of what this is not.
 *
 * WHAT MAKES IT CHEAP. Every layer here only ever *darkens*. The canvas is
 * `object-fit: contain`, so a 4:3 disc on a landscape phone is letterboxed, and
 * an overlay covering the whole stage would normally have to be clipped to the
 * picture. It does not need to be: `#stage.active` is `#000`, and
 * semi-transparent black over black is black. The layers vanish in exactly the
 * places where they would be wrong.
 *
 * The one thing that has to *brighten* is the phosphor punch, so that is a
 * `filter` on the canvas rather than a layer: a filter applies to what the
 * element paints, and the letterbox is not painted.
 *
 * Deleting this file leaves a working app with no filter.
 */

#crt-overlay {
  position: absolute;
  inset: 0;
  /* Above the canvas by z-index, not by document order. replaceCanvas()
     removes the canvas and appends a fresh one, which puts it *after* this
     element in the DOM — order-based stacking would then paint the game back
     over the filter on every second game. */
  z-index: 1;
  pointer-events: none;
  display: none;
}

body[data-crt] #crt-overlay { display: block; }
/* Scaled so small that a line has no room for a dark half and a light half.
   Drawing it anyway produces a grey wash, which is worse than nothing. */
body.crt-too-fine #crt-overlay { display: none; }

/* Two layers rather than one background with two gradients, so the scanline
   period (a property of the game) and the mask pitch (a property of the
   screen) stay independent of each other. */
#crt-overlay::before,
#crt-overlay::after {
  content: '';
  position: absolute;
  inset: 0;
}

/* ---- scanlines ----------------------------------------------------------
 *
 * The profile is a smooth ramp, not a hard bar. That is the single biggest
 * difference between this and the first cut: an electron beam has a falloff
 * either side of its centre, and a rectangular band reads as a window screen
 * rather than as a scanline. The stops are percentages of `--crt-period`, so
 * the shape holds at every resolution the core throws at it.
 *
 * `--crt-period` is one source line (see crt.js), and `--crt-offset` puts the
 * first band at the top edge of the *picture* rather than of the stage, so the
 * bands sit between the game's own pixel rows instead of drifting across them.
 */
#crt-overlay::before {
  background-image: linear-gradient(
    to bottom,
    rgba(0, 0, 0, var(--crt-beam, 0)) 0%,
    rgba(0, 0, 0, 0) 42%,
    rgba(0, 0, 0, 0) 58%,
    rgba(0, 0, 0, var(--crt-beam, 0)) 100%
  );
  background-size: 100% var(--crt-period, 3px);
  background-position: 0 var(--crt-offset, 0px);
  background-repeat: repeat;
}

/* ---- shadow mask --------------------------------------------------------
 *
 * Pitched in *device* pixels (`--crt-mask` is 3 ÷ devicePixelRatio), because a
 * phosphor mask belongs to the screen, not to the game. At the old 3 CSS px it
 * was 9 device pixels on a phone — visible as stripes, which is why the first
 * cut read as a fishnet over the picture rather than as a texture in it.
 *
 * A real aperture grille tints in red/green/blue, which means *brightening* —
 * and a brightening layer would show over the letterbox bars, which is the
 * whole thing this design avoids. Full level only.
 */
#crt-overlay::after {
  background-image: linear-gradient(
    to right,
    rgba(0, 0, 0, var(--crt-maskalpha, 0)) 0%,
    rgba(0, 0, 0, 0) 60%,
    rgba(0, 0, 0, 0) 100%
  );
  background-size: var(--crt-mask, 1px) 100%;
  background-repeat: repeat;
}

/* ---- the two levels -----------------------------------------------------
 *
 * `brightness` is the compensation for what the beam profile takes out. The
 * arithmetic says 1 ÷ (1 − 0.58 × beam); these are deliberately a little under
 * that, because CSS composites in sRGB rather than linear light and the full
 * correction clips highlights. A CRT was slightly dim anyway.
 */
body[data-crt='soft'] {
  --crt-beam: 0.26;
  --crt-maskalpha: 0;
}
body[data-crt='soft'] #canvas {
  filter: saturate(1.12) contrast(1.03) brightness(1.11);
}

body[data-crt='full'] {
  --crt-beam: 0.52;
  --crt-maskalpha: 0.16;
}
body[data-crt='full'] #canvas {
  filter: saturate(1.25) contrast(1.06) brightness(1.24);
}

/* ---- the toggle ---------------------------------------------------------
 * In the panel that hides with the rest of the chrome. */

/* Fixed width, not fit-to-content: the label changes with the level AND with
   the language, and #play-toolbar reserves this panel's lane by a hard-coded
   number. A panel that is 227px in Arabic and 255px in English makes that
   number a lie in one of them. */
#touch-crt-toggle {
  appearance: none;
  height: 30px;
  width: 52px;
  padding: 0;
  text-align: center;
  overflow: hidden;
  border-radius: 8px;
  border: 1px solid rgba(110, 118, 142, 0.5);
  background: rgba(23, 26, 34, 0.85);
  color: #8b93a7;
  font-family: var(--font-display, inherit);
  font-size: 9px;
  letter-spacing: 0.06em;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}
/* Two on-states, told apart by weight rather than by a number: soft is an
   outline, full is filled. */
#touch-crt-toggle[data-level='soft'] {
  color: #9ad2ff;
  border-color: rgba(120, 190, 255, 0.8);
}
#touch-crt-toggle[data-level='full'] {
  color: #0b0d12;
  background: rgba(120, 190, 255, 0.92);
  border-color: rgba(160, 215, 255, 0.9);
}
#touch-crt-toggle:active { transform: scale(0.94); }
