:root {
  --bg: #faf9f6;
  --surface: #ffffff;
  --text: #1a1a1a;
  --text-muted: #8a857c;
  --border: #ebe7df;
  --accent: #2c5950;
  /* Breathing-light is the temporal midpoint the pill cycles toward
     (and the static state under prefers-reduced-motion). Hoisted out
     of @keyframes in Layer 2 #4 so persona swaps reach the pill. */
  --accent-breathing-light: #4a7268;
  /* Layer 2 #5: ring color around the presence avatar. Defaults to
     the accent so the ring matches each persona; royal overrides it
     to the antique-gold flourish so the ring picks up the same gold
     as the body frame, not the navy. */
  --accent-ring: var(--accent);
  --accent-text: #ffffff;
  --error-bg: #fdf2f2;
  --error-text: #8a2a2a;
  --error-border: #f1d4d4;
  --radius: 14px;
  --max-width: 720px;
  --gutter: 16px;
}

/* --- Persona theming (Layer 2 #4) -----------------------------------
   `data-tone` on <html> is the stable theming interface. CSS targets
   the attribute, not the source that feeds it: today its value comes
   from currentMe.persona_id (the 4 fixed personas), and in Layer 3 it
   will come from tone_style on the composite axis (see memory
   `personalization-target-model`). Adding new tone_style values then
   adds new selectors here without touching the rest of the stylesheet.

   DRAFT palette — final colors by user sign-off, same discipline as
   persona texts. Each persona overrides two variables; the rest of
   the stylesheet (bubbles, buttons, pill) consumes them unchanged. */
html[data-tone="formal"] {
  --accent: #2c5950;
  --accent-breathing-light: #4a7268;
}
html[data-tone="informal"] {
  --accent: #7a4a2c;
  --accent-breathing-light: #9c6e4a;
}
html[data-tone="royal"] {
  /* Deep midnight navy (سرمه‌ای) — dignified, not bright. Holds AA
     comfortably against --accent-text (#fff). The plum draft was
     rejected by live sign-off; this is the navy rework. */
  --accent: #1c2e5a;
  --accent-breathing-light: #3a4e7c;
  /* Antique gold flourish — same hex as the body frame below, so
     the presence ring and the viewport frame read as one gilded
     family. Royal is the only persona that breaks the
     ring-follows-accent default. */
  --accent-ring: #a8843a;
}

/* Royal-only flourish: a substantial antique-gold frame around the
   viewport. Inset box-shadow paints the ring inside body's edge —
   zero layout impact (no shift vs the other personas where the body
   has no border), so swapping into and out of royal stays crisp.
   8px reads as a deliberate gilded border the moment royal is
   picked — visible from across the room, not on inspection. Same
   hex as --accent-ring under royal — the frame and the avatar ring
   are one gilded family. */
html[data-tone="royal"] body {
  box-shadow: inset 0 0 0 8px #a8843a;
}

/* --- Presence stripe (Layer 2 #5) -----------------------------------
   The «other party» tile: a fixed presence between the chrome and
   the thread, like the remote face in a 1:1 video call. Lives
   outside the thread's scroll container so it stays at the top as
   messages scroll. Centered, flush against the thread (no bottom
   border — clean handoff). Ring color follows --accent-ring, which
   defaults to the persona accent and switches to antique gold
   under royal.

   Sizing is responsive by media query (not clamp/vw): desktop
   stays dignified at 72px; mobile bumps to 96px so the presence
   reads larger on a phone where it matters more — closer to a
   video-call remote tile. */
.presence {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 16px 0;
  background: var(--surface);
}

/* [hidden] vs author-set display — same gotcha as .modal and
   .topbar__user. Author `display: flex` wins against UA `[hidden]`;
   an explicit override is needed so JS toggling `hidden` actually
   collapses the stripe (zero reserved space when no avatar.url). */
.presence[hidden] {
  display: none;
}

.presence__avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--bg);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

