/* The room. Cycle 35, design-11.

   IT COVERS THE SCENE, THE WAY THE ASK VIEW DOES, AND THAT IS A DECISION WITH A COST THAT CYCLE 36
   INHERITS. The first draft of this file said the opposite — *a panel over the street, so a person
   can see who is drawn and read what was said* — and the screenshot said otherwise, which is
   design-09 §1.3's failure (a caption that outlived its drawing) caught by looking.

   A BOTTOM SHEET WOULD NOT HAVE FIXED IT EITHER, which is why this is a cost rather than a bug.
   Viewer figures stand on the ground, at roughly 0.78 to 0.88 down the stage — the bottom fifth of
   the frame. Any sheet tall enough to hold a conversation covers exactly the band the people are
   drawn in, so *covering the scene* and *a sheet over the scene* are the same picture here.

   THE COST IS design-11 §5.1's, AND IT IS NOT DUE YET. That section says a bubble is how a person
   can see §4's anonymity rule working WITHOUT BEING TOLD IT — *the drawing teaches the rule*. A
   bubble is drawn on a figure in the scene, and while this is open there is no scene to draw it
   on. Cycle 35 has no bubbles and no messages, so nothing is lost today; **cycle 36 is where it
   has to be answered**, and the answer is not obviously a layout change — it may be that a bubble
   is for the person who is NOT in the room, which is a different and smaller claim than §5.1's.

   NOTHING IN HERE DRAWS A COUNT, A MEMBER LIST, AN AVATAR, A TIMESTAMP OR A BUBBLE, and every one
   of those is a rule rather than a thing not got round to yet:

     - a count (§5.3)      two numbers on one screen wearing one label
     - a bubble (§7)       a bubble is a claim that somebody spoke, and nobody has
     - an avatar or a name the room is anonymous until somebody speaks (§4), and cycle 35 has
                           nobody speaking, so it has nobody named

   There is no CSS here for any of them, which is the cheapest way to keep them out. */

.room {
  position: absolute;
  /* Below the chrome for the ask view's reason, measured the same way: the way back must stay as
     legible under this as it is everywhere else (design-01 §4.3). */
  inset: var(--chrome-h, 62px) 0 0 0;
  z-index: 34;
  display: flex;
  flex-direction: column;
  /* OPAQUE, AND THE ASK VIEW'S 93% WASH IS WHAT THIS IS A CORRECTION TO. The first build reused
     `--companion-bg` — ink at 93% — which reads as a deliberate dimming of the STREET and reads as
     a fault over the LIST, where the room is opened from on a keyboard (§6.3): cream rows, dark
     headings and the door's own pill all printed faintly through the panel, including a control
     offering to open the room the reader was already in.
     Found by looking at the screenshot, which is the only instrument that could have found it —
     every assertion in the test passed. */
  background: var(--ink);
  color: var(--canvas);
  animation: companion-in .22s ease both;
}

.room[hidden] { display: none; }

/* The street is inert behind it, exactly as it is behind the ask view and the record. */
body[data-room="true"] .foot-bar,
body[data-room="true"] .add-memory,
body[data-room="true"] .sign-in,
body[data-room="true"] .companion-host { display: none; }

.room-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px 8px;
}

.room-place { min-width: 0; }

/* HOW MANY ARE IN THIS ROOM — review round 1, and it is set as a SUBTITLE rather than as a badge.

   A pill or a dot beside the name would be a notification's grammar, and this is not one: it is a
   fact about the room you are standing in, in the register the chrome's own subtitle uses one bar
   up. design-11 §5.3 refused a count because two numbers wearing one label is a failure this repo
   has met before — so the words carry the set they count (*in this room*, against the list's
   *have this scene open*), and the styling is deliberately not the kind that shouts a number. */
.room-here {
  margin: 2px 0 0;
  font: 400 9.5px/1.3 var(--font-mono);
  letter-spacing: .09em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .55);
}

.room-here[hidden] { display: none; }

/* THE PLACE, AND IT IS THE ONLY THING THE HEAD CARRIES. A subtitle would have to say something
   about the room, and everything true about this room today is in the empty line below. */
