/* art.css — Art v1 §2, the pixel rendering standard.
 *
 * Its own stylesheet rather than a section of spine.css, for one practical reason:
 * it declares no global rules, so the disposable harness can link it and measure the
 * REAL shipped values without inheriting the app's identity. spine.css cannot be
 * loaded that way. Steps 5 (top bar) and 6 (ambient) extend this file.
 *
 * The whole standard is four numbers:
 *
 *   1 art px = 2 CSS px, INTEGER ONLY   (D2)
 *   1 tile   = 16 art px = 32 CSS px    (D2a)
 *   canvas   = 192 x 384 art px  ->  384 x 768 CSS  =  12 x 24 tiles
 *   safe zone= 160 x 352 art px, centered — a one-tile bleed on all four sides
 *
 * Two rules follow from those, and both are the reason this is a layer and not a
 * handful of magic numbers in a component:
 *
 *   - The scale never becomes fractional. A viewport that cannot hold the canvas
 *     letterboxes against cream and SCROLLS; it never shrinks the art to fit. A
 *     fractional scale is what destroys a pixel grid — half an art pixel cannot be
 *     drawn, so the browser invents a blend color and the hard edges go soft.
 *   - The one-tile bleed is what absorbs a too-narrow viewport. Anything the owner
 *     must be able to see or tap lives inside the safe zone, so clipping the bleed
 *     costs nothing. That is what the bleed is FOR.
 *
 * No coordinate here is a hit area. Hotspots are art-canvas pixels read from
 * meta/rooms/<room>.json (step 4) and multiplied by --art-scale — never hardcoded
 * in CSS, never measured off a finished image.
 */

:root {
  /* Integer only. A future density change edits THIS and nothing else — which is
     why every coordinate in meta/ is art-canvas px and never CSS px. */
  --art-scale: 2;

  /* One art pixel, as a CSS length. `calc(N * var(--art-px))` converts any
     art-canvas measurement into CSS with no per-site arithmetic. */
  --art-px: calc(var(--art-scale) * 1px);

  /* Art-canvas pixels — unitless on purpose, so they multiply cleanly above. */
  --art-tile: 16;
  --art-canvas-w: 192;
  --art-canvas-h: 384;
  --art-bar-h: 32;        /* the Gym top bar (A1) — reserved here, drawn in step 5 */
  --art-bleed: 16;        /* one tile of sacrificial edge on all four sides */
}

/* The cream field the canvas floats on. Off-aspect viewports letterbox against
   this — never a crop into the safe zone, never a fractional scale.
   `--tol-cream` comes from the skin's palette.css; the literal is the fallback
   until that file is wired up, and is already live as the app's `theme-color`. */
.art-stage {
  display: flex;
  align-items: center;
  justify-content: center;
  /* `safe` degrades to start-alignment instead of centering when the canvas is
     larger than the stage. Plain `center` would push the top-left overflow out of
     the scroll range, making it permanently unreachable — which IS cropping the
     safe zone, just by a subtler route. */
  align-items: safe center;
  justify-content: safe center;
  overflow: auto;
  background: var(--tol-cream, #f8f3e4);
}

/* The room canvas: exactly 192 x 384 art px, always. */
.art-canvas {
  /* `0 0 auto` is load-bearing, not boilerplate. A flex item shrinks by default,
     so without it a 375 px-wide viewport would quietly squeeze the canvas to 375
     and hand us a 1.953x scale — the exact failure this layer exists to prevent. */
  flex: 0 0 auto;
  position: relative;
  width: calc(var(--art-canvas-w) * var(--art-px));
  height: calc(var(--art-canvas-h) * var(--art-px));

  /* Hard pixel edges at 2x. Without this the browser smooths the upscale and every
     outline in the Style Bible turns to mush. */
  image-rendering: pixelated;

  background-color: var(--tol-cream, #f8f3e4);
  background-repeat: no-repeat;
  background-position: top left;
  /* The source is authored at exactly the canvas size, so 100% 100% IS the integer
     2x scale — it cannot stretch, because there is nothing to stretch. */
  background-size: 100% 100%;
}

/* ── Tap targets (step 4) ───────────────────────────────────────────────────
   Position and size are written as inline `calc(N * var(--art-px))` by
   artRoom.js, from meta/rooms/<room>.json. Deliberately NOT here: a hit area in
   this file would be a coordinate that outlived the art it was measured against,
   which is the failure the JSON seam exists to end.

   Invisible by design. The room art IS the UI — a target is the painted object it
   sits on, so anything drawn here would be a second, worse affordance on top. */
.art-hot {
  position: absolute;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  color: inherit;
  cursor: pointer;
  /* Above the base still and above the ambient layer, which is pointer-events:none
     (step 6). Motion can never move or swallow a hit area. */
  z-index: 2;
  -webkit-tap-highlight-color: transparent;
}

/* Press feedback only — no idle state, so the scene stays art rather than chrome. */
.art-hot:active { transform: scale(.97); }

.art-hot:focus-visible {
  outline: 2px solid var(--tol-terracotta, #c96f4a);
  outline-offset: -2px;
}

/* Proof surfaces only. Never rendered by the app — artRoom.js adds `bounds` solely
   when a harness asks, so hit areas can be SEEN to land where the JSON says. */
.art-hot.bounds {
  outline: 2px dashed var(--tol-terracotta, #c96f4a);
  outline-offset: -2px;
  background: rgba(201, 111, 74, .14);
}
