/* ============================================================
   NxtAtlas AI — chat.html
   Loaded after styles.css, redesign.css and atlas.css.

   Three things to know before editing:

   1. Tokens only. Never a literal colour. The app ships seven themes
      and two of them are the ones people actually use.

   2. redesign.css wraps most of itself in `@layer redesign`. Cascade
      layers invert for !important — an important declaration inside a
      layer beats an unlayered one no matter how specific. So the few
      properties redesign.css pins with a layered `!important` can only
      be undone from inside that same layer; that is what the first
      block below is for, and it is the only reason it exists. All the
      real design lives unlayered underneath, where a plain declaration
      already outranks anything layered.

   3. data-motion="app". Motion answers a pointer or a state change —
      never the scroll position, never the clock. No idle pulses, no
      reveal-on-scroll, no ambient drift.
   ============================================================ */


/* ============================================================
   0. UNDOING THE LAYERED !IMPORTANTS
   Same layer, later source: wins the tie. Every declaration here
   has to carry !important or a plain styles.css rule (unlayered)
   would outrank it in turn.
   ============================================================ */
@layer redesign {

  /* surfaces — the old build tinted these to let a neon backdrop
     bleed through. There is no backdrop any more. */
  #sidebar.sidebar,
  [data-theme="dark"] #sidebar.sidebar,
  [data-theme="light"] #sidebar.sidebar {
    background: var(--bg-sidebar) !important;
  }
  /* padding has to live in here too: redesign.css pins the shorthand with
     a layered !important, which an unlayered rule can never reach — and
     the top value is what carries the iOS safe-area inset. */
  #main .topbar,
  [data-theme="dark"] #main .topbar,
  [data-theme="light"] #main .topbar {
    background: var(--bg) !important;
    padding: env(safe-area-inset-top) var(--s-4) 0 !important;
  }
  @media (max-width: 768px) {
    #main .topbar { padding: env(safe-area-inset-top) var(--s-2) 0 !important; }
  }
  #main .composer-wrap,
  [data-theme="dark"] #main .composer-wrap,
  [data-theme="light"] #main .composer-wrap {
    background: var(--bg) !important;
  }

  /* composer — was a translucent blue pill */
  #composer.composer,
  [data-theme="light"] #composer.composer {
    background: var(--bg-elev) !important;
    border: 1px solid var(--border-input) !important;
    border-radius: 20px !important;
    padding: 10px 10px 8px !important;
  }
  #composer.composer:has(.attachments:not([hidden])) {
    border-radius: 20px !important;
    padding: 10px 10px 8px !important;
  }
  #composer.composer.is-voice-inline {
    border-radius: 20px !important;
    padding: 12px 12px 10px !important;
  }
  @media (max-width: 768px) {
    #composer.composer,
    #composer.composer:has(.attachments:not([hidden])) {
      border-radius: 18px !important;
      padding: 8px 8px 6px !important;
    }
  }
  #composer.composer:focus-within,
  #composer.composer.is-dragover {
    border-color: var(--accent) !important;
  }
  #composer.composer.is-dragover { border-style: dashed !important; }
  /* Temporary chat used to be signalled by a white halo behind the whole
     app. Without the halo the mode was invisible, so the composer wears
     it: a dashed brass edge, plus the note added to the hint below. */
  body.neon-temporary #composer.composer {
    border-style: dashed !important;
    border-color: var(--accent) !important;
  }
  #composer .composer-plus.composer-icon-btn {
    width: 34px !important;
    height: 34px !important;
    color: var(--text-soft) !important;
  }
  #composer .composer-plus.composer-icon-btn:hover,
  [data-theme="light"] #composer .composer-plus.composer-icon-btn:hover {
    background: var(--bg-hover) !important;
    color: var(--text) !important;
  }

  /* send button — the one filled control on the page */
  #send-btn.send-btn,
  #send-btn.send-btn:not(:disabled) {
    background: var(--accent) !important;
    color: var(--accent-text) !important;
    border: 1px solid transparent !important;
    box-shadow: none !important;
  }
  #send-btn.send-btn:hover:not(:disabled) {
    background: var(--accent-hover) !important;
    box-shadow: none !important;
  }
  #send-btn.send-btn:disabled {
    background: var(--bg-active) !important;
    color: var(--text-soft) !important;
  }
  /* Declared after the hover rule on purpose: mid-stream the button is a
     Stop, and hovering a Stop must not repaint it as a Send. */
  #send-btn.send-btn.is-streaming,
  #send-btn.send-btn.is-streaming:not(:disabled),
  #send-btn.send-btn.is-streaming:hover:not(:disabled) {
    background: var(--bg-active) !important;
    color: var(--text) !important;
  }
  #send-btn.send-btn.is-streaming:hover:not(:disabled) {
    background: var(--bg-hover) !important;
  }

  /* the person's message */
  #messages .msg-user .bubble,
  [data-theme="light"] #messages .msg-user .bubble {
    background: var(--bg-bubble) !important;
    color: var(--text) !important;
    border: 1px solid var(--border) !important;
    border-radius: 16px 16px 5px 16px !important;
    padding: 11px 15px !important;
    box-shadow: none !important;
  }
  /* the bubble becomes its own editor in place, so it has to be able to
     out-rank the bubble's pinned background */
  #messages .msg-user .bubble.is-editing {
    background: var(--bg-input) !important;
    border-color: var(--accent) !important;
  }
  #messages .msg-avatar {
    width: 26px !important;
    height: 26px !important;
    box-shadow: none !important;
  }

  /* model picker */
  #model-menu.model-menu,
  [data-theme="light"] #model-menu.model-menu {
    background: var(--bg-elev) !important;
    border: 1px solid var(--border) !important;
    border-radius: 14px !important;
    padding: 6px !important;
    box-shadow: var(--shadow-3) !important;
  }
  #model-menu .model-item:hover,
  [data-theme="light"] #model-menu .model-item:hover {
    background: var(--bg-hover) !important;
  }
  #model-menu .model-item.is-active {
    background: var(--accent-soft) !important;
  }
  #model-btn.model-btn {
    padding: 7px 12px !important;
  }
  #model-btn.model-btn:hover,
  [data-theme="light"] #model-btn.model-btn:hover {
    background: var(--bg-hover) !important;
  }
  #main .topbar .icon-btn:hover,
  [data-theme="light"] #main .topbar .icon-btn:hover {
    background: var(--bg-hover) !important;
  }

  /* conversation list */
  #conv-list .conv-item {
    border-radius: 10px !important;
  }
  #conv-list .conv-item:hover {
    background: var(--bg-hover) !important;
  }
  #conv-list .conv-item.is-active,
  [data-theme="light"] #conv-list .conv-item.is-active {
    background: var(--bg-active) !important;
  }

  /* voice */
  .composer #voice-btn.is-active {
    background: var(--accent) !important;
    color: var(--accent-text) !important;
    width: 34px !important;
    height: 34px !important;
  }
  #voice-overlay .voice-orb {
    background: radial-gradient(circle at 34% 30%,
                  var(--accent) 0%,
                  var(--accent-hover) 38%,
                  var(--bg-elev) 78%,
                  var(--bg) 100%) !important;
    box-shadow: 0 0 90px var(--accent-soft) !important;
  }
  #voice-overlay .voice-lang {
    background: var(--bg-elev) !important;
    border: 1px solid var(--border) !important;
  }
  #voice-overlay .voice-lang-btn.is-active {
    background: var(--accent) !important;
    color: var(--accent-text) !important;
  }

  /* persona textarea */
  #persona-text.persona-text {
    background: var(--bg-input) !important;
    border-color: var(--border-input) !important;
  }
  #persona-text.persona-text:focus {
    border-color: var(--accent) !important;
    box-shadow: 0 0 0 3px var(--accent-soft) !important;
  }

  /* the composer used to breathe on its own, forever, whether or not
     anyone was looking at it */
  #composer.composer:focus-within {
    animation: none !important;
  }
}


