:root {
  --primary: #0B6FA8;
  --primary-deep: #064F7B;
  --primary-soft: #E6F0F7;
  --primary-glow: rgba(11, 111, 168, 0.10);

  --bg: #EFEAE3;
  --panel-bg: #FFFFFF;

  --text: #0F1A2A;
  --text-muted: #5B6675;
  --text-subtle: #94A0AE;

  --border: #E5E7EB;
  --border-soft: #EEF0F3;
  --card-bg: #F8FAFC;
  --source-bg: #F2F5F9;

  --user-bubble: #0B6FA8;
  --user-bubble-text: #FFFFFF;

  --success: #10B981;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 18px;

  --shadow-panel: 0 10px 40px rgba(15, 26, 42, 0.08), 0 1px 3px rgba(15, 26, 42, 0.04);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
/* Defensive backstop: nothing inside the page should ever produce
   horizontal scroll. Long thread IDs in the meta line, raw URLs in
   answers, and code blocks have all caused widths > viewport on
   iPhone. overflow-x: hidden clamps any rogue element, and the
   chat panel below also clamps internally so its scroll container
   stays within the viewport. */
html, body { overflow-x: hidden; }
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", sans-serif;
  color: var(--text);
  background: var(--bg);
  background-image:
    radial-gradient(circle at 18% 22%, rgba(11, 111, 168, 0.06), transparent 55%),
    radial-gradient(circle at 88% 80%, rgba(11, 111, 168, 0.04), transparent 50%);
  display: flex;
  justify-content: flex-end;
  -webkit-font-smoothing: antialiased;
}
button { font-family: inherit; cursor: pointer; }
[hidden] { display: none !important; }
a { color: var(--primary); }

/* === Right-side chat panel === */
/* Width is driven by --chat-panel-width (set by the splitter drag),
   defaulting to 480px when no preference is stored. The panel still
   shrinks to the viewport on narrow screens via the implicit
   min(panelWidth, 100%) coming from `width: 100%`. */
.chat-panel {
  width: 100%;
  max-width: var(--chat-panel-width, 480px);
  /* 100dvh = dynamic viewport height. On iOS Safari, 100vh includes the
     area behind the dynamic toolbar, which pushes the composer below the
     fold; 100dvh tracks the actually-visible viewport. Fallback to 100vh
     for ancient browsers that don't support dvh. */
  height: 100vh;
  height: 100dvh;
  background: var(--panel-bg);
  display: flex;
  flex-direction: column;
  /* min-width: 0 lets flex children shrink below their content's intrinsic
     width — without this, a long unbreakable token inside a message can
     force the panel wider than the viewport, hiding the right-edge
     send button. overflow-x: hidden clips anything that still tries. */
  min-width: 0;
  overflow-x: hidden;
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-panel);
}

/* === Splitter handle ===
   6px-wide vertical hit zone centered on the panel's left edge
   (right offset = panelWidth - 3px so the hit zone straddles the
   seam). Visual indicator only appears on hover / focus / drag, so
   it's invisible at rest but discoverable on the cursor change. */
.splitter {
  position: fixed;
  top: 0;
  bottom: 0;
  right: calc(var(--chat-panel-width, 480px) - 3px);
  width: 6px;
  cursor: col-resize;
  background: transparent;
  z-index: 50;
  transition: background 0.12s;
  touch-action: none;
}
.splitter::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2px;
  height: 40px;
  margin-left: -1px;
  margin-top: -20px;
  background: var(--primary);
  border-radius: 2px;
  opacity: 0;
  transition: opacity 0.12s;
}
.splitter:hover,
.splitter:focus-visible,
.splitter.dragging {
  background: var(--primary-glow);
  outline: none;
}
.splitter:hover::before,
.splitter:focus-visible::before,
.splitter.dragging::before {
  opacity: 0.8;
}

/* === Header === */
.panel-header {
  flex: 0 0 auto;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-logo {
  width: 38px; height: 38px;
  border-radius: 10px;
  background: var(--primary);
  color: #FFFFFF;
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 38px;
}
.brand-logo svg { width: 22px; height: 22px; }
/* PNG variant of the brand-logo — the image already has its own blue
   background, so this just frames + rounds + sizes it. Sits next to
   the SVG-based .brand-logo so other markup paths still work. */
.brand-logo-img {
  width: 38px; height: 38px;
  border-radius: 10px;
  display: block;
  flex: 0 0 38px;
}
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-text h1 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
}
.brand-subtitle {
  font-size: 12px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}