@media (max-width: 600px) {
  .presence {
    padding: 20px 0;
  }
  .presence__avatar {
    width: 96px;
    height: 96px;
    box-shadow: 0 0 0 4px var(--accent-ring);
  }
}
html[data-tone="street"] {
  --accent: #5a4a2c;
  --accent-breathing-light: #7c6e4a;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Vazirmatn", "Tahoma", "Segoe UI", sans-serif;
  font-size: 16px;
  line-height: 1.65;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 16px max(var(--gutter), calc((100% - var(--max-width)) / 2));
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.topbar h1 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--accent);
  letter-spacing: 0.3px;
}

.topbar__user {
  display: inline-block;
  padding: 4px 14px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--bg);
  font-size: 14px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 25%, transparent);
  animation: breathing-presence 2.5s ease-in-out infinite;
}

/* Same [hidden]-vs-author-display gotcha as .modal — author
   `display: inline-block` wins the tie against UA `[hidden]`, so an
   explicit override is needed for `userBadge.hidden = true` to do
   anything visible. */
.topbar__user[hidden] {
  display: none;
}

/* Pill breathes on its SURFACE, not its text: background cycles
   between --accent and a clearly lighter --accent-breathing-light;
   a low-alpha halo (color-mix → transparent) expands and contracts
   in lockstep for a soft aura. Text color stays constant for
   maximum legibility. 2.5s reads as a calm pulse — present, not
   anxious. Colors come from CSS vars (hoisted in Layer 2 #4), so
   a persona/tone swap on <html> re-evaluates the keyframe values
   on the next frame — no animation restart. */
@keyframes breathing-presence {
  0%, 100% {
    background-color: var(--accent);
    box-shadow: 0 0 6px color-mix(in srgb, var(--accent) 25%, transparent);
  }
  50% {
    background-color: var(--accent-breathing-light);
    box-shadow: 0 0 14px color-mix(
      in srgb, var(--accent-breathing-light) 40%, transparent
    );
  }
}

/* Honor OS reduced-motion: pill holds the temporal midpoint
   (--accent-breathing-light) with a faint static halo — the
   "living presence" intent reads, just without the movement. */
@media (prefers-reduced-motion: reduce) {
  .topbar__user {
    animation: none;
    background: var(--accent-breathing-light);
    box-shadow: 0 0 10px color-mix(in srgb, var(--accent) 30%, transparent);
  }
}

/* CTA «اینجا رو خونهٔ خودت کن» — the inviting ownership trigger for
   the settings modal. Sits next to the breathing pill in the topbar.
   Label-only (per the recorded CTA principle: not a gear icon, not
   the word تنظیمات — the trigger has to carry the invitation). Low-
   key by default so the pill stays the dominant identity element;
   warms up on hover to signal it's clickable. */
.topbar__cta {
  background: transparent;
  color: var(--text-muted);
  border: 1px dashed var(--border);
  border-radius: 999px;
  padding: 4px 14px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s, border-style 0.15s;
}

.topbar__cta:hover {
  color: var(--accent);
  border-color: var(--accent);
  border-style: solid;
}

.topbar__logout {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 12px;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.topbar__logout:hover:not(:disabled) {
  color: var(--accent);
  border-color: var(--accent);
}

.topbar__logout:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.thread {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 28px max(var(--gutter), calc((100% - var(--max-width)) / 2));
}

.bubble {
  max-width: 78%;
  padding: 12px 16px;
  border-radius: var(--radius);
  word-wrap: break-word;
  white-space: pre-wrap;
}

.bubble--user {
  align-self: flex-start;
  background: var(--accent);
  color: var(--accent-text);
}

.bubble--assistant {
  align-self: flex-end;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
}

.bubble__line {
  text-align: start;
}

.bubble__meta {
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-muted);
  opacity: 0.85;
}