/* ============================================================
   1. PAGE FRAME
   ============================================================ */
:root {
  --sidebar-w: 268px;
  --topbar-h: 60px;
  /* one measure for the thread, the composer and the welcome column,
     so the eye tracks a single vertical channel */
  --content-max: 46rem;

  --atlas-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --atlas-rail: 3px;          /* the brass marker on an active row */
  --atlas-gutter: clamp(16px, 4vw, 32px);
}

@media (max-width: 1100px) {
  :root { --sidebar-w: 244px; }
}

/* data-motion="app": nothing here glides. styles.css turns on smooth
   scrolling globally for the marketing pages; in a chat log it fights
   every jump to the newest message. */
html { scroll-behavior: auto; }

body {
  background: var(--bg) !important;
  color: var(--text);
  font-family: var(--atlas-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Landing-page furniture that anim.js injects into every document it
   loads on. None of it belongs in an application shell. Kept in the
   DOM (the modules hold references) and only taken out of sight. */
.jn-ambient,
.jn-scroll-progress,
#jn-scroll-top,
#scroll-progress,
.cursor-ring,
.cursor-glow,
.cursor-blob,
#cursor-spot,
.jn-custom-cursor {
  display: none !important;
}

/* Boot — .admin-loading already fixes and centres it; only the surface
   changes (redesign.css painted it with a hard-coded radial). */
#boot {
  background: var(--bg);
}
#boot .spinner {
  border-color: var(--border-strong);
  border-top-color: var(--accent);
}

.app { background: transparent; }

/* Scrollbars — present, quiet, themed. */
.messages,
.sidebar,
.conv-section,
.model-menu,
.search-results,
.memories-list,
.quota-popover {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
.messages::-webkit-scrollbar,
.sidebar::-webkit-scrollbar,
.conv-section::-webkit-scrollbar,
.model-menu::-webkit-scrollbar { width: 10px; }
.messages::-webkit-scrollbar-thumb,
.sidebar::-webkit-scrollbar-thumb,
.conv-section::-webkit-scrollbar-thumb,
.model-menu::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 999px;
}
.messages::-webkit-scrollbar-track,
.sidebar::-webkit-scrollbar-track { background: transparent; }


/* ============================================================
   2. TYPE
   ============================================================ */
.atlas-wm { font-size: 13px; }

h1, h2, h3, h4,
.lock-title,
.welcome-title,
.model-item-title,
.dl-nag-title {
  font-family: var(--atlas-display);
  letter-spacing: -0.03em;
  font-weight: 500;
}

.lock-title { font-size: 22px; }
.lock-sub { color: var(--text-muted); line-height: 1.6; }
.lock-foot { color: var(--text-soft); }


/* ============================================================
   3. SIDEBAR
   Chrome. It should read as the wall, not the room.
   ============================================================ */
#sidebar {
  border-right: 1px solid var(--border);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: var(--s-3) var(--s-3) var(--s-2);
  gap: var(--s-2);
}

.sidebar-head {
  padding: var(--s-2) var(--s-1) var(--s-3);
}
.brand {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}
.brand .atlas-wm {
  font-size: 14px;
  color: var(--text);
}
.brand-suffix {
  font-family: var(--atlas-display);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--text-soft);
}

/* New chat — the one thing in here anyone reaches for on purpose */
.new-chat-row { gap: var(--s-2); padding: 0; }
#new-chat.btn-newchat {
  border-radius: 11px;
  border-color: var(--border-strong);
  background: var(--bg-elev);
  color: var(--text);
  font-weight: 500;
  min-height: 38px;
  transition: border-color var(--t-fast), background-color var(--t-fast), transform var(--t-fast);
}
#new-chat.btn-newchat:hover {
  border-color: var(--accent);
  background: var(--bg-hover);
}
#new-chat.btn-newchat:active { transform: translateY(1px); }
#new-temp-chat.icon-btn-temp {
  border-radius: 11px;
  border: 1px solid var(--border);
  color: var(--text-muted);
}
#new-temp-chat.icon-btn-temp:hover { color: var(--accent); border-color: var(--border-strong); }

/* Search */
.conv-search { margin: var(--s-1) 0 0; }
.conv-search-icon { left: 11px; color: var(--text-soft); }
.conv-search-input {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px 10px 8px 32px;
  color: var(--text);
  font-size: 13px;
  transition: border-color var(--t-fast), background-color var(--t-fast);
}
.conv-search-input::placeholder { color: var(--text-soft); }
.conv-search-input:focus {
  border-color: var(--accent);
  background: var(--bg-elev);
}
.search-results { margin: var(--s-2) 0 0; }
.search-result-item {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 10px;
  padding: 9px 11px;
}
.search-result-item:hover { background: var(--bg-hover); border-color: var(--border); }
.search-result-conv { color: var(--text-soft); letter-spacing: 0.08em; font-size: 10px; }
.search-result-snippet { color: var(--text-muted); font-size: 12.5px; }
.search-result-empty { color: var(--text-soft); }

