.chat-layout {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.chat-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--spacing-sm) var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  flex-shrink: 0;
}

.chat-header h1 {
  font-size: var(--font-size-base);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 60%;
}

.chat-header-meta {
  font-family: var(--font-mono);
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.chat-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--spacing-lg);
  display: flex;
  justify-content: center;
}

.chat-body-inner {
  width: 100%;
  max-width: var(--max-width-chat);
}

.chat-messages {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

.chat-msg {
  padding: var(--spacing-sm) var(--spacing-md);
  border-radius: var(--radius-lg);
  max-width: 85%;
  word-wrap: break-word;
  line-height: 1.6;
  white-space: normal;
}

.chat-msg ul, .chat-msg ol {
  padding-left: var(--spacing-lg);
  margin: var(--spacing-xs) 0;
}

.chat-msg li { margin-bottom: var(--spacing-xs); }

.chat-msg-user {
  background: var(--color-user-bubble);
  align-self: flex-end;
  border-bottom-right-radius: var(--radius-sm);
}

.chat-msg-assistant {
  background: var(--color-assistant-bubble);
  align-self: flex-start;
  border-bottom-left-radius: var(--radius-sm);
  /* Reserve the streaming rule's 3px so coloring it in (.chat-streaming) and
     dropping it at turn end causes no horizontal shift under border-box. */
  border-left: 3px solid transparent;
}

/* Streaming deltas are now rendered as markdown live (see _appendToStream), so
   the element is already in its final white-space: normal shape — no pre-wrap,
   no mode flip at turn end. Only the left rule + pulsing caret mark it live. */
.chat-streaming {
  border-left: 3px solid var(--color-streaming-indicator);
}

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

.chat-streaming::after {
  content: '\25CF';
  color: var(--color-streaming-indicator);
  animation: pulse 1.2s ease-in-out infinite;
  margin-left: 2px;
}

/* Typing indicator: a three-dot "assistant is thinking" bubble shown from turn
   start until the first token (see _showThinking). Styled as an assistant
   bubble so the streaming message lands in the same spot. */
.chat-thinking {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 24px;
}

.chat-thinking span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-streaming-indicator);
  animation: chat-thinking-bounce 1.2s ease-in-out infinite;
}

.chat-thinking span:nth-child(2) { animation-delay: 0.2s; }
.chat-thinking span:nth-child(3) { animation-delay: 0.4s; }

@keyframes chat-thinking-bounce {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

.chat-footer {
  border-top: 1px solid var(--color-border);
  padding: var(--spacing-md) var(--spacing-lg);
  background: var(--color-surface);
  flex-shrink: 0;
}

/* The composer is one unified container: the container owns the border and
   lights up on focus-within, the textarea is seamless inside it, and Send is a
   ghost action rather than a filled pill. */
.chat-input-wrap {
  display: flex;
  align-items: flex-end;
  gap: var(--spacing-sm);
  max-width: var(--max-width-chat);
  margin: 0 auto;
  padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-sm) var(--spacing-md);
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  transition: border-color 0.15s, box-shadow 0.15s;
}

.chat-input-wrap:focus-within {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-ring);
}

.chat-input-wrap textarea {
  flex: 1;
  padding: 7px 0;
  background: transparent;
  border: none;
  resize: none;
  min-height: 24px;
  max-height: 160px;
  line-height: 1.5;
  font-size: var(--font-size-base);
  color: var(--color-text);
}

.chat-input-wrap textarea:focus {
  outline: none;
}

/* Send carries state in its text colour, not a fill: muted when there's nothing
   to send (empty field — the wrap lacks .has-text — or disabled mid-turn),
   forest once a message is ready. Uppercase + tracking borrows Survlet's own
   label voice (dashboard headers, status chips). */
.chat-input-wrap .chat-send-btn {
  align-self: flex-end;
  height: 34px;
  padding: 0 var(--spacing-sm);
  background: transparent;
  color: var(--color-text-muted);
  border: none;
  border-radius: var(--radius-sm);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}

.chat-input-wrap.has-text .chat-send-btn:not(:disabled) {
  color: var(--color-primary);
}

.chat-input-wrap.has-text .chat-send-btn:not(:disabled):hover {
  background: var(--sv-forest-soft);
}

