/* css/app.css — chat shell */

:root {
  /* Two extra steps below --radius-sm (8px), for small glyph-scale
     elements (inline code, thumbnails, tiny marks) where the full
     --radius-sm/md/lg scale reads as too heavy. Kept here rather than
     in shared.css since only app.css currently needs them. */
  --radius-2xs: 4px;
  --radius-xs:  6px;
  /* A quicker-out curve reserved for things entering/leaving the
     screen (popovers, modals) — distinct from --ease, which is used
     for routine hover/focus state changes. Popovers should feel like
     they're "arriving with intent", not just linearly fading in. */
  --ease-pop: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ── Small layout utilities ──
   A handful of reusable one-property patterns that recur across the
   resource/reminder/document forms. Kept intentionally tiny (not a
   full utility-class framework) — anything more component-specific
   than this belongs in that component's own rule, not here. */
.field-row      { display: flex; gap: var(--space-3); }
.field-grow     { flex: 1; }
.field-narrow   { max-width: 280px; }
.btn-flush      { margin-bottom: 0; }
.btn-inline     { width: auto !important; white-space: nowrap; } /* !important: must reliably beat component base rules like .resource-download-btn's width:100%, whatever order stylesheets load in */
.text-danger    { color: var(--danger) !important; } /* !important: same reasoning as .btn-inline above */
.mt-tight       { margin-top: var(--space-2); }

.app-page { height: 100vh; height: 100dvh; overflow: hidden; }

.app-shell {
  display: grid;
  grid-template-columns: 272px 1fr;
  height: 100vh;
  height: 100dvh;
  background: var(--bg-base);
  transition: grid-template-columns var(--duration-base) var(--ease);
}

/* ── Sidebar ── */
.app-sidebar {
  background: var(--bg-base);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: var(--space-4) var(--space-3);
  min-width: 0;
  transition: width var(--duration-base) var(--ease), padding var(--duration-base) var(--ease);
  overflow: hidden;
}

/* ── Collapsed rail (desktop only) ──
   shell.js toggles .is-sidebar-collapsed on .app-shell alongside
   .is-collapsed on the sidebar: the grid track has to shrink too, or the
   64px rail sits inside a 272px column with a dead gap beside it.
   Primary navigation stays reachable as an icon rail (labels hidden,
   tooltips via title); only the chat list and usage detail are dropped. */
@media (min-width: 901px) {
  .app-shell.is-sidebar-collapsed { grid-template-columns: 64px 1fr; }

  .app-sidebar.is-collapsed {
    padding-left: var(--space-2);
    padding-right: var(--space-2);
  }
  .app-sidebar.is-collapsed .sidebar-top {
    flex-direction: column;
    gap: var(--space-3);
    padding-left: 0;
    padding-right: 0;
  }
  .app-sidebar.is-collapsed .sidebar-logo span,
  .app-sidebar.is-collapsed .new-chat-btn span,
  .app-sidebar.is-collapsed .sidebar-nav .sidebar-history-item span,
  .app-sidebar.is-collapsed .sidebar-history,
  .app-sidebar.is-collapsed .sidebar-section-label,
  .app-sidebar.is-collapsed .usage-widget,
  .app-sidebar.is-collapsed .account-info,
  .app-sidebar.is-collapsed .account-menu-trigger,
  .app-sidebar.is-collapsed .upgrade-link span {
    display: none;
  }
  .app-sidebar.is-collapsed .new-chat-btn,
  .app-sidebar.is-collapsed .sidebar-nav .sidebar-history-item,
  .app-sidebar.is-collapsed .upgrade-link,
  .app-sidebar.is-collapsed .account-btn { justify-content: center; }
  .app-sidebar.is-collapsed .sidebar-nav { flex: 1; }
  .app-sidebar.is-collapsed .account-menu {
    position: fixed;
    left: calc(64px + var(--space-2));
    right: auto;
    bottom: var(--space-4);
    width: 232px;
  }
}

.sidebar-scrim { display: none; }

.sidebar-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-2) var(--space-2) var(--space-5);
  flex-shrink: 0;
}

.sidebar-top-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.sidebar-logo {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 600;
  font-size: var(--text-base);
  letter-spacing: -0.01em;
  min-width: 0;
  color: var(--text-1);
}
.sidebar-logo img { height: 20px; width: auto; border-radius: var(--radius-xs); flex-shrink: 0; }

.sidebar-collapse-btn,
.sidebar-close-btn {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-3);
  flex-shrink: 0;
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.sidebar-collapse-btn:hover,
.sidebar-close-btn:hover { background: var(--bg-subtle); color: var(--text-1); }

.sidebar-close-btn { display: none; }

.new-chat-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-3) var(--space-3);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-weight: 500;
  font-size: var(--text-sm);
  color: var(--text-2);
  margin-bottom: var(--space-5);
  flex-shrink: 0;
  box-shadow: var(--shadow-sm);
  transition: border-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease), box-shadow var(--duration-fast) var(--ease);
}
.new-chat-btn:hover { color: var(--text-1); border-color: var(--border-strong); box-shadow: var(--shadow-md); }
.new-chat-btn i { color: var(--accent); }

/* ── Primary navigation — fixed height. Previously this shared
     .sidebar-history (flex: 1) with the chat list, so the two split the
     free space 50/50 and the chat list was squeezed to half the sidebar. ── */
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
  flex-shrink: 0;
}

/* ── Chat history list ── */
.sidebar-history {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 0 calc(var(--space-3) * -1);
  padding: 0 var(--space-3);
}

.sidebar-history-empty {
  padding: var(--space-4) var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-4);
  text-align: left;
}

.sidebar-history-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--text-2);
  text-align: left;
  min-width: 0;
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.sidebar-history-item i.ph {
  width: 18px;
  font-size: var(--text-base);
  text-align: center;
  flex-shrink: 0;
}
.sidebar-history-item span:not(.history-delete-btn) {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sidebar-history-item:hover { background: var(--bg-subtle); color: var(--text-1); }
.sidebar-history-item.is-active { background: var(--accent-subtle); color: var(--text-1); font-weight: 600; }

/* Chat rows: the open button and the delete button are siblings inside
   one row (a button nested in a button/span isn't valid or keyboard
   reachable). Delete is revealed on hover, on keyboard focus, and always
   on touch screens where there is no hover. */
.sidebar-history-row {
  display: flex;
  align-items: center;
  gap: 2px;
  border-radius: var(--radius-sm);
  min-width: 0;
  transition: background var(--duration-fast) var(--ease);
}
.sidebar-history-row:hover { background: var(--bg-subtle); }
.sidebar-history-row.is-active { background: var(--accent-subtle); }
.sidebar-history-row .sidebar-history-item {
  flex: 1;
  width: auto;
  background: none;
}
.sidebar-history-row .sidebar-history-item:hover { background: none; }
.sidebar-history-row.is-active .sidebar-history-item { background: none; color: var(--text-1); font-weight: 600; }

.history-delete-btn {
  flex-shrink: 0;
  width: 28px; height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-4);
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease), background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.sidebar-history-row:hover .history-delete-btn,
.sidebar-history-row:focus-within .history-delete-btn { opacity: 1; }
.history-delete-btn:hover { background: var(--border-strong); color: var(--danger); }
@media (hover: none) {
  .history-delete-btn { opacity: 0.7; width: 32px; height: 32px; }
}

/* Small label that separates past conversations from the fixed routes
   above them — deliberately a size down from .sidebar-history-item's
   text-sm so it reads as a section heading, not another link. */
.sidebar-section-label {
  font-size: var(--text-xs);
  font-weight: 600;
  color: var(--text-4);
  padding: var(--space-4) var(--space-2) var(--space-1);
  flex-shrink: 0;
}

/* ── Sidebar footer ── */
.sidebar-bottom {
  position: relative;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding-top: var(--space-3);
  margin-top: var(--space-2);
  border-top: 1px solid var(--border);
}

.usage-widget { padding: 0 var(--space-1); }

