/* ============================================================================
   BOB HQ — base, layout, components
   ========================================================================= */

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--t-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;                 /* the app scrolls in panes, not as a page */
}
h1, h2, h3, h4 { margin: 0; letter-spacing: var(--track-tight); }
p { margin: 0; }
button, input, textarea, select { font: inherit; color: inherit; }
a { color: var(--cyan); text-decoration: none; }
a:hover { color: var(--cyan-l); }
svg.ic { flex: none; display: block; }

/* Focus: visible, cyan (the interaction colour), and never on mouse clicks. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Scrollbars, restyled — the OS default light scrollbar on a near-black
   surface is the single most "unfinished web page" tell there is. */
* { scrollbar-width: thin; scrollbar-color: var(--line-2) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 99px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: #3a445e; background-clip: content-box; }

.sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* ============================================================================
   APP SHELL
   Grid, not flex: the sidebar is a fixed track and the main pane is the only
   thing that scrolls. Making the PAGE scroll instead is the usual mistake —
   the sidebar then scrolls away, and a permanent sidebar that isn't permanent
   is worse than not having one.
   ========================================================================= */
.hq {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  height: 100dvh;
  transition: grid-template-columns var(--d-2) var(--ease);
}
body.is-rail .hq { grid-template-columns: var(--sidebar-w-rail) 1fr; }

/* --- sidebar -------------------------------------------------------------- */
.side {
  background: var(--bg-1);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  min-width: 0; position: relative; z-index: var(--z-sidebar);
}
.side-top { padding: 18px 14px 12px; }
.brand {
  display: flex; align-items: center; gap: 11px;
  padding: 6px; border-radius: var(--r);
  transition: background var(--d-1) var(--ease);
}
.brand:hover { background: var(--surface); }
.brand canvas { border-radius: 7px; flex: none; box-shadow: var(--e-1); }
.brand-tt { min-width: 0; }
.brand-tt b { display: block; font: var(--t-h3); color: var(--text); letter-spacing: .01em; }
.brand-tt span { display: block; font: var(--t-xs); color: var(--text-3); text-transform: uppercase; letter-spacing: var(--track-caps); }
body.is-rail .brand-tt { display: none; }
body.is-rail .brand { justify-content: center; }

.side-nav { flex: 1; overflow-y: auto; padding: 6px 12px; }
.side-nav::-webkit-scrollbar { width: 0; }
.nav-lbl {
  font: var(--t-xs); color: var(--text-4); text-transform: uppercase;
  letter-spacing: var(--track-caps); padding: 16px 10px 7px;
}
body.is-rail .nav-lbl { text-align: center; font-size: 0; padding: 14px 0 8px; }
body.is-rail .nav-lbl::after { content: ''; display: block; height: 1px; background: var(--line); }

.nav-i {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 10px; margin: 1px 0;
  border-radius: var(--r); color: var(--text-2);
  font: var(--t-h3); position: relative;
  transition: background var(--d-1) var(--ease), color var(--d-1) var(--ease);
}
.nav-i:hover { background: var(--surface); color: var(--text); }
.nav-i .ic { transition: transform var(--d-2) var(--ease); }
.nav-i:hover .ic { transform: translateX(1px) scale(1.06); }

/* Active nav is CYAN — it is a state of the software, not a Bob element.
   The left bar is drawn with a pseudo-element so it can animate independently
   of the row's own background. */
.nav-i.is-on { background: var(--surface-2); color: var(--cyan-l); }
.nav-i.is-on::before {
  content: ''; position: absolute; left: -12px; top: 50%;
  width: 3px; height: 20px; margin-top: -10px;
  background: var(--cyan); border-radius: 0 3px 3px 0;
  box-shadow: 0 0 12px var(--cyan);
}
.nav-i-n {
  margin-left: auto; font: var(--t-xs); font-weight: 700;
  background: var(--cyan); color: var(--cyan-t);
  padding: 2px 6px; border-radius: var(--r-pill); font-style: normal;
}
body.is-rail .nav-i { justify-content: center; padding: 11px 0; }
body.is-rail .nav-i span, body.is-rail .nav-i-n { display: none; }

.side-bot { padding: 10px 12px 14px; border-top: 1px solid var(--line); }

/* The user chip. Gold on the XP bar because XP is value; everything else here
   is neutral so the chip does not compete with page content. */
.me { display: flex; align-items: center; gap: 10px; padding: 8px; border-radius: var(--r); width: 100%; text-align: left; background: none; border: 0; cursor: pointer; transition: background var(--d-1) var(--ease); }
.me:hover { background: var(--surface); }
.me-tt { min-width: 0; flex: 1; }
.me-tt b { display: block; font: var(--t-h3); color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.me-tt span { display: block; font: var(--t-xs); color: var(--text-3); }
body.is-rail .me-tt, body.is-rail .me .prog { display: none; }
body.is-rail .me { justify-content: center; }

.side-collapse {
  position: absolute; top: 74px; right: -11px; z-index: 2;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--surface-2); border: 1px solid var(--line-2);
  color: var(--text-3); display: grid; place-items: center; cursor: pointer;
  opacity: 0; transition: opacity var(--d-1) var(--ease), color var(--d-1);
}
.side:hover .side-collapse { opacity: 1; }
.side-collapse:hover { color: var(--cyan); border-color: var(--cyan-d); }
.side-collapse .ic { transition: transform var(--d-2) var(--ease); }
body.is-rail .side-collapse .ic { transform: rotate(180deg); }

/* --- main pane ------------------------------------------------------------ */
/* min-height: 0 is load-bearing, and its absence is invisible until you try to
   scroll. Grid and flex items default to `min-height: auto`, which means they
   REFUSE to shrink below their content's height. So .hq-body ignored its 100dvh
   grid row and grew to whatever Home was tall (1593px), .hq-main grew with it,
   and `overflow-y: auto` never fired — an element that is exactly as tall as its
   content has nothing to overflow. `body { overflow: hidden }` then clipped the
   excess, so the page below the fold was rendered and completely unreachable.

   The fix has to be on BOTH: .hq-body so it obeys the grid row, and .hq-main so
   it obeys the flex column. Fixing only one just moves the overflow down a level. */
.hq-body { display: flex; flex-direction: column; min-width: 0; min-height: 0; position: relative; }

.topbar {
  height: var(--topbar-h); flex: none;
  display: flex; align-items: center; gap: 14px;
  padding: 0 var(--gutter);
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg-1) 82%, transparent);
  backdrop-filter: blur(14px) saturate(1.3);
  position: relative; z-index: var(--z-sticky);
}
.topbar-t { font: var(--t-h2); }
.topbar-sp { flex: 1; }
.burger { display: none; }

