/* SMAU FILE
 * Path: css/smau-residentWindow.css
 * Owns: THE VIDEO CALL (js/smau.residentWindow.js) — a live window onto
 * wherever a resident currently is. Full screen while you are watching it, a
 * draggable corner tile when you are not.
 *
 * IT IS A CALL, NOT A CAMERA (spec/RESIDENT-SPACES.md §0.1). The chrome is
 * deliberately video-call chrome: dark glass, a name bar, an end-call ✕.
 *
 * THE BUG THIS FILE WAS SHIPPED WITH (owner, 2026-07-29):
 *   "The x button to close the video does not work. Neither does the maximize."
 *   Both buttons were fine. `pointer-events` is an INHERITED property, and
 *   #smau-overlay-root is `pointer-events: none` so a closed overlay can never
 *   eat a tap. Every child inherits that unless it says otherwise — so the
 *   whole window, buttons and drag included, was invisible to the pointer.
 *   One declaration (`pointer-events: auto`, below) is the entire fix, and the
 *   suite now asserts a real hit-test rather than a synthetic .click().
 *   NOTE FOR THE NEXT PERSON: css/smau-mapsPip.css has the same shape and the
 *   same missing declaration — if the Maps PiP is ever reported as dead, this
 *   is why.
 *
 * FULL SCREEN FIRST (owner mandate, 2026-07-29). An answered video call fills
 * the phone. The corner tile is a thing you choose, and once chosen it is
 * genuinely draggable — so it must never be wider than a corner.
 *
 * ALL MOTION IN HERE IS FREE. Breathing, the slow room drift, the light grade,
 * the reconnect stutter — every one of them is CSS over a single still PNG.
 * Spec §4.1: a perfectly still figure reads as a game asset rather than a
 * person, and this is the fix that costs zero bytes and ships everywhere.
 *
 * Every animation here is disabled under prefers-reduced-motion. A person who
 * gets motion sick should still be able to see who they are talking to.
 */

#smau-resident-window {
  position: absolute;
  z-index: 250;
  display: none;
  flex-direction: column;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 16px;
  overflow: hidden;
  background: rgba(14, 16, 22, 0.96);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.5);
  cursor: grab;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  /* THE FIX. See the header — without this the window is a picture you cannot
     touch, because the overlay root it lives in is deliberately inert. */
  pointer-events: auto;
  animation: rwIn 220ms cubic-bezier(0.2, 0.9, 0.24, 1.02);
}
#smau-resident-window[data-state="open"] { display: flex; }
#smau-resident-window:active { cursor: grabbing; }

/* ── the two sizes ──────────────────────────────────────────────────────── */

/* MINI — a call you glanced at, parked in a corner and draggable. */
#smau-resident-window[data-mode="mini"] { width: 132px; }

/* FULL — the call itself. It is the whole phone, like every real one.
   `inset: 0` wins over any left/top the drag left behind because applyMode()
   clears those inline values on the way in. */
#smau-resident-window[data-mode="full"] {
  inset: 0;
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  cursor: default;
  background: #07080c;
  animation: rwFullIn 200ms cubic-bezier(0.2, 0.9, 0.24, 1.02);
}

/* A CALL SURFACE CAN OWN THE SCREEN AND PUT THIS BEHIND IT.
   SMAU.mindVoice draws the transcript and the buttons; this draws him. While
   the picture is full screen it sits UNDER that surface (which is transparent
   over it); minimised, the corner tile goes back on top, because a tile you
   cannot tap is not a tile. Its own furniture is hidden in that arrangement —
   two end-call buttons on one screen is a bug with a shortcut. */
#smau-resident-window[data-behind="true"][data-mode="full"] { z-index: 190; }
#smau-resident-window[data-chrome="off"][data-mode="full"] .rw-bar,
#smau-resident-window[data-chrome="off"][data-mode="full"] .rw-dock,
#smau-resident-window[data-chrome="off"][data-mode="full"] .rw-controls,
#smau-resident-window[data-chrome="off"][data-mode="full"] .rw-caption { display: none; }

@keyframes rwIn {
  from { opacity: 0; transform: scale(0.88) translateY(8px); }
  to { opacity: 1; transform: none; }
}
@keyframes rwFullIn {
  from { opacity: 0; transform: scale(1.03); }
  to { opacity: 1; transform: none; }
}