.usage-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: var(--space-3);
  font-size: var(--text-xs);
  color: var(--text-3);
  margin-bottom: var(--space-2);
}
.usage-label { white-space: nowrap; }
.usage-value {
  font-weight: 600;
  color: var(--text-2);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.usage-bar {
  height: 3px;
  border-radius: var(--radius-full);
  background: var(--border);
  overflow: hidden;
}
.usage-bar-fill {
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: var(--radius-full);
  transition: width var(--duration-slow) var(--ease);
}
.usage-bar-fill.is-near-limit { background: var(--warning); }
.usage-bar-fill.is-at-limit { background: var(--danger); }

.upgrade-link {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--accent);
  transition: background var(--duration-fast) var(--ease);
}
.upgrade-link:hover { background: var(--accent-subtle); }

.account-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  min-width: 0;
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--ease);
}
.account-btn:hover { background: var(--bg-subtle); }

.account-avatar {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-weight: 600;
  font-size: var(--text-xs);
  flex-shrink: 0;
}

.account-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
}
.account-name {
  display: block;
  width: 100%;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.account-plan {
  display: block;
  width: 100%;
  font-size: var(--text-xs);
  color: var(--text-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.account-menu-trigger {
  flex-shrink: 0;
  color: var(--text-3);
  font-size: var(--text-base);
}

.account-menu {
  position: absolute;
  bottom: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  z-index: 50;
  opacity: 0;
  visibility: hidden;
  transform: translateY(4px) scale(0.98);
  transform-origin: bottom left;
  pointer-events: none;
  transition: opacity var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease), visibility var(--duration-fast) var(--ease);
}
.account-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}
.account-menu a,
.account-menu button {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--text-2);
  text-align: left;
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.account-menu a i.ph,
.account-menu button i.ph { width: 16px; text-align: center; flex-shrink: 0; }
.account-menu a:hover,
.account-menu button:hover { background: var(--bg-subtle); color: var(--text-1); }

/* ── Main area ── */
.app-main {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  min-width: 0;
  background: var(--bg-elevated);
}

.app-topbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  /* iPhone home-screen app: the status bar is transparent and draws over the
     page, so push the top bar down by the height of that area. */
  padding-top: calc(var(--space-4) + env(safe-area-inset-top, 0px));
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.mobile-sidebar-btn {
  display: none;
  width: 30px; height: 30px;
  align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-2);
  flex-shrink: 0;
}

.conversation-title {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 60vw;
}

.topbar-spacer { flex: 1; }

/* ── Conversation ── */
/* Shared reading width for the message list AND the composer, so both
   always line up. Fluid: fills the space on phones/tablets, and caps at a
   comfortable line length on large desktop screens. */
.app-content-wrap { --chat-max-width: 860px; }

.conversation {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--space-7) var(--space-5) var(--space-5);
}

.empty-state {
  max-width: 560px;
  margin: 8vh auto 0;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.empty-state-mark {
  width: 34px;
  margin: 0 0 var(--space-5);
  border-radius: var(--radius-sm);
}
.empty-state-title {
  font-size: var(--text-3xl);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--text-1);
  margin-bottom: var(--space-3);
}
.empty-state-subtitle {
  color: var(--text-3);
  font-size: var(--text-sm);
  line-height: 1.55;
  max-width: 420px;
}

/* ── Composer suggestions — a row of quiet chips docked to the top of
     the composer itself, not the empty state. Shown once per session
     (see wireComposerSuggestions in app.js) and faded out shortly after,
     so returning users aren't shown the same four prompts every time
     they open the chat.

     Desktop: chips wrap onto as many rows as they need.
     Mobile (≤600px): chips sit on ONE row that scrolls sideways, so
     they're never cropped and never push the input down.

     max-height is only there to animate the collapse in .is-hidden; it
     must be comfortably larger than the tallest wrapped layout, or the
     last row gets clipped (that was the "cut off" bug). ── */
.composer-suggestions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: 0 var(--space-1) var(--space-3);
  opacity: 1;
  max-height: 240px;
  overflow: hidden;
  transition: opacity var(--duration-slow) var(--ease), max-height var(--duration-slow) var(--ease), padding var(--duration-slow) var(--ease), margin var(--duration-slow) var(--ease);
}
.composer-suggestions.is-hidden {
  opacity: 0;
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: 0;
  margin-bottom: 0;
}
.composer-suggestion-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-shrink: 0;
  white-space: nowrap;
  padding: 6px 12px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 500;
  color: var(--text-2);
  transition: color var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease), background var(--duration-fast) var(--ease);
}
.composer-suggestion-chip i {
  font-size: 0.9rem;
  color: var(--text-4);
  transition: color var(--duration-fast) var(--ease);
}
.composer-suggestion-chip:hover {
  color: var(--text-1);
  border-color: var(--border-strong);
  background: var(--bg-elevated);
}
.composer-suggestion-chip:hover i { color: var(--accent); }