.bubble--thinking {
  align-self: flex-end;
  background: transparent;
  color: var(--text-muted);
  font-style: italic;
  border: none;
  box-shadow: none;
  padding-inline: 4px;
  animation: pulse 1.6s ease-in-out infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

.bubble--error {
  align-self: center;
  background: var(--error-bg);
  color: var(--error-text);
  border: 1px solid var(--error-border);
  font-size: 14px;
  max-width: 90%;
}

.composer {
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 12px max(var(--gutter), calc((100% - var(--max-width)) / 2));
  display: flex;
  gap: 8px;
  align-items: flex-end;
}

.composer__input {
  flex: 1;
  resize: none;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
  font: inherit;
  background: var(--bg);
  color: var(--text);
  outline: none;
  max-height: 200px;
  min-height: 42px;
  line-height: 1.5;
  transition: border-color 0.15s;
}

.composer__input:focus {
  border-color: var(--accent);
}

.composer__send {
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 10px;
  padding: 10px 20px;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.15s;
  min-height: 42px;
}

.composer__send:hover:not(:disabled) { opacity: 0.9; }

.composer__send:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* --- Settings modal («خونهٔ خودت») --------------------------------
   Backdrop dims chat; centered panel holds the three settings fields
   (name, persona, language). Persian RTL throughout — flex direction
   inherits from <html dir="rtl">, so DOM order [save, cancel] in
   .modal__actions renders [cancel right, save left]: primary on the
   left per Persian convention. */

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

/* The author `.modal { display: flex }` above wins the specificity tie
   against the UA stylesheet's `[hidden] { display: none }` (both 0,1,0,
   author wins). That means a bare `settingsModal.hidden = true` is
   functionally a no-op and the modal stays on screen. This selector
   (0,2,0) explicitly re-hides whenever the attribute is present —
   restores the standard `hidden` behavior we expected. */
.modal[hidden] {
  display: none;
}

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(26, 26, 26, 0.4);  /* var(--text) at 40% alpha */
}

.modal__panel {
  position: relative;
  background: var(--surface);
  border-radius: 16px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.15);
  padding: 24px;
  width: 100%;
  max-width: 520px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.modal__title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--accent);
}

/* Layer 2 #3: first-open cue under the title. Sits between the
   h2 and the first .modal__field; .modal__panel's gap:18px handles
   the spacing above and below. Muted weight so it reads as a soft
   prompt, not a second header. */
.modal__subtitle {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-muted);
}

.modal__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.modal__label {
  font-size: 13px;
  color: var(--text-muted);
}

.modal__input,
.modal__select {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 12px;
  font: inherit;
  font-size: 15px;
}

.modal__input:focus,
.modal__select:focus {
  outline: none;
  border-color: var(--accent);
}

.modal__select {
  /* Native select; keep the chevron in its OS-default position
     (the browser flips it under RTL automatically). */
  appearance: auto;
}

/* Persona cards — 4 across on a comfortable viewport, 2x2 on
   narrow. Each card shows the persona's label + its unnamed
   greeting template as a one-line voice sample. Selected card
   flips to the accent green with cream text (STATIC — no breathing;
   breathing is reserved for the live identity pill). */
.persona-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}

@media (max-width: 520px) {
  .persona-cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

.persona-card {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 8px;
  font: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: center;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.persona-card:hover:not(.persona-card--selected) {
  border-color: var(--accent);
}

.persona-card__label {
  font-size: 14px;
  font-weight: 500;
}

.persona-card__example {
  font-size: 12px;
  color: var(--text-muted);
  line-height: 1.5;
}

.persona-card--selected {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
}

.persona-card--selected .persona-card__example {
  color: var(--bg);
  opacity: 0.85;
}

.modal__actions {
  display: flex;
  gap: 8px;
  justify-content: flex-start;
  margin-top: 4px;
}

.modal__save {
  background: var(--accent);
  color: var(--accent-text);
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 8px 18px;
  font: inherit;
  font-weight: 500;
  cursor: pointer;
  transition: opacity 0.15s;
}

.modal__save:hover:not(:disabled) { opacity: 0.9; }

.modal__save:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.modal__cancel {
  background: transparent;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 18px;
  font: inherit;
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
}

.modal__cancel:hover {
  color: var(--accent);
  border-color: var(--accent);
}