/* Filters */
.conv-filters { padding: var(--s-2) 0 var(--s-1); gap: 5px; }
.conv-filter {
  background: transparent;
  color: var(--text-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 11px;
  font-size: 11px;
  letter-spacing: 0.01em;
  transition: color var(--t-fast), border-color var(--t-fast), background-color var(--t-fast);
}
.conv-filters .conv-filter:hover { color: var(--text); background: var(--bg-hover); }
.conv-filters .conv-filter.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--text);
}

/* History */
.conv-section { padding: var(--s-1) 0 0; margin-top: 0; }
.conv-section-title {
  padding: var(--s-3) var(--s-2) var(--s-2);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--text-soft);
  font-weight: 600;
}
.conv-list { padding: 0; gap: 2px; }
.conv-item {
  position: relative;
  padding: 8px 8px 8px 12px;
  font-size: 13.5px;
  color: var(--text-muted);
  min-height: 34px;
}
.conv-item:hover { color: var(--text); }
.conv-item.is-active { color: var(--text); font-weight: 500; }
#conv-list .conv-item.is-active::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 8px;
  bottom: 8px;
  width: var(--atlas-rail);
  border-radius: 999px;
  background: var(--accent);
}
.conv-item-title { font-size: 13.5px; }
.conv-item-del,
.conv-item-share { color: var(--text-soft); border-radius: 7px; }
.conv-item-del:hover { background: var(--bg-active); color: var(--danger); }
.conv-item-share:hover { background: var(--bg-active); color: var(--text); }
.conv-empty { color: var(--text-soft); font-size: 12.5px; padding: var(--s-2); }

/* Native-app shortcut */
.sidebar-download-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  margin: var(--s-1) 0;
  border: 1px solid var(--border);
  border-radius: 11px;
  background: transparent;
  color: var(--text-muted);
  font-size: 13px;
  text-decoration: none;
  transition: border-color var(--t-fast), color var(--t-fast);
}
.sidebar-download-row:hover { border-color: var(--accent); color: var(--text); }
.sidebar-download-row strong { color: inherit; font-weight: 500; }

/* Footer */
.sidebar-foot {
  gap: var(--s-2);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border);
}
.user-card {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 9px;
  gap: 9px;
}
.user-card-name { font-size: 13px; font-weight: 500; color: var(--text); }
.user-card-email { font-size: 11px; color: var(--text-soft); }
.user-card-action { color: var(--text-soft); border-radius: 8px; }
.user-card-action:hover { background: var(--bg-hover); color: var(--text); }
.user-card-action.is-on { color: var(--accent); }
.badge.is-accent {
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent);
}

.session-timer {
  margin: 0;
  background: transparent;
  border-color: var(--border);
  color: var(--text-soft);
  font-size: 11px;
}
.session-timer .session-time { color: var(--text-muted); font-weight: 600; }
.session-timer.is-owner {
  border-color: var(--border);
  background: transparent;
  color: var(--text-soft);
}
.session-timer.is-owner .session-dot {
  background: var(--accent);
  box-shadow: none;
}
.session-timer.is-owner .session-time {
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
}
.session-timer .session-dot { background: var(--success); }

/* Two quiet columns beat an eight-row stack of near-identical links.
   The theme picker keeps a full-width row of its own: its menu is
   absolutely positioned against it, and the sidebar clips overflow, so
   a half-width anchor would cut the swatches off at the edge. */
.sidebar-links {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
}
.sidebar-links .theme-picker { grid-column: 1 / -1; position: relative; }
.sidebar-links .theme-picker > .ghost-btn { width: 100%; }
.sidebar-links .ghost-btn {
  padding: 7px 9px;
  min-height: 32px;
  border-radius: 9px;
  font-size: 12.5px;
  color: var(--text-soft);
  gap: 7px;
}
.sidebar-links .ghost-btn:hover { background: var(--bg-hover); color: var(--text); }
.sidebar-links .ghost-btn svg { opacity: 0.85; }
#admin-link.admin-link { color: var(--accent); }
#admin-link.admin-link:hover { background: var(--accent-soft); color: var(--accent); }
#logout:hover { color: var(--danger); }

.theme-menu {
  background: var(--bg-elev);
  border-color: var(--border);
  box-shadow: var(--shadow-3);
  border-radius: 14px;
  /* stretch to the picker instead of a fixed 260px, which overflowed the
     rail and got clipped by .sidebar { overflow: hidden } */
  left: 0;
  right: 0;
  width: auto;
  padding: 8px;
  gap: 5px;
}
.theme-swatch { border-color: var(--border); }
.theme-swatch:hover { border-color: var(--border-strong); transform: none; background: var(--bg-hover); }
.theme-swatch.is-active { border-color: var(--accent); background: var(--accent-soft); }
.theme-swatch.is-active::after { background: var(--accent); }
.theme-swatch-name { color: var(--text-muted); font-size: 10.5px; }

.lang-toggle {
  align-self: stretch;
  justify-content: center;
  margin: 0;
  background: transparent;
  border-color: var(--border);
  border-radius: 9px;
}
.lang-btn { color: var(--text-soft); font-size: 11px; }
.lang-btn:hover { color: var(--text); }
.lang-btn.is-active { background: var(--accent-soft); color: var(--text); }


/* ============================================================
   4. TOPBAR
   ============================================================ */
#main .topbar {
  height: auto;
  min-height: var(--topbar-h);
  gap: var(--s-2);
  border-bottom: 1px solid var(--border);
  padding-top: env(safe-area-inset-top);
}

.topbar-wm {
  display: none;
  font-size: 13px;
  color: var(--text);
}

.topbar-right {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
}
#topbar-new { margin-left: 0; }

.topbar .icon-btn {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  color: var(--text-muted);
}
.topbar .icon-btn:hover { color: var(--text); }