@media (max-width: 600px) {
  .composer-suggestions {
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Let the strip run edge-to-edge inside the composer card
       (the composer has 12px side padding) and keep a clear gap
       between the chips and the input below. */
    margin-left: calc(var(--space-3) * -1);
    margin-right: calc(var(--space-3) * -1);
    padding: 2px var(--space-3) var(--space-3);
    /* Soft fade on both edges hints that there's more to scroll to. */
    -webkit-mask-image: linear-gradient(to right, transparent 0, #000 var(--space-3), #000 calc(100% - var(--space-5)), transparent 100%);
            mask-image: linear-gradient(to right, transparent 0, #000 var(--space-3), #000 calc(100% - var(--space-5)), transparent 100%);
  }
  .composer-suggestions::-webkit-scrollbar { display: none; }
  /* Slightly roomier chips = easier to tap on a phone. */
  .composer-suggestion-chip { padding: 8px 14px; }
}
@media (prefers-reduced-motion: reduce) {
  .composer-suggestions { transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .attach-menu-list,
  .attach-menu-list .attach-menu-item,
  .quality-picker-menu {
    transition: opacity var(--duration-fast) linear !important;
    animation: none !important;
    transform: none !important;
  }
}

.message-list {
  width: 100%;
  max-width: var(--chat-max-width, 860px);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  min-width: 0;
}

/* ── Message alignment — user right, assistant left.
     Assistant reads as editorial content, not a chat bubble. ── */
.message {
  display: flex;
  min-width: 0;
  animation: fadeInUp var(--duration-base) var(--ease);
}

/* No avatars: assistant replies use the full width of the chat column;
   user messages are right-aligned bubbles that can grow up to 85%. */
.message.is-assistant {
  align-self: stretch;
  width: 100%;
  max-width: 100%;
  flex-direction: row;
}

.message.is-user {
  align-self: flex-end;
  max-width: 85%;
  flex-direction: row-reverse;
}

.message-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.message.is-assistant .message-body { align-items: flex-start; }
.message.is-user .message-body { align-items: flex-end; }

.message-content {
  font-size: var(--text-base);
  line-height: 1.65;
  color: var(--text-1);
  max-width: 100%;
  min-width: 0;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.message.is-user .message-content {
  background: var(--bg-subtle);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  display: inline-block;
  text-align: left;
}

.message-content h1, .message-content h2, .message-content h3,
.message-content h4, .message-content h5, .message-content h6 {
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
  margin: var(--space-5) 0 var(--space-2);
}
.message-content h1 { font-size: 1.4em; }
.message-content h2 { font-size: 1.25em; }
.message-content h3 { font-size: 1.1em; }
.message-content h4, .message-content h5, .message-content h6 { font-size: 1em; }
.message-content h1:first-child, .message-content h2:first-child,
.message-content h3:first-child, .message-content h4:first-child { margin-top: 0; }

.message-content p { margin-bottom: var(--space-3); }
.message-content p:last-child { margin-bottom: 0; }
.message-content ul, .message-content ol { margin: var(--space-3) 0; padding-left: 1.3em; }
.message-content li { margin-bottom: var(--space-2); }
.message-content code {
  background: var(--bg-subtle);
  padding: 2px 6px;
  border-radius: var(--radius-xs);
  font-size: 0.9em;
  overflow-wrap: anywhere;
}

/* Clickable links inside a reply — the base reset sets `a { color:
   inherit }` everywhere, which makes a link inside a message look like
   plain text. This restores a visible, theme-aware link color (accent
   already flips correctly between light/dark via the root variables). */
.message-content a:not(.citation-marker) {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 2px;
  transition: text-decoration-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.message-content a:not(.citation-marker):hover {
  color: var(--accent-hover);
  text-decoration-color: currentColor;
}

/* Fill-in-the-blank template placeholders such as "[target market]" that
   a reply uses on purpose — styled distinctly so they read as intentional
   formula slots rather than a broken/failed link. */
.message-content .md-placeholder {
  color: var(--text-2);
  font-style: italic;
}

.message-content blockquote {
  margin: var(--space-3) 0;
  padding: var(--space-1) 0 var(--space-1) var(--space-3);
  border-left: 3px solid var(--border-strong);
  color: var(--text-3);
}
.message-content hr {
  border: none;
  border-top: 1px solid var(--border);
  margin: var(--space-5) 0;
}

/* ── Code blocks — deliberately fixed-dark regardless of app theme,
     using GitHub's dark "canvas" color (#0d1117 — near-black with a
     blue undertone) so it reads as its own distinct surface even when
     the app's own dark mode background is a similar shade. ── */
.code-block-wrap {
  position: relative;
  max-width: 100%;
  margin: var(--space-4) 0;
}
.message-content pre {
  background: #0d1117;
  border: 1px solid #30363d;
  color: #e6edf3;
  padding: var(--space-4);
  padding-top: 36px;
  border-radius: var(--radius-md);
  overflow-x: auto;
  margin: 0;
  text-align: left;
  white-space: pre;
  max-width: 100%;
}
.message-content pre code {
  background: none;
  padding: 0;
  color: inherit;
  white-space: pre;
  overflow-wrap: normal;
}

.code-copy-btn {
  position: absolute;
  top: 8px;
  right: 8px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px 9px;
  font-size: 11px;
  font-weight: 600;
  color: #c9d1d9;
  background: #21262d;
  border: 1px solid #30363d;
  border-radius: var(--radius-sm);
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
  z-index: 1;
}
.code-copy-btn:hover { background: #30363d; color: #fff; }
.code-copy-btn.is-copied { color: var(--accent-2); }

/* ── KaTeX math ── */
.katex-target { overflow-x: auto; max-width: 100%; }
div.katex-target { display: block; margin: var(--space-3) 0; text-align: center; }
.katex-display { margin: 0; }

.md-table-wrap { overflow-x: auto; margin: var(--space-4) 0; max-width: 100%; }
.md-table { border-collapse: collapse; width: 100%; font-size: var(--text-sm); }
.md-table th, .md-table td {
  border: 1px solid var(--border);
  padding: var(--space-2) var(--space-3);
  text-align: left;
}
.md-table th { background: var(--bg-subtle); font-weight: 600; }

.citation-marker { color: var(--accent); font-weight: 600; font-size: 0.85em; }

/* ── Message attachments (images + files attached by the user) ── */
.message-image-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  max-width: 100%;
}
.message-image {
  max-width: 220px;
  max-height: 220px;
  border-radius: var(--radius-md);
  object-fit: cover;
}

.message-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: var(--space-2);
  max-width: 100%;
}

/* ── Generated document download chip ── */
.document-download-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-1);
  margin-bottom: var(--space-2);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--duration-fast) var(--ease), border-color var(--duration-fast) var(--ease);
}
.document-download-chip i { color: var(--accent); font-size: 1.1rem; }
.document-download-chip:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }

/* ── Generated document download chip — button-specific resets + states ── */
.document-download-chip {
  cursor: pointer;
  font-family: inherit;
}

.document-download-chip:disabled {
  cursor: not-allowed;
  opacity: 0.65;
}

.document-download-chip-state {
  display: inline-flex;
  align-items: center;
  font-size: 1rem;
  color: var(--text-3);
}

.document-download-chip-state:empty {
  display: none;
}

/* ── Shimmer loading effect ── */
.document-download-chip-state.is-loading {
  background: linear-gradient(
    90deg,
    var(--text-3) 0%,
    var(--text-3) 35%,
    var(--text-1) 50%,
    var(--text-3) 65%,
    var(--text-3) 100%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: document-download-shimmer 1.6s ease-in-out infinite;
}

@keyframes document-download-shimmer {
  0% {
    background-position: 200% 0;
  }

  100% {
    background-position: -200% 0;
  }
}

/* ── Accessibility ── */
@media (prefers-reduced-motion: reduce) {
  .document-download-chip-state.is-loading {
    animation: none;
    background: none;
    -webkit-text-fill-color: var(--text-3);
    color: var(--text-3);
  }
}

/* ── Typewriter reveal — a thin blinking caret shown at the end of an
     assistant message while its text is still being typed out. Removed
     once the reveal finishes. ── */
.message-content.is-typing::after {
  content: '';
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--text-3);
  animation: typing-caret-blink 0.85s step-end infinite;
}
@keyframes typing-caret-blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .message-content.is-typing::after { animation: none; }
}

.md-table { table-layout: auto; }
.md-table th, .md-table td {
  white-space: nowrap;
}

/* ── Thought block — small, unobtrusive, not a card ──
     Font sizes here were reduced below the normal --text-xs (12px)
     token on purpose: this is meant to read as quiet, secondary
     text, not a regular label. */
.thought-block {
  margin-bottom: var(--space-3);
  max-width: 100%;
}
.thought-block summary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 0;
  font-size: 0.6875rem; /* 11px — was var(--text-xs) / 12px */
  font-weight: 500;
  color: var(--text-4);
  cursor: pointer;
  list-style: none;
}
.thought-block summary::-webkit-details-marker { display: none; }
.thought-caret {
  font-size: 0.65rem;
  flex-shrink: 0;
  color: var(--text-4);
  transition: transform var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.thought-block[open] .thought-caret { transform: rotate(90deg); }
.thought-block summary:hover { color: var(--text-2); }
.thought-block summary:hover .thought-caret { color: var(--text-2); }
.thought-content {
  margin-top: var(--space-2);
  padding: var(--space-1) 0 var(--space-2) var(--space-3);
  border-left: 2px solid var(--border);
  font-size: 0.6875rem; /* 11px — was var(--text-xs) / 12px */
  color: var(--text-3);
  line-height: 1.6;
  overflow-wrap: anywhere;
}

/* The markdown renderer wraps thought text in <p>, <li>, etc. Those tags
   are targeted directly by a global rule in shared.css (p { font-size:
   var(--text-base) }), which overrides simple inheritance from
   .thought-content above. These rules force every text element inside
   the thought block back down to the small size. */
.thought-content p,
.thought-content li,
.thought-content span,
.thought-content code,
.thought-content blockquote,
.thought-content h1,
.thought-content h2,
.thought-content h3,
.thought-content h4,
.thought-content h5,
.thought-content h6 {
  font-size: inherit;
}
.thought-content p { margin-bottom: var(--space-2); }
.thought-content ul,
.thought-content ol { margin: var(--space-2) 0; padding-left: 1.2em; }

/* Tool-using turns show only a short heading here instead of raw
   reasoning (see _thinkingHeadingFromSteps in chat-endpoint.js) — no
   bullet/paragraph spacing needed for a single line. */
.thought-content--heading {
  margin-bottom: 0;
  padding-bottom: 0;
}

.message-sources {
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  width: 100%;
}
.message-sources-label {
  font-size: 0.625rem; /* 10px — was var(--text-xs) / 12px */
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-4);
  margin-bottom: var(--space-2);
}
.message-sources-list { font-size: var(--text-xs); padding-left: 1.2em; color: var(--text-2); }
.message-sources-list a { color: var(--accent); }
.message-sources-list a:hover { text-decoration: underline; }

