/* App-shell layout: fixed top bar + fixed left sidebar, the content
   scrolls — the YouTube-recognizable frame. Loaded after css/common.css
   (tokens live there); this file is shell chrome only. Every page uses the
   shell since 2026-08-30 (js/nav.js and the #topnav styles are dead). */

:root {
  --topbar-h: 56px;
  --sidebar-w: 240px;
}

/* The shell page owns its main layout: fills the space beside the fixed
   chrome. common.css centers main at 900px for the document-style pages.
   width:auto matters — common.css sets width:100%, which together with the
   sidebar margin made the page 240px wider than the viewport: the whole
   feed could scroll sideways under the sidebar (read as "the sidebar is an
   overlay"). auto = exactly the remaining space, no sideways scroll. */
.shell-page main {
  max-width: none;
  width: auto;
  margin: 0 0 0 var(--sidebar-w);
  padding: calc(var(--topbar-h) + 1.25rem) 1.5rem 4rem;
  transition: margin-left 0.15s ease;
}
.shell-page.sidebar-collapsed main { margin-left: 0; }

/* ── Top bar ──────────────────────────────────────────────────────────── */
#topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 120;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 1rem;
  background: var(--nav-bg);
  backdrop-filter: blur(8px);
  /* deliberately no bottom line — dividers live between content and
     sidebar and between sidebar sections only (2026-08-30) */
}
.topbar-menu {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--fg);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.topbar-menu:hover { background: var(--row-hover); }
/* brand reuses .nav-brand from common.css (the "Bubble" wordmark —
   no logo image), centered in the bar — absolute so hamburger/right-side
   widths can't push it off-center */
#topbar .nav-brand {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  margin-right: 0;
}
/* On app pages the wash spans 95% of the page, painted on the BAR itself
   (::before), not on the link — a 95vw anchor would cover the hamburger and
   sign-in chip and steal their taps. It sits behind the bar's children
   (near-transparent at the edges anyway, thanks to the eased fades) and is
   click-transparent; the brand link shrinks back to its text. */
#topbar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--brand-wash);
  pointer-events: none;
  z-index: 0;
}
#topbar .brand-box {
  display: inline-flex;
  align-items: center;
  height: var(--topbar-h);
  border-radius: 0;
  background: none;
  padding-left: 0.42rem;
  padding-right: 0.42rem;
}
.topbar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.topbar-signin {
  padding: 0.45rem 1.1rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: var(--card);
  color: var(--accent);
  font-size: 0.875rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}
.topbar-signin:hover { background: rgba(37, 99, 235, 0.08); }
.topbar-user {
  color: var(--nav-fg);
  font-size: 0.75rem;
  white-space: nowrap;
}
.topbar-signout {
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--nav-fg);
  text-decoration: none;
  white-space: nowrap;
}
.topbar-signout:hover {
  color: var(--fg);
  background: rgba(37, 99, 235, 0.08);
}

/* ── Sidebar ──────────────────────────────────────────────────────────── */
#sidebar {
  --bubble-row-h: 2.25rem;   /* fixed toggle-row height — the scroll cap's unit */
  position: fixed;
  top: var(--topbar-h);
  left: 0;
  bottom: 0;
  width: var(--sidebar-w);
  z-index: 110;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 1rem 0.75rem 1.5rem;
  /* solid, not translucent — nothing ever shows through the sidebar.
     The content/sidebar divider is a background layer, not a border: a
     1px line inset 14px from top and bottom so its tips never touch the
     viewport edges or read as a full-height wall. (Backgrounds don't
     scroll with the sidebar's own overflow content, so the line stays
     put.) */
  background:
    linear-gradient(var(--divider), var(--divider)) right 0 top 14px / 1px calc(100% - 28px) no-repeat,
    var(--card);
  transition: transform 0.15s ease, visibility 0.15s;
}
.shell-page.sidebar-collapsed #sidebar {
  transform: translateX(-100%);
  visibility: hidden;
}
.sidebar-section {
  padding: 0.6rem 0;
  /* same dark divider as the sidebar's right edge; the sections sit
     inside the sidebar's 0.75rem side padding, so these lines already
     stop short of the vertical line — no touching corners */
  border-top: 1px solid var(--divider);
}
.sidebar-section:first-child { border-top: none; padding-top: 0; }
.sidebar-heading {
  padding: 0 0.75rem 0.35rem;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.75rem;
  border-radius: 8px;
  color: var(--fg);
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
}
.sidebar-link:hover { background: var(--row-hover); }
/* holds an inline Lucide svg (bubbleIcon) since 2026-08-30, emoji before */
.sidebar-link-icon {
  display: inline-flex;
  align-items: center;
  font-size: 0.95rem;
}
/* the current page's sidebar link */
.sidebar-link.active {
  background: rgba(37, 99, 235, 0.10);
  color: var(--accent);
  font-weight: 600;
}
/* "Add bubble" — the sidebar's lead action, styled as a button */
.sidebar-new {
  justify-content: center;
  border: 1px solid var(--accent);
  color: var(--accent);
  font-weight: 600;
  margin-bottom: 0.6rem;
}
.sidebar-new:hover { background: rgba(37, 99, 235, 0.08); }