/* Model picker */
#model-btn {
  font-family: var(--atlas-display);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
  border: 1px solid transparent;
  border-radius: 10px;
  gap: 6px;
}
#model-btn:hover { border-color: var(--border); }
#model-btn svg { color: var(--text-soft); transition: transform var(--t-fast); }
#model-btn[aria-expanded="true"] svg { transform: rotate(180deg); }

.model-menu-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-soft);
  padding: 10px 12px 5px;
}
.model-menu .model-item {
  border-radius: 9px;
  margin: 1px 0;
  padding: 9px 11px;
  gap: var(--s-3);
}
.model-menu .model-item:hover { transform: none; }
.model-item-title { font-size: 13.5px; letter-spacing: -0.02em; }
.model-item-sub { font-size: 11.5px; color: var(--text-soft); font-family: var(--atlas-body); }
.model-item .check { color: var(--accent); }
.model-menu-divider { background: var(--border); }
.pro-pill {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 2px 6px;
  border-radius: 5px;
  background: var(--accent-soft);
  color: var(--accent);
  vertical-align: 1px;
}
.pro-pill.is-owner-pill {
  background: transparent;
  border: 1px solid var(--accent);
}

/* Quota ring */
.quota-btn { width: 34px; height: 34px; border-radius: 10px; }
.quota-btn:hover { background: var(--bg-hover); }
.quota-ring {
  --quota-color: var(--accent);
  background: conic-gradient(var(--quota-color) calc(var(--pct) * 1%), var(--border-strong) 0);
}
.quota-ring::after { background: var(--bg); }
#quota-ring-label { font-size: 8.5px; color: var(--text); }
.quota-popover {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-3);
}
.quota-pop-head { color: var(--text); }
.quota-pop-tier {
  background: var(--accent-soft);
  color: var(--accent);
}
.quota-pop-owner { color: var(--text-muted); }
.quota-row-ring {
  --quota-color: var(--accent);
  background: conic-gradient(var(--quota-color) calc(var(--pct) * 1%), var(--border-strong) 0);
}
.quota-row-ring::after { background: var(--bg-elev); }
.quota-row-label { color: var(--text); font-size: 12.5px; }
.quota-row-detail { color: var(--text-soft); }


/* ============================================================
   5. WELCOME — the empty thread
   ============================================================ */
.welcome { padding: var(--s-7) var(--atlas-gutter); }
.welcome-inner {
  max-width: var(--content-max);
  gap: var(--s-5);
  align-items: center;
}

.welcome-eyebrow {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-family: var(--atlas-display);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.2em;
  color: var(--text-soft);
}
.welcome-eyebrow .atlas-wm { font-size: 11px; letter-spacing: 0.2em; }

#welcome .welcome-title {
  margin: 0;
  font-family: var(--atlas-display);
  font-size: clamp(26px, 4.2vw, 38px);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.15;
  color: var(--text);
  background: none;
  -webkit-text-fill-color: currentColor;
  text-align: center;
  animation: none;
}

.suggestions { gap: 7px; margin-top: var(--s-2); }
.suggestions .pill,
.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
  animation: none;
  transition: border-color var(--t-fast), color var(--t-fast), background-color var(--t-fast);
}
.pill:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--text);
}
.pill-icon { display: inline-flex; color: var(--text-soft); }
.pill:hover .pill-icon { color: var(--accent); }

.tools-row { margin-top: var(--s-3); gap: 8px; }
.tools-row .tool-chip,
.tool-chip {
  padding: 9px 15px;
  border-radius: 999px;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 500;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  animation: none;
  transition: border-color var(--t-fast), color var(--t-fast), background-color var(--t-fast), transform var(--t-fast);
}
.tools-row .tool-chip:hover,
.tool-chip:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--text);
  transform: none;
}
.tool-chip .tool-chip-icon { color: var(--text-soft); }
.tool-chip:hover .tool-chip-icon { color: var(--accent); }


/* ============================================================
   6. THE THREAD
   This is the product. Everything above is furniture around it.
   ============================================================ */
#messages {
  padding: var(--s-6) var(--atlas-gutter) var(--s-4);
  scroll-behavior: auto;      /* app.js sets scrollTop directly */
  overscroll-behavior-y: contain;
}
.messages-inner {
  max-width: var(--content-max);
  gap: 26px;
  padding-bottom: var(--s-4);
}

/* A user turn followed by an assistant turn is one exchange; the gap
   before the NEXT question is what separates exchanges. */
.messages-inner > .msg-assistant + .msg-user { margin-top: 12px; }
.messages-inner > .msg-user + .msg-assistant { margin-top: -8px; }

/* app.js appends the toolbar row as a SIBLING of the bubble, inside the
   same flex row (it has to — the streaming renderer rewrites .msg-body's
   innerHTML on every tick and would eat a nested toolbar). Wrapping it
   onto its own line is therefore the layout's job, not the module's. */
.msg { gap: var(--s-3); flex-wrap: wrap; row-gap: 0; }
.msg > .msg-actions,
.msg > .msg-user-actions { flex: 0 0 100%; width: 100%; }

/* ---- the person ---- */
.msg-user { justify-content: flex-end; }
.msg-user .user-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  max-width: 82%;
  min-width: 0;
}
#messages .msg-user .bubble {
  font-size: 15px;
  line-height: 1.6;
  white-space: pre-wrap;
  max-width: 100%;
}
.msg-user-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  justify-content: flex-end;
  margin-top: 5px;
}
.msg-edit-btn {
  color: var(--text-soft);
  border-radius: 7px;
  font-size: 12px;
}
.msg-edit-btn:hover { background: var(--bg-hover); color: var(--text); }
.msg-edit-input {
  color: var(--text);
  font-size: 15px;
  line-height: 1.6;
  background: transparent;
}
.msg-edit-confirm { color: var(--accent); }
.msg-edit-confirm:hover { color: var(--accent-hover); }
.msg-edit-cancel:hover { color: var(--danger); }

/* ---- the assistant ---- */
.msg-assistant { column-gap: 14px; row-gap: 0; align-items: flex-start; }

/* app.js hard-codes the old avatar image into every assistant bubble.
   Swap the picture for the Λ mark without touching the module. */