.chat-input-wrap .chat-send-btn:disabled {
  color: var(--color-text-muted);
  cursor: default;
}

.chat-banner {
  padding: var(--spacing-md);
  border-radius: var(--radius-md);
  text-align: center;
  margin: var(--spacing-md) 0;
}

.chat-banner-success {
  background: rgba(5, 150, 105, 0.1);
  border: 1px solid var(--color-success);
  color: var(--color-success);
}

.chat-banner-error {
  background: rgba(220, 38, 38, 0.1);
  border: 1px solid var(--color-error);
  color: var(--color-error);
}

.chat-banner-info {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-secondary);
}

.chat-banner-actions {
  display: flex;
  gap: var(--spacing-sm);
  justify-content: center;
  margin-top: var(--spacing-md);
  flex-wrap: wrap;
}

.chat-config-summary {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--spacing-md);
  margin-bottom: var(--spacing-md);
  font-size: var(--font-size-sm);
}

.chat-config-summary-title {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--color-primary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin-bottom: var(--spacing-sm);
  font-weight: 600;
}

.chat-config-field {
  margin-bottom: var(--spacing-xs);
  line-height: 1.4;
}

.chat-config-label {
  color: var(--color-text-muted);
  font-family: var(--font-mono);
  font-size: 11px;
}

.chat-config-value { color: var(--color-text); }

.proposal-card {
  background: var(--color-surface);
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: var(--spacing-md);
  margin: var(--spacing-md) 0;
  font-size: var(--font-size-sm);
}

.proposal-card-title {
  font-weight: 600;
  color: var(--color-text);
  margin-bottom: var(--spacing-md);
}

.proposal-field {
  display: flex;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-xs);
  line-height: 1.4;
}

.proposal-field-block { flex-direction: column; gap: 4px; }
/* In a column block the flex main axis is vertical, so the label's
   `flex: 0 0 110px` would become a 110px *height* — reset it to hug its text. */
.proposal-field-block .proposal-label { flex: 0 0 auto; padding-top: 0; }

.proposal-label {
  flex: 0 0 110px;
  color: var(--color-text-muted);
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding-top: 2px;
}

.proposal-value { color: var(--color-text); }

.proposal-zones {
  margin: 0;
  padding-left: var(--spacing-md);
  color: var(--color-text);
}

.proposal-zones li { margin-bottom: 2px; }

.proposal-actions {
  display: flex;
  gap: var(--spacing-sm);
  margin-top: var(--spacing-md);
  flex-wrap: wrap;
}

.respondent-layout {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
}

.respondent-body {
  flex: 1;
  overflow-y: auto;
  padding: var(--spacing-lg) var(--spacing-md);
  display: flex;
  justify-content: center;
}

.respondent-body-inner {
  width: 100%;
  max-width: var(--max-width-chat);
}

.respondent-footer {
  border-top: 1px solid var(--color-border);
  padding: var(--spacing-md);
  background: var(--color-surface);
  flex-shrink: 0;
}

.respondent-footer .chat-input-wrap {
  max-width: var(--max-width-chat);
}

.respondent-disclaimer {
  max-width: var(--max-width-chat);
  margin: var(--spacing-xs) auto 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--color-text-muted);
  text-align: center;
}

/* Respondent header: a slim persistent bar that paints instantly (before the
   /runtime/start round-trip) so the first frame is oriented, not a blank void.
   Distinct from composer's .chat-header so the shared surfaces are unaffected. */
.respondent-header {
  padding: var(--spacing-sm) var(--spacing-lg);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  flex-shrink: 0;
}

.respondent-header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spacing-md);
  /* Constrain to the chat column (like the messages, input, and disclaimer) so
     the title and brand align with the content edges, not the window edges. */
  width: 100%;
  max-width: var(--max-width-chat);
  margin: 0 auto;
}

