/* ======================================
   CHATROOMS - the halls
   ====================================== */

/* YOUR OWN WORDS IN A HALL. A faint gold wash and a thin edge down the left,
   nothing else: the wording, the spacing and the order of the lines are exactly
   as they were, so a room that was readable stays readable. Built from
   --accent-gold, so the parchment theme gets its own darker wash for free.
   A system line never takes this class (see renderMsg in js/ui/chat.js). */
.chat-mine {
  background: color-mix(in srgb, var(--accent-gold) 11%, transparent);
  border-left: 2px solid color-mix(in srgb, var(--accent-gold) 50%, transparent);
  border-radius: 0 3px 3px 0;
  padding: 0.14rem 0.4rem 0.16rem 0.45rem;
}

/* ======================================
   THE COLOUR A PLAYER SPEAKS IN (maggie, 2026-08-20)
   ======================================
   Each player may choose one colour for themselves in the hall's Appearance
   tab. Their lines are then drawn on a wash of it with a thin edge down the
   left - the SAME shape .chat-mine above already uses, so a hall that was
   readable stays readable and nothing about the wording, the spacing or the
   order of the lines moves.

   THE STRENGTH IS FIXED AND THE PLAYER CANNOT TOUCH IT. That is the whole
   safety of letting the colour be free: only the BACKGROUND is tinted, never
   the text, and at these percentages no choice on the wheel - not white, not
   black - can make a line harder to read on parchment or on the dark theme.
   The two numbers below are the only place they are set. Change them here and
   every hall changes together. They match .chat-mine deliberately: your own
   gold wash and somebody's chosen colour must weigh the same, or the hall
   reads as though one of them matters more.

   --chat-hue is set per line, inline, by renderMsg in js/ui/chat.js, and is
   never anything but six hex digits behind a hash: it is checked in the
   browser before it is drawn and again on the server before it is stored
   (routes/characters.js), because it lands in a CSS declaration on every other
   player's screen and escaping does not touch a stylesheet. */
.chat-hued {
  --chat-hue-wash: 11%;
  --chat-hue-edge: 50%;
  background: color-mix(in srgb, var(--chat-hue, var(--accent-gold)) var(--chat-hue-wash), transparent);
  border-left: 2px solid color-mix(in srgb, var(--chat-hue, var(--accent-gold)) var(--chat-hue-edge, 50%), transparent);
  border-radius: 0 3px 3px 0;
  padding: 0.14rem 0.4rem 0.16rem 0.45rem;
}

/* The Appearance tab's own strip: the swatch you are choosing, and one line of
   pretend speech drawn exactly as a real one would be, so what you see before
   you save is what the hall will look like. */
.chat-look-row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 0.5rem; }
.chat-look-swatch {
  width: 2.4rem; height: 1.8rem; padding: 0; border: 1px solid var(--border-dim);
  border-radius: 4px; background: var(--bg-surface); cursor: pointer;
}
.chat-look-preview {
  background: var(--bg-surface); border: 1px solid var(--border-dim);
  border-radius: 6px; padding: 0.6rem;
}
.chat-look-tick { display: flex; align-items: flex-start; gap: 0.5rem; margin: 0.55rem 0; cursor: pointer; }
.chat-look-tick input { margin-top: 0.2rem; flex: none; }

/* == THE GAUGE UNDER THE BOX YOU SPEAK IN ==================================
   The room's 500-character limit, drawn as a fill along the bottom edge of the
   input rather than as a sentence beside it, and the count of what is left
   sitting inside the box's right-hand end so it costs no row of a phone
   screen. The track is the shared .bar-track.thin / .bar-fill, so it fills in
   the same gold as every other bar in the game.

   The input carries its layout style inline (INP in ui/chat.js); everything
   here is position and the two "you are out" states. */
.chat-compose { position: relative; flex: 1; display: flex; }
.chat-compose-input {
  flex: 1;
  padding-right: 2.6rem !important;
  /* It is a textarea of one row now, not a single-line input: a long line
     wraps and stays readable instead of scrolling off to the left, and
     chatGrow (js/ui/chat.js) raises the height to match what is in it. THE
     CEILING IS HERE, not there: five lines, then it scrolls. */
  display: block;
  resize: none;
  line-height: 1.35;
  max-height: 7.6rem;
  overflow-y: auto;
}
/* The touch floor, same 44px the rest of the game uses (components/touch.css).
   One row of 16px text in a 0.45rem padding comes out at 38, and the desktop
   box is deliberately left the height it always was. */
@media (pointer: coarse) {
  /* And it may grow further on a phone, because a phone line holds a third of
     what a desktop line does: five lines there is most of the 500, five lines
     here is about 170 characters. Measured on a 375px screen - a one-line box
     showed 28 characters of a 126-character sentence. */
  .chat-compose-input { min-height: 44px; max-height: 12rem; }
}
/* The placeholder does not wrap. It is longer than the box is wide, and a
   textarea wraps it where an input clipped it - which left the empty box
   showing half of a second line. The real text still wraps; only the hint
   is cut. */
