/* messages.css — message bubbles, roleplay setup, admin command surface
   Extracted verbatim from index.html lines 147-350 (the inline <style>).
   Design TOKENS are not here: they live in /assets/shell.css, shared with the
   document pages, exactly as before. */

/* ===================== messages ===================== */
.thread{flex:1;overflow-y:auto;padding:var(--s6) var(--s4) var(--s7);min-height:0}
.thread-inner{max-width:720px;margin:0 auto;display:flex;flex-direction:column;gap:var(--s5)}

.scene{
  align-self:center;max-width:80%;text-align:center;
  font-family:var(--font-msg);font-style:italic;
  color:var(--ink-3);font-size:var(--t-sm);
  padding:var(--s3) var(--s4);
}
.scene::before,.scene::after{content:'—';opacity:.5;margin:0 var(--s2)}

.msg{display:flex;gap:var(--s3);position:relative}
.msg-body{min-width:0;flex:1}
.msg-name{font-size:var(--t-xs);color:var(--ink-3);margin-bottom:var(--s1);font-weight:500}

/* ⭐ Companion speaks in SERIF — this is a roleplay and creative-writing app,
   so its output is prose, not notifications. The interface stays sans. This is
   the single choice that stops it looking like every other AI chat product. */
.msg.ai .text{
  font-family:var(--font-msg);
  font-size:var(--t-lg);line-height:1.62;color:var(--ink);
  letter-spacing:.002em;
  /* A quiet bubble, not a coloured one. The user's turn keeps the only strong colour in the
     thread, so the two sides stay tellable apart at a glance while the companion's side still
     reads as prose — which is what lets the serif work here.
     width:fit-content so a two-word reply gets a small bubble instead of an empty band;
     max-width keeps a long passage at a readable measure. */
  background:var(--bg-2);
  border:1px solid var(--line-soft);
  /* ⭐ Her edge, mirroring yours (2026-08-17). The user's turn carries blue on its RIGHT edge —
     the side it is aligned to — so the companion's carries violet on its LEFT, for the same
     reason: the colour sits on the outer edge of each side, pointing away from the centre.
     ⚠ The bubble ground stays neutral. The whole argument in the comment above is that a coloured
     ground leaves no tonal room for the italic stage directions; a 3px edge costs none of it. */
  border-left:3px solid var(--accent-ai);
  padding:var(--s3) var(--s4);
  border-radius:var(--r3) var(--r3) var(--r3) var(--r1);
  width:fit-content;
  max-width:88%;
}
.msg.ai .text em{color:var(--ink-2)}
/* Her name in her colour, exactly as yours is in yours. */
.msg.ai .msg-name{color:var(--accent-ai)}

.msg.me{flex-direction:row-reverse}
.msg.me .msg-body{display:flex;flex-direction:column;align-items:flex-end}
/* ⭐ THE USER'S TURN IS GREY, NOT BLUE (decided 2026-08-16, measured not guessed).
   A solid blue ground leaves no tonal room: white sits at 5.17:1 against it, so the italic
   stage-direction colour landed at 2.04:1 — under half the 4.5:1 floor and genuinely hard to
   read. On this grey it is 6.16:1 AND still recedes, so *actions* read as stage direction
   rather than competing with the spoken line.
   The blue is not lost, it is promoted: it now marks the edge and the name, which is enough to
   tell the two sides apart alongside alignment and the avatar. */
.msg.me .text{
  background:var(--bg-3); color:var(--ink);
  border:1px solid var(--line);
  border-right:3px solid var(--accent);
  padding:var(--s3) var(--s4);
  border-radius:var(--r3) var(--r1) var(--r1) var(--r3);
  max-width:min(560px,86%);
  box-shadow:var(--shadow-1);
}
.msg.me .msg-name{color:var(--accent-2)}
.msg.me .msg-name{text-align:right}

/* actions appear on hover, not permanently */

.photo{
  margin-top:var(--s3);border-radius:var(--r3);overflow:hidden;
  border:1px solid var(--line);max-width:340px;
  background:linear-gradient(140deg,var(--bg-3),var(--bg-2));
  aspect-ratio:4/5;display:grid;place-items:center;position:relative;
}
.photo span{color:var(--ink-4);font-size:var(--t-xs);letter-spacing:.06em;text-transform:uppercase}
.photo::after{
  content:'AI-generated';position:absolute;left:var(--s3);bottom:var(--s3);
  font-size:10px;letter-spacing:.05em;color:var(--ink-2);
  background:rgba(0,0,0,.55);padding:3px 7px;border-radius:var(--r1);
  backdrop-filter:blur(6px);
}

/* AI Act 50(1) notice — kept, restyled */
.disclosure{
  align-self:flex-start;max-width:560px;
  background:var(--notice-bg);border:1px solid var(--notice-line);
  color:var(--ink-2);border-radius:var(--r3) var(--r3) var(--r3) var(--r1);
  padding:var(--s3) var(--s4);font-size:var(--t-sm);
}
.disclosure b{color:var(--notice-ink);font-weight:600}

.typing{display:flex;gap:5px;align-items:center;padding:var(--s2) 0}
.typing i{width:7px;height:7px;border-radius:var(--r-pill);background:var(--ink-3);animation:blink 1.3s var(--ease) infinite}
.typing i:nth-child(2){animation-delay:.18s}
.typing i:nth-child(3){animation-delay:.36s}
@keyframes blink{0%,60%,100%{opacity:.25;transform:translateY(0)}30%{opacity:1;transform:translateY(-3px)}}

/* An undecryptable message says so. It must never render as a blank bubble - that is exactly
   the silent failure the whole library exists to prevent, and it would look like the companion
   sent an empty message. */