.hq-main { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; scroll-behavior: smooth; }
.page {
  max-width: var(--page-max); margin: 0 auto;
  padding: 28px var(--gutter) 80px;
}
.page--flush { max-width: none; padding: 0; height: 100%; }

/* Route transition. Content rises 10px and fades — short, and only on the
   outlet, so the shell never moves. A sliding or scaling page transition looks
   impressive once and then costs you 300ms on every single navigation. */
#outlet { transition: opacity var(--d-2) var(--ease), transform var(--d-2) var(--ease); }
#outlet.is-leaving { opacity: 0; transform: translateY(-6px); }
#outlet.is-entering { opacity: 0; transform: translateY(10px); }

/* ============================================================================
   BUTTONS
   ========================================================================= */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid transparent; border-radius: var(--r);
  padding: 9px 15px; font: var(--t-h3); cursor: pointer;
  background: var(--surface-2); color: var(--text);
  white-space: nowrap; text-decoration: none;
  transition: background var(--d-1) var(--ease), border-color var(--d-1) var(--ease),
              transform var(--d-1) var(--ease), box-shadow var(--d-1) var(--ease),
              color var(--d-1) var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn--sm { padding: 6px 11px; font: var(--t-xs); font-weight: 600; border-radius: var(--r-sm); }
.btn--lg { padding: 12px 22px; font: var(--t-h2); border-radius: var(--r-lg); }
.btn--full { width: 100%; }
.btn[disabled] { opacity: .45; pointer-events: none; }

/* PRIMARY = gold. One per screen. The gradient foot and the warm shadow are
   what make it read as a physical key rather than a coloured rectangle. */