.message-actions {
  display: flex;
  gap: var(--space-1);
  margin-top: var(--space-3);
  opacity: 0;
  transition: opacity var(--duration-fast) var(--ease);
}
.message:hover .message-actions,
.message-actions:focus-within { opacity: 1; }
/* No hover on touch screens — without this the copy/regenerate buttons
   could never be seen or tapped on a phone. */
@media (hover: none) {
  .message-actions { opacity: 1; }
  .message-action-btn { width: 32px; height: 32px; }
}
.message-action-btn {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-3);
  font-size: var(--text-sm);
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.message-action-btn:hover { background: var(--bg-subtle); color: var(--text-1); }

/* ── Thinking indicator — quiet inline text with a soft pulsing
     dot, not a spinner and not "AI is thinking…" ── */
.thinking-indicator {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text-3);
  font-size: var(--text-xs); /* 12px — was var(--text-sm) / 14px */
  font-weight: 450;
  padding: 4px 0;
}
.thinking-dot {
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent-2);
  flex-shrink: 0;
  animation: thinking-pulse 1.3s ease-in-out infinite;
}
@keyframes thinking-pulse {
  0%, 100% { opacity: 0.35; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1); }
}
.thinking-word {
  font-weight: 450;
  background: linear-gradient(
    90deg,
    var(--text-3) 0%,
    var(--text-3) 35%,
    var(--text-1) 50%,
    var(--text-3) 65%,
    var(--text-3) 100%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: thinking-word-shimmer 1.6s ease-in-out infinite;
}
@keyframes thinking-word-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.thinking-timer { color: var(--text-4); font-variant-numeric: tabular-nums; font-size: 0.625rem; } /* 10px — was var(--text-xs) / 12px */

@media (prefers-reduced-motion: reduce) {
  .thinking-word {
    animation: none;
    background: none;
    -webkit-text-fill-color: var(--text-3);
    color: var(--text-3);
  }
}

/* ── Composer — the most polished surface in the app: a soft
     elevated panel with a thin inner highlight, not a plain box ── */
.composer-wrap { padding: 0 var(--space-5) var(--space-5); flex-shrink: 0; }

.composer {
  width: 100%;
  max-width: var(--chat-max-width, 860px);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  padding: var(--space-3) var(--space-3) var(--space-2);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255,255,255,0.5);
  transition: border-color var(--duration-base) var(--ease), box-shadow var(--duration-base) var(--ease);
}
@media (prefers-color-scheme: dark) {
  .composer { box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255,255,255,0.03); }
}
.composer:focus-within { border-color: var(--accent-2); box-shadow: var(--shadow-lg); }

/* ── Staged attachments (before sending) ── */
.composer-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 var(--space-1) var(--space-2);
}
.attachment-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  color: var(--text-2);
  max-width: 220px;
}
.attachment-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attachment-chip button { color: var(--text-4); flex-shrink: 0; }
.attachment-chip button:hover { color: var(--danger); }
.attachment-chip-image img {
  width: 20px; height: 20px;
  object-fit: cover;
  border-radius: var(--radius-2xs);
  flex-shrink: 0;
}
.attachment-chip-static { cursor: default; }

.composer-input {
  width: 100%;
  border: none;
  outline: none;
  resize: none;
  background: transparent;
  font-size: var(--text-base);
  line-height: 1.5;
  color: var(--text-1);
  padding: var(--space-1) var(--space-1) var(--space-2);
  max-height: 200px;
}
.composer-input::placeholder {
  color: var(--text-4);
  font-size: var(--text-sm);
}

.composer-tools-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.composer-tools-left,
.composer-tools-right {
  display: flex;
  align-items: center;
  gap: var(--space-1);
}

.composer-tool-btn {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-3);
  flex-shrink: 0;
  position: relative;
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease-pop);
}
.composer-tool-btn:hover { background: var(--bg-subtle); color: var(--text-1); }
.composer-tool-btn:active { transform: scale(0.9); }

/* ── "+" attach menu ── */
.attach-menu { position: relative; flex-shrink: 0; }

.attach-menu-list {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  width: 240px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  z-index: 60;
  /* Always in the DOM (like .account-menu) so the close motion has
     something to animate — display:none can't be transitioned. */
  opacity: 0;
  visibility: hidden;
  transform: scale(0.94) translateY(6px);
  transform-origin: bottom left;
  pointer-events: none;
  transition: opacity var(--duration-fast) var(--ease-pop),
              transform var(--duration-fast) var(--ease-pop),
              visibility var(--duration-fast) var(--ease-pop);
}
.attach-menu-list.is-open {
  opacity: 1;
  visibility: visible;
  transform: scale(1) translateY(0);
  pointer-events: auto;
}
/* Each item rises in a beat behind the last, so the menu reads as one
   composed reveal rather than a static rectangle popping into place.
   Capped at 6 items — beyond that the stagger would read as lag. */
.attach-menu-list.is-open .attach-menu-item {
  animation: attachItemRise var(--duration-base) var(--ease-pop) backwards;
}
.attach-menu-list.is-open .attach-menu-item:nth-child(1) { animation-delay: 0ms; }
.attach-menu-list.is-open .attach-menu-item:nth-child(2) { animation-delay: 18ms; }
.attach-menu-list.is-open .attach-menu-item:nth-child(3) { animation-delay: 36ms; }
.attach-menu-list.is-open .attach-menu-item:nth-child(4) { animation-delay: 54ms; }
.attach-menu-list.is-open .attach-menu-item:nth-child(5) { animation-delay: 72ms; }
.attach-menu-list.is-open .attach-menu-item:nth-child(6) { animation-delay: 90ms; }
@keyframes attachItemRise {
  from { opacity: 0; transform: translateY(3px); }
  to   { opacity: 1; transform: translateY(0); }
}

.attach-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--text-2);
  text-align: left;
  position: relative;
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease);
}
.attach-menu-item:hover { background: var(--bg-subtle); color: var(--text-1); }
.attach-menu-item i:first-child {
  font-size: 1rem;
  color: var(--text-3);
  flex-shrink: 0;
  width: 18px;
  text-align: center;
}

/* Locked (plan-gated) menu item gets a small lock badge rather than
   silently doing nothing when clicked. Uses an inline SVG rather than an
   icon-font codepoint, so it renders correctly regardless of font
   loading order or icon-set version. */
.attach-menu-item.is-locked { color: var(--text-4); }
.attach-menu-item.is-locked::after {
  content: '';
  position: absolute;
  top: 6px;
  right: 8px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath fill='%23888880' d='M208 80h-24V56a56 56 0 0 0-112 0v24H48a16 16 0 0 0-16 16v112a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16V96a16 16 0 0 0-16-16ZM96 56a32 32 0 0 1 64 0v24H96Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 9px 9px;
}

/* ── Quality picker ── */
.quality-picker {
  position: relative;
  flex-shrink: 0;
}

.quality-picker-trigger {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px var(--space-3) 6px var(--space-2);
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text-2);
  font-size: var(--text-xs);
  font-weight: 600;
  white-space: nowrap;
  transition: background var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease), transform var(--duration-fast) var(--ease-pop);
}
.quality-picker-trigger:hover { background: var(--border); color: var(--text-1); }
.quality-picker-trigger:active { transform: scale(0.96); }
.quality-picker-trigger i:first-child { font-size: 0.9rem; color: var(--accent); }
.quality-picker-caret { font-size: 0.65rem; color: var(--text-4); transition: transform var(--duration-fast) var(--ease-pop); }
.quality-picker-trigger.is-open .quality-picker-caret { transform: rotate(180deg); }

