/* Sill — the whole stylesheet.
 *
 * Palette inverted from the Pact (which is a light vellum document; this is a dark
 * room). The correction that matters: the cat is a *black* cat read against window
 * light, so the cat is the darkest thing on the page and the window is the only
 * bright one. Vellum is the moonlight, never the cat.
 *
 * Oxblood is declared and deliberately unspent in Epic 1 — the Pact spends it
 * exactly three times and that discipline carries over. */

:root {
  --night:    #14100c;  /* the ground; darker than irongall so the room can sit above it */
  --irongall: #2b2117;  /* walls and floor */
  --tarnish:  #7a7365;  /* the sill, and the floor edge */
  --vellum:   #dcd3be;  /* window light — the only bright thing on the page */
  --cat:      #0a0806;  /* the silhouette: the darkest thing in the room */
  --oxblood:  #6e1512;  /* reserved */

  --pane-top: #4a4436;
  --pane-bottom: #2f2b22;
  --spill: rgba(220, 211, 190, 0.10);

  --breath: 0;  /* driven by requestAnimationFrame in sill.js */
  --tail: 0;
  --breath-amp: 0.018;   /* deepens while she is scratching it */
}

/* Daylight: the window is brighter and warmer, the room lifts a little. Nothing
 * here ever exceeds vellum. */
body.light-day, body.light-day-shifted {
  --pane-top: #cfc6ac;
  --pane-bottom: #9c937c;
  --spill: rgba(220, 211, 190, 0.22);
  --irongall: #35291d;
}
body.light-dusk {
  --pane-top: #6d5f45;
  --pane-bottom: #3a3326;
  --spill: rgba(220, 211, 190, 0.14);
}

* { box-sizing: border-box; }

/* An author `display` beats the UA stylesheet's `[hidden] { display: none }`, so
 * `.shelf` and `.reader` — both of which set display — painted over the room the
 * moment the attribute was the only thing hiding them. Without this the room is a
 * black screen whenever the script has not run yet. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  /* The wall. Painted here rather than as a rect in the room SVG so the letterbox
     bands `meet` leaves are the same colour as the room and the fit is invisible. */
  background: var(--irongall);
  height: 100%;
  overscroll-behavior: none;   /* no rubber-band revealing white behind the page */
}

body {
  /* 100dvh with a 100vh fallback — iOS Safari's toolbar makes 100vh lie (§9) */
  min-height: 100vh;
  min-height: 100dvh;
  overflow: hidden;            /* the room never scrolls */
  color: var(--vellum);
  font: 400 1rem/1.6 ui-serif, Georgia, "Times New Roman", serif;
  -webkit-font-smoothing: antialiased;
  /* Nothing sits under the notch or the home indicator (§9) */
  padding:
    env(safe-area-inset-top) env(safe-area-inset-right)
    env(safe-area-inset-bottom) env(safe-area-inset-left);
}

.scene {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
}

.room, .cat {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}

/* --- the room ------------------------------------------------------------ */

.glass  { stroke: none; }
.pane-top    { stop-color: var(--pane-top); }
.pane-bottom { stop-color: var(--pane-bottom); }
.mullion { stroke: var(--night); stroke-width: 3; }
.spill  { fill: var(--spill); }
.sill   { fill: var(--tarnish); opacity: 0.55; }
.sill-shadow { fill: var(--night); opacity: 0.6; }
.floor  { stroke: var(--tarnish); stroke-width: 1; opacity: 0.28; }

/* --- the cat -------------------------------------------------------------- */

.cat path {
  fill: var(--cat);            /* near-black: a silhouette against the window */
}

.cat {
  /* No selection callout, no magnifier, no save sheet when she holds it (§9). */
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  /* Taps fall through to the targets in the furniture layer. Epic 4 gives the cat
     its own gesture; until then it is something to look at, not something to press. */
  pointer-events: none;
}

/* Breathing and tail, both driven by custom properties so one rAF loop moves
 * everything and there is nothing running when that loop is stopped. */
.cat-body {
  transform-box: fill-box;
  transform-origin: 50% 100%;  /* the cat rises off the sill, it does not float */
  transform: scaleY(calc(1 + var(--breath) * var(--breath-amp)))
             rotate(calc(var(--tail) * 0.35deg));
}

/* Two things move the whole cat, so both go through custom properties rather than
 * fighting over the same `transform`: which way it faces, and how near it is. */
.cat {
  transform-origin: 50% 100%;      /* it grows off the sill, it does not float */
  transform: scaleX(var(--face, 1)) scale(var(--near, 1));
  transition: transform 900ms cubic-bezier(.22,.61,.36,1);
}

/* Just come in and ignoring her, or a week away and aloof for one visit.
 * Mirrored rather than redrawn: the same silhouette, turned away. */
body.facing-away { --face: -1; }

/* She called it and it came (§7). Nearer, and nothing else — no bounce, no sound,
 * no acknowledgement. Scaling about the sill reads as approach without motion blur. */
body.called { --near: 1.09; }

/* Her thumb is on its head and it has settled under it (§8). The breath slows in
 * sill.js and deepens here; nothing else changes, and nothing makes a sound — the
 * purr is Phase 2 (§11, §15) and there is deliberately nothing to un-mute. */
body.scratching { --breath-amp: 0.036; }

/* An open window: the night comes in a little. One value, no new geometry — §10
 * allows the room to be implied and forbids decorating it. */
body.window-open { --pane-top: #2f2b22; --pane-bottom: #14100c; }

/* --- text ----------------------------------------------------------------- */

.line {
  position: absolute;
  left: 50%;
  bottom: 22%;
  transform: translateX(-50%);
  margin: 0;
  max-width: 26ch;
  text-align: center;
  color: var(--tarnish);
  font-size: 0.95rem;
  letter-spacing: 0.01em;
}

body.unknown .line { bottom: 50%; transform: translate(-50%, 50%); }

/* --- touch only (§9) -----------------------------------------------------
 * Every affordance must be discoverable and operable by touch alone, so this
 * stylesheet declares no pointer-hover state anywhere. tools/lint.js fails the
 * build if one is ever introduced. */

/* --- reduced motion ------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* The loop is not started at all in sill.js; this is the belt to that braces.
   * Poses cross-fade instead of moving (§9). */
  .cat-body { transform: none !important; }
  .cat { transition: opacity 900ms ease-in-out; }
  .naming { transition: opacity 900ms ease-in-out; }
}

/* --- what the cat brought ------------------------------------------------- */

.furniture {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;   /* only the sill target below takes touches */
}

.object { fill: var(--cat); }       /* on the sill: a silhouette against the window */

/* `ring`, `bead` and the key's bow are drawn as an outer and an inner arc. Both run
 * the same sweep direction, so the default nonzero rule fills the counter in and a
 * ring renders as a plain disc — which is what it did. */
.object path { fill-rule: evenodd; }

/* On the shelf there is no window to be silhouetted against, so the same near-black
 * was invisible on the near-black ground. Here she is examining a thing rather than
 * seeing a shape against light, so it takes a tone of its own — still well under the
 * window's brightness (§9). */
.shelf .object, .reader .object { fill: var(--tarnish); }

.sill-target, .room-target, .window-target, .head-target, .bowl-target {
  fill: transparent;
  pointer-events: auto;
  -webkit-tap-highlight-color: transparent;
}