/* ── the scene ─────────────────────────────────────────────────────────── */

#smau-resident-window .rw-scene {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: #0b0d12;
}
#smau-resident-window[data-mode="mini"] .rw-scene { aspect-ratio: 3 / 4; }
/* Full screen: the picture takes everything the chrome does not. */
#smau-resident-window[data-mode="full"] .rw-scene { flex: 1 1 auto; min-height: 0; }

/* The room. A photograph if the author has one; the space's own two colours
   if not. A ROOM may degrade to a gradient without embarrassment — a PERSON
   may not, which is why there is no sprite fallback anywhere in this file
   (spec §10.1). */
#smau-resident-window .rw-bg {
  position: absolute;
  inset: -4%;
  background-size: cover;
  background-position: center;
  /* The drift is what stops a still room reading as a screenshot. */
  animation: rwDrift 38s ease-in-out infinite alternate;
}
@keyframes rwDrift {
  from { transform: scale(1.04) translate3d(-1%, 0, 0); }
  to   { transform: scale(1.08) translate3d(1%, -1%, 0); }
}

/* Time of day, over whatever the room is. */
#smau-resident-window .rw-light {
  position: absolute;
  inset: 0;
  mix-blend-mode: soft-light;
  opacity: 0.9;
  pointer-events: none;
}
#smau-resident-window[data-light="dawn"] .rw-light {
  background: linear-gradient(180deg, rgba(255, 214, 190, 0.55), rgba(120, 140, 190, 0.25));
}
#smau-resident-window[data-light="day"] .rw-light {
  background: linear-gradient(180deg, rgba(240, 246, 255, 0.42), rgba(200, 214, 235, 0.12));
}
#smau-resident-window[data-light="dusk"] .rw-light {
  background: linear-gradient(180deg, rgba(255, 178, 122, 0.45), rgba(88, 74, 120, 0.35));
}
#smau-resident-window[data-light="night"] .rw-light {
  background: linear-gradient(180deg, rgba(58, 74, 120, 0.5), rgba(10, 12, 24, 0.55));
}

#smau-resident-window .rw-weather { position: absolute; inset: 0; pointer-events: none; }

/* THE LAMP AT HIS END (immersion, owner ask B19). A phone propped on a table
   in a dark room is lit by one thing, and it is not the sun. At night the
   scene gets a soft off-centre pool of light so his side of the call reads as
   a ROOM at that hour rather than a photo with a filter over it. It is drawn
   from the same fact the light grade is (the clock), so it never claims
   anything that is not true. */
#smau-resident-window[data-light="night"] .rw-weather,
#smau-resident-window[data-light="dusk"] .rw-weather {
  background: radial-gradient(70% 48% at 72% 24%, rgba(255, 206, 150, 0.16), transparent 70%);
  animation: rwLamp 9s ease-in-out infinite alternate;
}
@keyframes rwLamp {
  from { opacity: 0.75; }
  to   { opacity: 1; }
}

/* ── him ───────────────────────────────────────────────────────────────── */

/* THE FRAMING WRAPPER — this is what centres his head.
   Every sprite carries its own head anchor (--rw-hx, --rw-hy, normalized to
   the image) because emotion packs are framed inconsistently: one is a full
   body, the next is cropped at the waist, the next has the figure off to one
   side. The wrapper is positioned so that anchor lands on the SAME point of
   the frame every time (--rw-tx/--rw-ty), which is why swapping the mood
   changes the expression without the face jumping.

   The trick that makes it possible in pure CSS: percentages inside a
   `transform: translate()` resolve against the ELEMENT'S OWN box, so
   `translate(-42%, -18%)` means "42% of this image's width" — exactly the
   units a head anchor is stored in. `left`/`top` percentages resolve against
   the container. Two different reference boxes, which is the whole reason
   this needs a wrapper element rather than living on the <img>.

   A CALL IS A HEAD, IN BOTH SIZES (owner mandate, 2026-07-29: "only that
   section should show when doing a video call… its showing me the entire sprite
   when in full screen mode and still too much of the sprite when in mini
   mode"). That is why the figure is sized off the frame's HEIGHT (--rw-fill,
   the drawn height as a multiple of the frame's) rather than its width: a
   width multiple crops differently in a 3:4 tile than in a tall phone frame,
   which is exactly the two symptoms above. js/smau.residentWindow.js computes
   the number, from the author's crop when there is one and from the sprite's
   own measured silhouette when there is not. */
