:root {
  --bg: #FAFAF7;
  --panel-bg: #FFFFFF;
  --ink: #1A1D1A;
  --ink-soft: #55594F;
  --label: #8A8A82;
  --line: #E7E7E0;
  --green: #1E4D36;
  --green-hover: #173D2B;
  --green-tint: #EEF3EF;
  --red: #B23A2F;
  --red-tint: #FBEAE8;
  --radius: 8px;
  --sidebar-w-left: 340px;
  --icon-rail-w: 72px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body { height: 100%; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

button { font-family: inherit; cursor: pointer; }
textarea, input { font-family: inherit; }

/* ---------- App shell ---------- */

.shell {
  display: flex;
  height: 100vh;
  width: 100vw;
}

/* ---------- Icon rail: Feed & Chat / Brain / Deposits. Always visible,
   fixed width, never collapsible. The two panels to its right (tree/list
   panel, main panel) are resized by dragging the divider between them,
   see .divider below; there is no collapse/expand control anywhere in
   this layout. ---------- */

.icon-rail {
  width: var(--icon-rail-w);
  flex-shrink: 0;
  height: 100%;
  background: var(--panel-bg);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 14px 6px;
  gap: 6px;
}
/* Icon-plus-label pairs stacked vertically, not icon-only circles or
   plain text tabs (matches a typical app-rail nav pattern: small icon on
   top, short label underneath). */
.icon-rail-btn {
  width: 100%;
  min-height: 52px;
  padding: 8px 4px 7px;
  border-radius: 10px;
  background: none;
  border: none;
  color: var(--ink-soft);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  flex-shrink: 0;
}
.icon-rail-label {
  font-size: 10px;
  font-weight: 600;
  line-height: 1.15;
  text-align: center;
}
.icon-rail-btn:hover { background: var(--bg); color: var(--ink); }
.icon-rail-btn.active { background: var(--green-tint); color: var(--green); }

.sidebar {
  background: var(--panel-bg);
  height: 100%;
  overflow: hidden;
  flex-shrink: 0;
  width: var(--sidebar-w-left);
}

.sidebar-inner {
  height: 100%;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 280px;
}

/* Draggable resize handle, the only way to adjust the split between the
   tree/list panel and the main panel (no collapse/expand buttons). Wider
   hit target than its visible line for an easier grab. */
.divider {
  width: 8px;
  flex-shrink: 0;
  cursor: col-resize;
  background: transparent;
  position: relative;
}
.divider::after {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: 3px;
  width: 2px;
  background: var(--line);
}
.divider:hover::after, .divider.dragging::after { background: var(--green); }

.main-panel-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}

/* Persistent app title, always present regardless of which rail tab is
   active (main-panel-head itself never goes away), pinned to the far
   right of the header row. */
.main-panel-head-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
.app-brand {
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 14px;
  color: var(--green);
  white-space: nowrap;
}

.panel-close-btn {
  background: none;
  border: none;
  color: var(--label);
  font-size: 18px;
  line-height: 1;
  width: 24px; height: 24px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.panel-close-btn:hover { color: var(--red); background: var(--red-tint); }

/* ---------- Main panel: Feed & Chat, or Contents/Deposits, always fills
   whatever space isn't claimed by the icon rail and the tree/list panel
   (flex:1, no fixed/max width), so its content never sits narrow inside a
   mostly-empty container. Contents/Deposits can be closed outright (see
   .panel-close-btn above); while closed the tree/list panel expands to
   fill the space it frees, the same way it does when the whole tab has
   no left-panel content (Feed & Chat, see the tab-chat rule below).
   Reopens automatically once a node/item is selected again (app.js). ---- */

.main-panel {
  flex: 1;
  min-width: 0;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--panel-bg);
}

@media (min-width: 901px) {
  body.contents-closed.tab-brain .main-panel,
  body.contents-closed.tab-brain #divider-left,
  body.contents-closed.tab-deposits .main-panel,
  body.contents-closed.tab-deposits #divider-left { display: none; }

  body.contents-closed.tab-brain .sidebar-left,
  body.contents-closed.tab-deposits .sidebar-left {
    flex: 1 1 auto;
    width: auto !important;
    max-width: none;
  }
}

/* ---------- Sidebar chrome ---------- */

.sidebar-brand {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 16px 18px;
  border-bottom: 1px solid var(--line);
  flex-shrink: 0;
}

.panel-heading {
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 16px;
  color: var(--green);
}

/* ---------- Mobile-only chrome (hamburger topbar, drawer backdrop) -----
   Inert on desktop: display:none here, only ever shown inside the mobile
   media query below, so none of this affects the desktop layout. ---------- */

.mobile-topbar { display: none; }
.mobile-backdrop { display: none; }

.mobile-icon-btn {
  background: none;
  border: none;
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px;
  min-width: 44px;
  min-height: 44px;
  border-radius: 8px;
  flex-shrink: 0;
}
.mobile-icon-btn:hover { background: var(--bg); }
.mobile-icon-btn-label { font-size: 13px; font-weight: 600; }

/* Exactly one .tab-panel is ever unhidden at a time; the [hidden] attribute
   (native display:none) is what does the actual hiding, this rule only
   supplies the flex layout for whichever one is currently shown, and is
   deliberately scoped with :not([hidden]) so it never fights that. Same
   trick applies below to .chat-view, which is also toggled via [hidden]
   but (unlike #right-panel-body) needs its own flex layout when visible. */
.tab-panel:not([hidden]) {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* ---------- Deposits: flat list of raw ingested files ---------- */
.tab-panel-deposits { padding: 14px 18px; overflow: hidden; }
.deposits-hint { font-size: 12px; color: var(--label); margin-bottom: 10px; }
.deposits-list { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; margin: 0 -6px; }
.deposit-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  text-align: left;
  width: 100%;
}
.deposit-row:hover { background: var(--bg); }
.deposit-row.selected-item { background: var(--green-tint); border-color: var(--green); }
.deposit-title {
  font-size: 12.5px; font-weight: 500; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
.deposit-meta { font-size: 11px; color: var(--label); }

/* Toggled by JS to hide the Brain-specific breadcrumb/back-button while
   the Feed & Chat or Deposits tab is active (neither has a breadcrumb
   concept). Scoped to desktop widths only so a viewport resize down to
   mobile (which never exposes tab switching, see the mobile media query
   at the bottom of this file) can never leave these hidden while mobile's
   own Contents view is showing real Brain content. */
@media (min-width: 901px) {
  .desktop-tab-hidden { display: none !important; }
}

/* Feed & Chat has no left-panel content at all (a tree/list panel next to
   an empty chat would just waste the space), so the tree/list panel and
   its divider are hidden outright for that tab and the main panel
   (already flex:1) simply fills the freed width. Desktop-scoped for the
   same reason as .desktop-tab-hidden above. */
@media (min-width: 901px) {
  body.tab-chat .sidebar-left, body.tab-chat #divider-left { display: none; }
}

/* ---------- Left panel: the Brain tree diagram fills it entirely, no
   Recall section (removed: Download now lives directly in Contents,
   see .asset-link below). ---------- */

.pane {
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.pane-brain { padding: 10px 6px; }

/* Back navigation, shared look for the main panel head's back button */
.tree-back-btn {
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  color: var(--ink-soft);
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  flex-shrink: 0;
}
.tree-back-btn:hover:not(:disabled) { color: var(--green); border-color: var(--green); }
.tree-back-btn:disabled { opacity: 0.35; cursor: not-allowed; }

/* Breadcrumb trail in the main panel (Brain tab only) */
.breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  padding: 10px 20px 0;
  flex-shrink: 0;
}
.crumb {
  background: none;
  border: none;
  color: var(--label);
  font-size: 12px;
  padding: 2px 2px;
}
.crumb:not(:disabled):hover { color: var(--green); text-decoration: underline; }
.crumb.current { color: var(--ink); font-weight: 600; }
.crumb-sep { color: var(--line); font-size: 12px; }

/* ---------- Mode / category tabs ---------- */
.mode-tabs {
  display: flex;
  gap: 3px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 3px;
  width: max-content;
  max-width: 100%;
  margin-bottom: 12px;
  flex-shrink: 0;
}

.mode-tab {
  border: none;
  background: transparent;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  white-space: nowrap;
}
.mode-tab.active { background: var(--green); color: #fff; }
.mode-tab:not(.active):hover { color: var(--ink); }

.mode-panel { margin-bottom: 4px; }

.actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.btn-primary, .btn-secondary, .btn-ghost {
  border: none;
  border-radius: var(--radius);
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.btn-primary { background: var(--green); color: #fff; }
.btn-primary:hover { background: var(--green-hover); }
.btn-secondary { background: var(--green-tint); color: var(--green); }
.btn-secondary:hover:not(:disabled) { background: #e2ece5; }
.btn-secondary:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-ghost { background: transparent; color: var(--ink-soft); border: 1px solid var(--line); }
.btn-ghost:hover { color: var(--ink); }
.btn-recording { background: var(--red); color: #fff; border: none; border-radius: var(--radius); padding: 8px 14px; font-size: 13px; font-weight: 600; display: inline-flex; align-items: center; gap: 6px; }

.rec-dot { width: 8px; height: 8px; border-radius: 50%; background: #fff; animation: pulse 1.2s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.35; } }

.file-label { display: inline-block; }

.audio-status { font-size: 12px; color: var(--label); }
.audio-status.ready { color: var(--green); font-weight: 500; }
.audio-status.error { color: var(--red); }

.text-input {
  width: 100%;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  font-size: 13px;
  color: var(--ink);
  resize: vertical;
  background: var(--bg);
}
.text-input:focus { outline: none; border-color: var(--green); }

.drops-section { margin-top: 12px; flex-shrink: 0; }
.drop-list { display: flex; flex-direction: column; gap: 6px; max-height: 140px; overflow-y: auto; }
.drop-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 10px;
  border-radius: 6px;
  background: var(--bg);
  border: 1px solid var(--line);
  font-size: 12px;
}
.drop-preview { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drop-status { color: var(--label); flex-shrink: 0; }
.drop-row.done .drop-status { color: var(--green); }
.drop-row.failed .drop-status { color: var(--red); }

/* ---------- Brain tree: ONE merged horizontal node-link diagram (D3)
   covering every top-level folder as sibling root branches, not separate
   boxed canvases. Pan/zoom (d3.zoom: click-drag to pan, wheel/pinch to
   zoom) inside one fixed-height viewport, not a scrollbar-driven one, so
   branching in any direction stays reachable without fighting a
   scrollbar. Loading/empty placeholders reuse the same classes Deposits
   uses for the same states. ---------- */

.brain-tree-viz { flex: 1; overflow: hidden; padding: 4px 4px; display: flex; }
/* overflow:hidden, not auto: panning happens via the SVG's own transform
   (d3.zoom), a native scrollbar here would just double up on that. */
.brain-tree-svg-wrap {
  flex: 1;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
}
.brain-tree-svg-wrap svg { display: block; }

.tree-link {
  fill: none;
  stroke: var(--line);
  stroke-width: 1.5px;
}

/* Nodes render as a pill (rounded rect) with the (truncated) title
   inscribed inside, not a small dot with an external label; width is
   sized per-node to fit its own text (see the getBBox measurement in
   app.js), not a fixed width, so short titles don't look artificially
   wide and truncated ones never get cut off mid-pill. The full,
   untruncated title is available as a native SVG <title> tooltip on
   hover, and always shown in full once a node is selected (Contents). */
.tree-node-pill {
  fill: var(--panel-bg);
  stroke: var(--green);
  stroke-width: 1.5px;
}
.tree-node-pill.root { fill: var(--green-tint); }
.tree-node-g:hover .tree-node-pill { stroke: var(--green-hover); }
.tree-node-g:hover .tree-node-label { fill: var(--green); }
.tree-node-g.selected .tree-node-pill { fill: var(--green); stroke: var(--green); }
.tree-node-g.selected .tree-node-label { font-weight: 600; fill: #fff; }

/* High-fan-out nodes (10+ children) collapse into a single "N items"
   cluster badge instead of spreading every child into its own branch
   line; clicking it opens a scrollable list in Contents rather than
   drilling into the diagram (see onTreeNodeClick/showClusterList). Styled
   distinctly (dashed, muted) so it reads as a summary, not real content. */
.tree-node-g.cluster .tree-node-pill { fill: var(--bg); stroke: var(--label); stroke-dasharray: 3 2; }
.tree-node-g.cluster .tree-node-label { fill: var(--label); font-style: italic; }
.tree-node-g.cluster:hover .tree-node-label { fill: var(--ink-soft); }

.tree-node-label {
  font-size: 11px;
  fill: var(--ink);
  font-family: 'Inter', system-ui, sans-serif;
}

.tree-empty { color: var(--label); font-size: 12px; padding: 4px 6px 4px 8px; }
.tree-loading { color: var(--label); font-size: 12px; padding: 4px 6px 4px 8px; }

/* ---------- Chat view: message history + input pinned at the bottom.
   No max-width cap: fills the main panel's full width like every other
   view does, so it never sits narrow inside a wide container. ---------- */

.chat-view:not([hidden]) {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 20px 24px;
}

.chat-window {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--panel-bg);
  padding: 18px 20px;
  overflow: hidden;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 2px 12px;
}

/* ---------- Empty state: greeting + tappable suggestion chips, shown
   only until the first message is sent ---------- */
.chat-empty-state {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding: 24px 12px;
  text-align: center;
}
.chat-empty-greeting {
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 17px;
  color: var(--ink-soft);
}
.chat-suggestions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  max-width: 480px;
}
.chat-chip {
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink-soft);
  border-radius: 16px;
  padding: 8px 14px;
  font-size: 12px;
  text-align: left;
}
.chat-chip:hover { border-color: var(--green); color: var(--green); background: var(--green-tint); }

.chat-msg { padding: 10px 14px; border-radius: 12px; font-size: 14px; line-height: 1.5; max-width: 85%; white-space: pre-wrap; }
.chat-msg.user { align-self: flex-end; background: var(--green); color: #fff; border-bottom-right-radius: 3px; }
.chat-msg.assistant { align-self: flex-start; background: var(--panel-bg); border: 1px solid var(--line); border-bottom-left-radius: 3px; }
.chat-msg.pending { align-self: flex-start; color: var(--label); font-style: italic; background: none; }
.chat-msg.error { align-self: flex-start; background: var(--red-tint); color: var(--red); }

/* Markdown rendered inside an assistant bubble (see renderChatMarkdown):
   font-size/line-height are deliberately left alone here so they keep
   inheriting the 14px/1.5 set on .chat-msg above, only spacing/indentation
   changes between block types. */
.chat-msg.assistant p { margin: 0 0 8px; }
.chat-msg.assistant ul, .chat-msg.assistant ol { margin: 0 0 8px; padding-left: 20px; }
.chat-msg.assistant li { margin-bottom: 3px; }
.chat-msg.assistant li:last-child { margin-bottom: 0; }
.chat-msg.assistant .chat-md-heading { font-weight: 700; margin: 4px 0 6px; }
.chat-msg.assistant strong { font-weight: 700; }
.chat-msg.assistant em { font-style: italic; }
.chat-msg.assistant code {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 1px 5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.9em;
}
.chat-msg.assistant a { color: var(--green); text-decoration: underline; text-decoration-color: var(--line); }
.chat-msg.assistant a:hover { text-decoration-color: var(--green); }
.chat-msg.assistant > *:first-child { margin-top: 0; }
.chat-msg.assistant > *:last-child { margin-bottom: 0; }

.chat-form { flex-shrink: 0; }
.chat-input-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1px solid var(--line);
  border-radius: 24px;
  /* Tall enough for the placeholder (or typed text) to wrap onto two
     full lines without clipping; align-items:center above is what keeps
     the +/send buttons centered on this as it grows taller still. */
  min-height: 72px;
  padding: 6px;
  background: var(--panel-bg);
}
.chat-input {
  flex: 1;
  border: none;
  background: none;
  /* 16px, not 14px: also the minimum that keeps iOS Safari from
     auto-zooming the whole page in when the field gets focus. */
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink);
  min-width: 0;
  resize: none;
  overflow-y: auto;
  max-height: 200px;
  padding: 8px 2px;
  font-family: inherit;
}
.chat-input:focus { outline: none; }
.chat-input:disabled { color: var(--label); }
/* The placeholder is allowed to wrap like any other content in the
   textarea (this is the default; stated explicitly so a future change
   doesn't reintroduce nowrap/ellipsis truncation here). Long copy wraps
   onto its second line instead of getting cut off. */
.chat-input::placeholder { white-space: normal; overflow: visible; text-overflow: clip; }
.chat-send-btn, .tell-toggle-btn {
  border: none;
  width: 32px; height: 32px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.chat-send-btn { background: var(--green); color: #fff; }
.chat-send-btn:hover { background: var(--green-hover); }
.chat-send-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.tell-toggle-btn {
  background: var(--green-tint);
  color: var(--green);
  font-size: 20px;
  font-weight: 600;
  line-height: 1;
  transition: transform 0.15s ease, background 0.15s ease;
}
.tell-toggle-btn:hover { background: #e2ece5; }
.tell-toggle-btn[aria-expanded="true"] {
  transform: rotate(45deg);
  background: var(--red-tint);
  color: var(--red);
}

/* ---------- Tell panel: opened by the + button, feeds context to Brain ---------- */

.tell-panel {
  flex-shrink: 0;
  max-height: 60%;
  overflow-y: auto;
  border-top: 1px solid var(--line);
  margin-top: 4px;
  padding: 14px 2px 12px;
}

.tell-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.tell-panel-title {
  font-family: 'Fraunces', serif;
  font-weight: 600;
  font-size: 14px;
  color: var(--green);
}
.tell-close-btn {
  background: none;
  border: none;
  color: var(--label);
  font-size: 18px;
  line-height: 1;
  width: 22px; height: 22px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.tell-close-btn:hover { color: var(--red); background: var(--red-tint); }

.tell-hint { font-size: 12px; color: var(--label); padding: 4px 0; }

.tell-select-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--label);
  margin-bottom: 6px;
}
.tell-select {
  width: 100%;
  appearance: none;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2355594F' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 12px center;
  padding: 9px 32px 9px 12px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 12px;
}
.tell-select:focus { outline: none; border-color: var(--green); }

/* ---------- Contents / Deposits view ---------- */

.right-panel-body { flex: 1; overflow-y: auto; padding: 16px 24px; }

.muted { color: var(--label); }
.small { font-size: 12px; }

.hub-head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.hub-name { font-family: 'Fraunces', serif; font-weight: 600; font-size: 18px; color: var(--ink); }
.hub-subtitle { font-size: 12px; color: var(--label); }
.hub-summary { margin-bottom: 12px; font-size: 13px; color: var(--ink-soft); }
.hub-summary p { margin-bottom: 8px; }
.hub-summary ul { padding-left: 18px; margin-bottom: 8px; }

.page-detail p { margin-bottom: 10px; font-size: 13px; line-height: 1.6; }
.page-detail ul { padding-left: 18px; margin-bottom: 10px; }
.page-detail .hub-name { margin-bottom: 12px; }

.hub-summary a, .page-detail a {
  color: var(--green);
  text-decoration: underline;
  text-decoration-color: var(--line);
  text-underline-offset: 2px;
}
.hub-summary a:hover, .page-detail a:hover { text-decoration-color: var(--green); }

/* Download is a direct action right where content is viewed, no separate
   Recall staging area to add something to first. */
.asset-links { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 16px; }
.asset-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 12px;
  color: var(--green);
  text-decoration: none;
  background: var(--green-tint);
}
.asset-link:hover { background: #e2ece5; }
.asset-link.btn-like { border: none; cursor: pointer; }

.bit-view {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  align-items: flex-start;
}
.bit-view .bit-image { flex: 1 1 320px; max-width: 100%; }
.bit-view .bit-image img { width: 100%; border-radius: 8px; border: 1px solid var(--line); display: block; }
.bit-view .bit-text { flex: 1 1 320px; min-width: 0; }

.node-list { display: flex; flex-direction: column; gap: 4px; }
.node-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--panel-bg);
  text-align: left;
  width: 100%;
}
.node-row:hover { border-color: var(--green); }
.node-title { font-size: 13px; font-weight: 500; color: var(--ink); }
.node-desc { font-size: 11px; color: var(--label); }

/* ---------- Mobile: single main view (Chat or Contents) below a top bar,
   with Brain as a slide-in drawer overlay. Desktop layout above is
   entirely untouched; every rule here is scoped inside this media query.
   The icon rail and its tab-switching are desktop-only concepts here;
   mobile keeps its pre-existing hamburger + single-view pattern, just
   retargeted at .chat-view/#right-panel-body now that both live inside
   one .main-panel instead of being separate top-level siblings. ---------- */

@media (max-width: 900px) {
  :root {
    --mobile-topbar-h: 52px;
    /* Total occupied height including the notch/status-bar safe area, used
       anywhere something needs to sit flush below the topbar. */
    --mobile-topbar-total: calc(var(--mobile-topbar-h) + env(safe-area-inset-top, 0px));
  }

  body { overflow: hidden; }
  .shell { flex-direction: column; height: 100vh; overflow: hidden; }

  .mobile-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: var(--mobile-topbar-total);
    padding: env(safe-area-inset-top, 0px) 8px 0 14px;
    border-bottom: 1px solid var(--line);
    background: var(--panel-bg);
    box-shadow: 0 2px 6px rgba(20, 20, 15, 0.05);
    flex-shrink: 0;
    z-index: 70;
  }
  .mobile-topbar-title {
    font-family: 'Fraunces', serif;
    font-weight: 600;
    font-size: 15px;
    color: var(--green);
  }

  /* Drag-resize is a desktop concept for reclaiming horizontal space
     between panels; the drawer + single-view pattern replaces that
     entirely on mobile. The icon rail is likewise desktop-only, mobile
     keeps its own hamburger button instead. Closing Contents outright is
     also a desktop-only concept (see the .contents-closed rule, already
     scoped to min-width:901px), the button itself is hidden here too so
     there's nothing to tap into that dead state. */
  .divider { display: none; }
  .icon-rail { display: none !important; }
  .panel-close-btn { display: none !important; }

  /* ---- Brain drawer: overlay, not push. Off-canvas by default, slides
     over the content on top of a dimmed backdrop. Full viewport width, not
     a partial-width inset panel: a narrower drawer leaves a visible strip
     of dimmed backdrop (the real page content showing through, tinted)
     beside it, which reads as a rendering bug rather than a deliberate
     drawer edge. ---- */
  .sidebar-left {
    position: fixed;
    top: var(--mobile-topbar-total);
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: auto;
    z-index: 80;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    box-shadow: 2px 0 24px rgba(20, 20, 15, 0.18);
  }
  .sidebar-left.mobile-drawer-open { transform: translateX(0); }
  .sidebar-left .sidebar-brand { display: none; } /* heading: redundant with the topbar */
  .sidebar-inner { min-width: 0; }

  /* The desktop tab-panel choice inside the tree/list panel is driven by
     the icon rail, a desktop-only concept; the drawer here always shows
     Brain content, regardless of which tab was last active on desktop
     (the choice is persisted in localStorage, shared across a resize of
     the same browser window). */
  #tab-panel-deposits { display: none !important; }
  #tab-panel-brain { display: flex !important; flex-direction: column; flex: 1; min-height: 0; }

  .mobile-backdrop.visible {
    display: block;
    position: fixed;
    top: var(--mobile-topbar-total);
    left: 0; right: 0; bottom: 0;
    background: rgba(20, 20, 15, 0.4);
    z-index: 75;
  }

  /* ---- Main view: Chat and Contents, exactly one visible at a time,
     each filling the remaining height below the topbar. Tapping a Brain
     item switches to Contents (see app.js); the topbar's right icon
     switches back to Chat. Both now live inside .main-panel (itself
     always the single full-width view on mobile), so the toggle targets
     its children directly instead of top-level siblings; !important is
     required here since app.js also toggles these via the native
     `hidden` attribute for the desktop tab logic, which these rules must
     override on mobile regardless of that (see the .tab-panel comment
     above the same pattern). ---- */
  .main-panel {
    width: 100% !important;
    height: auto;
    flex: 1;
    min-height: 0;
  }
  .main-panel .chat-view, .main-panel #right-panel-body {
    display: flex !important;
    flex-direction: column;
    width: 100%;
    min-height: 0;
  }
  body.mobile-show-contents .main-panel .chat-view { display: none !important; }
  body:not(.mobile-show-contents) .main-panel #right-panel-body { display: none !important; }
  /* The main panel's own header (heading + back button) only makes sense
     while Contents is showing; while Chat is active the mobile topbar
     above already carries the app name, so this would just be a
     redundant second header bar. */
  body:not(.mobile-show-contents) .main-panel-head,
  body:not(.mobile-show-contents) .breadcrumb { display: none !important; }

  .chat-view:not([hidden]) { padding: 8px 6px; }
  .chat-window { padding: 10px 8px; }

  /* min-height:72px already covers the two-line floor (see the shared
     rule above); horizontal padding/gap trimmed down further from the
     desktop values here to give the row as much width as possible on a
     narrow phone screen. */
  .chat-input-wrap { padding: 8px 6px 8px 10px; gap: 4px; border-radius: 26px; }

  /* Slightly larger tap targets than the desktop 32px circle. */
  .chat-send-btn, .tell-toggle-btn { width: 40px; height: 40px; }

  .main-panel-head { padding: 10px 14px; }
  /* The mobile topbar already carries "Vectram Room"; showing it again
     here would just be a duplicate title. */
  .app-brand { display: none; }
  .right-panel-body { padding: 14px 16px; }
  .breadcrumb { padding: 10px 16px 0; }
  .pane-brain { padding: 10px 10px; }
}