.quality-picker-menu {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  left: auto;
  width: 260px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--space-1);
  z-index: 60;
  opacity: 0;
  visibility: hidden;
  transform: scale(0.94) translateY(6px);
  transform-origin: bottom right;
  pointer-events: none;
  transition: opacity var(--duration-fast) var(--ease-pop),
              transform var(--duration-fast) var(--ease-pop),
              visibility var(--duration-fast) var(--ease-pop);
}
.quality-picker-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: scale(1) translateY(0);
  pointer-events: auto;
}

.quality-picker-option {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-2) var(--space-2);
  border-radius: var(--radius-sm);
  text-align: left;
  position: relative;
  transition: background var(--duration-fast) var(--ease);
}
.quality-picker-option:hover { background: var(--bg-subtle); }
.quality-picker-option > i:first-child {
  font-size: 1rem;
  color: var(--text-3);
  flex-shrink: 0;
  width: 18px;
  text-align: center;
}

.quality-picker-option-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.quality-picker-option-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-1); }
.quality-picker-option-desc { font-size: var(--text-xs); color: var(--text-3); }

.quality-picker-check {
  flex-shrink: 0;
  font-size: 0.9rem;
  color: var(--accent);
  opacity: 0;
}
.quality-picker-option.is-active .quality-picker-check { opacity: 1; }

/* Locked (plan-gated) quality level — same treatment as attach-menu-item:
   dimmed text and a small lock badge, rather than a button that silently
   does nothing (or worse, silently applies a lower tier) when clicked.
   Uses an inline SVG rather than an icon-font codepoint, so it renders
   correctly regardless of font loading order or icon-set version. */
.quality-picker-option.is-locked .quality-picker-option-name,
.quality-picker-option.is-locked .quality-picker-option-desc { color: var(--text-4); }
.quality-picker-option.is-locked > i:first-child { color: var(--text-4); }
.quality-picker-option.is-locked::after {
  content: '';
  position: absolute;
  top: 6px;
  right: 8px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath fill='%23888880' d='M208 80h-24V56a56 56 0 0 0-112 0v24H48a16 16 0 0 0-16 16v112a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16V96a16 16 0 0 0-16-16ZM96 56a32 32 0 0 1 64 0v24H96Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 9px 9px;
}

.composer-send-btn {
  width: 32px; height: 32px;
  border-radius: 50%;
  background: var(--text-1);
  color: var(--bg-base);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background var(--duration-fast) var(--ease), opacity var(--duration-fast) var(--ease);
}
.composer-send-btn:hover:not(:disabled) { background: var(--accent); }
.composer-send-btn:disabled { background: var(--border); color: var(--text-4); cursor: not-allowed; }

.composer-hint {
  text-align: center;
  font-size: 0.6875rem; /* 11px — was var(--text-xs) / 12px */
  color: var(--text-4);
  margin-top: var(--space-2);
}

/* ── Toast ── */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--text-1);
  color: var(--bg-base);
  padding: 10px 18px;
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: 500;
  box-shadow: var(--shadow-md);
  z-index: 2000;
  max-width: 90vw;
  text-align: center;
}

/* ── Modal ──
   .is-open is added/removed by shell.js's openModal/closeModal (which
   also handles the hidden-attribute timing) — this file only owns what
   that class looks like. The overlay fades; the box itself also rises
   and scales in very slightly, so it reads as an object arriving in
   front of you rather than a rectangle blinking into existence. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: var(--bg-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: var(--space-4);
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-pop);
}
.modal-overlay.is-open { opacity: 1; }
.modal-box {
  width: min(440px, 92vw);
  max-height: 90vh;
  max-height: 90dvh;
  overflow-y: auto;
  background: var(--bg-elevated);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  transform: scale(0.97) translateY(8px);
  transition: transform var(--duration-base) var(--ease-pop);
}
.modal-overlay.is-open .modal-box { transform: scale(1) translateY(0); }
@media (prefers-reduced-motion: reduce) {
  .modal-overlay, .modal-box { transition: opacity var(--duration-fast) linear !important; transform: none !important; }
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
}
.modal-header h2 { font-size: var(--text-lg); font-weight: 600; color: var(--text-1); }
.modal-close-btn {
  width: 28px; height: 28px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--bg-subtle);
  color: var(--text-3);
}
.modal-close-btn:hover { color: var(--text-1); }

.modal-body {
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.modal-field { display: flex; flex-direction: column; gap: var(--space-2); }
.modal-field span { font-size: var(--text-sm); font-weight: 600; color: var(--text-1); }
.modal-field textarea {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  font-size: var(--text-sm);
  color: var(--text-1);
  resize: vertical;
  outline: none;
  background: var(--bg-subtle);
  transition: border-color var(--duration-fast) var(--ease);
}
.modal-field textarea:focus { border-color: var(--accent-2); background: var(--bg-elevated); }

.visual-type-toggle { display: flex; gap: var(--space-2); flex-wrap: wrap; }
.visual-type-option {
  flex: 1;
  min-width: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-3);
  transition: border-color var(--duration-fast) var(--ease), color var(--duration-fast) var(--ease), background var(--duration-fast) var(--ease);
}
.visual-type-option.is-active { border-color: var(--accent); color: var(--accent); background: var(--accent-subtle); }

.modal-submit-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3);
  background: var(--text-1);
  color: var(--bg-base);
  border-radius: var(--radius-md);
  font-weight: 600;
  transition: opacity var(--duration-fast) var(--ease);
}
.modal-submit-btn:hover:not(:disabled) { opacity: 0.85; }
.modal-submit-btn:disabled { opacity: 0.6; cursor: not-allowed; }

/* ── Connectors modal ── */
.connector-list { display: flex; flex-direction: column; gap: var(--space-2); }
.connector-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
}
.connector-row i.ph { font-size: 22px; color: var(--text-2); flex-shrink: 0; }
.connector-row-icon { width: 22px; height: 22px; flex-shrink: 0; }
.connector-row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.connector-row-name { font-size: var(--text-sm); font-weight: 600; color: var(--text-1); }
.connector-row-desc { font-size: var(--text-xs); color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.connector-row-desc.is-connected { color: var(--accent); font-weight: 600; }
.connector-row-hint { display: block; font-size: var(--text-xs); color: var(--text-3); white-space: normal; margin-top: 2px; }
.connector-row-cta {
  flex-shrink: 0;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  color: var(--text-1);
  transition: opacity var(--duration-fast) var(--ease);
}
.connector-row-cta:hover:not(:disabled) { opacity: 0.75; }
.connector-row-cta:disabled { opacity: 0.6; cursor: not-allowed; }
.connector-row-cta.is-danger { color: var(--danger); border-color: var(--danger); }
.connectors-modal-footnote { font-size: var(--text-xs); color: var(--text-3); line-height: 1.5; }
.connectors-modal-footnote a { color: var(--accent); font-weight: 600; }

/* Plan-gate explanation shown at the top of the modal for any plan
   without connectorTools (see entitlements.js / updateConnectorsAvailability).
   Deliberately distinct from .connectors-modal-banner, which is a
   transient OAuth-redirect result message — this one stays up for the
   whole time a locked account has the modal open. */
.connectors-modal-plan-note {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3);
  border-radius: var(--radius-md);
  background: var(--accent-subtle);
  border: 1px solid var(--accent);
  color: var(--text-1);
  font-size: var(--text-xs);
  line-height: 1.5;
  margin-bottom: var(--space-3);
}
.connectors-modal-plan-note i { flex-shrink: 0; font-size: 1rem; color: var(--accent); margin-top: 1px; }
.connectors-modal-plan-note a { color: var(--accent); font-weight: 600; margin-left: 4px; }

/* A connector row this plan can't actually use yet (not-yet-connected,
   Free tier). Same dimmed treatment as .attach-menu-item.is-locked and
   .quality-picker-option.is-locked, applied here instead of a lock
   badge since the row already carries its own "Upgrade" button. */
.connector-row.is-locked { opacity: 0.7; }
.connector-row-cta.is-locked {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--text-3);
}
.connector-row-cta.is-locked i { font-size: 0.85em; }

