/*
 * SoulBridge AI - application shell.
 *
 * One design system across the home, chat and auth screens. Each character has
 * an accent, set per-scope as --accent, but the surfaces, spacing and type stay
 * identical so five characters read as one platform rather than five apps.
 *
 * Glow is deliberately restrained: a soft accent shadow on the focused or
 * hovered element, never ambient neon on everything.
 */

:root {
  /* Ground: dark navy rather than pure black, so panels can sit above it. */
  --bg:            #080b14;
  --bg-raised:     #0e1420;
  --panel:         #141c2e;
  --panel-hover:   #1b2540;
  --line:          #24304a;
  --line-strong:   #35406b;

  --text:          #e6edf6;
  --text-dim:      #9aabc0;
  --text-faint:    #647893;

  /*
   * Platform palette. Cyan, magenta and violet over the deep navy ground -
   * taken from the character artwork, where all three already appear together.
   * Characters override --accent within their own scope.
   */
  --accent:        #22d3ee;   /* electric cyan  */
  --accent-dim:    #0891b2;
  --magenta:       #f0479c;   /* vivid pink     */
  --violet:        #a855f7;   /* violet         */

  /* The three-stop sweep used on primary buttons, the brand mark and focus
     glows, so the identity reads the same everywhere. */
  --brand-sweep: linear-gradient(120deg, #22d3ee 0%, #a855f7 52%, #f0479c 100%);

  /* Controlled glow. One soft accent shadow on the focused or hovered thing -
     never ambient neon on every surface. */
  --glow:        0 0 0 3px rgba(34, 211, 238, .16);
  --glow-strong: 0 8px 28px rgba(168, 85, 247, .28);

  --danger:        #f87171;
  --danger-bg:     #2a1416;
  --ok:            #4ade80;

  --radius:        14px;
  --radius-sm:     9px;
  --gap:           18px;

  --font: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15.5px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); }

/* Keyboard focus must always be visible - several legacy screens removed it. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
  box-shadow: var(--glow);
}

/* ---------------------------------------------------------------- app bar */

.sb-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 22px;
  background: var(--bg-raised);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 40;
}

.sb-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--text);
  text-decoration: none;
  letter-spacing: -0.01em;
}

/*
 * Compact header mark: the SoulBridge heart emblem cropped from the approved
 * logo. The full mascot logo is far too detailed at 30px, and the plain "SB"
 * square it replaces was placeholder branding.
 */
.sb-mark {
  width: 30px; height: 30px;
  border-radius: 8px;
  object-fit: contain;
  display: block;
  flex: none;
  background: none;
}

.sb-bar-spacer { flex: 1; }

.sb-bar nav { display: flex; align-items: center; gap: 6px; }

.sb-navlink {
  color: var(--text-dim);
  text-decoration: none;
  font-size: 0.92rem;
  padding: 7px 12px;
  border-radius: var(--radius-sm);
}
.sb-navlink:hover { color: var(--text); background: var(--panel); }

/* ---------------------------------------------------------------- layout */

.sb-page { max-width: 1140px; margin: 0 auto; padding: 34px 22px 72px; }

.sb-hello { margin: 0 0 4px; font-size: 1.85rem; font-weight: 700; letter-spacing: -0.02em; }
.sb-sub { margin: 0 0 30px; color: var(--text-dim); font-size: 1.02rem; }

.sb-section-label {
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 34px 0 12px;
  font-weight: 600;
}

/* ------------------------------------------------------------- guide card */

.sb-guide {
  display: flex;
  align-items: center;
  gap: 20px;
  background: linear-gradient(125deg, rgba(34,211,238,.12), rgba(168,85,247,.10) 55%, rgba(240,71,156,.10));
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 20px 22px;
}

.sb-guide-art {
  width: 92px; height: 92px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 9%;   /* frame her face, not the full figure */
  border: 2px solid var(--violet);
  background: var(--panel);
  flex: none;
}

.sb-guide-body { flex: 1; min-width: 0; }
.sb-guide h2 { margin: 0; font-size: 1.15rem; color: #7dd3fc; }
.sb-guide .role {
  margin: 1px 0 7px;
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 600;
}
.sb-guide p { margin: 0 0 14px; color: var(--text-dim); font-size: 0.94rem; }
.sb-guide-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ------------------------------------------------------------- specialists */

.sb-grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

.sb-card {
  --accent: #22d3ee;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
  width: 100%;
  background: var(--panel);
  border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius);
  padding: 20px;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.sb-card:hover {
  background: var(--panel-hover);
  border-color: var(--line-strong);
  border-top-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: 0 10px 30px rgba(0,0,0,.35);
}

.sb-card-head { display: flex; align-items: center; gap: 12px; }
.sb-card-art {
  /* The artwork is full-body at 1024x1536. Shrunk to a 46px square the
     character was an unreadable speck, so the frame is larger and crops to the
     head and shoulders instead of fitting the whole figure. */
  width: 72px; height: 72px; border-radius: 12px;
  object-fit: cover;
  object-position: 50% 10%;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  flex: none;
}
.sb-card h3 { margin: 0; font-size: 1.06rem; color: var(--accent); }
.sb-card .role {
  margin: 0;
  font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 600;
}
.sb-card p { margin: 0; color: var(--text-dim); font-size: 0.9rem; }

.sb-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 2px; }
.sb-tag {
  font-size: 0.7rem;
  padding: 3px 8px;
  border-radius: 20px;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  color: var(--text-faint);
}