/* one row per bubble — the sidebar version of the old filter chips: click
   toggles the bubble in/out of the feed. Enabled = an enclosing FULL-rainbow
   border (same six-stop gradient as .sidebar-whatis, painted border-box
   under a solid padding-box fill) + full-color text; disabled rows stay
   plain and muted. Every row carries a permanent transparent border and a
   fixed height so toggling never shifts the layout — the fixed height is
   also what .sidebar-bubble-scroll's 8-row cap is computed from. */
.sidebar-bubble {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  height: var(--bubble-row-h, 2.25rem);
  padding: 0.45rem 0.75rem;
  border: 2px solid transparent;
  border-radius: 8px;
  background: none;
  color: var(--muted);
  font-size: 0.8125rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.sidebar-bubble:hover { background: var(--row-hover); }
.sidebar-bubble.on {
  color: var(--fg);
  background:
    linear-gradient(var(--card), var(--card)) padding-box,
    linear-gradient(100deg, #ff5f6d, #ffc371, #3ddc84, #24c6dc, #7367f0, #f76ecb) border-box;
}
.sidebar-bubble.on:hover {
  background:
    linear-gradient(var(--row-hover), var(--row-hover)) padding-box,
    linear-gradient(100deg, #ff5f6d, #ffc371, #3ddc84, #24c6dc, #7367f0, #f76ecb) border-box;
}
/* the toggle rows live in this wrapper (browse.js): at most 8 rows tall,
   scrolls beyond that so the nav sections below never get pushed away —
   the all/none actions row sits outside it and stays visible */
.sidebar-bubble-scroll {
  max-height: calc(8 * var(--bubble-row-h, 2.25rem));
  overflow-y: auto;
  overscroll-behavior: contain;
}
.sidebar-bubble-label {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* small marker on rows that are someone else's PUBLIC bubble (globe svg) */
.sidebar-bubble-public {
  display: inline-flex;
  align-items: center;
  margin-left: auto;
  flex-shrink: 0;
  font-size: 0.8rem;
  opacity: 0.75;
}
/* the × on added public rows — un-adds the bubble (a span acting as a
   button: the row itself is a <button>, so it can't nest one) */
.sidebar-bubble-remove {
  flex-shrink: 0;
  padding: 0 0.2rem;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
}
.sidebar-bubble-remove:hover { color: var(--danger); }
/* All / None under the toggle rows — centered proper small buttons
   (2026-09-02; they used to be bare accent-text links) */
.sidebar-bubble-actions {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.4rem 0.45rem 0.15rem;
}
.sidebar-bubble-actions button {
  padding: 0.28rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  color: var(--fg);
  font-size: 0.78rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
}
.sidebar-bubble-actions button:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.sidebar-empty {
  margin: 0;
  padding: 0 0.75rem;
  color: var(--muted);
  font-size: 0.8125rem;
  line-height: 1.5;
}
.sidebar-empty a {
  color: var(--accent);
  text-decoration: none;
}
.sidebar-empty a:hover { text-decoration: underline; }

/* "What is Bubble ?" — the sidebar's lead button → welcome.html. FULL
   rainbow fill (deliberately louder than the "bubble rainbow" cyan→pink
   brand gradient — see bubble/CLAUDE.md for the color vocabulary), with
   the logo's exact text treatment: white + 8-direction 1px black outline
   (text-stroke paints over the fill in WebKit, shadows work everywhere).
   Theme-independent by design — the rainbow is the surface. */
.sidebar-whatis {
  justify-content: center;
  font-weight: 700;
  margin-bottom: 0.6rem;
  border: 2px solid transparent;
  border-radius: 999px;
  background: linear-gradient(100deg, #ff5f6d, #ffc371, #3ddc84, #24c6dc, #7367f0, #f76ecb);
  color: #fff;
  text-shadow:
    -1px -1px 0 #000, 0 -1px 0 #000, 1px -1px 0 #000,
    -1px  0   0 #000,                1px  0   0 #000,
    -1px  1px 0 #000, 0  1px 0 #000, 1px  1px 0 #000;
}
/* re-assert the gradient (the generic .sidebar-link:hover would flatten it
   to --row-hover) and catch the light a little */
.sidebar-whatis:hover {
  background: linear-gradient(100deg, #ff5f6d, #ffc371, #3ddc84, #24c6dc, #7367f0, #f76ecb);
  filter: brightness(1.1) saturate(1.1);
}

/* ── Feed end-of-pool note — the feed scrolls endlessly (2026-09-02:
   chunks revealed as #feed-sentinel nears the viewport; the old
   Shuffle / Show toolbar is gone) and this line closes it out ─────────── */
#feed-end {
  margin: 2rem 0 0;
  text-align: center;
  color: var(--muted);
  font-size: 0.8125rem;
}

/* ── Sign-in modal (Google + beta), opened from the top bar ───────────── */
.shell-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.shell-modal[hidden] { display: none; }
.shell-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(20, 38, 58, 0.45);
}
.shell-modal-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.1rem;
  width: 100%;
  max-width: 400px;
  padding: 2.25rem 1.75rem 1.75rem;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
  text-align: center;
}
.shell-modal-card > p { margin: 0; color: var(--muted); font-size: 0.9rem; }
.shell-modal-close {
  position: absolute;
  top: 0.5rem;
  right: 0.7rem;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}
.shell-modal-close:hover { color: var(--fg); }

/* ── Add Bubble overlay (js/addoverlay.js) — one dialog on every app page,
   so adding a bubble never leaves the feed. (The Find Bubbles panel left
   it for its own page, find.html, on 2026-09-01.) ────────────────────── */
.bubble-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 4.5rem 1rem 2rem;
  overflow-y: auto;
}
.bubble-overlay[hidden] { display: none; }
.bubble-overlay-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(20, 38, 58, 0.45);
}
.bubble-overlay-card {
  position: relative;
  width: 100%;
  max-width: 640px;
  padding: 1.5rem 1.75rem;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card);
}
.overlay-title { margin: 0 0 1rem; font-size: 1.05rem; font-weight: 700; }