.btn--primary {
  background: linear-gradient(180deg, var(--gold-l), var(--gold));
  color: var(--gold-t); font-weight: 700;
  box-shadow: 0 1px 0 rgba(255,255,255,.4) inset, var(--e-gold);
}
.btn--primary:hover { background: linear-gradient(180deg, #fff0b8, var(--gold-l)); box-shadow: 0 1px 0 rgba(255,255,255,.5) inset, 0 10px 34px -8px rgba(255,206,58,.55); }

.btn--accent { background: linear-gradient(180deg, var(--cyan-l), var(--cyan)); color: var(--cyan-t); font-weight: 700; box-shadow: 0 1px 0 rgba(255,255,255,.35) inset, var(--e-cyan); }
.btn--accent:hover { filter: brightness(1.08); }

.btn--subtle { background: var(--surface-2); border-color: var(--line); color: var(--text-2); }
.btn--subtle:hover { background: var(--surface-3); border-color: var(--line-2); color: var(--text); }

.btn--ghost { background: transparent; color: var(--text-2); }
.btn--ghost:hover { background: var(--surface-2); color: var(--text); }

.btn--danger { background: transparent; border-color: color-mix(in srgb, var(--danger) 40%, transparent); color: var(--danger); }
.btn--danger:hover { background: color-mix(in srgb, var(--danger) 12%, transparent); }

.icobtn {
  width: 34px; height: 34px; border-radius: var(--r-sm);
  display: grid; place-items: center; cursor: pointer;
  background: transparent; border: 0; color: var(--text-3);
  transition: background var(--d-1) var(--ease), color var(--d-1) var(--ease);
}
.icobtn:hover { background: var(--surface-2); color: var(--text); }
.icobtn.is-on { color: var(--gold); }

/* ============================================================================
   BADGES · AVATARS
   ========================================================================= */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 8px; border-radius: var(--r-pill);
  font: var(--t-xs); font-weight: 600;
  background: var(--surface-3); color: var(--text-2);
  border: 1px solid var(--line);
}
.badge--gold { background: color-mix(in srgb, var(--gold) 15%, transparent); color: var(--gold); border-color: color-mix(in srgb, var(--gold) 30%, transparent); }
.badge--cyan { background: color-mix(in srgb, var(--cyan) 14%, transparent); color: var(--cyan-l); border-color: color-mix(in srgb, var(--cyan) 30%, transparent); }
.badge--live { background: color-mix(in srgb, var(--ok) 14%, transparent); color: var(--ok); border-color: color-mix(in srgb, var(--ok) 30%, transparent); }
.badge--warn { background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 28%, transparent); }

.av {
  position: relative; flex: none; border-radius: 50%;
  display: inline-grid; place-items: center;
  font-weight: 700; color: #fff; letter-spacing: .02em;
  text-shadow: 0 1px 2px rgba(0,0,0,.45);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.08);
}
.av--ring { box-shadow: inset 0 0 0 1px rgba(255,255,255,.08), 0 0 0 2px var(--bg-1), 0 0 0 3.5px var(--cyan); }
.av-dot { position: absolute; right: -1px; bottom: -1px; width: 30%; height: 30%; min-width: 8px; min-height: 8px; border-radius: 50%; background: var(--ok); border: 2px solid var(--bg-1); }

.verified { display: inline-grid; place-items: center; width: 15px; height: 15px; border-radius: 50%; background: var(--verified); color: var(--cyan-t); flex: none; }

/* ============================================================================
   CARDS
   The lift on hover is 4px and the shadow does most of the work. Bigger lifts
   (8–12px, the "impressive" range) make a grid feel like it is flinching as
   the pointer crosses it.
   ========================================================================= */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
  display: flex; flex-direction: column;
  color: inherit; text-decoration: none;
  box-shadow: var(--e-1);
  transition: transform var(--d-2) var(--ease), box-shadow var(--d-2) var(--ease), border-color var(--d-2) var(--ease);
}
.card--tap { cursor: pointer; }
.card--tap:hover { transform: translateY(-4px); border-color: var(--line-2); box-shadow: var(--e-3); }
.card--tap:hover .cover-sky { transform: translateY(-3px) scale(1.04); }
.card--tap:hover .cover-glow { opacity: 1; }
.card--tap:hover .card-t { color: var(--cyan-l); }