/* ---------------------------------------------------------------- buttons */

.sb-btn {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--text);
  font: inherit; font-size: 0.92rem; font-weight: 500;
  cursor: pointer;
  text-decoration: none;
}
.sb-btn:hover { background: var(--panel-hover); border-color: var(--accent); }

.sb-btn-primary {
  background: var(--brand-sweep);
  border-color: transparent;
  color: #06121c;
  font-weight: 600;
}
.sb-btn-primary:hover { filter: brightness(1.1); box-shadow: var(--glow-strong); }

.sb-btn-danger { border-color: #7f2427; color: var(--danger); background: var(--danger-bg); }
.sb-btn-danger:hover { background: #3a1a1d; border-color: var(--danger); }

.sb-btn-sm { padding: 5px 11px; font-size: 0.84rem; }

/* ------------------------------------------------------- recent list */

.sb-list { display: flex; flex-direction: column; gap: 8px; }

.sb-item {
  display: flex; align-items: center; gap: 13px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent, var(--line-strong));
  border-radius: var(--radius-sm);
  padding: 12px 15px;
}
.sb-item:hover { background: var(--panel-hover); }
.sb-item-main { flex: 1; min-width: 0; }
.sb-item-title {
  margin: 0; font-size: 0.95rem; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sb-item-meta { margin: 2px 0 0; font-size: 0.78rem; color: var(--text-faint); }
.sb-item-actions { display: flex; gap: 6px; flex: none; }

.sb-empty {
  padding: 26px;
  text-align: center;
  color: var(--text-faint);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  font-size: 0.92rem;
}

/* ---------------------------------------------------------------- auth */

.sb-auth-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 32px 20px;
}
.sb-auth {
  width: 100%;
  max-width: 400px;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 32px 28px;
}
.sb-auth-brand { text-align: center; margin-bottom: 24px; }
.sb-auth-brand .sb-mark { width: 44px; height: 44px; font-size: 1rem; margin: 0 auto 12px; }
.sb-auth-brand h1 { margin: 0 0 4px; font-size: 1.4rem; letter-spacing: -0.02em; }
.sb-auth-brand p { margin: 0; color: var(--text-dim); font-size: 0.92rem; }

.sb-field { margin-bottom: 15px; }
.sb-field label {
  display: block; margin-bottom: 6px;
  font-size: 0.85rem; color: var(--text-dim); font-weight: 500;
}
.sb-field input {
  width: 100%;
  padding: 11px 13px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  font: inherit; font-size: 0.95rem;
}
.sb-field input:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px rgba(34,211,238,.14); }

.sb-auth .sb-btn-primary { width: 100%; justify-content: center; padding: 11px; margin-top: 4px; }
.sb-auth-alt { margin-top: 18px; text-align: center; font-size: 0.9rem; color: var(--text-dim); }
.sb-auth-links { margin-top: 10px; text-align: center; font-size: 0.86rem; }