.brand-subtitle.online::before {
  content: "";
  width: 7px; height: 7px;
  background: var(--success);
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(16, 185, 129, 0.18);
}

.header-actions { display: flex; align-items: center; gap: 2px; }
.icon-btn {
  background: none;
  border: none;
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  border-radius: var(--radius-sm);
  transition: background 0.12s, color 0.12s;
}
.icon-btn:hover { background: var(--border-soft); color: var(--text); }
.icon-btn:disabled { opacity: 0.45; cursor: default; }
.icon-btn:disabled:hover { background: none; color: var(--text-muted); }
.icon-btn svg { width: 18px; height: 18px; }

/* === Thread bar === */
.thread-bar {
  flex: 0 0 auto;
  padding: 9px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--border-soft);
  font-size: 13px;
  color: var(--text-muted);
  background: #FBFCFD;
}
.thread-bar #thread-info { display: inline-flex; align-items: center; gap: 7px; }
.thread-bar #thread-info svg { width: 14px; height: 14px; }
#new-thread-btn {
  background: none;
  border: none;
  color: var(--primary);
  font-size: 13px;
  font-weight: 500;
  padding: 4px 8px;
  border-radius: var(--radius-sm);
  display: inline-flex; align-items: center; gap: 4px;
}
#new-thread-btn:hover { background: var(--primary-soft); }

/* === Login screen === */
.login-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 24px 28px 18px;
  overflow-y: auto;
}
.hero {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-top: 36px;
}
.hero-logo {
  width: 88px; height: 88px;
  background: var(--primary);
  color: #FFFFFF;
  border-radius: 20px;
  display: flex; align-items: center; justify-content: center;
  margin-bottom: 22px;
  box-shadow: 0 0 0 12px var(--primary-glow);
}
.hero-logo svg { width: 50px; height: 50px; }
/* PNG variant of the hero-logo for the Kairos brand icon — kept
   separate from .hero-logo so the lock-screen lock SVG (which still
   needs the blue tile background) is unaffected. */
.hero-logo-img {
  width: 88px; height: 88px;
  border-radius: 20px;
  display: block;
  margin-bottom: 22px;
  box-shadow: 0 0 0 12px var(--primary-glow);
}
.hero-tagline {
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--primary);
  font-weight: 600;
  margin: 0 0 14px;
}
.hero-title {
  font-size: 24px;
  font-weight: 600;
  line-height: 1.18;
  color: var(--text);
  margin: 0 0 14px;
  max-width: 320px;
  letter-spacing: -0.015em;
}
.hero-sub {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0 0 26px;
  max-width: 340px;
}
.primary-btn {
  background: var(--primary);
  color: white;
  border: none;
  padding: 12px 22px;
  border-radius: var(--radius-md);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 10px;
  transition: background 0.15s, transform 0.05s;
}
.primary-btn:hover { background: var(--primary-deep); }
.primary-btn:active { transform: translateY(1px); }
.primary-btn svg { width: 14px; height: 14px; }

.trust-list {
  list-style: none;
  padding: 0;
  margin: 32px 0 0;
  display: flex; flex-direction: column; gap: 10px;
  align-self: stretch;
  text-align: left;
}
.trust-list li {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px;
  color: var(--text);
}
.trust-list svg {
  width: 16px; height: 16px;
  color: var(--primary);
  flex: 0 0 16px;
}

.footer-version {
  text-align: center;
  font-size: 11px;
  color: var(--text-subtle);
  padding: 16px 0 4px;
}

/* === Chat screen === */
.chat-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

/* Empty state (signed in, fresh conversation) */
.empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 36px 22px 16px;
  overflow-y: auto;
}
.empty-state .hero-logo,
.empty-state .hero-logo-img { margin-bottom: 18px; }
.empty-title {
  font-size: 22px;
  font-weight: 600;
  margin: 0 0 10px;
  color: var(--text);
  letter-spacing: -0.01em;
}
.empty-sub {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-muted);
  margin: 0 0 22px;
  max-width: 340px;
}
.example-chips {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 380px;
}
.example-chips button {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 12px 14px;
  font-size: 14px;
  text-align: left;
  color: var(--text);
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  transition: background 0.15s, border-color 0.15s, transform 0.05s;
}
.example-chips button:hover {
  background: #FFFFFF;
  border-color: var(--primary);
}
.example-chips button:active { transform: translateY(1px); }
.example-chips .chip-icon {
  flex: 0 0 18px;
  width: 18px; height: 18px;
  color: var(--primary);
}
.example-chips .chip-text { flex: 1; }
.example-chips .chip-arrow {
  width: 16px; height: 16px;
  color: var(--text-subtle);
  flex: 0 0 16px;
}