.cover {
  position: relative; aspect-ratio: 16 / 9;
  overflow: hidden; flex: none;
  border-bottom: 1px solid var(--line);
}
.cover--tall { aspect-ratio: 4 / 5; }
.cover-sky {
  position: absolute; inset: 0; display: flex; align-items: flex-end;
  gap: 3.5%; padding: 0 8%;
  transition: transform var(--d-3) var(--ease);
}
.cover-sky i { background: rgba(0,0,0,.55); border-radius: 2px 2px 0 0; }
.cover-glow {
  position: absolute; inset: 0; opacity: 0;
  background: radial-gradient(120% 80% at 50% 110%, rgba(255,206,58,.22), transparent 60%);
  transition: opacity var(--d-3) var(--ease);
}
.cover::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 40%, rgba(7,8,13,.6));
}
.cover-tag, .cover-label {
  position: absolute; z-index: 1; font: var(--t-xs); font-weight: 700;
  padding: 4px 9px; border-radius: var(--r-pill);
  background: rgba(7,8,13,.78); backdrop-filter: blur(6px);
  border: 1px solid rgba(255,255,255,.1);
}
.cover-tag { top: 10px; left: 10px; color: var(--text-2); }
.cover-label { bottom: 10px; right: 10px; color: var(--gold); }

.card-b { padding: 14px 15px 15px; display: flex; flex-direction: column; gap: 7px; flex: 1; }
.card-t { font: var(--t-h3); font-size: 15.5px; color: var(--text); transition: color var(--d-1) var(--ease); }
.card-by { display: flex; align-items: center; gap: 6px; font: var(--t-xs); color: var(--text-3); }
.card-s {
  font: var(--t-sm); color: var(--text-2);
  /* Two lines, hard clamped. Ragged card heights across a grid is the fastest
     way to make a storefront look amateur, and truncating on height alone
     leaves a half-cut third line showing. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.card-badges { display: flex; flex-wrap: wrap; gap: 5px; }
.card-f { display: flex; align-items: center; gap: 12px; margin-top: auto; padding-top: 9px; border-top: 1px solid var(--line); }
.card-stats { display: flex; gap: 12px; flex: 1; }
.stat { display: inline-flex; align-items: center; gap: 4px; font: var(--t-xs); color: var(--text-3); }
.stat b { font-weight: 600; color: var(--text-2); }
.price { font: var(--t-h3); color: var(--gold); font-variant-numeric: tabular-nums; }
.card-a { display: flex; gap: 7px; padding-top: 4px; }

/* ============================================================================
   LAYOUT HELPERS
   ========================================================================= */
.grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
}
.grid--wide { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
.grid--tight { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 13px; }
.row { display: flex; align-items: center; gap: 10px; }
.row--wrap { flex-wrap: wrap; }
.sp { flex: 1; }
.stack { display: flex; flex-direction: column; gap: 10px; }

.sec { margin-bottom: 38px; }
.sec-h { display: flex; align-items: flex-end; gap: 16px; margin-bottom: 15px; }
.sec-tt { flex: 1; min-width: 0; }
.sec-tt h2 { font: var(--t-h1); font-size: 20px; display: flex; align-items: center; gap: 9px; }
.sec-tt h2 .ic { color: var(--gold); }
.sec-tt p { font: var(--t-sm); color: var(--text-3); margin-top: 4px; }

/* --- rail ----------------------------------------------------------------- */
.rail { position: relative; margin: 0 calc(var(--gutter) * -1); padding: 0 var(--gutter); }
.rail-track {
  display: flex; gap: 15px; overflow-x: auto; scroll-snap-type: x mandatory;
  padding: 4px 0 14px; scroll-padding-left: var(--gutter);
}
.rail-track::-webkit-scrollbar { height: 0; }
.rail-track > * { flex: 0 0 268px; scroll-snap-align: start; }
.rail-nav {
  position: absolute; top: 50%; margin-top: -34px; z-index: 2;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--surface-3); border: 1px solid var(--line-2);
  color: var(--text); display: grid; place-items: center; cursor: pointer;
  opacity: 0; transition: opacity var(--d-2) var(--ease), background var(--d-1);
  box-shadow: var(--e-2);
}
.rail:hover .rail-nav { opacity: 1; }
.rail-nav:hover { background: var(--cyan); color: var(--cyan-t); border-color: var(--cyan); }
.rail-nav--l { left: calc(var(--gutter) - 17px); transform: scaleX(-1); }
.rail-nav--r { right: calc(var(--gutter) - 17px); }
/* Touch has no hover, so the arrows would be permanently invisible; the track
   is natively swipeable there, which is the better interaction anyway. */