/* ── In-chat tool confirmation (inline trace row) ──
   A pending write no longer floats in its own separate card below the
   reply text — it's the trace's own terminal row (see renderMessage in
   js/app.js), so approving it reads as "the next step in the list",
   which is what it actually is. Distinct from the plain read-only rows
   above it: a soft highlighted background, a full-size label (not the
   muted .tool-trace-card default), and the Confirm/Cancel buttons
   inline on the same row. */
.tool-trace-card--confirm {
  margin-top: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  color: var(--text-1);
  font-size: var(--text-sm);
  flex-wrap: wrap;
}
.tool-trace-card--confirm i.ph-hand-palm { color: #c8952f; }
.tool-trace-card--confirm .tool-trace-card-label { flex: 1 1 auto; min-width: 160px; }
.tool-trace-card-actions { display: flex; gap: var(--space-2); margin-left: auto; }
.tool-confirm-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: 600;
  transition: opacity var(--duration-fast) var(--ease);
}
.tool-confirm-btn:disabled { opacity: 0.6; cursor: not-allowed; }
.tool-confirm-btn--confirm { background: var(--text-1); color: var(--bg-base); }
.tool-confirm-btn--confirm:hover:not(:disabled) { opacity: 0.85; }
.tool-confirm-btn--cancel { background: transparent; border: 1px solid var(--border); color: var(--text-2); }
.tool-confirm-btn--cancel:hover:not(:disabled) { background: var(--bg-elevated); }

/* Action Trace: an ordered record of the steps the agent loop actually
   ran — either silently-executed reads (list/get/search) or writes the
   user already confirmed. Deliberately lighter-weight than
   .tool-trace-card--confirm (no padding/border box) since it's a passive
   log, not a prompt. .tool-trace-list stacks multiple steps from one
   turn with a tighter gap than the default message spacing. */
.tool-trace-list { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
.tool-trace-card {
  margin-top: 0;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--text-3);
}
.tool-trace-card i.ph { font-size: var(--text-sm); flex-shrink: 0; }
.tool-trace-card--ok i.ph { color: var(--accent, var(--text-2)); }
.tool-trace-card--error { color: var(--text-2); }
.tool-trace-card--error i.ph { color: #d0645a; }
.tool-trace-card--blocked { color: var(--text-2); }
.tool-trace-card--blocked i.ph { color: #c8952f; }
.tool-trace-card--done i.ph { color: var(--accent, var(--text-2)); }
.tool-trace-card--done .tool-trace-card-label { font-weight: 500; color: var(--text-2); }

/* Live step-in-progress state (createLiveTurnIndicator in js/app.js) — a
   card in this state is a real "the agent is working on the next step
   right now" placeholder, inserted the instant a `round` SSE event
   arrives from the backend: spinning icon (.trace-spin) and a
   shimmering label using the same text-gradient technique as
   .thinking-word above. It's swapped for the real, settled card the
   moment the matching `step` event arrives with that step's actual
   result. */
.tool-trace-card--pending i.ph { color: var(--text-4); }
.tool-trace-card--pending .tool-trace-card-label {
  background: linear-gradient(
    90deg,
    var(--text-4) 0%,
    var(--text-4) 35%,
    var(--text-1) 50%,
    var(--text-4) 65%,
    var(--text-4) 100%
  );
  background-size: 200% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  animation: thinking-word-shimmer 1.4s ease-in-out infinite;
}
.trace-spin { animation: trace-spin-rotate 0.85s linear infinite; }
@keyframes trace-spin-rotate { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .tool-trace-card--pending .tool-trace-card-label {
    animation: none;
    background: none;
    -webkit-text-fill-color: var(--text-4);
    color: var(--text-4);
  }
  .trace-spin { animation: none; }
}


/* ── Responsive ── */
@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr; }

  .app-sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    height: 100vh;
    height: 100dvh;
    width: 272px !important;
    padding: var(--space-4) var(--space-3) !important;
    padding-top: calc(var(--space-4) + env(safe-area-inset-top, 0px)) !important;
    z-index: 200;
    transform: translateX(-100%);
    transition: transform var(--duration-base) var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .app-sidebar.is-open { transform: translateX(0); }
  .app-sidebar.is-open .sidebar-logo span,
  .app-sidebar.is-open .new-chat-btn span:not(.ph),
  .app-sidebar.is-open .sidebar-history,
  .app-sidebar.is-open .usage-widget,
  .app-sidebar.is-open .account-info,
  .app-sidebar.is-open .account-menu-trigger,
  .app-sidebar.is-open .upgrade-link span { display: flex; }
  .app-sidebar.is-open .account-info { display: flex; }

  .sidebar-collapse-btn { display: none; }
  .sidebar-close-btn { display: flex; }

  .sidebar-scrim {
    display: block;
    position: fixed;
    inset: 0;
    background: var(--bg-overlay);
    z-index: 150;
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease);
  }
  .sidebar-scrim.is-visible { opacity: 1; pointer-events: auto; }

  .mobile-sidebar-btn { display: flex; }
  .conversation-title { max-width: 46vw; }

  .message.is-user { max-width: 90%; }
  .conversation { padding-top: var(--space-5); }

  .quality-picker-menu {
    position: fixed;
    left: var(--space-4);
    right: var(--space-4);
    bottom: auto;
    top: auto;
    /* This translateY is what anchors the menu above the composer on
       mobile — see the .is-open override just below for why it must
       be repeated there rather than left to the desktop rule. */
    transform: translateY(calc(-100% - 68px)) scale(0.96);
    transform-origin: bottom center;
    width: auto;
  }
  /* The desktop `.attach-menu-list.is-open` / `.quality-picker-menu.is-open`
     rules (same two-class specificity) would otherwise win this fight and
     wipe out the translateY(-100% - 68px) anchor above the instant the
     menu opens — the exact bug that made these menus fly off to the
     wrong spot on mobile. Redeclaring the anchor here, inside the same
     media query, keeps it in every state without depending on which
     rule happens to lose the specificity contest. */
  .quality-picker-menu.is-open {
    transform: translateY(calc(-100% - 68px)) scale(1);
  }

  .attach-menu-list {
    position: fixed;
    left: var(--space-4);
    right: auto;
    bottom: auto;
    top: auto;
    transform: translateY(calc(-100% - 68px)) scale(0.96);
    transform-origin: bottom left;
    width: 240px;
  }
  .attach-menu-list.is-open {
    transform: translateY(calc(-100% - 68px)) scale(1);
  }
}


/* ══════════════════════════════════════════════════════════════
   Note Taker — redone for a tighter, native-iOS-sheet feel.
   Rewritten (not minified) on purpose: this block used to be one
   1900-character line, which made every future diff unreviewable.
   Sizes below are deliberately ~15–20% smaller across the board —
   the old version read as "everything is big" because every
   element (title, inputs, buttons, transcript rows) independently
   reached for a generous size with nothing to anchor it back down.
   ══════════════════════════════════════════════════════════════ */
.attach-menu-item small { display: block; color: var(--text-4); font-size: 11px; font-weight: 400; margin-top: 2px; }
.attach-menu-item strong { display: block; }