.room-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: .01em;
}

.room-leave {
  flex: 0 0 auto;
  min-height: var(--tap-min);
  padding: 0 14px;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, .12);
  color: var(--canvas);
  font-family: inherit;
  font-size: 13px;
  letter-spacing: .04em;
  cursor: pointer;
}

.room-leave:hover { background: rgba(255, 255, 255, .2); }

/* ------------------------------------------------------------------------- the room's bubble

   REVIEW ROUND 1, 2026-09-11. There used to be a `.room-brought-in` line here — the first thing
   inside a room B had not asked to be in. The human tested the door on two devices and said the
   room filling their screen was weird, which it was, and design-11 §2.1's *B's app opens it too*
   is reversed: a tap raises this, and B goes in by tapping it.

   BOTTOM LEFT, ABOVE THE FOOT BAR, and every side of that is somebody else's. mkv's bubble owns
   the top left (app.css `.companion`), `add-memory` owns the bottom right, and the chrome owns
   the top. It is also the right corner on its own merits: this bubble is about the people drawn
   on the ground, and the ground is the bottom of the frame.

   NOT §5's BUBBLE. That one sits ON A FIGURE and means *this person has spoken*. This is chrome,
   it is about a ROOM, and it is a control — so it gets a control's affordances, which §5's must
   never have. */
.room-bubble-host {
  position: absolute;
  inset: 0;
  z-index: 38;
  pointer-events: none;
}

.room-bubble-host[hidden] { display: none; }

.room-bubble {
  pointer-events: auto;
  position: absolute;
  left: 12px;
  /* IT SITS ABOVE WHATEVER THE BOTTOM-LEFT ALREADY HAS, AND A TEST FOUND OUT THE HARD WAY.

     `.sign-in` occupies exactly this spot — `left: 12px; right: 12px; bottom: calc(--foot-bar-h +
     14px)` at z-index 39 — so for a SIGNED-OUT viewer the first build put the bubble underneath
     the Google button. Playwright could not click it and said so; a person would have tapped the
     sign-in.

     THAT IS WORSE THAN A LAYOUT BUG AND IT IS WHY THE LIFT IS MEASURED RATHER THAN GUESSED.
     `design-07` §9 forbids presence being *"a conversion lever, and never a reason to sign in"*,
     and the one person most likely to be knocked is a guest (§9 again: guest and resident are
     identical). A knock whose only visible affordance is a sign-in button is that rule failing in
     the most direct way available. `--room-bubble-lift` is set by app.js from the sign-in block's
     own height, so the bubble clears whatever is actually there rather than what was there when
     this was written. */
  bottom: calc(var(--foot-bar-h, 58px) + 14px + var(--room-bubble-lift, 0px));
  max-width: min(300px, calc(100% - 24px));
  min-height: var(--tap-min);
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  text-align: left;
  padding: 9px 13px 10px;
  border: 0;
  border-radius: var(--radius);
  background: var(--companion-bg);
  color: var(--canvas);
  font-family: inherit;
  box-shadow: 0 6px 18px rgba(31, 44, 38, .28);
  cursor: pointer;
  animation: companion-in .3s ease both;
}

/* WHY IT IS HERE. Quiet and secondary, and NOT in mkv's mono — which is where the first build put
   it, and the screenshot said no.

   `.companion-name` is uppercase mono because it is one word: a NAME, in the register of a label
   on a thing. This is a sentence, and a sentence set in 8.5px uppercase mono across two lines
   shouts and is hard to read at once. It is the app saying why a bubble appeared, so it is set
   like the app's own quiet voice and sized under the line below it, which is what the reader is
   actually here for. */
.room-bubble-label {
  font-size: 10.5px;
  line-height: 1.4;
  color: rgba(255, 255, 255, .68);
}

/* WHAT THE ROOM LAST SAID — an authored quiet mark today, the last message from cycle 36.

   NO ANIMATION ON THIS, EVER, AND IT IS A RULE RATHER THAN A STYLE. design-11 §5 forbids a typing
   indicator in as many words. A static ellipsis is a placeholder for a message that does not
   exist; a pulsing one is a claim that somebody is typing, which is a claim about a person's
   behaviour that nobody made. The two are one `@keyframes` apart. */