@media (pointer: coarse) { .rail-nav { display: none; } }

/* ============================================================================
   TABS · SEARCH · FILTERS
   ========================================================================= */
.tabs { display: flex; gap: 3px; background: var(--surface); border: 1px solid var(--line); padding: 3px; border-radius: var(--r); overflow-x: auto; }
.tabs::-webkit-scrollbar { height: 0; }
.tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: var(--r-sm); border: 0; cursor: pointer;
  background: transparent; color: var(--text-3); font: var(--t-h3);
  white-space: nowrap; transition: background var(--d-1) var(--ease), color var(--d-1) var(--ease);
}
.tab:hover { color: var(--text); background: var(--surface-2); }
.tab.is-on { background: var(--surface-3); color: var(--cyan-l); box-shadow: var(--e-1); }
.tab-n { font-style: normal; font: var(--t-xs); color: var(--text-4); }
.tab.is-on .tab-n { color: var(--cyan-d); }

.sf {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r); padding: 0 13px; color: var(--text-3);
  transition: border-color var(--d-1) var(--ease), box-shadow var(--d-1) var(--ease);
  min-width: 0;
}
.sf:focus-within { border-color: var(--cyan-d); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cyan) 14%, transparent); color: var(--cyan); }
.sf-in { flex: 1; min-width: 0; background: none; border: 0; padding: 10px 0; color: var(--text); }
.sf-in::placeholder { color: var(--text-4); }
.sf-in::-webkit-search-cancel-button { filter: invert(.6); }

.chips { display: flex; gap: 7px; flex-wrap: wrap; }
.chip {
  padding: 6px 12px; border-radius: var(--r-pill); cursor: pointer;
  background: var(--surface); border: 1px solid var(--line);
  color: var(--text-3); font: var(--t-xs); font-weight: 600;
  transition: all var(--d-1) var(--ease);
}
.chip:hover { color: var(--text); border-color: var(--line-2); }
.chip.is-on { background: color-mix(in srgb, var(--cyan) 15%, transparent); border-color: var(--cyan-d); color: var(--cyan-l); }

/* ============================================================================
   MISC COMPONENTS
   ========================================================================= */
.empty { text-align: center; padding: 60px 20px; color: var(--text-3); }
.empty-ic { width: 58px; height: 58px; margin: 0 auto 16px; border-radius: 50%; display: grid; place-items: center; background: var(--surface-2); border: 1px solid var(--line); color: var(--gold); }
.empty h3 { font: var(--t-h1); font-size: 19px; color: var(--text); margin-bottom: 7px; }
.empty p { font: var(--t-sm); max-width: 42ch; margin: 0 auto 18px; }

.sk { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; }
.sk-cover { aspect-ratio: 16/9; background: var(--surface-2); }
.sk-l { height: 11px; margin: 13px 15px; border-radius: 4px; background: var(--surface-2); }
.sk-l--s { width: 55%; }
.sk-cover, .sk-l { background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%); background-size: 200% 100%; animation: shimmer 1.4s infinite linear; }
@keyframes shimmer { to { background-position: -200% 0; } }

.statbox { display: flex; align-items: center; gap: 11px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 13px 15px; }
.statbox-ic { width: 32px; height: 32px; border-radius: var(--r-sm); display: grid; place-items: center; background: var(--surface-2); color: var(--text-3); flex: none; }
.statbox b { display: block; font: var(--t-h1); font-size: 20px; font-variant-numeric: tabular-nums; }
.statbox span { display: block; font: var(--t-xs); color: var(--text-3); margin-top: 2px; }
.statbox--gold b { color: var(--gold); }
.statbox--gold .statbox-ic { color: var(--gold); background: color-mix(in srgb, var(--gold) 12%, transparent); }
.statbox--cyan b { color: var(--cyan-l); }
.statbox--cyan .statbox-ic { color: var(--cyan); background: color-mix(in srgb, var(--cyan) 12%, transparent); }