.note-taker-modal { position: fixed; inset: 0; z-index: 100; background: var(--bg-overlay); display: grid; place-items: center; padding: var(--space-4); }
.note-taker-modal[hidden], .note-taker-chip[hidden] { display: none; }
.note-taker-panel {
  width: min(680px, 100%); max-height: min(760px, calc(100dvh - 32px)); overflow: auto;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg); padding: var(--space-6);
}
.note-taker-header, .note-taker-complete-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--space-3); }
.note-taker-header h2, .note-taker-complete h3 { margin: 0; font-size: var(--text-lg); font-weight: 600; letter-spacing: -0.01em; color: var(--text-1); }
.note-taker-header p, .note-taker-complete-head p { margin: 4px 0 0; font-size: var(--text-sm); color: var(--text-2); }
.note-taker-icon-btn { display: grid; place-items: center; width: 44px; height: 44px; margin: -10px -10px 0 0; border: 0; border-radius: var(--radius-sm); background: none; color: var(--text-3); cursor: pointer; }
.note-taker-icon-btn:hover { color: var(--text-1); background: var(--bg-subtle); }
.note-taker-recovery { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-4); padding: var(--space-3) var(--space-4); background: var(--accent-subtle); border-radius: var(--radius-sm); }
.note-taker-recovery p { margin: 0; font-size: var(--text-sm); color: var(--text-1); overflow-wrap: anywhere; }
.note-taker-recovery-actions { display: flex; gap: var(--space-1); flex-shrink: 0; }
.note-taker-setup { display: grid; gap: var(--space-4); margin-top: var(--space-6); }
.note-taker-setup label { display: grid; gap: 6px; font-size: var(--text-sm); font-weight: 500; color: var(--text-2); }
.note-taker-setup input, .note-taker-setup select, .note-taker-editor {
  width: 100%; min-height: 44px; padding: 0 var(--space-3); font: inherit; font-size: var(--text-base, 15px); color: var(--text-1);
  background: var(--bg-base); border: 1px solid var(--border); border-radius: var(--radius-sm); outline: 0;
}
.note-taker-setup input:focus, .note-taker-setup select:focus, .note-taker-editor:focus { border-color: var(--accent-2); background: var(--bg-elevated); }
.note-taker-hint { margin: -8px 0 0; font-size: var(--text-xs); line-height: 1.5; color: var(--text-3); }
.note-taker-error { margin: 0; padding: var(--space-3); font-size: var(--text-sm); color: var(--danger); background: var(--danger-subtle); border-radius: var(--radius-sm); }
.note-taker-primary, .note-taker-secondary, .note-taker-stop, .note-taker-ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 0 var(--space-4);
  border: 0; border-radius: var(--radius-sm); font: inherit; font-size: var(--text-sm); font-weight: 600; cursor: pointer;
  transition: background-color 0.15s, color 0.15s;
}
.note-taker-primary { background: var(--accent); color: #fff; }
.note-taker-primary:hover:not(:disabled) { background: var(--accent-hover); }
.note-taker-primary:disabled { opacity: 0.5; cursor: default; }
.note-taker-setup .note-taker-primary { width: 100%; }
.note-taker-secondary { background: var(--bg-subtle); color: var(--text-1); }
.note-taker-secondary:hover { background: var(--border); }
.note-taker-ghost { background: none; color: var(--text-2); font-weight: 500; }
.note-taker-ghost:hover { background: var(--bg-subtle); color: var(--text-1); }
.note-taker-stop { margin-left: auto; background: var(--danger-subtle); color: var(--danger); }
.note-taker-stop:hover { background: color-mix(in srgb, var(--danger) 18%, transparent); }
.note-taker-modal :is(button, input, select, textarea, [tabindex]):focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.note-taker-live { margin-top: var(--space-5); }
.note-taker-status { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; font-size: var(--text-sm); color: var(--text-2); }
.note-taker-status strong { color: var(--text-1); font-weight: 600; }
.note-taker-timer { font-variant-numeric: tabular-nums; color: var(--text-1); }
.note-taker-connection { flex-basis: 100%; padding-left: 16px; font-size: var(--text-xs); color: var(--text-3); }
.note-taker-connection:empty { display: none; }
.note-taker-pulse { width: 8px; height: 8px; flex-shrink: 0; border-radius: 50%; background: var(--text-4); transition: box-shadow 0.08s; }
[data-state="recording"] .note-taker-pulse, [data-state="degraded"] .note-taker-pulse { background: var(--danger); box-shadow: 0 0 0 calc(var(--level, 0) * 6px) color-mix(in srgb, var(--danger) 28%, transparent); }
[data-state="error"] .note-taker-pulse { background: var(--warning); }
.note-taker-transcript { height: clamp(220px, 46dvh, 420px); margin-top: var(--space-4); padding: var(--space-4) 0; overflow: auto; border-block: 1px solid var(--border); }
.note-segment { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: var(--space-3); margin: 0 0 var(--space-3); font-size: var(--text-base, 15px); line-height: 1.65; max-width: 62ch; overflow-wrap: anywhere; }
.note-segment time { padding-top: 3px; font-size: 12px; font-variant-numeric: tabular-nums; color: var(--text-4); }
.note-segment.interim { color: var(--text-3); }
.note-taker-empty { margin: 0; padding: var(--space-8) var(--space-4); text-align: center; font-size: var(--text-sm); color: var(--text-3); }
.note-taker-controls { display: flex; gap: var(--space-2); padding-top: var(--space-4); }
.note-taker-complete { margin-top: var(--space-5); }
.note-taker-editor { display: block; min-height: 300px; margin: var(--space-4) 0; padding: var(--space-4); resize: vertical; line-height: 1.7; }
.note-taker-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); }
/* ── Saved notes: tabs, save state, summary, list ── */
.note-taker-tabs { display: flex; gap: var(--space-5); margin-top: var(--space-4); border-bottom: 1px solid var(--border); }
.note-taker-tab {
  position: relative; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 0 2px;
  border: 0; background: none; font: inherit; font-size: var(--text-sm); font-weight: 500; color: var(--text-3); cursor: pointer;
  transition: color var(--duration-fast) var(--ease);
}
.note-taker-tab:hover { color: var(--text-1); }
.note-taker-tab[aria-selected="true"] { color: var(--text-1); }
.note-taker-tab[aria-selected="true"]::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; background: var(--accent); }
.note-taker-tab-count { font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-3); }
.note-taker-agenda summary { min-height: 44px; display: flex; align-items: center; font-size: var(--text-sm); font-weight: 500; color: var(--text-2); cursor: pointer; }
.note-taker-agenda[open] summary { min-height: 32px; }
.note-taker-agenda textarea {
  display: block; width: 100%; padding: var(--space-3); margin-bottom: var(--space-2); font: inherit; font-size: var(--text-sm); line-height: 1.6; color: var(--text-1);
  background: var(--bg-base); border: 1px solid var(--border); border-radius: var(--radius-sm); outline: 0; resize: vertical;
}
.note-taker-agenda textarea:focus { border-color: var(--accent-2); background: var(--bg-elevated); }
.note-taker-agenda .note-taker-hint { margin: 0; }
.note-taker-setup .note-taker-check { display: flex; align-items: center; gap: var(--space-3); min-height: 44px; font-weight: 400; color: var(--text-1); cursor: pointer; }
.note-taker-setup .note-taker-check input { width: 18px; height: 18px; min-height: 0; padding: 0; flex-shrink: 0; accent-color: var(--accent); }
.note-taker-title-input {
  width: 100%; min-height: 32px; margin: 0; padding: 0 0 2px; font: inherit; font-size: var(--text-lg); font-weight: 600; letter-spacing: -0.01em; color: var(--text-1);
  background: none; border: 0; border-bottom: 1px solid transparent; border-radius: 0; outline: 0; text-overflow: ellipsis;
}
.note-taker-title-input:hover { border-bottom-color: var(--border-strong); }
.note-taker-title-input:focus { border-bottom-color: var(--accent-2); }
.note-taker-title-input::placeholder { color: var(--text-3); }
.note-taker-complete-head > div { min-width: 0; flex: 1; }
.note-taker-complete-head .note-taker-ghost { flex-shrink: 0; }
.note-taker-save-state { margin: 0 0 var(--space-3); font-size: var(--text-xs); line-height: 1.5; color: var(--text-3); }
.note-taker-save-state[data-error="true"] { color: var(--danger); font-size: var(--text-sm); }
.note-taker-actions-main .note-taker-primary { margin-left: 0; }
.note-taker-actions-more { margin-top: var(--space-4); gap: var(--space-1); }
.note-taker-delete { margin-left: auto; }
.note-taker-delete:hover { color: var(--danger); background: var(--danger-subtle); }
:is(#noteTakerSave, #noteTakerSummarize).is-busy i { animation: spin 0.9s linear infinite; }
.note-taker-summary { margin-top: var(--space-5); padding-top: var(--space-5); border-top: 1px solid var(--border); }
.note-summary-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.note-taker-summary h3 { margin: 0; font-size: var(--text-lg); font-weight: 600; color: var(--text-1); }
.note-taker-summary h4 { margin: var(--space-5) 0 var(--space-2); font-size: var(--text-sm); font-weight: 600; color: var(--text-1); }
.note-overview { margin: 0; max-width: 62ch; font-size: var(--text-base); line-height: 1.65; color: var(--text-1); }
.note-taker-summary ul { margin: 0; padding-left: 1.1em; max-width: 62ch; font-size: var(--text-sm); line-height: 1.6; color: var(--text-1); }
.note-taker-summary li { margin-bottom: 6px; overflow-wrap: anywhere; }
.note-taker-summary ul.note-actions { list-style: none; padding: 0; }
.note-actions li { padding: var(--space-2) 0; border-bottom: 1px solid var(--border); margin: 0; }
.note-actions li:last-child { border-bottom: 0; }
.note-actions small { display: block; margin-top: 2px; font-size: var(--text-xs); color: var(--text-3); }
.note-skeleton { display: grid; gap: var(--space-3); }
.note-skeleton span, .note-row-skeleton { display: block; border-radius: 4px; background: linear-gradient(90deg, var(--bg-subtle) 25%, var(--border) 50%, var(--bg-subtle) 75%); background-size: 200% 100%; animation: skeleton-sweep 1.4s ease-in-out infinite; }
.note-skeleton span { height: 14px; }
.note-skeleton span:nth-child(2) { width: 85%; }
.note-skeleton span:nth-child(3) { width: 60%; }
.note-taker-saved { margin-top: var(--space-4); }
.note-taker-search { position: relative; display: block; }
.note-taker-search i { position: absolute; left: var(--space-3); top: 50%; transform: translateY(-50%); color: var(--text-3); pointer-events: none; }
.note-taker-search input {
  width: 100%; min-height: 44px; padding: 0 var(--space-3) 0 36px; font: inherit; font-size: var(--text-base, 15px); color: var(--text-1);
  background: var(--bg-base); border: 1px solid var(--border); border-radius: var(--radius-sm); outline: 0;
}
.note-taker-search input:focus { border-color: var(--accent-2); background: var(--bg-elevated); }
.note-taker-search input:disabled { opacity: 0.5; }
.note-taker-saved .note-taker-error { margin-top: var(--space-3); }
.note-taker-saved-list { margin-top: var(--space-3); }
.note-row { display: grid; gap: 2px; width: 100%; padding: var(--space-3) var(--space-2); text-align: left; font: inherit; color: var(--text-1); background: none; border: 0; border-bottom: 1px solid var(--border); border-radius: 0; cursor: pointer; }
.note-row:hover { background: var(--bg-subtle); }
.note-row:disabled { cursor: progress; opacity: 0.6; }
.note-row-top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); }
.note-row-top strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--text-base, 15px); font-weight: 600; }
.note-row-top time { flex-shrink: 0; font-size: var(--text-xs); color: var(--text-3); }
.note-row-meta { font-size: var(--text-xs); color: var(--text-3); }
.note-row-meta:empty { display: none; }
.note-row-preview { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; font-size: var(--text-sm); line-height: 1.5; color: var(--text-2); overflow-wrap: anywhere; }
.note-row-skeleton { height: 64px; margin-bottom: var(--space-2); }
.note-empty-sub { margin: var(--space-2) auto var(--space-4); max-width: 40ch; font-size: var(--text-xs); line-height: 1.5; color: var(--text-3); }
.note-taker-saved .note-taker-empty p { margin: 0; }
.note-taker-saved .note-taker-hint { margin: var(--space-3) 0 0; }
.note-taker-tabs[hidden], .note-taker-saved[hidden], .note-taker-summary[hidden], .note-taker-delete[hidden], .note-taker-hint[hidden], .note-taker-tab-count[hidden] { display: none; }
@media (prefers-reduced-motion: reduce) {
  .note-skeleton span, .note-row-skeleton { animation: none; }
  :is(#noteTakerSave, #noteTakerSummarize).is-busy i { animation: none; }
}
@media (max-width: 600px) {
  .note-taker-actions-main button { flex: 1; }
  .note-taker-actions-more .note-taker-ghost { flex: 1 1 auto; }
  .note-taker-delete { margin-left: 0; }
  .note-summary-head .note-taker-ghost { padding: 0 var(--space-2); }
}
.note-taker-chip {
  position: fixed; right: var(--space-4); bottom: calc(var(--space-4) + env(safe-area-inset-bottom)); z-index: 90;
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 var(--space-4);
  border: 1px solid var(--border-strong); border-radius: var(--radius-full); background: var(--bg-elevated); color: var(--text-1);
  font: inherit; font-size: var(--text-sm); font-variant-numeric: tabular-nums; box-shadow: var(--shadow-md); cursor: pointer;
}
.note-taker-chip-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--danger); }
.note-taker-chip[data-state="paused"] .note-taker-chip-dot { background: var(--text-4); }
@media (prefers-reduced-motion: reduce) { .note-taker-pulse, .note-taker-primary, .note-taker-secondary { transition: none; } }
@media (max-width: 600px) {
  .note-taker-modal { padding: 0; align-items: end; }
  .note-taker-panel { max-height: calc(100dvh - 8px); padding: var(--space-4); padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom)); border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .note-taker-transcript { height: 46dvh; }
  .note-segment { grid-template-columns: 44px minmax(0, 1fr); gap: var(--space-2); }
  .note-taker-controls { position: sticky; bottom: 0; background: var(--bg-elevated); }
  .note-taker-controls button { flex: 1; }
  .note-taker-recovery { flex-direction: column; align-items: stretch; }
}