.room-bubble-say {
  font-size: 14px;
  line-height: 1.4;
  color: var(--canvas);
}

@media (prefers-reduced-motion: reduce) {
  .room-bubble { animation: none; }
}

.room-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 10px 14px 18px;
  display: flex;
  flex-direction: column;
}

/* THE EMPTY ROOM, IN design-04's EMPTY-TRAY REGISTER — §7.1's second constraint, and the list of
   things it must not have is longer than the list of things it has. Centred, quiet, and plainly
   interface: a reader should not be able to mistake it for somebody having spoken. */
.room-empty {
  margin: auto 0;
  padding: 0 6px;
  text-align: center;
  font-size: 14px;
  line-height: 1.5;
  color: rgba(255, 255, 255, .62);
}

.room-empty[hidden] { display: none; }

/* ─────────────────────────────────────────────────────────── what was said, cycle 36

   ONE COLUMN, NO SIDES, NO AVATARS. A chat app puts your own messages on the right and everybody
   else's on the left, and it is the right choice there because a thread is between people you
   know. **This room is a PLACE's conversation and most of the names in it are `Visitor 248`** —
   sides would imply a relationship the room does not have, and an avatar is a likeness, which
   design-03 §2.3 refuses everywhere else in this app for reasons that do not stop at a chat.

   THE NAME CARRIES THE ATTRIBUTION AND NOTHING ELSE DOES. design-11 §4: a figure with no bubble
   has said nothing and is Visitor 248; a message says who said it and that is the whole of who
   anybody is here. */
/* ANCHORED TO THE BOTTOM, WHICH A SCREENSHOT ASKED FOR. The first build let the log sit at the
   top of a mostly empty room with the box at the bottom, and it read as a page rather than as a
   conversation. The human's standard for this surface is *"whatsapp or any realtime chat app"*,
   and the one structural thing every one of them does is grow the messages UP FROM the box. */
.room-log {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* THREE COLUMNS SINCE CYCLE 37 AND THE THIRD IS WHY. The flag went in at `grid-row: 2`, where the
   body already spans every column, so it was pushed onto a line of its own between the name and
   the words — a control floating in the middle of a message. The screenshot is what showed it; the
   assertions were about whether it existed and it did.

   who | when | flag  on the first row, and the words across all three on the second. */
.room-message {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 1px 8px;
  font-size: 14px;
  line-height: 1.45;
}

.room-who {
  grid-column: 1;
  font: 500 9px/1.4 var(--font-mono);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gold);
}

.room-what {
  grid-column: 1 / -1;
  grid-row: 2;
  color: var(--canvas);
  overflow-wrap: anywhere;
}

/* Wall-clock and nothing else. A time is not a count (§5.3) and not a recency signal on a figure
   (§5) — it is the ordinary thing a message carries. */
.room-when {
  grid-column: 2;
  grid-row: 1;
  align-self: baseline;
  font: 400 9px/1.4 var(--font-mono);
  letter-spacing: .06em;
  color: rgba(255, 255, 255, .4);
}

/* WHO CAME AND WENT — review round 1, and every line of this is what keeps it CHROME.

   §7's test is *a bubble is a claim that somebody spoke.* These say somebody arrived, which is a
   different and smaller thing, and they have to look it: centred rather than in the log's column,
   no name gutter, no timestamp, no bubble shape, and gone in six seconds. A permanent *Visitor 248
   left* sitting in the history would be a room whose record is mostly the app talking about
   itself, which is spine §9's filler arriving through a door nobody was watching.

   THEY SIT UNDER THE LOG AND ABOVE THE BOX, which is where they happen: the last thing that
   occurred, on its way out. */
.room-comings {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 8px;
}

.room-coming {
  margin: 0;
  text-align: center;
  font: 400 10px/1.4 var(--font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .42);
  animation: room-coming-in .25s ease both;
}

@keyframes room-coming-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* The line is still there, for exactly as long, and only the fade goes — design-01 §6.2's rule
     that reduced motion is never reduced INFORMATION. */
  .room-coming { animation: none; }
}