.prog-l { font: var(--t-xs); color: var(--text-3); margin-bottom: 5px; display: flex; justify-content: space-between; }
.prog-track { height: 5px; border-radius: 99px; background: var(--surface-3); overflow: hidden; }
.prog-bar { display: block; height: 100%; border-radius: 99px; transition: width var(--d-3) var(--ease); }
.prog-bar--gold { background: linear-gradient(90deg, var(--gold-d), var(--gold)); box-shadow: 0 0 10px color-mix(in srgb, var(--gold) 50%, transparent); }
.prog-bar--cyan { background: linear-gradient(90deg, var(--cyan-d), var(--cyan)); }

.cd { display: flex; gap: 7px; }
.cd-u { display: grid; place-items: center; min-width: 42px; padding: 6px 8px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-sm); }
.cd-u b { font: var(--t-h2); font-variant-numeric: tabular-nums; line-height: 1; }
.cd-u i { font: var(--t-xs); font-style: normal; color: var(--text-4); margin-top: 3px; text-transform: uppercase; }
.cd.is-urgent .cd-u b { color: var(--warn); }
.cd.is-done { font: var(--t-h3); color: var(--text-4); }

/* --- modal ---------------------------------------------------------------- */
.modal {
  width: min(520px, calc(100vw - 32px)); padding: 0; border: 1px solid var(--line-2);
  border-radius: var(--r-xl); background: var(--surface); color: var(--text);
  box-shadow: var(--e-3); max-height: 86dvh; overflow: hidden;
  flex-direction: column;
}
.modal[open] { display: flex; animation: modalIn var(--d-2) var(--ease); }
.modal--wide { width: min(760px, calc(100vw - 32px)); }
.modal::backdrop { background: rgba(3,4,8,.72); backdrop-filter: blur(4px); animation: fadeIn var(--d-2) var(--ease); }
@keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(.98); } }
@keyframes fadeIn { from { opacity: 0; } }
.modal-h { display: flex; align-items: center; gap: 12px; padding: 17px 17px 14px 22px; border-bottom: 1px solid var(--line); }
.modal-h h2 { flex: 1; font: var(--t-h2); }
.modal-b { padding: 20px 22px; overflow-y: auto; font: var(--t-body); color: var(--text-2); }
.modal-f { display: flex; gap: 9px; justify-content: flex-end; padding: 15px 22px; border-top: 1px solid var(--line); background: var(--bg-1); }

/* --- toast ---------------------------------------------------------------- */
.toasts { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: var(--z-toast); display: flex; flex-direction: column; gap: 8px; align-items: center; pointer-events: none; }
.toast {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 17px; border-radius: var(--r-pill);
  background: var(--surface-3); border: 1px solid var(--line-2);
  box-shadow: var(--e-3); font: var(--t-h3);
  opacity: 0; transform: translateY(14px);
  transition: opacity var(--d-2) var(--ease), transform var(--d-2) var(--ease);
}
.toast.is-on { opacity: 1; transform: none; }
.toast--ok .ic { color: var(--ok); }
.toast--gold .ic { color: var(--gold); }

/* ============================================================================
   BOB — his face, and the bubble he speaks through
   ========================================================================= */
.bobface { display: block; image-rendering: pixelated; }

.bob-pop {
  position: fixed; right: 22px; bottom: 22px; z-index: var(--z-pop);
  display: flex; align-items: flex-start; gap: 11px;
  width: min(340px, calc(100vw - 32px));
  padding: 13px 14px; border-radius: var(--r-lg) var(--r-lg) 4px var(--r-lg);
  background: var(--surface-2); border: 1px solid var(--line-2);
  box-shadow: var(--e-3), 0 0 0 1px rgba(255,206,58,.08);
  opacity: 0; transform: translateY(14px) scale(.96);
  pointer-events: none;
  transition: opacity var(--d-2) var(--ease), transform var(--d-2) var(--ease);
}
.bob-pop.is-on { opacity: 1; transform: none; pointer-events: auto; }
.bob-pop .bp-face { border-radius: 7px; flex: none; width: 34px; height: 34px; }
.bp-body { flex: 1; min-width: 0; }
.bp-who { font: var(--t-xs); font-weight: 700; color: var(--gold); text-transform: uppercase; letter-spacing: var(--track-caps); }
.bp-text { font: var(--t-sm); color: var(--text); margin-top: 3px; }
.bp-x { background: none; border: 0; color: var(--text-4); font-size: 19px; line-height: 1; cursor: pointer; padding: 0 2px; transition: color var(--d-1); }
.bp-x:hover { color: var(--text); }

