/* css/pet-room.css — THE ROOM (Pixel Pet).
   Contract: _specs/2026-08-01-pixel-pets-alive.md §6.

   EVERY selector is prefixed `.pet-room` so nothing can leak into the rest of
   the OS — this project has a documented history of specificity/leak bugs
   (.cc-pcard, the [hidden] traps). Keyframes are prefixed `pr-` for the same
   reason.

   Brutalist rules: 2px black outlines, hard offset shadows, no soft drop
   shadows, no rounded corners (the pet's ground shadow and the lamp glow are
   representational and therefore exempt), and no gradients except the
   CSS-generated wall/floor patterns.

   Motion: transform/opacity only, steps() on pixel art, reduced-motion kills
   everything. No per-frame box-shadow or filter — this runs on Chromebooks. */

.pet-room {
  --pr-wall-a:  #35244a;
  --pr-wall-b:  #3d2a54;
  --pr-wall-hi: rgba(255, 255, 255, 0.05);
  --pr-floor-a: #4a3524;
  --pr-floor-b: #543c29;
  --pr-seam:    rgba(0, 0, 0, 0.35);
  --pr-trim:    #1a0f28;
  --pr-rug-a:   #7a2547;
  --pr-rug-b:   #a3315d;
  --pr-sky:     #7fd4f5;
  --pr-tint:    255, 214, 140;
  --pr-tint-a:  0.05;
  --pr-lamp-a:  0;

  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 5 / 3;      /* a height set by the caller wins over this */
  min-height: 160px;
  overflow: hidden;
  background: var(--pr-wall-a);
  border: 2px solid #0a0a0a;
  box-shadow: 6px 6px 0 #05000a, inset 0 0 0 2px rgba(255, 82, 146, 0.35);
  contain: paint;
}

/* The [hidden] trap (CLAUDE.md gotchas #4 / #5b): an author `display` always
   beats the UA [hidden] rule, so state it explicitly. */
.pet-room [hidden] { display: none !important; }

.pet-room .pr-scene {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;   /* only .pr-hit opts back in */
}

/* ── wall ────────────────────────────────────────────────────────────────── */
.pet-room .pr-wall {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 56%;
  overflow: hidden;   /* décor and the window must never widen the scene box */
  /* Striped wallpaper, with the wainscot below the dado rail knocked down a
     shade. Hard colour stops — a pattern, not a gradient. */
  background:
    linear-gradient(to bottom, transparent 0 68%, rgba(0, 0, 0, 0.14) 68% 100%),
    repeating-linear-gradient(90deg,
      var(--pr-wall-a) 0 14px,
      var(--pr-wall-b) 14px 28px),
    var(--pr-wall-a);
}
/* A single hairline of light along the top of the wall — cheap, static, and
   it stops the band reading as a flat rectangle. */
.pet-room .pr-wall::before,
.pet-room .pr-wall::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  pointer-events: none;
}
.pet-room .pr-wall::before { top: 0; height: 3px; background: var(--pr-wall-hi); }
/* A dado rail two thirds down: one more static line, and the wall stops
   reading as a single flat rectangle. */
.pet-room .pr-wall::after {
  top: 68%; height: 5px;
  background: var(--pr-trim);
  border-top: 2px solid rgba(0, 0, 0, 0.4);
  border-bottom: 2px solid rgba(255, 255, 255, 0.06);
}

/* A drawn window: it motivates the light pool on the floor and gives the
   clock somewhere visible to happen. Pure CSS, no art file. */
.pet-room .pr-window {
  position: absolute;
  left: 63%; top: 14%;
  width: 21%; height: 52%;
  min-width: 34px;
  background: var(--pr-sky);
  border: 3px solid #0a0a0a;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.22);
  transition: background 900ms linear;
}
.pet-room .pr-window i,
.pet-room .pr-window b {
  position: absolute;
  display: block;
}
.pet-room .pr-window i {            /* vertical mullion */
  left: 50%; top: 0; bottom: 0;
  width: 3px; margin-left: -1.5px;
  background: #0a0a0a;
}
/* Horizontal mullion — a child of the WINDOW, so it can span it with 0/0
   insets. (Hanging it off `i` with ±1000px insets inflated the scene's
   scrollWidth by ~800px — clipped, but still real overflow.) */