/* Messages */
.messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px 18px 8px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.message {
  display: flex;
  gap: 10px;
  max-width: 92%;
}
.message--user {
  align-self: flex-end;
  flex-direction: row-reverse;
}
.message--assistant { align-self: flex-start; }
.message-avatar {
  flex: 0 0 28px;
  width: 28px; height: 28px;
  border-radius: 8px;
  background: var(--primary);
  color: #FFFFFF;
  display: flex; align-items: center; justify-content: center;
  margin-top: 2px;
}
.message-avatar svg { width: 16px; height: 16px; }
.message--user .message-avatar { display: none; }

.message-body { flex: 1; min-width: 0; }
.message__content {
  padding: 4px 0 0;
  color: var(--text);
  font-size: 14px;
  line-height: 1.55;
  word-wrap: break-word;
}
.message--user .message__content {
  padding: 10px 14px;
  border-radius: var(--radius-md);
  background: var(--user-bubble);
  color: var(--user-bubble-text);
  border-bottom-right-radius: 4px;
}
.message__content p { margin: 0 0 8px; }
.message__content p:last-child { margin-bottom: 0; }
.message__content strong { font-weight: 600; }
.message__content code {
  background: rgba(15, 26, 42, 0.06);
  padding: 1px 5px;
  border-radius: 4px;
  font-size: 0.9em;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
.message--user .message__content code { background: rgba(255, 255, 255, 0.20); }
.message__content ul, .message__content ol {
  padding-left: 20px;
  margin: 6px 0;
}
.message__content a { word-break: break-word; }

/* Thinking/searching status row (shown until first delta arrives) */
.message__status {
  display: flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  max-width: 100%;
  font-size: 13px;
  color: var(--text-muted);
  padding: 8px 12px;
  background: var(--card-bg);
  border-radius: var(--radius-md);
  border-bottom-left-radius: 4px;
  margin-bottom: 6px;
}
.message__content + .message__status,
.message__status + .message__content { margin-top: 0; }
.message__status:empty { display: none; }
.message__status .dots { display: inline-flex; gap: 4px; }
.message__status .dots span {
  width: 5px; height: 5px;
  background: var(--primary);
  border-radius: 50%;
  animation: dot-bounce 1.4s infinite;
}
.message__status .dots span:nth-child(2) { animation-delay: 0.15s; }
.message__status .dots span:nth-child(3) { animation-delay: 0.30s; }
.message__content:empty { display: none; }
@keyframes dot-bounce {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

/* Notice — used by renderNotice() for HTTP-level and SSE error rendering.
   Three variants distinguished by a modifier class. */
.message__notice {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: #FFFFFF;
  font-size: 14px;
  line-height: 1.4;
}
.message__notice-icon { flex: 0 0 auto; font-size: 18px; line-height: 1; }
.message__notice-body { flex: 1; min-width: 0; }
.message__notice-title { font-weight: 600; margin: 0 0 2px; }
.message__notice-message { margin: 0; color: var(--text); }
.message__notice-actions { margin-top: 8px; }
.message__notice-actions button {
  font: inherit;
  background: var(--primary);
  color: #fff;
  border: 0;
  border-radius: 6px;
  padding: 6px 12px;
  cursor: pointer;
}
.message__notice-actions button:hover { background: var(--primary-deep); }

.message__notice--info    { border-color: #BFDBFE; background: #EFF6FF; }
.message__notice--warning { border-color: #FDE68A; background: #FFFBEB; }
.message__notice--error   { border-color: #FECACA; background: #FEF2F2; }

/* Sources block */
.message__sources {
  margin-top: 8px;
  background: var(--source-bg);
  border-radius: var(--radius-md);
  padding: 10px 12px;
}
.message__sources:empty { display: none; }
.sources-label {
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.10em;
  color: var(--text-muted);
  font-weight: 600;
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 8px;
}
.sources-label svg { width: 12px; height: 12px; }
.sources-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sources-list a {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--primary);
  text-decoration: none;
  font-size: 13px;
  line-height: 1.4;
  padding: 6px 8px;
  margin: 0 -8px;
  border-radius: var(--radius-sm);
  transition: background 0.12s;
}
.sources-list a:hover { background: rgba(11, 111, 168, 0.06); }
.sources-list a:hover .source-text { text-decoration: underline; }
.sources-list .source-icon {
  width: 16px; height: 16px;
  color: var(--text-muted);
  flex: 0 0 16px;
}
.sources-list .source-text {
  flex: 1;
  min-width: 0;
  word-break: break-word;
}
.sources-list .source-open {
  width: 14px; height: 14px;
  color: var(--text-subtle);
  flex: 0 0 14px;
}
.sources-list a:hover .source-open { color: var(--primary); }

.message__meta {
  margin-top: 6px;
  font-size: 11px;
  color: var(--text-subtle);
  /* Long thread IDs (ask-{32 hex}) have no break opportunities, so
     break-word lets them wrap mid-token instead of pushing the
     parent wider than the viewport. */
  overflow-wrap: anywhere;
  word-break: break-word;
}
.message__meta:empty { display: none; }

/* Catch-all: long URLs, code identifiers, and other unbreakable
   tokens inside a message body should wrap rather than overflow. */
.message__content { overflow-wrap: anywhere; }

/* Composer */
.composer {
  flex: 0 0 auto;
  /* Bottom padding includes the iPhone home-indicator inset via env().
     max() falls back to 14px on devices without an inset (most desktop
     browsers report 0). viewport-fit=cover on the meta tag is required
     for env() to produce a non-zero value. */
  padding: 12px 16px max(14px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--border);
  background: var(--panel-bg);
}
.composer-input {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 8px 8px 8px 14px;
  transition: border-color 0.15s, background 0.15s;
  /* Allow this row to shrink below the textarea's intrinsic min-content
     width (which defaults to ~20 ems from the textarea's cols attribute).
     Without this the row was 360+ px wide on a 390 px iPhone viewport,
     pushing the send button half off-screen. */
  min-width: 0;
}
.composer-input:focus-within {
  border-color: var(--primary);
  background: #FFFFFF;
}
.composer-input textarea {
  flex: 1;
  /* Same reason as above: a flex item's default min-width is auto, which
     resolves to the textarea's intrinsic width from its `cols` attribute
     (20 by default = ~280px). Override so the textarea actually obeys
     flex:1 and shrinks to fit a narrow viewport. */
  min-width: 0;
  border: none;
  outline: none;
  resize: none;
  background: transparent;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.45;
  max-height: 140px;
  color: var(--text);
  padding: 6px 0;
}
.composer-input textarea::placeholder { color: var(--text-subtle); }
.send-btn {
  flex: 0 0 32px;
  width: 32px; height: 32px;
  background: var(--primary);
  color: white;
  border: none;
  border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s;
}
.send-btn:hover:not(:disabled) { background: var(--primary-deep); }
.send-btn:disabled { background: var(--text-subtle); cursor: not-allowed; }
.send-btn svg { width: 14px; height: 14px; }

.composer-helper {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 8px;
  padding: 0 4px;
  font-size: 11px;
  color: var(--text-subtle);
  gap: 12px;
}
.composer-helper kbd {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  background: var(--border-soft);
  border-radius: 3px;
  padding: 1px 5px;
  font-size: 10px;
  color: var(--text-muted);
  border: 1px solid var(--border);
}

.composer-controls {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.verbosity-label {
  color: var(--text-muted);
}
.verbosity-select {
  font-family: inherit;
  font-size: 11px;
  color: var(--text-muted);
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 1px 4px;
  cursor: pointer;
}
.verbosity-select:hover { border-color: var(--primary); }
.composer-keys { white-space: nowrap; }

/* Chronos link CTA — small banner at the top of the chat screen when
   the integration is enabled but the user hasn't linked yet. */
.chronos-banner {
  margin: 12px 16px 0;
  padding: 10px 14px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-left: 3px solid var(--primary);
  border-radius: 6px;
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  color: var(--text);
}
.chronos-banner .banner-text { flex: 1; }
.chronos-banner .banner-text strong { color: var(--text); }
.chronos-banner .banner-text small { color: var(--text-muted); display: block; margin-top: 2px; }
.chronos-banner button {
  flex-shrink: 0;
  background: var(--primary);
  color: #fff;
  border: 0;
  border-radius: 4px;
  padding: 6px 12px;
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.chronos-banner button:hover { filter: brightness(1.05); }
.chronos-banner button:disabled { opacity: 0.5; cursor: not-allowed; }
.chronos-banner .banner-dismiss {
  background: transparent;
  color: var(--text-muted);
  border: 0;
  padding: 4px;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}
.chronos-banner .banner-dismiss:hover { color: var(--text); }

.chronos-toast {
  position: fixed;
  top: 16px;
  right: 16px;
  background: var(--text);
  color: #fff;
  padding: 8px 14px;
  border-radius: 6px;
  font-size: 13px;
  box-shadow: var(--shadow-panel);
  z-index: 1000;
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 0.2s, transform 0.2s;
  pointer-events: none;
}
.chronos-toast.show { opacity: 1; transform: translateY(0); }

/* Settings popover anchored to the gear icon in the header. Position is
   fixed-relative-to-the-button via JS (top/right computed at open time)
   so the popover stays glued under the icon even on narrow chat panels. */
.settings-popover {
  position: absolute;
  top: 60px;
  right: 16px;
  width: 320px;
  max-width: calc(100vw - 32px);
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow-panel);
  z-index: 900;
  overflow: hidden;
  font-size: 13px;
}
.settings-popover[hidden] { display: none; }
.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  color: var(--text);
}
.settings-close {
  background: transparent;
  border: 0;
  font-size: 20px;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 4px;
}
.settings-close:hover { color: var(--text); }
.settings-section { padding: 12px 14px; }
.settings-section h3 {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-muted);
}
.settings-row {
  display: flex;
  flex-direction: column;
  gap: 8px;
  color: var(--text);
}
.settings-row .row-label { color: var(--text-muted); font-size: 12px; }
.settings-row .row-value { color: var(--text); font-size: 13px; }
.settings-row .row-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}
.settings-row button {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 5px 10px;
  font-family: inherit;
  font-size: 12px;
  cursor: pointer;
}
.settings-row button:hover { border-color: var(--primary); color: var(--primary); }
.settings-row button.danger:hover { border-color: #c0392b; color: #c0392b; }
.settings-row button:disabled { opacity: 0.5; cursor: not-allowed; }
.settings-row button.primary {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}
.settings-row button.primary:hover { color: #fff; filter: brightness(1.05); }

/* Mobile */
@media (max-width: 600px) {
  /* Drop the desktop flex-end body layout. On iOS Chrome the combination
     of `display: flex; justify-content: flex-end` with a `width: 100%`
     child was letting the chat-panel's intrinsic min-content (driven by
     header-actions and other flex rows) push the panel wider than the
     viewport — invisibly on desktop Chrome at the same logical width,
     but visibly on the device, where the right-aligned panel ended up
     offset to the LEFT of the visual viewport, clipping content on both
     sides. Switching to plain block layout pins the panel to exactly
     the viewport width with no flex-driven expansion. We use `100%`
     (relative to body, which is constrained by html, which is the
     layout viewport) rather than `100vw` because on iOS `100vw` can
     resolve to the layout viewport width *including* any horizontal
     overflow that would push the page wider than what the user sees;
     `100%` of body is always the visible width. */
  html, body { width: 100%; max-width: 100%; overflow-x: hidden; }
  body {
    display: block;
    justify-content: initial;
    background: var(--panel-bg);
  }
  .chat-panel {
    width: 100%;
    max-width: 100%;
    border-left: none;
    box-shadow: none;
  }
  /* Make sure no column-flex child of the panel can claim min-content
     width on the cross axis. Without these, a child like .panel-header
     (which has space-between brand + action icons) can ignore the
     parent's overflow-x: hidden on iOS and still force the panel
     layout wider. */
  .panel-header, .thread-bar, .chat-screen, .composer { min-width: 0; }
  .splitter { display: none; }
  .login-screen, .empty-state { padding-left: 18px; padding-right: 18px; }
  .hero-logo,
  .hero-logo-img { width: 80px; height: 80px; }
  .hero-logo svg { width: 46px; height: 46px; }
  .hero-title, .empty-title { font-size: 20px; }

  /* Keyboard shortcut hints are meaningless on touch devices and the
     white-space: nowrap was forcing horizontal overflow past the screen
     right edge, which clipped the send button and produced the
     "slightly too wide" feel. */
  .composer-keys { display: none; }

  /* Allow the helper row to wrap when the controls don't fit. */
  .composer-helper { flex-wrap: wrap; row-gap: 4px; }

  /* Long thread keys (ask-{32 hex}) were overflowing the bar. Truncate
     with ellipsis and let the New button keep its space. */
  .thread-bar { gap: 8px; }
  .thread-bar #thread-info {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  #new-thread-btn { flex: 0 0 auto; }

  /* In PWA / Add-to-Home-Screen mode, iOS lets content reach the very
     edge of the device including the rounded corners. Inset horizontally
     so nothing gets clipped. (env() returns 0 in portrait on most
     iPhones, so this is mainly a landscape / future-proofing measure.) */
  .panel-header,
  .thread-bar,
  .messages,
  .composer { padding-left: max(16px, env(safe-area-inset-left));
              padding-right: max(16px, env(safe-area-inset-right)); }
}