.msg-avatar {
  position: relative;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--accent-soft);
  margin-top: 3px;
  overflow: hidden;
}
/* The avatar is the brand mark itself, not a letter standing in for it.
   app.js writes an <img> here; show it. */
.msg-avatar img {
  display: block !important;
  width: 100%; height: 100%;
  object-fit: contain;
}
.msg-avatar::after {
  /* Only when the image is genuinely missing does a glyph stand in. */
  content: "";
}
/* Same substitution for the JS-built fallback (it renders a literal "j"). */
.avatar-fallback {
  background: var(--accent-soft);
  color: transparent;
  font-size: 0 !important;
  position: relative;
}
.avatar-fallback::after {
  content: "\039B";
  font-family: var(--atlas-display);
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
}
.avatar-fallback.size-56::after { font-size: 24px; }

.msg-body {
  font-size: 16px;
  line-height: 1.75;
  color: var(--text);
  padding-top: 0;
}
.msg-body.is-streaming::after {
  width: 2px;
  height: 1.05em;
  background: var(--accent);
  vertical-align: -0.18em;
  margin-left: 3px;
}

/* Markdown */
.markdown > * + * { margin-top: 14px; }
.markdown h1, .markdown h2, .markdown h3, .markdown h4 {
  font-family: var(--atlas-display);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.25;
  color: var(--text);
}
.markdown h1 { font-size: 22px; margin-top: 28px; }
.markdown h2 { font-size: 19px; margin-top: 26px; }
.markdown h3 { font-size: 17px; margin-top: 22px; }
.markdown h4 { font-size: 15.5px; margin-top: 18px; }
.markdown p { color: var(--text); }
.markdown ul, .markdown ol { padding-left: 24px; gap: 6px; }
.markdown li::marker { color: var(--text-soft); }
.markdown blockquote {
  border-left: 2px solid var(--accent);
  padding: 2px 0 2px 16px;
  color: var(--text-muted);
}
.markdown a {
  color: var(--accent);
  text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
  text-underline-offset: 3px;
}
.markdown a:hover { text-decoration-color: var(--accent); }
.markdown hr { border-top: 1px solid var(--border); margin: 24px 0; }
.markdown strong { font-weight: 600; color: var(--text); }

/* Code — has to be pleasant in both themes, so it is built from
   --bg-code / --border and nothing else. */
.markdown code {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1.5px 5px;
  color: var(--text);
}
.markdown pre {
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  margin-top: 16px;
}
.markdown pre .code-head {
  padding: 7px 8px 7px 14px;
  border-bottom: 1px solid var(--border);
  background: transparent;
  font-size: 11px;
}
.markdown pre .code-head .lang {
  font-family: var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.markdown pre .copy-btn {
  border-radius: 7px;
  padding: 4px 9px;
  font-size: 11.5px;
  color: var(--text-soft);
}
.markdown pre .copy-btn:hover { background: var(--bg-hover); color: var(--text); }
.markdown pre .copy-btn.is-copied { color: var(--success); }
#messages .markdown pre code,
.markdown pre code {
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 14px 16px;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--text);
  overflow-x: auto;
}
/* KaTeX inherits the body colour instead of the browser default */
.markdown .katex { color: var(--text); }
.markdown .katex-display { overflow-x: auto; overflow-y: hidden; padding: 2px 0; }

/* Message toolbar */
.msg-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 6px;
  margin-left: 40px;
}
.msg-action-btn {
  color: var(--text-soft);
  border-radius: 7px;
  padding: 4px 8px;
  font-size: 12px;
  transition: background-color var(--t-fast), color var(--t-fast);
}
.msg-action-btn:hover:not(:disabled) { background: var(--bg-hover); color: var(--text); }
.msg-action-version-label { color: var(--text-soft); font-size: 11.5px; }

/* Attachments and media inside the thread */
.msg-images { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
.chat-img-wrap,
.chat-video-wrap {
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-code);
}
.chat-img-dl {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 9px;
}
.doc-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 12px;
  text-decoration: none;
}
.doc-card:hover { border-color: var(--border-strong); }
.doc-card-name { color: var(--text); }
.doc-card-sub { color: var(--text-soft); }
.doc-card-dl { color: var(--text-muted); }
.game-dl-btn {
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  color: var(--accent);
}
.game-dl-btn:hover:not(:disabled) { background: var(--accent-soft); border-color: var(--accent-hover); }

/* Research citations */
.chat-sources {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
}
.chat-sources-head { color: var(--text-soft); letter-spacing: 0.12em; }
.chat-sources-list a { color: var(--accent); }

/* Waiting states.
   The stock loaders are two different animated silver orbs plus a
   shimmering gradient headline that never stops. One brass arc says
   "working" for all of them — thinking, image, video, music, game —
   and it says it the same way every time.

   The properties reset below are the ones the old ::before glow set
   (absolute, blurred, behind); a partial override would leave a 17px
   spinner smeared behind the card. */
.thinking-loader,
.image-loader {
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  margin-top: 8px;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 12px;
  color: var(--text-muted);
  font-size: 14px;
}
.thinking-loader { display: inline-flex; border-radius: 999px; padding: 9px 15px; }
.image-loader { display: flex; }
.thinking-loader .thinking-svg,
.image-loader .image-loader-svg { display: none; }
.thinking-loader::before,
.image-loader::before {
  content: "";
  position: static;
  inset: auto;
  z-index: auto;
  filter: none;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: none;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  animation: atlas-spin 780ms linear infinite;
}
.thinking-text,
.image-loader-title {
  background: none;
  background-clip: border-box;
  -webkit-background-clip: border-box;
  -webkit-text-fill-color: currentColor;
  animation: none;
}
.thinking-text { color: var(--text-muted); font-size: 14px; font-weight: 500; }
.thinking-dots span { background: var(--text-soft); }
.image-loader-title {
  font-family: var(--atlas-display);
  font-size: 14px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
}
.image-loader-prompt { color: var(--text-soft); font-size: 12.5px; }
.thought-stream { color: var(--text-soft); }
.thought-text { color: var(--text-soft); font-size: 13px; line-height: 1.55; }
.loader-note { color: var(--text-soft); }

.error-banner {
  border: 1px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 10%, transparent);
  color: var(--danger);
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 13.5px;
}