.sb-msg { padding: 10px 13px; border-radius: var(--radius-sm); font-size: 0.88rem; margin-bottom: 15px; }
.sb-msg-error { background: var(--danger-bg); border: 1px solid #7f2427; color: #fca5a5; }
.sb-msg-ok { background: #0d2818; border: 1px solid #166534; color: #86efac; }

/* ---------------------------------------------------------------- chat */

.sb-chat { display: flex; height: calc(100vh - 53px); overflow: hidden; }

.sb-side {
  width: 268px; flex: none;
  background: var(--bg-raised);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
}
.sb-side-head { padding: 14px; border-bottom: 1px solid var(--line); }
.sb-side-head .sb-btn { width: 100%; justify-content: center; }
.sb-side-list { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 5px; }

.sb-conv {
  display: block; width: 100%; text-align: left;
  background: none; border: 1px solid transparent;
  border-left: 3px solid var(--accent, var(--line-strong));
  border-radius: var(--radius-sm);
  padding: 9px 11px; color: var(--text-dim);
  font: inherit; font-size: 0.87rem; cursor: pointer;
}
.sb-conv:hover { background: var(--panel); color: var(--text); }
.sb-conv.active { background: var(--panel); color: var(--text); border-color: var(--line-strong); border-left-color: var(--accent); }
.sb-conv-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sb-conv-meta { font-size: 0.72rem; color: var(--text-faint); margin-top: 1px; }

.sb-main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.sb-chat-head {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 20px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-raised);
}
.sb-chat-art {
  width: 42px; height: 42px; border-radius: 10px;
  object-fit: cover; object-position: 50% 10%;
  border: 1px solid var(--line-strong); flex: none;
}
.sb-chat-who { flex: 1; min-width: 0; }
.sb-chat-who h2 { margin: 0; font-size: 1rem; color: var(--accent); }
.sb-chat-who p { margin: 0; font-size: 0.78rem; color: var(--text-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sb-thread { flex: 1; overflow-y: auto; padding: 22px 20px; display: flex; flex-direction: column; gap: 14px; }

.sb-msg-row { display: flex; gap: 10px; max-width: 760px; }
.sb-msg-row.me { align-self: flex-end; flex-direction: row-reverse; }

/* A picture and the words about it are one message, so they stack.
   They used to be siblings in the row's flex layout, which put the image and
   the caption side by side as two columns - and on a phone that left the
   caption a strip a few characters wide, wrapping one word per line. */
.sb-msg-row:has(> .sb-attachments) {
  flex-direction: column;
  align-items: flex-end;          /* the reader's own turn stays right-aligned */
  max-width: min(560px, 92%);
}
.sb-msg-row:not(.me):has(> .sb-attachments) { align-items: flex-start; }

.sb-attachments {
  order: -1;                      /* above the caption, whatever the DOM order */
  width: 100%;
  display: grid;
  gap: 8px;
}
/* Several pictures share the width rather than each taking all of it. */
.sb-attachments.many { grid-template-columns: 1fr 1fr; }

.sb-attachments .sb-image { margin: 0; }
.sb-attachments .sb-image img {
  display: block;
  width: 100%;
  height: auto;                   /* the aspect ratio is the image's own */
  border-radius: 10px;
}
/* The caption sits under the picture and uses the same width. */
.sb-msg-row:has(> .sb-attachments) > .sb-bubble {
  max-width: 100%;
  align-self: stretch;
}

@media (max-width: 560px) {
  .sb-msg-row:has(> .sb-attachments) { max-width: 92%; }
  /* Two thumbnails at 390px are too small to read; stack them instead. */
  .sb-attachments.many { grid-template-columns: 1fr; }
}


.sb-bubble {
  padding: 11px 15px;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--line);
  font-size: 0.94rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.sb-msg-row.me .sb-bubble {
  background: linear-gradient(135deg, rgba(34,211,238,.14), rgba(99,102,241,.12));
  border-color: var(--line-strong);
}

.sb-composer { border-top: 1px solid var(--line); padding: 14px 20px; background: var(--bg-raised); }
.sb-composer form { display: flex; gap: 10px; align-items: flex-end; }
.sb-composer textarea {
  flex: 1;
  min-width: 0;                  /* a flex item may shrink below its content */
  min-height: 46px;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--text); font: inherit; font-size: 0.94rem;
  line-height: 1.45;             /* the unit the growth ceiling is counted in */
  /* The height is set from content, so the height the box is given must be
     the height it takes - padding and border included. */
  box-sizing: border-box;
  /* The drag handle fought the auto-grow: a manually resized box was
     overwritten on the next keystroke. Growing with the text is the better of
     the two behaviours, so it is the only one. */
  resize: none;
  overflow-y: hidden;            /* until there is more than the ceiling */
}
.sb-composer textarea:focus { border-color: var(--accent); outline: none; }
.sb-hint { margin: 7px 0 0; font-size: 0.76rem; color: var(--text-faint); min-height: 1.1em; }
.sb-hint.error { color: var(--danger); }

/*
 * Shown only under a reply the model was cut off mid-way. Deliberately quiet:
 * it explains what happened and offers the fix, rather than competing with the
 * answer above it.
 */
/*
 * Creator tools.
 *
 * One small button beside the composer, opening a short menu. Deliberately not
 * a row of permanent buttons: the composer belongs to the message, and a tool
 * the reader is not using should not be taking up space in it.
 */
.sb-tools { position: relative; flex: none; align-self: flex-end; }
.sb-tool-btn {
  width: 38px; height: 38px; border-radius: 10px;
  border: 1px solid var(--line-strong); background: var(--bg-raised);
  color: var(--text-dim); font-size: 1.3rem; line-height: 1; cursor: pointer;
}
.sb-tool-btn:hover { color: var(--accent); border-color: var(--accent); }
.sb-tool-menu {
  position: absolute; bottom: 46px; left: 0; z-index: 30;
  min-width: 186px; padding: 5px;
  background: var(--panel); border: 1px solid var(--line-strong);
  border-radius: 12px; box-shadow: 0 12px 30px rgba(0,0,0,.5);
  display: flex; flex-direction: column; gap: 2px;
}
.sb-tool-menu[hidden] { display: none; }
.sb-tool-menu button {
  text-align: left; padding: 9px 12px; border-radius: 8px;
  background: none; border: none; color: var(--text);
  font: inherit; font-size: .88rem; cursor: pointer;
}
.sb-tool-menu button:hover { background: var(--panel-hover); color: var(--accent); }

/* A generated result is the answer, so it gets the room. The text above it
   is one short line; nothing should push the picture below the fold. */
.sb-image .cap a.saved { color: var(--text-faint); cursor: default; }
.sb-image .cap a.saved::before { content: "✓"; margin-right: 5px; }

/* Several pending attachments sit in a row above the composer. */
.sb-pending-strip { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.sb-pending-strip[hidden] { display: none; }
.sb-pending b {
  font-size: .7rem; color: var(--accent); background: var(--panel);
  border: 1px solid var(--line-strong); border-radius: 5px;
  width: 18px; height: 18px; display: grid; place-items: center; flex: none;
}

/* The image waiting to be sent with the next message. */
.sb-pending {
  display: flex; align-items: center; gap: 10px;
  margin-top: 8px; padding: 7px 10px; max-width: 420px;
  background: var(--bg-raised); border: 1px solid var(--line-strong);
  border-radius: 10px; font-size: .8rem; color: var(--text-dim);
}
.sb-pending[hidden] { display: none; }
.sb-pending img { width: 42px; height: 42px; object-fit: cover; border-radius: 6px; }
.sb-pending span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sb-pending button {
  background: none; border: none; color: var(--text-faint);
  font-size: 1.1rem; cursor: pointer; padding: 0 4px;
}
.sb-pending button:hover { color: var(--danger); }

/* An image inside the conversation, generated or attached. */
.sb-image { margin-top: 8px; max-width: 460px; }
.sb-image img {
  width: 100%; border-radius: 12px; display: block;
  border: 1px solid var(--line-strong); background: var(--bg-raised);
}
.sb-image .cap {
  margin-top: 5px; font-size: .74rem; color: var(--text-faint);
  display: flex; gap: 10px; align-items: center;
}
.sb-image .cap a { color: var(--accent); text-decoration: none; }
.sb-image .cap a:hover { text-decoration: underline; }

/*
 * Sources under a research answer. Quiet by design: the evidence supports the
 * answer, it does not compete with it, and long URLs are never shown as prose.
 */
/* The row is a flex line; sources belong under the reply, not beside it. */
.sb-msg-row:has(> .sb-sources) { flex-wrap: wrap; }
.sb-sources {
  flex-basis: 100%;
  margin-top: 8px;
  padding: 10px 13px;
  border-left: 2px solid var(--line-strong);
  background: var(--bg-raised);
  border-radius: 0 10px 10px 0;
  max-width: 760px;
}
.sb-sources-head {
  font-size: .68rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--text-faint); font-weight: 700; margin-bottom: 5px;
}
.sb-sources ol { margin: 0; padding-left: 18px; }
.sb-sources li { font-size: .82rem; line-height: 1.5; margin: 3px 0; }
.sb-sources a { color: var(--accent); text-decoration: none; }
.sb-sources a:hover { text-decoration: underline; }
.sb-source-meta { color: var(--text-faint); }

.sb-continue-row { align-items: center; gap: 10px; margin-top: -4px; }
.sb-continue-note { font-size: 0.76rem; color: var(--text-faint); }
.sb-btn.sb-continue {
  padding: 5px 14px;
  font-size: 0.8rem;
  border-radius: 20px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  color: var(--accent);
}
.sb-btn.sb-continue:hover:not(:disabled) { border-color: var(--accent); box-shadow: var(--glow); }
.sb-btn.sb-continue:disabled { opacity: .6; cursor: default; }

.sb-typing { color: var(--text-faint); font-size: 0.88rem; font-style: italic; }

/* --------------------------------------------------------------- mobile */

.sb-side-toggle { display: none; }

@media (max-width: 820px) {
  .sb-page { padding: 24px 16px 60px; }
  .sb-hello { font-size: 1.5rem; }

  .sb-guide { flex-direction: column; align-items: flex-start; gap: 14px; }
  .sb-guide-art { width: 60px; height: 60px; }

  .sb-grid { grid-template-columns: 1fr; }

  /* The history rail slides over the thread rather than squeezing it. */
  .sb-side-toggle { display: inline-flex; }
  .sb-side {
    position: fixed; top: 53px; bottom: 0; left: 0; z-index: 30;
    transform: translateX(-100%);
    transition: transform .2s ease;
    box-shadow: 0 0 40px rgba(0,0,0,.5);
  }
  .sb-side.open { transform: translateX(0); }

  .sb-thread { padding: 16px 14px; }

  /* Not 100%: at full width both sides fill the column and align-self has no
     visible effect, so you cannot tell your own messages from the reply. */
  .sb-msg-row { max-width: 88%; }

  .sb-composer { padding: 11px 14px; }

  .sb-bar { padding: 10px 12px; gap: 10px; }
  .sb-bar nav { gap: 2px; }
  .sb-bar nav .sb-navlink { padding: 6px 8px; font-size: 0.84rem; white-space: nowrap; }
  /* The SB mark alone carries the brand once space is tight; the wordmark was
     wrapping onto two lines and pushing the nav out of shape. */
  .sb-brand { font-size: 0; gap: 0; }
  .sb-brand .sb-mark { font-size: 0.78rem; }
}

@media (max-width: 420px) {
  .sb-bar nav .sb-navlink { padding: 6px 6px; font-size: 0.8rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .sb-card:hover { transform: none; }
}

/* ------------------------------------------------------- overflow menu */
/*
 * Secondary and destructive row actions live behind this rather than sitting
 * on the row as bright buttons. Built on <details> so open/close and keyboard
 * access come from the element itself.
 */

.menu { position: relative; }
.menu > summary {
  list-style: none;
  cursor: pointer;
  width: 30px; height: 30px;
  border-radius: 7px;
  display: grid; place-items: center;
  color: var(--text-faint);
  border: 1px solid transparent;
  font-size: 1rem; line-height: 1;
}
.menu > summary::-webkit-details-marker { display: none; }
.menu > summary:hover {
  background: var(--bg-raised);
  color: var(--text);
  border-color: var(--line);
}

.menu-pop {
  position: absolute; right: 0; top: 34px; z-index: 25;
  min-width: 178px; padding: 5px;
  background: var(--panel);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 34px rgba(0,0,0,.5);
  display: flex; flex-direction: column; gap: 1px;
}
.menu-pop button {
  background: none; border: none; text-align: left;
  color: var(--text-dim);
  font: inherit; font-size: 0.87rem;
  padding: 8px 11px; border-radius: 6px;
  cursor: pointer; width: 100%;
}
.menu-pop button:hover { background: var(--bg-raised); color: var(--text); }
.menu-pop button.danger { color: var(--danger); }
.menu-pop button.danger:hover { background: var(--danger-bg); }
/* A conversation already in the Library says so rather than offering to
   save it again. Not a control - there is nothing to press - so it reads
   as state and cannot be clicked. */
.menu-pop .saved-state {
  color: var(--text-faint);
  cursor: default;
  opacity: 1;
}
.menu-pop .saved-state:hover { background: none; }

.menu-sep { height: 1px; background: var(--line); margin: 4px 2px; }

/* In the chat rail the menu sits inside a narrow row, so it opens leftward. */
.sb-conv-row { display: flex; align-items: center; gap: 4px; }
.sb-conv-row .sb-conv { flex: 1; min-width: 0; }
.sb-conv-row .menu-pop { right: auto; left: 0; }

/* ---------------------------------------------------- narrow-screen nav */
/*
 * At 414px the six nav links plus the brand are wider than the viewport, which
 * pushed the whole page sideways and clipped the last link. The bar scrolls on
 * its own instead of stretching the document.
 */
@media (max-width: 720px) {
  .sb-bar { gap: 10px; }
  .sb-bar nav {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    max-width: 100%;
  }
  .sb-bar nav::-webkit-scrollbar { display: none; }
  .sb-navlink { white-space: nowrap; }

  /* The brand may shrink; the nav must not. */
  .sb-brand { min-width: 0; }
  .sb-brand span:not(.sb-mark) {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }

  /* Nothing may make the document itself scroll sideways. */
  html, body { overflow-x: hidden; }
}

/*
 * Containment backstop. Flex and grid children default to min-width:auto, so a
 * long unbroken string (a conversation title, a saved song line) can force a
 * track wider than the screen and push the whole page sideways. These make the
 * page the limit rather than the content.
 */
.sb-page, .sb-list, .sb-item, .lib-filters, .lib-imgs { max-width: 100%; }
.sb-item-main, .sb-card, .sb-guide-body { min-width: 0; }
.sb-item-title, .sb-preview, .lib-preview { overflow-wrap: anywhere; }

/* The full mascot logo on the auth pages. Capped so the detail stays readable
   without dominating the card. */
.sb-auth-logo {
  display: block;
  width: min(260px, 72%);
  height: auto;
  margin: 0 auto 14px;
}
@media (max-width: 480px) { .sb-auth-logo { width: min(210px, 68%); } }

/* ===================================================== password reveal */

.sb-pw { position: relative; display: block; }
.sb-pw input { width: 100%; padding-right: 44px; }   /* room for the control */

.sb-pw-eye {
  position: absolute; right: 6px; top: 50%;
  transform: translateY(-50%);
  width: 32px; height: 32px;
  display: grid; place-items: center;
  background: none; border: 1px solid transparent; border-radius: 7px;
  color: var(--text-faint); cursor: pointer; padding: 0;
}
.sb-pw-eye:hover { color: var(--text); background: var(--bg-raised); border-color: var(--line); }
.sb-pw-eye[aria-pressed="true"] { color: var(--accent); }

/* ===================================================== character art */
/*
 * The supplied PNGs are full-body, transparent, 1024x1536. object-fit: cover
 * cropped heads and tails off to fill a square; contain shows the whole figure
 * as drawn. The frames are portrait-shaped so contain does not leave a band of
 * empty space either side.
 */
.sb-card-art,
.sb-guide-art,
.sb-chat-art {
  object-fit: contain !important;
  object-position: center bottom;
  background: transparent;
}

/* Home cards put the mascot on top, at a size where the artwork reads. */
.sb-card-portrait {
  width: 100%;
  height: 190px;
  display: block;
  object-fit: contain;
  object-position: center bottom;
  margin-bottom: 4px;
  /* A soft accent pool behind transparent art so it sits on the card rather
     than floating. */
  background: radial-gradient(ellipse at 50% 100%,
              color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%);
}

/* Section 12: the specialist in the chat header was too small to read. */
.sb-chat-art { width: 56px; height: 56px; border: none; }
.sb-guide-art { border-radius: 0; border: none; background: transparent; }

/* ===================================================== explore cards */

.sb-tile {
  position: relative;
  display: flex; flex-direction: column; gap: 8px;
  padding: 22px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: inherit; text-decoration: none;
  overflow: hidden;
  transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.sb-tile::before {
  /* Accent wash, strongest at the top edge. */
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(160deg,
              color-mix(in srgb, var(--accent) 16%, transparent), transparent 58%);
  pointer-events: none;
}
.sb-tile:hover, .sb-tile:focus-visible {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: 0 14px 34px rgba(0,0,0,.42), 0 0 26px color-mix(in srgb, var(--accent) 26%, transparent);
}
.sb-tile > * { position: relative; }
.sb-tile-icon {
  width: 46px; height: 46px; border-radius: 12px;
  display: grid; place-items: center; font-size: 1.4rem;
  background: color-mix(in srgb, var(--accent) 16%, var(--bg-raised));
  border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
}
.sb-tile h3 { margin: 6px 0 0; font-size: 1.1rem; color: var(--accent); }
.sb-tile .cat {
  margin: 0; font-size: .66rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--text-faint); font-weight: 700;
}
.sb-tile p { margin: 0; color: var(--text-dim); font-size: .9rem; }
.sb-tile .cta { margin-top: 6px; font-size: .86rem; font-weight: 600; color: var(--accent); }

/* ===================================================== empty states */

.sb-blank {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 52px 26px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-align: center;
}
.sb-blank-icon {
  width: 54px; height: 54px; border-radius: 16px;
  display: grid; place-items: center; font-size: 1.5rem;
  background: linear-gradient(135deg,
              color-mix(in srgb, var(--accent) 18%, var(--bg-raised)),
              color-mix(in srgb, var(--violet) 14%, var(--bg-raised)));
  border: 1px solid var(--line-strong);
  margin-bottom: 4px;
}
.sb-blank h3 { margin: 0; font-size: 1.02rem; }
.sb-blank p { margin: 0; color: var(--text-dim); font-size: .9rem; max-width: 42ch; }

/* Text affordance that opens the floating guide - no second mascot on Home. */
.sb-help { color: var(--text-dim); font-size: .96rem; margin: 0 0 26px; }
.sb-linkbtn {
  background: none; border: none; padding: 0;
  font: inherit; color: var(--accent); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.sb-linkbtn:hover { color: var(--magenta); }

/* ============================================ layering (one hierarchy) */
/*
 * Overlays were each solving their own stacking with ad-hoc numbers, which is
 * how the conversation menu ended up underneath the sidebar. One ladder,
 * referenced by name.
 */
:root {
  --z-content:  1;
  --z-sticky:   40;    /* app bar */
  --z-menu:     900;   /* dropdowns, overflow menus */
  --z-fab:      2000;  /* Sapphire collapsed */
  --z-panel:    2001;  /* Sapphire expanded */
  --z-modal:    3000;
}

.sb-bar   { z-index: var(--z-sticky); }
.menu-pop { z-index: var(--z-menu); }

/*
 * The rail clips its own overflow so long histories scroll, which also clipped
 * any menu opening inside it. The menu is taken out of flow instead: fixed
 * position, placed from JS against the button, so it can extend across the
 * main chat area.
 */
.sb-side-list { overflow-y: auto; overflow-x: visible; }
.menu-pop.floating { position: fixed; }

/* ============================================ chat empty state */

.sb-start {
  margin: auto;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  text-align: center; padding: 30px 20px;
}
.sb-start img {
  width: 180px; height: 240px;
  object-fit: contain; object-position: center bottom;
  margin-bottom: 6px;
}
.sb-start h2 { margin: 0; font-size: 1.3rem; font-weight: 600; }
.sb-start p { margin: 0; color: var(--text-dim); font-size: .95rem; max-width: 46ch; }

/* ============================================ chat safe area */
/*
 * Sapphire sat on top of the composer. Chat sets this offset from the real
 * composer height at runtime, so a textarea that grows never ends up beneath
 * her.
 */
:root { --sapphire-bottom: 24px; }

/*
 * The composer used to reserve a lane on the right so the floating Sapphire
 * could not cover Send. She is Home-only now - a navigation guide is not
 * useful once you are already inside a conversation - so the composer takes
 * the full width back.
 */

/* ------------------------------------------------ rendered assistant text */
/*
 * Assistant messages are Markdown now, so the bubble holds real block elements
 * instead of one run of text. pre-wrap would double the spacing these produce.
 */
.sb-bubble.sb-md { white-space: normal; }
.sb-md > :first-child { margin-top: 0; }
.sb-md > :last-child { margin-bottom: 0; }
.sb-md p { margin: 0 0 10px; }
.sb-md h3, .sb-md h4, .sb-md h5, .sb-md h6 {
  margin: 14px 0 6px; font-size: 1rem; font-weight: 600; color: var(--text);
}
.sb-md ul, .sb-md ol { margin: 0 0 10px; padding-left: 22px; }
.sb-md li { margin-bottom: 4px; }
.sb-md strong { font-weight: 650; color: var(--text); }
.sb-md em { font-style: italic; }
.sb-md a { color: var(--accent); text-underline-offset: 2px; }

.sb-md code {
  font-family: "Cascadia Code", Consolas, ui-monospace, monospace;
  font-size: .88em;
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 1px 5px;
}
.sb-md pre {
  margin: 0 0 10px;
  padding: 12px 14px;
  background: var(--bg-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  overflow-x: auto;                 /* long lines scroll, the bubble does not */
}
.sb-md pre code {
  background: none; border: none; padding: 0;
  font-size: .86rem; line-height: 1.55;
  white-space: pre;                 /* indentation preserved */
}

/*
 * Hide the browser's own password reveal control.
 *
 * Edge and IE inject ::-ms-reveal into every password field, so the field ended
 * up with two eyes: ours and the browser's. Ours is the one wired to
 * aria-pressed and the emoji states, so the built-in goes.
 */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear {
  display: none;
  width: 0;
  height: 0;
}
/* Safari/Chrome equivalents: the strong-password and caps-lock affordances. */
input[type="password"]::-webkit-credentials-auto-fill-button,
input[type="password"]::-webkit-strong-password-auto-fill-button,
input[type="password"]::-webkit-caps-lock-indicator {
  display: none !important;
  visibility: hidden;
  pointer-events: none;
}

/* ------------------------------------------------------------------ creation
   A generated picture is a Creator artifact, not a paragraph with an image
   under it. The card holds the whole event: it appears when the job starts,
   animates while it runs, and the finished picture lands in the same space the
   placeholder occupied, so nothing below it moves. */

/* A creation card is an artifact, not a speech bubble. Bubbles are capped so
   prose does not run to silly line lengths; a picture has the opposite need,
   so the row holding one takes the whole column. */
.sb-msg-row:has(> .sb-creation) { max-width: 100%; width: 100%; }
.sb-msg-row > .sb-creation { flex: 1 1 auto; min-width: 0; }

.sb-creation {
  --c1: #22d3ee;                       /* electric cyan  */
  --c2: #8b5cf6;                       /* violet         */
  --c3: #ec4899;                       /* controlled pink */
  margin-top: 10px;
  padding: 10px;
  border-radius: 16px;
  background:
    linear-gradient(180deg, rgba(13, 18, 34, .96), rgba(8, 11, 20, .96));
  border: 1px solid rgba(34, 211, 238, .22);
  /* A restrained glow rather than a neon frame: enough to read as active,
     not enough to compete with the picture it will hold. */
  box-shadow: 0 0 0 1px rgba(139, 92, 246, .08),
              0 10px 30px rgba(0, 0, 0, .38);
  animation: sb-breathe 5.2s ease-in-out infinite;
}
.sb-creation.done,
.sb-creation.failed { animation: none; }
.sb-creation.done { border-color: rgba(139, 92, 246, .22); }
.sb-creation.failed { border-color: rgba(239, 68, 68, .38); }

@keyframes sb-breathe {
  0%, 100% { box-shadow: 0 0 0 1px rgba(139, 92, 246, .08),
                         0 10px 30px rgba(0, 0, 0, .38); }
  50%      { box-shadow: 0 0 0 1px rgba(34, 211, 238, .20),
                         0 10px 34px rgba(0, 0, 0, .44); }
}

/* One slot per expected result. Reference Blend asks for two and gets two
   columns where there is room; everything narrow stacks. */
.sb-stage { display: grid; grid-template-columns: 1fr; gap: 10px; }
@media (min-width: 720px) {
  .sb-creation.pair .sb-stage { grid-template-columns: 1fr 1fr; }
  /* One result does not want the whole desk. Left at full width a square
     image ran taller than the viewport and pushed its own Save button off
     the bottom of the screen - the card should read as deliberate, not as
     something that expanded until it ran out of room. The card is capped
     rather than the picture inside it, so the frame hugs the image instead
     of trailing empty surface beside it. A pair keeps the full width,
     because two columns need it. */
  .sb-msg-row:has(> .sb-creation:not(.pair)) { max-width: 620px; }
}

.sb-slot {
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  background: radial-gradient(120% 100% at 50% 0%,
              rgba(34, 211, 238, .07), rgba(6, 9, 16, .9) 70%);
  min-height: 180px;
  display: grid;
  place-items: center;
}
/* Only a slot still waiting reserves height. Once the picture lands the slot
   is sized by the image, so a tall portrait is not letterboxed into a square. */
.sb-slot.working { aspect-ratio: 1 / 1; }

.sb-slot-tag {
  position: absolute; top: 8px; left: 10px; z-index: 3;
  font-size: .62rem; letter-spacing: .1em; text-transform: uppercase;
  font-weight: 700; color: rgba(226, 232, 240, .78);
  background: rgba(2, 6, 14, .6); padding: 3px 7px; border-radius: 6px;
}

/* The picture an edit works from, shown dimmed under the sweep so the reader
   can see what is being changed. */
.sb-slot-source {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: .3; filter: saturate(.6) blur(1px);
  transition: opacity .5s ease;
}
.sb-slot-source.fading { opacity: 0; }

/* The reflector: a slow diagonal highlight travelling across the surface. */
.sb-sweep {
  position: absolute; inset: -40%;
  background: linear-gradient(115deg,
      transparent 38%,
      rgba(34, 211, 238, .16) 46%,
      rgba(139, 92, 246, .22) 52%,
      rgba(236, 72, 153, .15) 58%,
      transparent 66%);
  transform: translateX(-60%);
  animation: sb-sweep 3.4s linear infinite;
  pointer-events: none;
}
.sb-slot:not(.working) .sb-sweep { display: none; }

@keyframes sb-sweep {
  from { transform: translateX(-60%); }
  to   { transform: translateX(60%); }
}

/* The finished picture, arriving in the space the placeholder held. */
.sb-slot-image {
  position: relative; z-index: 2;
  display: block; width: 100%; height: auto; border-radius: 12px;
  animation: sb-land .55s ease both;
}
@keyframes sb-land { from { opacity: 0; } to { opacity: 1; } }

.sb-slot.landed { box-shadow: 0 0 0 1px rgba(34, 211, 238, .5),
                              0 0 26px rgba(139, 92, 246, .34); }
.sb-slot { transition: box-shadow .6s ease; }

.sb-slot-actions {
  position: relative; z-index: 3;
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 8px 2px 2px;
}
.sb-slot-actions a,
.sb-slot-actions .sb-save {
  font: inherit; font-size: .74rem; cursor: pointer;
  color: var(--c1); background: none; border: 0; padding: 4px 2px;
  text-decoration: none; border-radius: 6px;
}
.sb-slot-actions a:hover,
.sb-slot-actions .sb-save:hover { text-decoration: underline; }
.sb-slot-actions a:focus-visible,
.sb-slot-actions .sb-save:focus-visible {
  outline: 2px solid var(--c1); outline-offset: 2px; text-decoration: none;
}
.sb-save.saved { color: rgba(226, 232, 240, .55); cursor: default; }
.sb-save.saved::before { content: "\2713"; margin-right: 5px; }
.sb-save.just-saved { animation: sb-saved .9s ease; }
@keyframes sb-saved {
  0%   { color: var(--c1); text-shadow: 0 0 12px rgba(34, 211, 238, .8); }
  100% { color: rgba(226, 232, 240, .55); text-shadow: none; }
}

.sb-creation-foot {
  padding: 9px 4px 3px;
  font-size: .76rem; color: rgba(226, 232, 240, .66);
  min-height: 1.4em;                   /* a changing phrase must not resize the card */
}
.sb-phrase { transition: opacity .3s ease; }
.sb-creation.failed .sb-creation-foot { color: #fca5a5; }

/* Announced to assistive technology, never drawn. */
.sb-sr {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Motion is decoration here; the card still reads as active without it. */
@media (prefers-reduced-motion: reduce) {
  .sb-creation { animation: none; }
  .sb-sweep {
    animation: none; transform: none; inset: 0;
    background: linear-gradient(115deg, transparent 30%,
                rgba(139, 92, 246, .16) 50%, transparent 70%);
    opacity: .8;
  }
  .sb-slot.working .sb-sweep { animation: sb-soft 3.6s ease-in-out infinite; }
  .sb-slot-image { animation: none; }
  @keyframes sb-soft { 0%, 100% { opacity: .5; } 50% { opacity: .95; } }
}

/* -------------------------------------------------------------------- dialog
   Asking before something is filed away. Built on the native element, so the
   focus trap, the Escape key and the inert page behind it are the browser's
   job rather than ours. */

.sb-dialog {
  width: min(420px, calc(100vw - 32px));
  padding: 20px 20px 16px;
  border: 1px solid rgba(34, 211, 238, .24);
  border-radius: 16px;
  background: linear-gradient(180deg, rgba(15, 20, 36, .99), rgba(9, 12, 22, .99));
  color: var(--text);
  box-shadow: 0 0 0 1px rgba(139, 92, 246, .10),
              0 24px 60px rgba(0, 0, 0, .55);
}
.sb-dialog::backdrop {
  background: rgba(3, 6, 14, .62);
  backdrop-filter: blur(2px);
}

.sb-dialog h2 {
  margin: 0 0 8px;
  font-size: 1.02rem;
  line-height: 1.3;
  color: var(--text);
}
.sb-dialog p {
  margin: 0 0 18px;
  font-size: .87rem;
  line-height: 1.5;
  color: var(--text-faint);
  /* A long conversation title must wrap rather than widen the dialog. */
  overflow-wrap: anywhere;
}

.sb-dialog-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;              /* narrow phones stack rather than overflow */
}
.sb-dialog-actions .sb-btn { min-width: 96px; }

/* Destructive, but not shouting. A warm border and warm text read as "this one
   is different" without turning the dialog into an alarm. */
.sb-btn-danger {
  border-color: rgba(244, 114, 182, .5);
  color: #fbcfe8;
  background: linear-gradient(135deg, rgba(236, 72, 153, .16),
                                      rgba(139, 92, 246, .12));
}
.sb-btn-danger:hover {
  border-color: rgba(244, 114, 182, .8);
  color: #fff;
}
.sb-btn-danger:focus-visible {
  outline: 2px solid rgba(244, 114, 182, .9);
  outline-offset: 2px;
}

@media (max-width: 420px) {
  .sb-dialog { padding: 18px 16px 14px; }
  .sb-dialog-actions .sb-btn { flex: 1 1 auto; }
}