/* ══════════════════════════════════════════════════════════════
   Reminders — shared bits used across the reminders view.
   Layout- and component-level rules live in css/reminders.css;
   this file keeps only the two small pieces of markup (the
   upcoming/past row layout and the per-row delete button) that
   were already here so nothing that referenced them breaks.
   ══════════════════════════════════════════════════════════════ */
.reminders-notif-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.reminder-row { cursor: pointer; }
.reminder-delete-btn {
  flex-shrink: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  color: var(--text-3);
  transition: color var(--duration-fast) var(--ease), background var(--duration-fast) var(--ease);
}
.reminder-delete-btn:hover { color: var(--danger); background: var(--danger-subtle); }
.visual-type-option.is-disabled { opacity: 0.4; cursor: not-allowed; }

@media (prefers-color-scheme: dark) {
  .reminder-delete-btn:hover { background: color-mix(in srgb, var(--danger) 18%, transparent); }
}


/* ── Chat width, mobile: use the whole screen. Less side padding, no
   fixed max-width on user bubbles beyond a small gutter. ── */
@media (max-width: 900px) {
  .conversation { padding-left: var(--space-4); padding-right: var(--space-4); }
  .composer-wrap { padding-left: var(--space-3); padding-right: var(--space-3); }
}
@media (max-width: 600px) {
  .conversation { padding-left: 14px; padding-right: 14px; }
  .message-list { gap: var(--space-5); }
  .message.is-user { max-width: 92%; }
}

/* ── Chat body loading state (synced chat whose messages are downloading) ── */
.conversation-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-7) 0;
  color: var(--text-3);
  font-size: var(--text-sm);
}
.conversation-loading i { animation: spin 0.9s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .conversation-loading i { animation: none; }
}

/* Sidebar row whose title hasn't been fetched yet */
.sidebar-history-item.is-pending span { color: var(--text-4); font-style: italic; }

/* Generated visuals (diagram SVG / illustration) shown in a reply */
.message-content.message-visual { overflow-x: auto; }
.message-content.message-visual svg,
.message-content.message-visual img {
  max-width: 100%;
  height: auto;
  border-radius: 12px;
}