/* Inline "Remember this?" banner */
.memory-prompt {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 14px;
}
.memory-prompt-title { font-family: var(--atlas-display); letter-spacing: -0.02em; color: var(--text); }
.memory-prompt-text { color: var(--text-muted); }
.memory-prompt-approve {
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid var(--accent);
}
.memory-prompt-approve:hover { background: var(--accent); color: var(--accent-text); }
.memory-prompt-decline {
  background: transparent;
  color: var(--text-soft);
  border: 1px solid var(--border);
}
.memory-prompt-decline:hover { background: var(--bg-hover); color: var(--text); }
.memory-prompt-done { color: var(--success); }


/* ============================================================
   7. COMPOSER
   Immediate and unmissable: the only elevated surface on the page
   and the only filled control.
   ============================================================ */
#main .composer-wrap {
  position: relative;
  padding: var(--s-2) var(--atlas-gutter) calc(var(--s-3) + env(safe-area-inset-bottom));
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-top: 0;
}
/* the thread dissolves into the composer rather than hitting a line */
#main .composer-wrap::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 28px;
  background: linear-gradient(to top, var(--bg), transparent);
  pointer-events: none;
}

#ctx-pill {
  display: flex;
  align-items: center;
  width: max-content;
  margin: 0 auto var(--s-2);
  padding: 3px 11px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: transparent;
  color: var(--text-soft);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  transition: color var(--t-fast), border-color var(--t-fast);
}
#ctx-pill:hover { color: var(--text); border-color: var(--border-strong); }
#ctx-pill.is-warn { color: var(--accent); border-color: var(--accent); }

#composer {
  position: relative;
  max-width: var(--content-max);
  margin: 0 auto;
  box-shadow: var(--shadow-2);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
  isolation: isolate;
}
/* data-a-spotlight feeds --mx/--my from the pointer. A hint of brass,
   only under the cursor, only while the cursor is over the field. */
#composer::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%), var(--accent-soft), transparent 72%);
  opacity: 0;
  transition: opacity 220ms var(--atlas-ease);
  pointer-events: none;
}
#composer:hover::before { opacity: 1; }
#composer:focus-within { box-shadow: 0 0 0 3px var(--accent-soft), var(--shadow-2); }
#composer.is-dragover { box-shadow: 0 0 0 3px var(--accent-soft); }

/* two rows: the field owns the full width, the controls sit beneath */
#composer .composer-row {
  flex-direction: column;
  align-items: stretch;
  gap: 6px;
  width: 100%;
}
.composer-field {
  display: flex;
  align-items: flex-end;
  min-width: 0;
  width: 100%;
}
#prompt {
  width: 100%;
  min-width: 0;
  min-height: 26px;
  max-height: 200px;
  padding: 6px 6px 4px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--text);
  background: transparent;
}
#prompt::placeholder { color: var(--text-soft); }

.composer-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  width: 100%;
}
.composer-gap { flex: 1 1 auto; }

.composer-icon-btn {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  color: var(--text-soft);
}
.composer-icon-btn:hover { background: var(--bg-hover); color: var(--text); }
.composer-icon-btn.is-recording,
.composer-icon-btn.is-transcribing { color: var(--accent); background: var(--accent-soft); }

#send-btn {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  margin-left: 4px;
  transition: background-color var(--t-fast), transform 140ms var(--atlas-ease);
}
#send-btn::after { display: none; }
/* the lean comes from data-a-magnetic (an inline transform, so it still
   wins); this only stops the inherited hover nudge on touch devices */
#send-btn:hover:not(:disabled) { transform: none; }

.composer-hint {
  max-width: var(--content-max);
  margin: 9px auto 0;
  font-size: 11px;
  letter-spacing: 0.01em;
  color: var(--text-soft);
  opacity: 1;
}

/* Attachments strip */
.attachments { padding-bottom: 2px; }
.attach-thumb { border-radius: 10px; border: 1px solid var(--border); overflow: hidden; }
.attach-remove {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  color: var(--text);
}
.attach-remove:hover { background: var(--bg-active); }
.attach-doc-name { color: var(--text); }

/* Video / music option strips */
.video-options,
.music-options {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding-bottom: 4px;
}
.vopt-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  font-size: 11.5px;
  color: var(--text-muted);
}
.vopt-label { color: var(--text-soft); letter-spacing: 0.04em; text-transform: uppercase; font-size: 9.5px; }
.vopt-chip select {
  background: transparent;
  border: 0;
  color: var(--text);
  font-size: 12px;
  outline: none;
}
.vopt-chip select option { background: var(--bg-elev); color: var(--text); }

/* Plus menu */
#plus-menu {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-3);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: 6px;
  min-width: 232px;
}
#plus-menu .plus-item {
  color: var(--text);
  border-radius: 9px;
  padding: 10px 12px;
  font-size: 13.5px;
  gap: 12px;
}
#plus-menu .plus-item:hover { background: var(--bg-hover); }
#plus-menu .plus-item svg { color: var(--text-soft); }
#plus-menu .plus-item:hover svg { color: var(--accent); }
.plus-divider { background: var(--border); }
.composer-icon-btn.composer-plus.is-active {
  background: var(--accent-soft) !important;
  color: var(--accent) !important;
}

/* Slash-command menu (app.js builds it into the form) */
#slash-menu {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-3);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.slash-item { border-radius: 9px; color: var(--text-muted); }
.slash-item.is-active { background: var(--bg-hover); color: var(--text); }
.slash-cmd { color: var(--text); font-family: var(--font-mono); }
.slash-desc { color: var(--text-soft); }


/* ============================================================
   8. VOICE
   ============================================================ */
.voice-inline { gap: 14px; }
/* the orb strip replaces the textarea, so the field stops bottom-aligning */
.composer.is-voice-inline .composer-field { align-items: center; }

/* Two loops that ran on their own clock: a halo that pulsed under the mic
   whenever the pointer passed over it, and a red siren on the live button.
   The button already turns brass while a call is up — that is the state. */