/* shared buttons (formerly bubbles.html-only — the overlay needs them on
   every app page; bubbles.html's Rerun/Delete use them too) */
.btn {
  padding: 0.5rem 1.1rem;
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
}
.btn.secondary {
  background: var(--card);
  color: var(--fg);
  border: 1px solid var(--border);
}
.btn.secondary:hover { border-color: var(--accent); }
.btn.danger {
  background: var(--card);
  color: var(--danger);
  border: 1px solid var(--border);
}
.btn.danger:hover { border-color: var(--danger); }
.btn:disabled { opacity: 0.5; cursor: default; }
/* a link dressed as a button (the Bubbles toolbar's Find Bubbles → find.html) */
a.btn {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

/* generate panel (inside the overlay card) */
#gen-panel {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
#gen-panel[hidden] { display: none; }
#gen-panel label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 0.3rem;
  display: block;
}
#gen-panel textarea {
  width: 100%;
  padding: 0.65rem 0.8rem;
  font-size: 0.9rem;
  font-family: inherit;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg);
  color: var(--fg);
  resize: vertical;
  min-height: 3.5rem;
}
#gen-panel textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -1px;
}
/* preference toggles — baked into the submitted prompt when on. A vertical
   list since 2026-08-30 (the wrapped chip cloud read as messy): one row per
   preference with a leading check that appears when it's on, showing 5 rows
   and scrolling past that. Fixed row height + flex-shrink: 0 keep the
   5-row cap exact inside the scrolling column. */
.pref-row {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  max-height: calc(5 * 2rem + 4 * 0.3rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 0.3rem;   /* the scrollbar never overlaps the rows */
}
.pref {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  height: 2rem;
  flex-shrink: 0;
  padding: 0 0.8rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.8125rem;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
}
.pref:hover { border-color: var(--accent); }
.pref .icon-svg {
  opacity: 0;              /* reserves the slot — rows never shift on toggle */
  color: var(--accent);
}
.pref.on {
  border-color: var(--accent);
  color: var(--fg);
}
.pref.on .icon-svg { opacity: 1; }
/* Add / Close — centered (2026-09-02) */
.gen-row { display: flex; justify-content: center; gap: 0.6rem; }
/* (#gen-count / #gen-backend styles removed 2026-08-30 — the count and
   backend controls left the generate dashboard; .gen-sched-row — the
   "Make public" checkbox row — removed 2026-09-01: every web bubble is
   public now, the option lives on server-side only) */
.gen-signin-row { display: flex; align-items: center; gap: 0.75rem; min-height: 32px; }
#gen-status { color: var(--muted); font-size: 0.8125rem; }
#gen-status.error { color: var(--danger); white-space: pre-wrap; }

/* ── Mobile: the sidebar becomes an off-canvas drawer over the grid ───── */
@media (max-width: 900px) {
  .shell-page main,
  .shell-page.sidebar-collapsed main { margin-left: 0; }
  #sidebar {
    z-index: 130;
    transform: translateX(-100%);
    visibility: hidden;
    box-shadow: 0 0 30px rgba(20, 38, 58, 0.25);
  }
  /* the drawer ignores the desktop collapse state — open wins */
  .shell-page.sidebar-open #sidebar,
  .shell-page.sidebar-collapsed.sidebar-open #sidebar {
    transform: none;
    visibility: visible;
  }
  #shell-scrim {
    position: fixed;
    inset: 0;
    z-index: 125;
    background: rgba(20, 38, 58, 0.4);
  }
  /* the centered wordmark stays on mobile — it's the bar's centerpiece;
     only the signed-in chip text gives way */
  .topbar-user { display: none; }
}