#smau-resident-window .rw-figure {
  --rw-hx: 0.5;
  --rw-hy: 0.18;
  --rw-fill: 1;
  --rw-tx: 0.5;
  --rw-ty: 0.34;
  position: absolute;
  left: calc(var(--rw-tx) * 100%);
  top: calc(var(--rw-ty) * 100%);
  height: calc(var(--rw-fill) * 100%);
  width: auto;
  transform: translate(calc(var(--rw-hx) * -100%), calc(var(--rw-hy) * -100%));
  pointer-events: none;
}
#smau-resident-window .rw-figure .rw-sprite {
  width: auto;
  height: 100%;
  max-width: none;
}

/* A VISIT IS FRAMED DIFFERENTLY (owner mandate, 2026-07-29): standing in a
   room with someone you see the WHOLE of them against the room, not a cropped
   head. Same picture, same anchors — the head anchor still centres him
   horizontally, and the figure is stood on the floor of the frame. Height is
   what is constrained here, not width, or a tall sprite would run off the top
   of a full-screen scene. */
#smau-resident-window[data-framing="body"] .rw-figure {
  width: auto;
  height: 96%;
  /* No width clamp: height is the constraint here. Clamping to the frame's
     width shrank any wide sprite until the figure inside it was a fraction of
     the room ("Kyung looks very small during a visit") — the scene's own
     overflow:hidden crops the sides instead, and the head anchor keeps him
     centred. */
  max-width: none;
  left: calc(var(--rw-tx) * 100%);
  top: auto;
  bottom: 0;
  transform: translate(calc(var(--rw-hx) * -100%), 0);
}
#smau-resident-window[data-framing="body"] .rw-sprite {
  width: auto;
  height: 100%;
  max-width: none;
}

#smau-resident-window .rw-sprite {
  display: block;
  transform-origin: 50% 100%;
  /* Breathing. Under four seconds and barely one percent — at this size the
     reader never consciously sees it and always feels it. It lives on the
     <img> so it composes with the wrapper's framing instead of fighting it. */
  animation: rwBreathe 4.6s ease-in-out infinite;
  filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.45));
}
@keyframes rwBreathe {
  0%, 100% { transform: scaleY(1) translateY(0); }
  50%      { transform: scaleY(1.012) translateY(-0.4%); }
}

/* Asleep breathes slower and deeper; pacing never sits still. */
#smau-resident-window[data-activity="sleeping"] .rw-sprite { animation-duration: 7.5s; }
#smau-resident-window[data-activity="pacing"] .rw-sprite  { animation-duration: 3.1s; }

/* A HAND-HELD CALL SHAKES (immersion, owner ask B19). Only while he is
   genuinely `travelling` — a van has a road under it — and never on a visit,
   where nobody is holding a phone. */
#smau-resident-window[data-activity="travelling"] .rw-scene {
  animation: rwSway 3.4s ease-in-out infinite alternate;
}
#smau-resident-window[data-framing="body"] .rw-scene { animation: none; }
@keyframes rwSway {
  from { transform: translate3d(-0.5%, 0.2%, 0) rotate(-0.25deg); }
  to   { transform: translate3d(0.5%, -0.2%, 0) rotate(0.25deg); }
}

/* A substituted sprite (the mood had no picture of its own, so the fallback
   chain found a neighbour) is held a shade flatter. A card with ONE picture
   should not appear to be acting out twelve moods. */
#smau-resident-window[data-exact="false"] .rw-sprite { filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.45)) saturate(0.94); }

#smau-resident-window .rw-vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 35%, transparent 45%, rgba(0, 0, 0, 0.5) 100%);
}

/* ── somewhere you may not see ─────────────────────────────────────────── */

/* visible:false is a STORY BEAT, not a missing asset (spec §2.4). So the room
   is not invented and the figure is not shown — it says so, in his voice. */