.text.unreadable{
  color:var(--bad); font-style:italic; font-family:var(--font-ui); font-size:var(--t-sm);
}

/* ⭐ Actions in *asterisks* render as italic and RECEDE; speech and narration stay full white.
   [H]: "I like that italic is gray and saying stuff is white" — so the emphasis goes to what is
   being SAID, and stage direction sits behind it rather than competing. */
.msg .text em{font-style:italic; color:var(--ink-2)}
.msg .text strong{font-weight:600; color:var(--ink)}
.msg .text p{margin:0}
.msg .text p + p{margin-top:.6em}
/* diagnostic output: exactly the bytes that came back */
.msg .text.verbatim{
  white-space:pre-wrap; font-family:var(--mono, ui-monospace, Consolas, monospace);
  font-size:var(--t-sm); line-height:1.5;
}

/* Generated photos in the transcript. Capped by VIEWPORT height as well as width: a portrait
   image at full width pushes the entire conversation off screen on a phone. */
.msg-image{
  display:block; margin-top:var(--s3); max-width:min(100%, 420px); border-radius:var(--r2);
  max-width:100%; max-height:60vh; object-fit:contain;
  background:var(--bg-3); border:1px solid var(--line-soft);
}

/* Sits UNDER the bubble, not in it, hugging the outer edge: right on your turns, left on hers.
   --ink-3 is hint-level on purpose — a timestamp under every message becomes noise the moment it
   competes with the text above it. */
.msg-time{
  font-size:var(--t-xs); color:var(--ink-3); margin-top:5px;
  font-variant-numeric:tabular-nums; letter-spacing:.01em;
}
.msg.ai .msg-time{text-align:left}
.msg.me .msg-time{text-align:right}

/* "Preparing photo…" — hint weight, and it is REPLACED by the image rather than sitting above it,
   so a finished photo never leaves a stale caption behind. */
.photo-note{
  margin-top:var(--s3); font-size:var(--t-sm); color:var(--ink-3); font-style:italic;
}

/* ---- roleplay setup + sheet ---- */
.rp-setup{text-align:center; padding-top:var(--s5)}
.rp-setup h2{margin:0 0 var(--s2); font-size:var(--t-xl); font-weight:600}
.rp-question{
  margin:var(--s4) auto var(--s3); max-width:46ch;
  font:400 var(--t-lg)/1.6 var(--font-msg); color:var(--ink);
}
/* A TEXTAREA, not an input. It was an <input>, which cannot hold a newline at all — so
   Shift+Enter did nothing on desktop either, and on a phone there is no Shift to press. */
.rp-input{
  width:min(420px,100%); padding:10px var(--s3); margin-top:var(--s2);
  background:var(--bg-3); border:1px solid var(--line); border-radius:var(--r1);
  color:var(--ink); font:inherit;
  font-size:16px;                 /* iOS: under 16px and focusing this zooms the page */
  min-height:44px; max-height:200px; resize:vertical; line-height:1.5;
}
.rp-go{margin-top:var(--s3)}
.rp-error{color:var(--bad); font-size:var(--t-sm); margin-top:var(--s3)}

.rp-sheet{
  margin:var(--s3) 0 var(--s4); padding-top:var(--s3);
  border-top:1px solid var(--line-soft); max-height:46vh; overflow-y:auto;
}
.rp-sec-title{
  font-size:var(--t-xs); letter-spacing:.09em; text-transform:uppercase;
  color:var(--ink-3); margin-top:var(--s3);
}
.rp-sec-body{
  font:400 var(--t-sm)/1.6 var(--font-msg); color:var(--ink-2);
  white-space:pre-wrap; margin-top:var(--s1);
}
.rp-char{display:flex; flex-direction:column; margin-top:var(--s2)}
.rp-char b{font-size:var(--t-sm); color:var(--ink)}
.rp-char small{font-size:var(--t-xs); color:var(--ink-3)}
/* Marked, not hidden: the story still refers to them. */
.rp-char.dead b{color:var(--ink-3); text-decoration:line-through}

/* ---- admin command surface ---- */
.cmd-sheet{
  margin:var(--s3) 0 var(--s4); padding-top:var(--s3);
  border-top:1px solid var(--line-soft); max-height:44vh; overflow-y:auto;
}
.cmd-title{font-size:var(--t-md); font-weight:600; color:var(--ink)}
.cmd-note{margin:var(--s1) 0 var(--s3); font-size:var(--t-xs); color:var(--ink-3); line-height:1.5}
.cmd-group-title{
  font-size:var(--t-xs); letter-spacing:.08em; text-transform:uppercase;
  color:var(--ink-3); margin-top:var(--s3);
}
.cmd-row{display:flex; flex-wrap:wrap; gap:var(--s2); margin-top:var(--s2)}
.cmd-chip{
  padding:6px var(--s3); border-radius:var(--r-pill);
  background:var(--bg-3); border:1px solid var(--line); color:var(--ink);
  font-family:var(--mono, ui-monospace, Consolas, monospace); font-size:var(--t-xs);
  transition:.16s var(--ease);
}
.cmd-chip:hover{border-color:var(--accent-line); background:var(--bg-2)}
/* Destructive commands read as destructive BEFORE they are pressed. Same red the sheet already
   uses for "Delete this conversation", so one danger colour means one thing throughout. */
.cmd-chip-danger{color:var(--bad); border-color:color-mix(in srgb, var(--bad) 35%, var(--line))}
.cmd-chip-danger:hover{
  border-color:var(--bad); background:color-mix(in srgb, var(--bad) 10%, var(--bg-2));
}