#voice-btn::before,
#voice-btn:hover::before { display: none; }
.composer #voice-btn.is-active { animation: none; }
.voice-inline-status {
  color: var(--text-soft);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 10px;
}
.composer.is-voice-thinking .voice-inline-status,
.composer.is-voice-speaking .voice-inline-status { color: var(--accent); }
.voice-inline-transcript { color: var(--text); }
.vi-halo,
.composer.is-voice-listening .vi-halo,
.composer.is-voice-thinking .vi-halo,
.composer.is-voice-speaking .vi-halo {
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 70%);
}
.vi-ring,
.composer.is-voice-listening .vi-ring,
.composer.is-voice-thinking .vi-ring,
.composer.is-voice-speaking .vi-ring { border-color: var(--accent); }
.vi-core,
.composer.is-voice-listening .vi-core,
.composer.is-voice-thinking .vi-core,
.composer.is-voice-speaking .vi-core { background: var(--accent); }
.vi-mute {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-soft);
}
.vi-mute:hover { background: var(--bg-hover); color: var(--text); }
.vi-mute.is-muted { background: var(--bg-active); color: var(--danger); }
.vi-gender.is-female { color: var(--accent); }

#voice-overlay .voice-card {
  background: var(--bg-modal);
  border: 1px solid var(--border);
}
#voice-overlay .voice-status { color: var(--text-muted); }
#voice-overlay .voice-transcript { color: var(--text); }
#voice-overlay .voice-close,
#voice-overlay .voice-mute { color: var(--text-muted); }
#voice-overlay .voice-mute.is-muted { color: var(--danger); }


/* ============================================================
   9. MODALS + OVERLAYS
   ============================================================ */
.lock { background: var(--backdrop); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); }
.lock-card {
  background: var(--bg-modal);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-3);
}
.upgrade-card::before { display: none; }   /* was an orange halo */
.upgrade-icon { color: var(--accent); }
.upgrade-actions { display: flex; flex-direction: column; gap: 8px; }
.upgrade-cancel { justify-content: center; color: var(--text-soft); }
.upgrade-cancel:hover { color: var(--text); }

.btn-primary { background: var(--accent); color: var(--accent-text); border-radius: 11px; }
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); }
.btn-outline { background: transparent; border-color: var(--border-strong); border-radius: 11px; }
.btn-outline:hover:not(:disabled) { background: var(--bg-hover); }

.input {
  background: var(--bg-input);
  border: 1px solid var(--border-input);
  border-radius: 11px;
}
.input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.lock-error { color: var(--danger); }

.persona-text { border-radius: 12px; }
.persona-meta { color: var(--text-soft); }
.persona-memory { border-top-color: var(--border); }
.persona-memory-head { color: var(--text-soft); }
.pmem-row { background: var(--bg-hover); border-radius: 10px; }
.pmem-pending { background: var(--accent-soft); border: 1px solid var(--accent); }
.pmem-input { color: var(--text); }
.pmem-input:focus { outline: 1px solid var(--accent); }
.pmem-btn { background: var(--bg-active); color: var(--text); }
.pmem-approve { background: var(--accent-soft); color: var(--accent); }
.pmem-save { background: var(--accent-soft); color: var(--accent); }
.pmem-delete { background: transparent; color: var(--danger); }
.pmem-empty { color: var(--text-soft); }

.memories-toggle {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 11px;
  color: var(--text);
}
.memories-toggle input[type="checkbox"] { background: var(--bg-active); }
.memories-toggle input[type="checkbox"]::after { background: var(--bg-elev); }
.memories-toggle input[type="checkbox"]:checked { background: var(--accent); }
.memories-toggle input[type="checkbox"]:checked::after { background: var(--accent-text); }
.memories-list { background: transparent; border: 1px solid var(--border); border-radius: 12px; }
.memories-list:empty::before,
.memories-list[data-disabled="1"]::before { color: var(--text-soft); }
.memory-row { border-bottom-color: var(--border); color: var(--text); }
.memory-row-delete { color: var(--text-soft); }
.memory-row-delete:hover { color: var(--danger); background: transparent; }
.memory-row-pending { background: var(--accent-soft); }
.memory-row-approve { background: var(--accent-soft); color: var(--accent); }

.tg-code-wrap { background: var(--bg-hover); border: 1px solid var(--border); border-radius: 12px; }
.tg-code-label { color: var(--text-soft); }
.tg-code {
  font-family: var(--font-mono);
  letter-spacing: 0.32em;
  color: var(--accent);
}
.tg-hint { color: var(--text-soft); }
.lock-sub code {
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--bg-code);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 5px;
}

.ctx-bar { background: var(--bg-active); border-radius: 999px; overflow: hidden; height: 6px; }
.ctx-bar-fill { background: var(--accent); height: 100%; }
.ctx-modal-note { margin-top: 14px; font-size: 13px; }

.dl-nag-backdrop { background: var(--backdrop); }
.dl-nag-card {
  background: var(--bg-modal);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-3);
}
.dl-nag-icon { color: var(--accent); }
.dl-nag-title { color: var(--text); }
.dl-nag-text { color: var(--text-muted); }
.dl-nag-cta { background: var(--accent); color: var(--accent-text); border-radius: 11px; text-decoration: none; }
.dl-nag-cta:hover { background: var(--accent-hover); }
.dl-nag-close { color: var(--text-soft); }
.dl-nag-checkbox { color: var(--text-soft); }

.chat-lightbox { background: var(--backdrop); }
.chat-lightbox-btn {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 10px;
}
.chat-lightbox-btn:hover { background: var(--bg-hover); }

.tool-toast {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 11px;
  box-shadow: var(--shadow-3);
}

.backdrop { background: var(--backdrop); }


/* ============================================================
   10. STATE
   Motion here is a reaction to something that changed, not decor.
   ============================================================ */

/* A message arriving. Fade for every row so a full re-render (which
   happens on every server sync) does not flash the whole thread;
   the newest row also rises, because that one really is new. */