.pet-room .pr-window::after {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 3px; margin-top: -1.5px;
  background: #0a0a0a;
}
.pet-room .pr-window b {            /* sun by day, moon at night */
  right: 12%; top: 10%;
  width: 22%; padding-bottom: 22%;
  background: #FFE79A;
  border: 2px solid rgba(0, 0, 0, 0.5);
  border-radius: 50%;               /* representational */
  transition: background 900ms linear, opacity 900ms linear;
}

/* When the art pack supplies a real window prop, the drawn one steps aside. */
.pet-room.pr-artwindow .pr-window { display: none; }

/* A pendant lamp over the pet's home spot. It is what the night glow comes
   from, so the light has a visible source instead of appearing from nowhere. */
.pet-room .pr-pendant {
  position: absolute;
  left: 48%; top: 0;
  width: 0; height: 0;
}
.pet-room .pr-pendant i {           /* cord */
  position: absolute;
  left: -1.5px; top: 0;
  width: 3px; height: 34px;
  background: #0a0a0a;
}
.pet-room .pr-pendant b {           /* shade */
  position: absolute;
  left: -19px; top: 32px;
  width: 38px; height: 20px;
  background: #6b5a86;
  border: 2px solid #0a0a0a;
  clip-path: polygon(26% 0%, 74% 0%, 100% 100%, 0% 100%);
  transition: background 900ms linear;
}

/* ── floor ───────────────────────────────────────────────────────────────── */
.pet-room .pr-floor {
  position: absolute;
  left: 0; right: 0; top: 56%; bottom: 0;
  overflow: hidden;   /* the light pool bleeds past the right edge on purpose */
  background:
    repeating-linear-gradient(0deg,
      transparent 0 17px,
      var(--pr-seam) 17px 19px),
    repeating-linear-gradient(90deg,
      var(--pr-floor-a) 0 46px,
      var(--pr-floor-b) 46px 92px),
    var(--pr-floor-a);
}

/* Window light spilling onto the boards. A flat parallelogram, not a gradient:
   it sits still and costs nothing. */
.pet-room .pr-lightpool {
  position: absolute;
  /* A shaft, not a wash: the top edge lines up with the drawn window
     (63–84% of the room) and leans left as it comes forward. */
  left: 50%; right: 0; top: -2%; bottom: 6%;
  background: rgb(255, 240, 200);
  opacity: 0.08;
  clip-path: polygon(26% 0%, 68% 0%, 56% 100%, 0% 100%);
  transition: opacity 900ms linear;
}

/* A rug marks the pet's home spot without adding an asset. */
.pet-room .pr-rug {
  position: absolute;
  left: 31%; right: 31%; top: 32%; height: 30%;
  background: repeating-linear-gradient(90deg,
    var(--pr-rug-a) 0 14px,
    var(--pr-rug-b) 14px 28px);
  border: 2px solid #0a0a0a;
  border-top-width: 0;
  clip-path: polygon(8% 0%, 92% 0%, 100% 100%, 0% 100%);
  opacity: 0.62;
}

/* The floor line — the hard brutalist seam where wall meets floor. */
.pet-room .pr-floorline {
  position: absolute;
  left: 0; right: 0; top: 56%;
  height: 8px; margin-top: -8px;
  background: var(--pr-trim);
  border-bottom: 3px solid #0a0a0a;
}

/* ── props ───────────────────────────────────────────────────────────────── */
.pet-room .pr-props {
  position: absolute;
  inset: 0;
  z-index: 2;
}
/* A prop is a one-cell window onto its sprite strip. left / bottom / width /
   height are set by layout() in js/pet-room.js. */
.pet-room .pr-prop {
  position: absolute;
  overflow: hidden;
  pointer-events: none;
}
.pet-room .pr-prop > img {
  position: absolute;
  left: 0; top: 0;
  image-rendering: pixelated;
  transform: translateX(0);
}
/* Multi-frame props step along the strip. Transform-only, so it stays on the
   compositor; steps() because choppy IS the aesthetic on pixel art. */
.pet-room .pr-prop.pr-strip > img {
  animation: pr-strip 1.1s steps(var(--pr-frames, 1)) infinite;
}
@keyframes pr-strip {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(-1 * var(--pr-strip, 0px))); }
}