#smau-resident-window .rw-offair {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 10px;
  text-align: center;
  background: rgba(8, 9, 13, 0.94);
}
#smau-resident-window[data-visible="false"] .rw-offair { display: flex; }
#smau-resident-window[data-visible="false"] .rw-figure,
#smau-resident-window[data-visible="false"] .rw-bg,
#smau-resident-window[data-visible="false"] .rw-light { visibility: hidden; }
#smau-resident-window .rw-offair-text {
  font-size: 11px;
  line-height: 1.4;
  color: rgba(235, 238, 245, 0.62);
  letter-spacing: 0.01em;
}
#smau-resident-window[data-mode="full"] .rw-offair-text { font-size: 15px; max-width: 22ch; }

/* ── the heads-up display: his side of the line, and the clock ──────────── */

#smau-resident-window .rw-hud {
  position: absolute;
  top: 7px;
  left: 8px;
  display: flex;
  align-items: center;
  gap: 7px;
  pointer-events: none;
  font-size: 9px;
  letter-spacing: 0.02em;
  color: rgba(236, 241, 250, 0.85);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
}
#smau-resident-window[data-mode="full"] .rw-hud { top: 14px; left: 14px; font-size: 11px; }

/* Three bars. They only ever report something true: "moving" while he really
   is travelling, "camera off" where the reader may not see him. Anything else
   simply shows full bars and no words (CLAUDE.md: never fake social proof). */
#smau-resident-window .rw-net { display: inline-flex; align-items: flex-end; gap: 1.5px; }
#smau-resident-window .rw-net i {
  display: block;
  width: 2.5px;
  border-radius: 1px;
  background: rgba(255, 255, 255, 0.9);
}
#smau-resident-window .rw-net i:nth-child(1) { height: 4px; }
#smau-resident-window .rw-net i:nth-child(2) { height: 7px; }
#smau-resident-window .rw-net i:nth-child(3) { height: 10px; }
#smau-resident-window .rw-net[data-level="weak"] i:nth-child(3) { background: rgba(255, 255, 255, 0.22); }
#smau-resident-window .rw-net[data-level="off"] i { background: rgba(255, 255, 255, 0.22); }
#smau-resident-window .rw-net[data-level="weak"] { animation: rwBarsFlicker 2.6s ease-in-out infinite; }
@keyframes rwBarsFlicker {
  0%, 62%, 100% { opacity: 1; }
  70%, 78% { opacity: 0.45; }
}
#smau-resident-window .rw-net-label { margin-left: 3px; opacity: 0.8; }
#smau-resident-window .rw-net-label:empty { display: none; }

#smau-resident-window .rw-timer {
  font-variant-numeric: tabular-nums;
  opacity: 0.9;
}
#smau-resident-window .rw-timer[data-on="false"] { display: none; }

/* ── A FEED IS NOT A CALL (js/smau.videoFeed.js, owner ask I5) ───────────── */

/* A call has a clock, because a call is a thing you are both spending. A feed
   has a LIVE chip, because it is simply on — there is no elapsed anything and
   nobody on the other end is waiting for you. */
#smau-resident-window .rw-live { display: none; }
#smau-resident-window[data-feed="true"] .rw-live {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 6px 1px 5px;
  border-radius: 999px;
  background: rgba(255, 59, 48, 0.22);
  border: 1px solid rgba(255, 99, 90, 0.55);
  font-size: 8.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: #ffd9d5;
}
#smau-resident-window[data-feed="true"] .rw-live::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #ff453a;
  animation: rwLive 2s ease-in-out infinite;
}
#smau-resident-window[data-feed="true"][data-mode="full"] .rw-live { font-size: 10px; padding: 2px 8px 2px 7px; }
@keyframes rwLive {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.35; }
}
/* A feed's clock is hidden even if a caller left one behind. */
#smau-resident-window[data-feed="true"] .rw-timer { display: none; }

/* The one sentence that keeps a feed honest: what you get, and what you do
   not. Only ever shown in the full frame — at 132px it would crowd out the
   room name, which is the thing a corner tile exists to show. */
#smau-resident-window .rw-feednote { display: none; }
#smau-resident-window[data-feed="true"][data-mode="full"] .rw-feednote[data-on="true"] {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-style: italic;
  color: rgba(214, 222, 240, 0.62);
}