/* ONE TAP, AND A PERSON LOOKS — cycle 37, design-05 §6.4, design-11 §6.2's *any viewer*.

   QUIET UNTIL IT IS WANTED, and that is the only judgement this control is allowed to make. A
   flag beside every message, at full contrast, tells a room it is the kind of place where things
   get flagged — which is the app having an opinion about a conversation it is only hosting. It
   sits at low opacity and comes up on hover, focus and touch.

   NO FLAGGED STATE, NO COUNT, NO UNDO, AND THE STYLESHEET HAS NOWHERE TO PUT ONE. §6.4's rule is
   *never adjudicate, always route*, and a control that greyed itself out afterwards would report
   that this message is now Being Dealt With — which is an outcome, told to the one person who
   should be told nothing. What a flagger gets is one authored line, once, from the refusal host. */
.room-flag {
  grid-column: 3;
  grid-row: 1;
  align-self: baseline;
  justify-self: end;
  min-width: 28px;
  min-height: 28px;
  padding: 0;
  border: 0;
  background: none;
  color: rgba(255, 255, 255, .3);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
}

.room-flag:hover,
.room-flag:focus-visible { color: var(--tile-pink); }

/* A MESSAGE THAT WAS TAKEN DOWN — cycle 37, and it is deliberately the quietest line in the room.

   A tombstone has to be there, because a conversation that silently loses a line is a record that
   lies by omission. It also must not be the most interesting thing on the screen: the failure mode
   of removal-with-a-trace is that the trace draws more attention than the message ever did. So it
   is italic, dim, centred like the comings, and carries no author, no words and no reason. */
.room-message-gone {
  grid-template-columns: 1fr;
  justify-items: center;
}

.room-message-gone .room-what {
  font-size: 12px;
  font-style: italic;
  color: rgba(255, 255, 255, .34);
}

/* ─────────────────────────────────────────────────────────── the box

   NO SIGN-IN GATE AND NO SECOND STATE. design-11 §6.1 — the human's *"zero barriers … open room
   with less restrictions"* — and the distinction that makes it consistent with design-03 §9 is
   that the lock sits on the CORPUS and not on the person. There is no disabled variant of this
   form in the stylesheet, because there is no state in which it is disabled. */
.room-say {
  flex: 0 0 auto;
  display: flex;
  gap: 8px;
  padding: 10px 14px calc(12px + env(safe-area-inset-bottom));
  border-top: 1px solid rgba(255, 255, 255, .12);
}

.room-field {
  flex: 1 1 auto;
  min-width: 0;
  min-height: var(--tap-min);
  padding: 0 12px;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 999px;
  background: rgba(255, 255, 255, .06);
  color: var(--canvas);
  font-family: inherit;
  font-size: 16px;   /* 16px or iOS zooms the page on focus, which moves the street behind it */
}

.room-field::placeholder { color: rgba(255, 255, 255, .38); }

.room-send {
  flex: 0 0 auto;
  min-height: var(--tap-min);
  padding: 0 16px;
  border: 0;
  border-radius: 999px;
  background: var(--tile-teal);
  color: var(--canvas);
  font-family: inherit;
  font-size: 13px;
  letter-spacing: .04em;
  cursor: pointer;
}

/* §9's line, above the box, before the first message and never again. It is the app explaining a
   trade at the moment it is offered, so it sits with the control that makes it rather than at the
   top of the room where it would read as a heading. */
.room-trade {
  flex: 0 0 auto;
  margin: 0;
  padding: 0 14px 2px;
  font-size: 11px;
  line-height: 1.45;
  color: rgba(255, 255, 255, .6);
}

.room-trade[hidden] { display: none; }

/* WHAT THE SERVICE SAID BACK, and since cycle 37 it is two different things in one place.

   §6.2's rate limit and length cap are refusals, and an ordinary refusal still has to be visible:
   a message that silently did not send is the worst outcome available here. **A flag's
   acknowledgement lands in the same host on purpose** — both are the service saying something
   short to one person about something they just did, and a second host would be a second thing to
   keep in step.

   THEY ARE NOT THE SAME COLOUR, AND A SCREENSHOT IS WHY. *Passed to a person.* came out in the
   refusal's pink, which reads as an error — the app telling somebody their flag failed at the
   moment it worked. The default here is now neutral and only a refusal is pink. */