@keyframes atlas-msg-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes atlas-msg-in-last {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes atlas-spin { to { transform: rotate(360deg); } }

.msg { animation: atlas-msg-in 170ms var(--atlas-ease) both; }
.messages-inner > .msg:last-child { animation: atlas-msg-in-last 240ms var(--atlas-ease) both; }

/* Working. app.js puts neon-thinking / neon-streaming on <body>; the old
   build answered with full-screen halos. A brass hairline crawling the
   top edge of the composer says the same thing and says it where the
   user is already looking. */
@keyframes atlas-work {
  from { background-position: -60% 0; }
  to   { background-position: 160% 0; }
}
#main .composer-wrap::after {
  content: "";
  position: absolute;
  left: var(--atlas-gutter);
  right: var(--atlas-gutter);
  top: 0;
  height: 1px;
  opacity: 0;
  transition: opacity 200ms var(--atlas-ease);
  pointer-events: none;
  background-image: linear-gradient(90deg, transparent, var(--accent), transparent);
  background-size: 45% 100%;
  background-repeat: no-repeat;
  background-position: -60% 0;
}
body.neon-thinking #main .composer-wrap::after,
body.neon-streaming #main .composer-wrap::after {
  opacity: 1;
  animation: atlas-work 1.5s linear infinite;
}

/* Temporary chat — the dashed composer edge is set in the layer block
   above (it has to out-rank a pinned border shorthand); this is the
   half that can live out here. */
body.neon-temporary #main .composer-wrap .composer-hint::before {
  content: "Temporary chat — not saved to your history. ";
  color: var(--accent);
}

/* Focus. atlas.css sets the ring; make sure nothing clips it. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.conv-item:focus-visible,
.model-item:focus-visible,
.pill:focus-visible,
.tool-chip:focus-visible { outline-offset: 1px; }

/* Sidebar drawer — a state change, so it may move. */
@media (max-width: 768px) {
  .sidebar { transition: transform 260ms var(--atlas-ease); }
}

@media (prefers-reduced-motion: reduce) {
  .msg,
  .messages-inner > .msg:last-child,
  #main .composer-wrap::after,
  .thinking-loader::before,
  .image-loader::before { animation: none !important; }
  #main .composer-wrap::after { opacity: 0 !important; }
  #composer::before { transition: none; }
}


/* ============================================================
   11. RESPONSIVE
   Down to 360px, no horizontal scroll.
   ============================================================ */
@media (max-width: 768px) {
  .topbar-wm { display: inline-block; }
  #main .topbar { gap: var(--s-1); }
  #model-btn { font-size: 13px; }
  #model-label { max-width: 34vw; }

  #sidebar { border-right: 0; box-shadow: var(--shadow-3); }
  #messages { padding: var(--s-4) var(--s-3) var(--s-2); }
  .messages-inner { gap: 22px; }
  .msg-body { font-size: 15.5px; line-height: 1.7; }
  .msg-user .user-stack { max-width: 90%; }
  #main .composer-wrap::after { left: var(--s-3); right: var(--s-3); }

  #main .composer-wrap { padding: var(--s-2) var(--s-3) calc(var(--s-3) + env(safe-area-inset-bottom)); }
  #composer::before { display: none; }         /* no pointer, no spotlight */

  .welcome { padding: var(--s-5) var(--s-4); }
  .welcome-inner { gap: var(--s-4); }
  .suggestions .pill { font-size: 12.5px; padding: 8px 12px; }
}

@media (max-width: 420px) {
  #welcome .welcome-title { font-size: 23px; }
  .composer-actions { gap: 0; }
  .msg-assistant { column-gap: 10px; }
  .msg-actions { margin-left: 36px; }
  #messages .markdown pre code { font-size: 12.5px; padding: 12px 13px; }
  .sidebar-links { grid-template-columns: 1fr; }
}

/* The thread must never be the thing that makes the page scroll sideways. */
.msg-body,
.bubble { overflow-wrap: anywhere; }
.markdown pre,
.markdown table { max-width: 100%; }

@media print {
  #sidebar, .topbar, .composer-wrap, .lock, #dl-nag { display: none !important; }

}

/* the mark beside the wordmark — the app should be recognisable at a glance */
.atlas-mark-img {
  display: inline-block; vertical-align: -6px; margin-right: 9px;
  border-radius: 6px; flex: none;
}

/* ============================================================
   Model picker — two fixes found in use
   ============================================================ */

/* The OWNER pill drew its label in the panel's own text colour over a dark
   fill: invisible until you selected it. The tier pills already read as brass
   on a tint, so this one now matches them. */
#model-menu [class*="owner"],
#model-menu .badge-owner,
#model-menu .tier-owner,
#model-menu .model-owner {
  color: var(--accent) !important;
  border-color: var(--accent-soft) !important;
  background: var(--accent-soft) !important;
}

/* The menu was as tall as its contents, so the last entries fell off the
   bottom of the window with nothing to scroll — it looked like models were
   missing rather than merely out of reach. */
#model-menu {
  max-height: min(70vh, 560px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
#model-menu::-webkit-scrollbar { width: 10px; }
#model-menu::-webkit-scrollbar-thumb {
  background: var(--border-strong); border-radius: 6px;
  border: 3px solid transparent; background-clip: content-box;
}

/* ============================================================
   GENERATION INDICATOR — the mark itself, waiting
   One loader serves images, video, music and games, so this shows up
   wherever the assistant is making something. A brass arc orbits the
   sphere; the sphere only breathes. Spinning a logo reads as cheap,
   and a mark that is recognisable while it works is worth more than
   another generic spinner.
   ============================================================ */
.image-loader {
  position: relative;
  padding-left: 96px;         /* room for the mark at the left */
  min-height: 84px;
}
.image-loader .image-loader-svg { display: none; }

.image-loader::before {
  content: "";
  position: absolute; left: 6px; top: 50%;
  width: 64px; height: 64px; margin-top: -32px;
  background: url("/assets/atlas-icon-192.png") center / contain no-repeat;
  animation: atlas-breathe 2.8s ease-in-out infinite;
  border: 0;
}
.image-loader::after {
  content: "";
  position: absolute; left: 0; top: 50%;
  width: 76px; height: 76px; margin-top: -38px; margin-left: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: var(--accent);
  border-right-color: var(--accent-soft);
  animation: atlas-orbit 1.1s linear infinite;
}

@keyframes atlas-breathe {
  0%, 100% { transform: scale(1);    opacity: 0.9; }
  50%      { transform: scale(1.06); opacity: 1;   }
}
@keyframes atlas-orbit { to { transform: rotate(360deg); } }

/* Someone who asked for less movement gets a still mark and no orbit. */
@media (prefers-reduced-motion: reduce) {
  .image-loader::before { animation: none; }
  .image-loader::after  { animation: none; border-top-color: var(--accent-soft); }
}