/* Stopping a feed is not hanging up on anyone, so it is not the red button. */
#smau-resident-window[data-feed="true"] .rw-dock-end .rw-dock-ico { background: rgba(255, 255, 255, 0.13); }
/* …and the way INTO a conversation only exists on a feed. */
#smau-resident-window .rw-dock-call { display: none; }
#smau-resident-window[data-feed="true"] .rw-dock-call { display: flex; }
#smau-resident-window[data-feed="true"] .rw-dock-call .rw-dock-ico { background: #30d158; }

/* ── the caller's own status line, and what is being said ───────────────── */

#smau-resident-window .rw-note {
  position: absolute;
  left: 0;
  right: 0;
  top: 42%;
  text-align: center;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: rgba(232, 238, 250, 0.9);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.85);
  pointer-events: none;
}
#smau-resident-window .rw-note[data-on="false"] { display: none; }
#smau-resident-window[data-mode="full"] .rw-note { font-size: 15px; }

/* The line he is saying right now, over his picture. Full screen only: at
   132px a caption is unreadable, and an unreadable caption is worse than the
   scrollback the call surface already keeps. */
#smau-resident-window .rw-caption {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 10px;
  padding: 8px 11px;
  border-radius: 12px;
  background: rgba(6, 8, 13, 0.72);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-size: 14px;
  line-height: 1.4;
  color: rgba(246, 249, 255, 0.97);
  pointer-events: none;
}
#smau-resident-window .rw-caption[data-on="false"] { display: none; }
/* MINIMISED, and he is still talking (owner ask 2026-07-31: "if the call is
   minimized and hes speaking but I'm browsing the phone make sure the subtitles
   are popping on my phone the way they do in the monty money call"). The line
   can't live INSIDE the 132px tile — it's unreadable there — so it breaks out
   ABOVE the tile as a wide, legible subtitle pill that floats over whatever app
   you're in. It reads right-to-left off the tile's right edge so it never runs
   off-screen when the tile is docked to a corner. */
#smau-resident-window[data-mode="mini"] .rw-caption[data-on="true"] {
  display: block;
  position: absolute;
  left: auto;
  right: 0;
  bottom: calc(100% + 8px);
  width: max-content;
  max-width: 68vw;
  padding: 9px 12px;
  font-size: 13.5px;
  background: rgba(6, 8, 13, 0.86);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  animation: rwCaptionPop 0.18s ease-out;
}
@keyframes rwCaptionPop {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  #smau-resident-window[data-mode="mini"] .rw-caption[data-on="true"] { animation: none; }
}

/* HE MOVED ROOMS MID-CALL. The picture drops for a beat and comes back
   somewhere else — the one connection cue this file can show with a straight
   face, because it only ever fires when his whereabouts really changed. */
#smau-resident-window .rw-hiccup {
  position: absolute;
  inset: 0;
  display: none;
  align-items: center;
  justify-content: center;
  background: rgba(6, 7, 11, 0.86);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: rgba(220, 228, 244, 0.8);
  pointer-events: none;
}
#smau-resident-window[data-hiccup="true"] .rw-hiccup { display: flex; }
#smau-resident-window[data-hiccup="true"] .rw-scene { animation: rwStutter 1.1s steps(4, end) 1; }
@keyframes rwStutter {
  0%, 100% { filter: none; }
  20% { filter: blur(2px) contrast(1.2); }
  55% { filter: blur(4px) saturate(0.6); }
  80% { filter: blur(1px); }
}

/* ── the call bar ──────────────────────────────────────────────────────── */