/* ── the animal ──────────────────────────────────────────────────────────── */
.pet-room .pr-actor {
  position: absolute;
  width: 0; height: 0;
  z-index: 3;
  transform: translateX(0);
  transition-property: transform;
  transition-timing-function: linear;
  transition-duration: 0ms;   /* set per-walk by JS */
  will-change: transform;
}
.pet-room .pr-hop {
  position: absolute;
  left: 0; bottom: 0;
  width: 0; height: 0;
}
/* Spec §5: "caller positions it" — the sprite renderer sets no `position` of
   its own, so the ROOM must, or the `left`/`bottom` seating in layout() is
   silently ignored and the animal lands a whole sprite-height off the floor. */
.pet-room .pr-hop > * {
  position: absolute;
  image-rendering: pixelated;
}

/* Ground shadow: a static ellipse that shrinks as the pet lifts. */
.pet-room .pr-shadow {
  position: absolute;
  bottom: -2px;
  background: #000;
  opacity: 0.4;
  border-radius: 50%;          /* representational */
  transform: scale(1);
}

.pet-room .pr-hit {
  position: absolute;
  bottom: 0;
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  pointer-events: auto;
}
.pet-room .pr-hit:focus-visible {
  outline: 2px solid var(--accent, #C6F542);
  outline-offset: 2px;
}

/* ── "I want something" bubble ───────────────────────────────────────────────
   A real <button> above the pet's head, so a student who can't type `feed` yet
   can still care for their animal. Brutalist: flat fill, 2px black border, hard
   0-blur offset shadow, square corners — no soft shadow, no gradient. It rides
   `.pr-actor`, so it follows the pet as it walks. */
.pet-room .pr-want[hidden] { display: none; }
.pet-room .pr-want {
  position: absolute;
  left: 50%;
  padding: 0;
  width: 30px; height: 30px;
  line-height: 26px;
  font-size: 15px;
  text-align: center;
  background: #fffdf5;
  color: #0a0a0a;
  border: 2px solid #0a0a0a;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.55);
  cursor: pointer;
  z-index: 6;
  pointer-events: auto;
}
/* The bob is on the ICON, not the button: a target that never holds still is
   hard for a young student to hit (and automation refuses to click it). */
.pet-room .pr-wanti {
  display: block;
  animation: pr-want-pop 1.6s ease-in-out infinite;
}
/* The little tail that turns a box into a speech bubble. */
.pet-room .pr-want::after {
  content: '';
  position: absolute;
  left: 50%; top: 100%;
  width: 0; height: 0;
  margin-left: -5px;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-top: 7px solid #0a0a0a;
}
.pet-room .pr-want:hover  { background: var(--accent, #C6F542); }
.pet-room .pr-want:active { transform: translate(1px, 1px); box-shadow: 2px 2px 0 rgba(0,0,0,0.55); }
.pet-room .pr-want:focus-visible {
  outline: 2px solid var(--accent, #C6F542);
  outline-offset: 2px;
}
@keyframes pr-want-pop {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}

/* Idle breathing — 1px of life at a pixel-art cadence. steps(2), because
   choppy IS the aesthetic here (ASSET-FRAMEWORK §5). */
.pet-room.pr-breathe .pr-hop   { animation: pr-breathe 1.9s steps(2) infinite; }
.pet-room.pr-breathe .pr-shadow { animation: pr-shadowpulse 1.9s steps(2) infinite; }
@keyframes pr-breathe     { 0%, 100% { transform: translateY(0);    } 50% { transform: translateY(-2px); } }
@keyframes pr-shadowpulse { 0%, 100% { transform: scale(1);         } 50% { transform: scale(0.9);       } }

/* ── time of day ─────────────────────────────────────────────────────────── */
.pet-room .pr-tint {
  position: absolute;
  inset: 0;
  z-index: 4;
  background: rgb(var(--pr-tint));
  opacity: var(--pr-tint-a);
  transition: opacity 900ms linear, background 900ms linear;
}
/* Lamp spill at night, anchored under the pendant. A static radial glow whose
   OPACITY is the only thing that ever changes — never animated per frame. */
.pet-room .pr-lamp {
  position: absolute;
  left: 22%; top: 4%;
  width: 52%; height: 84%;
  z-index: 1;
  background: radial-gradient(ellipse at 50% 8%,
    rgba(255, 214, 140, 0.5) 0%,
    rgba(255, 214, 140, 0.16) 44%,
    rgba(255, 214, 140, 0) 72%);
  opacity: var(--pr-lamp-a);
  transition: opacity 900ms linear;
}

.pet-room[data-phase='dawn']    { --pr-tint: 255, 176, 168; --pr-tint-a: 0.13; --pr-sky: #ffb4a8; }
.pet-room[data-phase='day']     { --pr-tint: 255, 244, 214; --pr-tint-a: 0.04; --pr-sky: #7fd4f5; }
.pet-room[data-phase='dusk']    { --pr-tint: 255, 186, 110; --pr-tint-a: 0.14; --pr-sky: #ffc06e; }
.pet-room[data-phase='evening'] { --pr-tint:  92, 108, 214; --pr-tint-a: 0.24; --pr-sky: #2f3f8f; --pr-lamp-a: 0.55; }
.pet-room[data-phase='night']   { --pr-tint:  38,  46, 122; --pr-tint-a: 0.40; --pr-sky: #101a3c; --pr-lamp-a: 0.75; }

.pet-room[data-phase='evening'] .pr-lightpool,
.pet-room[data-phase='night'] .pr-lightpool { opacity: 0.02; }
.pet-room[data-phase='evening'] .pr-window b,
.pet-room[data-phase='night'] .pr-window b { background: #E8ECFF; }
/* The lamp is only ON when the glow is. */
.pet-room[data-phase='evening'] .pr-pendant b,
.pet-room[data-phase='night'] .pr-pendant b { background: #FFE79A; }

/* ── themes (wallpaper / floor variants) ─────────────────────────────────── */
.pet-room[data-theme='mint'] {
  --pr-wall-a: #1f4a44; --pr-wall-b: #26584f;
  --pr-floor-a: #3d3a2c; --pr-floor-b: #474433;
  --pr-rug-a: #146b63; --pr-rug-b: #1c8f83; --pr-trim: #0d2b28;
}
.pet-room[data-theme='candy'] {
  --pr-wall-a: #5a2350; --pr-wall-b: #6a2a5e;
  --pr-floor-a: #55384a; --pr-floor-b: #614055;
  --pr-rug-a: #b03a72; --pr-rug-b: #d4508c; --pr-trim: #2c0f27;
}
.pet-room[data-theme='lab'] {
  --pr-wall-a: #1b2a3a; --pr-wall-b: #213345;
  --pr-floor-a: #2b3946; --pr-floor-b: #334352;
  --pr-rug-a: #145a63; --pr-rug-b: #1b7d89; --pr-trim: #0d1721;
}
.pet-room[data-theme='sunny'] {
  --pr-wall-a: #6b5326; --pr-wall-b: #7a5f2d;
  --pr-floor-a: #6b4a2a; --pr-floor-b: #7a5632;
  --pr-rug-a: #a8541f; --pr-rug-b: #cc6a2a; --pr-trim: #2e2210;
}

/* ── narrow rooms (ResizeObserver classes, never @media — this is a window
       inside an OS, so the viewport is the wrong thing to measure) ───────── */
.pet-room.pr-narrow .pr-window { left: 66%; width: 24%; }
.pet-room.pr-narrow .pr-rug    { left: 20%; right: 20%; }
.pet-room.pr-short  .pr-rug    { display: none; }
.pet-room.pr-short  .pr-window { top: 10%; height: 58%; }

/* ── reduced motion: everything static, no walking, no drift ─────────────── */
@media (prefers-reduced-motion: reduce) {
  .pet-room .pr-actor { transition: none !important; }
  .pet-room *,
  .pet-room *::before,
  .pet-room *::after { animation: none !important; transition: none !important; }
}
/* Same rules under a class so the harness can exercise the static path. */
.pet-room.pr-rm .pr-actor { transition: none !important; }
.pet-room.pr-rm *,
.pet-room.pr-rm *::before,
.pet-room.pr-rm *::after { animation: none !important; transition: none !important; }