.room-refusal {
  flex: 0 0 auto;
  margin: 0;
  padding: 0 14px 2px;
  font-size: 11.5px;
  line-height: 1.45;
  color: rgba(255, 255, 255, .62);
}

.room-refusal[data-kind="refused"] { color: var(--tile-pink); }

.room-refusal[hidden] { display: none; }

/* ─────────────────────────────────────────────────────── kv, cycle 38

   `design-05` §6.2 is that the host is ABSENT UNTIL ADDRESSED, and a stylesheet cannot enforce
   that — no row exists until somebody tags it. What this section can do is stop the one thing a
   renderer could get wrong: making the assistant look like a participant.

   SO IT IS A DIFFERENT KIND OF LINE AND NOT A LOUDER ONE. A rule down the left edge and a slightly
   quieter ground, which is the register `mkv`'s answer card already uses on the street; no avatar,
   no bubble, no accent colour of its own, and nothing that draws the eye past the people. **The
   failure mode of an AI in a room is that it becomes the most interesting thing in it**, and
   §14.2.1 cut this feature once for a version of that worry.

   IT KEEPS THE NAME, THE TIME AND THE FLAG. An assistant whose sentences could not be reported
   would be the one speaker in the room nobody could question. */
.room-message-host {
  padding: 5px 0 5px 9px;
  border-left: 2px solid rgba(255, 255, 255, .16);
  background: rgba(255, 255, 255, .028);
  border-radius: 0 4px 4px 0;
}

.room-message-host .room-who { color: rgba(255, 255, 255, .52); }

/* WHAT THE SENTENCE RESTS ON — spine §7.2, and the size is the argument.

   `design-11` §8: *"a room is not a place where an unconfirmed thing may be said plainly because
   the register is casual."* A basis that is legible but secondary is the whole of honouring that:
   big enough to read before you believe the sentence, small enough that a room stays a
   conversation rather than a bibliography. The words are `answer_basis_prefix`'s, reused from the
   street, because a claim that read differently in two places would be two vocabularies. */
.room-basis,
.room-source {
  grid-column: 1 / -1;
  margin: 2px 0 0;
  font: 400 10.5px/1.4 var(--font-sans);
  color: rgba(255, 255, 255, .44);
}

.room-source a {
  color: rgba(255, 255, 255, .62);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.room-source a:hover,
.room-source a:focus-visible { color: var(--canvas); }

/* HOW YOU ADDRESS `kv`, AND WHAT THAT SENDS — the line under the box.

   CHROME, AND IT IS STYLED TO SAY SO. §6.3's line is *a bubble is a claim that somebody spoke*, so
   this is the same weight and colour as `.room-trade` above the box: unattributed, no bubble, no
   name gutter. It sits BELOW the form rather than above it because it describes what the box can
   do, where the trade line describes what posting costs — one is about the control and one is
   about you.

   ABSENT WITH NO ASSISTANT rather than disabled, which is spine §9 and cycle 19's finding: a
   service that never had one must not look like one that is down. */
.room-host-hint,
.room-host-sends {
  flex: 0 0 auto;
  margin: 0;
  padding: 4px 14px 0;
  font-size: 10.5px;
  line-height: 1.45;
  color: rgba(255, 255, 255, .42);
}

/* THE LAST THING IN THE ROOM NEEDS A FLOOR UNDER IT, and a screenshot is why: the first build
   ended at `padding-bottom: 0` and the disclosure's last line sat on the bottom edge of a phone,
   touching the bezel. Whichever of the two is showing last carries it — the disclosure normally,
   and the hint on its own once somebody has tagged and the disclosure has gone. */
.room-host-sends { padding-bottom: 12px; }
.room:has(.room-host-sends[hidden]) .room-host-hint { padding-bottom: 12px; }

.room-host-hint[hidden],
.room-host-sends[hidden] { display: none; }