#smau-resident-window .rw-bar {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 30px 7px 9px;
  background: rgba(10, 12, 17, 0.98);
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
#smau-resident-window[data-mode="full"] .rw-bar {
  padding: 10px 14px 8px;
  align-items: center;
  text-align: center;
  background: rgba(8, 10, 15, 0.99);
}
#smau-resident-window .rw-name {
  font-size: 11px;
  font-weight: 650;
  color: rgba(244, 246, 252, 0.95);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* THE LINE HAS TO BE READABLE AT 132px (owner ask, 2026-07-29: "his
   apartment/sleeping needs to be more legible in the minimized mode maybe make
   it a marquee scroll"). The run swings left, waits, swings back — a one-way
   marquee spends half its cycle showing blank space, and a reader who glances
   at the wrong moment sees nothing at all. It only animates when the text
   genuinely overflows, measured in JS, and only in the corner tile. */
#smau-resident-window .rw-line {
  display: block;
  position: relative;
  font-size: 9.5px;
  color: rgba(210, 218, 235, 0.58);
  white-space: nowrap;
  overflow: hidden;
}
#smau-resident-window .rw-line-run {
  display: inline-block;
  white-space: nowrap;
  will-change: transform;
}
#smau-resident-window .rw-line[data-scroll="on"] .rw-line-run {
  animation: rwMarquee var(--rw-marquee-dur, 7s) ease-in-out infinite alternate;
}
@keyframes rwMarquee {
  0%, 14%   { transform: translateX(0); }
  86%, 100% { transform: translateX(calc(-1 * var(--rw-marquee-dist, 0px))); }
}
#smau-resident-window[data-mode="full"] .rw-name { font-size: 15px; }
#smau-resident-window[data-mode="full"] .rw-line { font-size: 11.5px; }

/* ── controls ──────────────────────────────────────────────────────────── */

/* The corner tile's two little glass buttons. Full screen has the dock
   instead — a 22px ✕ is not how you hang up a call you are watching. */
#smau-resident-window .rw-controls {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  gap: 4px;
  pointer-events: auto;
}
#smau-resident-window[data-mode="full"] .rw-controls { top: 12px; right: 12px; }
#smau-resident-window .rw-btn {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(8, 10, 16, 0.6);
  color: rgba(240, 244, 252, 0.85);
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
  pointer-events: auto;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
#smau-resident-window[data-mode="full"] .rw-btn { width: 30px; height: 30px; font-size: 14px; }
#smau-resident-window .rw-btn:hover { background: rgba(20, 24, 34, 0.85); }
#smau-resident-window .rw-btn:focus-visible { outline: 2px solid rgba(140, 180, 255, 0.9); outline-offset: 1px; }
#smau-resident-window .rw-size::before { content: "⤢"; }
#smau-resident-window[data-mode="full"] .rw-size::before { content: "⤡"; }
#smau-resident-window .rw-close { background: rgba(120, 22, 32, 0.72); }
#smau-resident-window .rw-close:hover { background: rgba(160, 30, 42, 0.9); }

/* THE DOCK — a full-screen call's real controls, thumb-sized and at the
   bottom where a phone puts them. Hidden entirely in the corner tile. */
#smau-resident-window .rw-dock {
  display: none;
  gap: 26px;
  justify-content: center;
  padding: 12px 16px calc(18px + env(safe-area-inset-bottom, 0px));
  background: rgba(8, 10, 15, 0.99);
  pointer-events: auto;
}
#smau-resident-window[data-mode="full"] .rw-dock { display: flex; }
#smau-resident-window .rw-dock-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  border: 0;
  padding: 0;
  background: none;
  color: rgba(232, 238, 250, 0.8);
  font-size: 10px;
  letter-spacing: 0.03em;
  cursor: pointer;
  pointer-events: auto;
}
#smau-resident-window .rw-dock-ico {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.13);
  font-size: 20px;
  line-height: 1;
  color: #fff;
}
#smau-resident-window .rw-dock-end .rw-dock-ico { background: #ff453a; }
#smau-resident-window .rw-dock-btn:focus-visible { outline: 2px solid rgba(140, 180, 255, 0.9); outline-offset: 3px; border-radius: 12px; }

/* ── reduced motion ────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  #smau-resident-window,
  #smau-resident-window .rw-bg,
  #smau-resident-window .rw-scene,
  #smau-resident-window .rw-weather,
  #smau-resident-window .rw-net,
  #smau-resident-window .rw-line-run,
  #smau-resident-window .rw-sprite {
    animation: none;
  }
  /* The framing transform stays — that is layout, not motion. Only the
     breathing is dropped. */
  #smau-resident-window .rw-sprite { transform: none; }
  /* A marquee that cannot move must not hide the half it cannot show. */
  #smau-resident-window .rw-line { text-overflow: ellipsis; }
}