.respondent-header-title {
  font-weight: 500;
  font-size: var(--font-size-base);
  color: var(--color-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.respondent-brand {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.4px;
  color: var(--color-text-muted);
}

/* Honest adaptive progress: a soft guide off the per-survey estimate, capped at
   90% until the real session_complete. Calm, not jumpy — the fill eases. Lives
   in the footer UNDER the input, constrained to the text-column width (like the
   input + disclaimer) so it reads as a quiet status cue, not a full-width banner. */
.respondent-progress {
  display: flex;
  align-items: center;
  gap: var(--spacing-sm);
  max-width: var(--max-width-chat);
  margin: var(--spacing-md) auto;
  padding: 0 var(--spacing-xs);
}

.respondent-progress-track {
  flex: 1;
  height: 6px;
  background: var(--color-border);
  border-radius: 3px;
  overflow: hidden;
}

.respondent-progress-fill {
  height: 100%;
  width: 0;
  background: var(--color-primary);
  border-radius: 3px;
  transition: width 0.6s ease;
}

.respondent-progress-label {
  flex-shrink: 0;
  min-width: 84px;
  text-align: right;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.4px;
  color: var(--color-text-muted);
}

/* One-time orientation line above the opener. A calm framing note, not a bubble. */
.respondent-intro {
  max-width: 85%;
  margin-bottom: var(--spacing-md);
  font-size: var(--font-size-sm);
  line-height: 1.5;
  color: var(--color-text-secondary);
}

/* Deliverable card (dual mode close). Promotes the final assistant bubble to a
   keepable result: raised surface + forest accent (not the throwaway 3px streaming
   border), a mono label, and a Copy affordance. */
.deliverable-card {
  align-self: stretch;
  max-width: 100%;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-primary);
  border-radius: var(--radius-md);
  padding: var(--spacing-md);
  box-shadow: var(--sv-shadow-md);
}

.deliverable-card-header {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--color-primary);
  margin-bottom: var(--spacing-sm);
}

/* The bubble inside the card is card content, not a floating message: drop the
   bubble background, the streaming rule's reserved border, and the width cap. */
.deliverable-card .chat-msg-assistant {
  background: transparent;
  border-left: none;
  border-radius: 0;
  padding: 0;
  max-width: 100%;
}

.deliverable-copy {
  margin-top: var(--spacing-md);
  padding: 6px var(--spacing-md);
  background: transparent;
  color: var(--color-primary);
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-sm);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}

.deliverable-copy:hover {
  background: var(--sv-forest-soft);
}

.deliverable-copy.is-copied {
  color: var(--color-success);
  border-color: var(--color-success);
}

/* Close screen (session_complete). A calm, full-width block that sits below the
   final message — a confirming line in the display serif, then one restrained
   outward CTA. Distinct from the throwaway .chat-banner-info it replaced. */
.chat-complete {
  margin: var(--spacing-lg) 0 var(--spacing-md);
  padding-top: var(--spacing-lg);
  border-top: 1px solid var(--color-border);
  text-align: center;
}

.chat-complete-line {
  font-family: var(--font-display);
  font-size: 24px;
  line-height: 1.3;
  color: var(--color-text);
  margin-bottom: var(--spacing-sm);
}

.chat-complete-cta {
  font-size: var(--font-size-sm);
  color: var(--color-text-muted);
}

.chat-complete-cta a {
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px solid var(--color-primary-ring);
}

.chat-complete-cta a:hover {
  border-bottom-color: var(--color-primary);
}

.passphrase-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--spacing-lg);
}

.passphrase-card {
  width: 100%;
  max-width: 360px;
  background: var(--color-surface-raised);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-xl);
  text-align: center;
}

.passphrase-card h2 {
  font-size: var(--font-size-lg);
  margin-bottom: var(--spacing-md);
}

.passphrase-card input {
  width: 100%;
  padding: var(--spacing-sm) var(--spacing-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  margin-bottom: var(--spacing-md);
  font-size: var(--font-size-base);
}

.passphrase-card input:focus {
  outline: none;
  border-color: var(--color-primary);
}

@media (max-width: 640px) {
  .chat-header { padding: var(--spacing-sm) var(--spacing-md); }
  .chat-body { padding: var(--spacing-md) var(--spacing-sm); }
  .chat-footer { padding: var(--spacing-sm); }
  .chat-msg { max-width: 92%; }
  .respondent-body { padding: var(--spacing-md) var(--spacing-sm); }
  .respondent-footer { padding: var(--spacing-sm); }
  .respondent-header { padding: var(--spacing-sm) var(--spacing-md); }
  .respondent-intro { max-width: 100%; }
}