/* ============================================================================
   RESPONSIVE
   Desktop-first, as briefed. Two real breakpoints, not five:
     ≤1180px — sidebar becomes an icon rail. HQ is dense; labels go first.
     ≤860px  — sidebar becomes a drawer + bottom tab bar. Below this a
               permanent sidebar costs more width than the content can spare.
   ========================================================================= */
@media (max-width: 1180px) {
  .hq { grid-template-columns: var(--sidebar-w-rail) 1fr; }
  .brand-tt, .nav-i span, .nav-i-n, .me-tt, .me .prog { display: none; }
  .nav-i { justify-content: center; padding: 11px 0; }
  .brand, .me { justify-content: center; }
  .nav-lbl { text-align: center; font-size: 0; padding: 14px 0 8px; }
  .nav-lbl::after { content: ''; display: block; height: 1px; background: var(--line); }
  .side-collapse { display: none; }
}

@media (max-width: 860px) {
  .hq { grid-template-columns: 1fr; }
  .side {
    position: fixed; inset: 0 auto 0 0; width: var(--sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--d-2) var(--ease);
    box-shadow: var(--e-3);
  }
  body.is-drawer .side { transform: none; }
  body.is-drawer::after {
    content: ''; position: fixed; inset: 0; z-index: 99;
    background: rgba(3,4,8,.6); backdrop-filter: blur(2px);
  }
  /* Labels come back inside the drawer — there is room for them there, and a
     drawer of unlabelled icons is a guessing game. */
  .brand-tt, .nav-i span, .nav-i-n, .me-tt, .me .prog { display: block; }
  .nav-i { justify-content: flex-start; padding: 9px 10px; }
  .brand, .me { justify-content: flex-start; }
  .nav-lbl { text-align: left; font-size: 11.5px; padding: 16px 10px 7px; }
  .nav-lbl::after { display: none; }
  .burger { display: grid; }
  .hq-main { padding-bottom: 62px; }   /* clear the tab bar */
  .bob-pop { bottom: 76px; }
}

/* Bottom tab bar — the five destinations that matter on a phone. Profile and
   Settings live behind the drawer; nobody opens Settings from a phone often
   enough to spend a permanent slot on it. */
.tabbar { display: none; }
@media (max-width: 860px) {
  .tabbar {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sticky);
    height: 58px; padding-bottom: env(safe-area-inset-bottom);
    background: color-mix(in srgb, var(--bg-1) 92%, transparent);
    backdrop-filter: blur(16px); border-top: 1px solid var(--line);
  }
  .tabbar a {
    display: grid; place-items: center; gap: 3px; color: var(--text-3);
    font: var(--t-xs); text-decoration: none;
    transition: color var(--d-1) var(--ease);
  }
  .tabbar a.is-on { color: var(--cyan); }
}

/* The topbar is the one row that cannot wrap — it is a fixed-height bar. At
   phone widths the title, the bell, the Bolts pill and "Ask Bob" together
   are wider than the screen, and the last one simply hangs off the edge. The
   Bolts pill goes first: the same number is on Home and on Profile, and
   "Ask Bob" is the one control that must survive at every width. */
@media (max-width: 620px) {
  .topbar { padding: 0 14px; gap: 8px; }
  .topbar-t { font: var(--t-h3); font-size: 16px; }
  .topbar a.btn--subtle { display: none; }
}

@media (max-width: 560px) {
  .grid, .grid--wide { grid-template-columns: 1fr; }
  .grid--tight { grid-template-columns: repeat(2, 1fr); }
  .sec-h { flex-direction: column; align-items: flex-start; gap: 10px; }
  .rail-track > * { flex-basis: 82%; }
}