.chat-compose-input::placeholder { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.chat-charleft {
  position: absolute;
  right: 0.5rem;
  /* Bottom, not centred: the middle of a box that has grown to five lines is
     nowhere in particular. It sits just above the gauge either way. */
  bottom: 0.4rem;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  color: var(--text-muted);
  pointer-events: none;
}
.chat-charleft-full { color: var(--text-danger); }
.chat-chartrack {
  position: absolute;
  left: 1px; right: 1px; bottom: 1px;
  width: auto;
  flex: none;
  background: transparent;
  border-radius: 0 0 3px 3px;
  pointer-events: none;
}
.chat-chartrack .bar-fill { border-radius: 0 0 0 3px; }
.chat-chartrack .chat-charfill-full { background: var(--text-danger); }
/* THE TRANSCRIPT MUST BREAK A WORD THAT WILL NOT BREAK ITSELF (maggie,
   2026-09-16, with a screenshot). A line with no spaces in it - a keyboard
   mash, a pasted link, a name typed forty times - has no break opportunity, so
   the row grew wider than #chat-messages, the box scrolled sideways, and every
   line in the hall was dragged left with it: the speakers' names were clipped
   at the edge and the shaded bubble ended in the middle of its own text.

   ON THE CONTAINER, not on the rows. A row carries .chat-mine, .chat-hued or no
   class at all depending on who spoke and what colour they chose, so there is no
   one selector that reaches all three - but overflow-wrap INHERITS, so setting
   it here covers every line that will ever be drawn inside, including the ones
   a later feature adds. overflow-x guards the box itself against anything else
   that cannot be broken, an image or a wide table.

   The value anywhere rather than break-word: it also lets the box shrink below the
   long word's width when the pane is narrow, which is the phone case. */
#chat-messages {
  overflow-wrap: anywhere;
  overflow-x: hidden;
}

/* WHO IS TYPING (maggie, 2026-09-23). One quiet line under the transcript;
   its height is held even when empty so the box you type in never jumps. */
.chat-typing {
  min-height: 1.1rem;
  margin-top: 0.25rem;
  font-size: 0.66rem;
  font-style: italic;
  color: var(--text-muted);
}
.chat-typing-dots { display: inline-flex; gap: 0.16rem; margin-left: 0.3rem; vertical-align: middle; }
.chat-typing-dots span {
  width: 0.28rem; height: 0.28rem; border-radius: 50%;
  background: var(--text-muted);
  animation: chat-typing-bob 1.2s infinite ease-in-out;
}
.chat-typing-dots span:nth-child(2) { animation-delay: 0.15s; }
.chat-typing-dots span:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-typing-bob {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-0.18rem); }
}
@media (prefers-reduced-motion: reduce) {
  .chat-typing-dots span { animation: none; opacity: 0.7; }
}

/* == PORTRAITS IN THE HALLS (maggie, 2026-09-29) ==========================
   "Arched window, two sides": a spoken line is a card beside its speaker's
   portrait, framed in a gold arch; everyone else on the left, your own lines
   on the right with the frame and the card's sharp corner mirrored. Drawn by
   _renderCard in js/ui/chat.js, and only while the reader's "Show portraits"
   tick is on - off, the single-line rules above draw the hall as before.

   THE WASHES ARE THE SAME TWO NUMBERS as .chat-mine and .chat-hued above
   (11% fill, 50% edge), laid on the card instead of the row, so a chosen
   colour weighs exactly what it did and the text colour is never touched.
   The image carries width/height attributes and the frame a fixed size, so
   nothing moves when a lazy portrait arrives. */
.chat-line {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}
.chat-line-mine { flex-direction: row-reverse; }
.chat-frame {
  flex: 0 0 64px;
  width: 64px;
  padding: 3px;
  box-sizing: border-box;
  border-radius: 32px 32px 4px 4px;
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--accent-gold) 70%, #fff),
    color-mix(in srgb, var(--accent-gold) 60%, #000) 55%,
    var(--accent-gold));
  box-shadow: 0 2px 6px color-mix(in srgb, #000 50%, transparent);
}
.chat-face {
  display: block;
  width: 58px;
  height: 78px;
  object-fit: cover;
  border-radius: 29px 29px 2px 2px;
  background: var(--bg-void);
}
.chat-card {
  /* Hugs a short line to its own side; a long one takes the rest of the row. */
  min-width: 0;
  max-width: 100%;
  background: var(--bg-panel);
  border: 1px solid var(--border-dim);
  border-radius: 4px 10px 10px 10px;
  padding: 0.45rem 0.7rem 0.5rem;
  box-sizing: border-box;
  font-size: 0.86rem;
  line-height: 1.45;
}
.chat-line-mine .chat-card { border-radius: 10px 4px 10px 10px; }
.chat-card-mine {
  --chat-hue: var(--accent-gold);
}
.chat-card-mine, .chat-card-hued {
  background: color-mix(in srgb, var(--chat-hue, var(--accent-gold)) 11%, var(--bg-panel));
  border-left: 2px solid color-mix(in srgb, var(--chat-hue, var(--accent-gold)) 50%, transparent);
}
.chat-line-mine .chat-card-mine, .chat-line-mine .chat-card-hued {
  border-left: 1px solid var(--border-dim);
  border-right: 2px solid color-mix(in srgb, var(--chat-hue, var(--accent-gold)) 50%, transparent);
}
.chat-card-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 0.45rem;
  margin-bottom: 0.1rem;
}
.chat-line-mine .chat-card-head { flex-direction: row-reverse; }
.chat-card-name {
  font-family: var(--font-display);
  font-size: 1.05rem;
  line-height: 1.2;
  color: var(--accent-gold);
}
.chat-card-text { color: var(--text-secondary); }
.chat-card-act { color: var(--accent-ember); font-style: italic; }
/* The cards of one speaker's run stack in one column beside the one face,
   so the later ones tuck up under the first however short it is. */
.chat-run {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.25rem;
}
.chat-line-mine .chat-run { align-items: flex-end; }
.chat-card-cont { padding-top: 0.35rem; }
@media (max-width: 520px) {
  .chat-line { gap: 0.55rem; }
  .chat-frame { flex-basis: 52px; width: 52px; border-radius: 26px 26px 4px 4px; }
  .chat-face { width: 46px; height: 62px; border-radius: 23px 23px 2px 2px; }
  .chat-card { padding: 0.4rem 0.6rem 0.45rem; }
  .chat-card-name { font-size: 1rem; }
}
