/* ======================================================================
   web/brandkit.css — Dreamer UI Brand Kit (Oct 3, 2026)
   PHASE 1 ROLLOUT:
     A. Design token foundation (:root and :root[data-theme="light"])
     B. Left rail (navigation)
     C. List column (New chat button, search, chat list)
     D. Top header of the chat view
     E. "New chat" screen (empty state + composer)
   ====================================================================== */

/* ======================================================================
   A. DESIGN TOKEN FOUNDATION (Dark / Graphite default, Light overrides)
   ====================================================================== */
:root {
  /* ------------------------------------------------------------------
     [BK11 token-alias-v1] PHASE-1 ALIAS LAYER — not a second palette.

     theme_b.css is the designed seam: it already carries the brand kit's
     literal value table as --tb-* AND re-points app.css's own bare names
     (--bg, --surface, --text …) at it, for dark and light both. This file
     previously re-declared those same literals a second time, which (a)
     duplicated the palette the audit already flagged as "Split Design
     Tokens", and (b) overrode six of app.css's names with hard hexes,
     cutting the seam that makes the light theme work.

     So every token below that HAS a --tb-* source is now an alias. Values
     were diffed against theme_b.css in both themes before this change:
     40/42 were byte-identical, so this is a no-op on screen — including
     on the non-phase-1 pages. The light block that used to sit under this
     one is gone: --tb-* already swaps for light, so the aliases follow on
     their own and there is nothing left to restate.

     Only tokens with NO --tb-* counterpart keep a literal here; those are
     grouped at the bottom and are this file's own source of truth.
     ------------------------------------------------------------------ */

  /* Surfaces & backgrounds */
  --bg: var(--tb-bg);
  --rail: var(--tb-bg-rail);
  --list: var(--tb-list);
  --panel: var(--tb-bg-panel);
  --surface: var(--tb-surface);
  --surface-2: var(--tb-surface-2);
  --surface-3: var(--tb-surface-3);
  --selected-fill: var(--tb-accent-soft);

  /* Borders */
  --border: var(--tb-border);
  --border-2: var(--tb-border-strong);
  --border-hover: var(--tb-border-hover);

  /* Typography & rail text */
  --text: var(--tb-text);
  --text-dim: var(--tb-text-secondary);
  --text-muted: var(--tb-text-muted);
  --placeholder: var(--tb-placeholder);
  --rail-text: var(--tb-rail-text);
  --avatar: var(--tb-avatar);

  /* Accent & actions */
  --primary: var(--tb-accent);
  --primary-hover: var(--tb-primary-hover);
  --primary-pressed: var(--tb-primary-press);
  --accent-text: var(--tb-accent-text);
  --selected-border: var(--tb-accent-border);

  /* Status semantics */
  --success: var(--tb-success);
  --success-text: var(--tb-success-text);
  --warning: var(--tb-warning);
  --danger: var(--tb-danger);
  --danger-btn: var(--tb-danger-fill);
  --condition: var(--tb-condition);
  --lilac: var(--tb-lilac);

  /* Status tints */
  --success-tint: var(--tb-success-soft);
  --warning-tint: var(--tb-warning-soft);
  --danger-tint: var(--tb-danger-soft);

  /* Elevation */
  --scrim: var(--tb-scrim);
  --shadow-pop: var(--tb-shadow-pop);
  --shadow-float: var(--tb-shadow-float);        /* [TK1] */
  --glow-accent: var(--tb-glow-accent);
  --glow-accent-sm: var(--tb-glow-accent-sm);
  --ring-accent: var(--tb-ring-accent);
  --shadow-dialog: var(--tb-shadow-dialog);

  /* Radii */
  --radius-input: var(--tb-radius-input);
  --radius-btn: var(--tb-radius-btn);
  --radius-card: var(--tb-radius-card);
  --radius-pop: var(--tb-radius-pop);
  --radius-dialog: var(--tb-radius-dialog);

  /* Type stack */
  --font-mono: var(--tb-font-mono);
  /* [UM1] height a user message is clamped to before it offers "Show more" */
  --user-msg-clamp: 15em;

  /* ------------------------------------------------------------------
     Kit tokens with no --tb-* counterpart. These literals ARE the token
     block, so they are the one place a raw value is allowed to live.
     ------------------------------------------------------------------ */

  /* Rail hover wash — white at low alpha, so it reads on the navy rail in
     BOTH themes (the rail stays navy in light; kit section 2.1). */
  --rail-hover: rgba(255,255,255,.04);

  /* Rail-surface states. The rail is navy in BOTH themes, so it cannot use
     the theme-switching --selected-fill (near-white in light) for its own
     active state; it needs navy-appropriate values that hold either way.
     Same reasoning as --rail-hover above. Values are the ones already in
     use — promoting them here changes nothing on screen, it just gets the
     last literals out of the rule bodies. */
  --rail-text-hover: #D6DEEF;
  --rail-active-fill: #172352;
  --rail-icon-active: #5C82FF;
  --rail-setup-label: #5A6689;

  /* Fixed, theme-independent by design (kit sections 2.2 / 2.3): the
     status tint borders hold the same alpha in both themes, and these two
     constants are literal colours, not palette entries. */
  --white: #FFFFFF;
  --on-lime: #0C0E13;
  --success-tint-border: rgba(198,242,78,.35);
  --warning-tint-border: rgba(245,181,68,.45);
  --danger-tint-border: rgba(242,131,122,.45);

  /* OPEN QUESTION (flagged, deliberately NOT aliased): theme_b.css sets
     --tb-accent-hover to #2648D9 in light, this file to #C3D0FF. Aliasing
     would change the light link-hover colour, so the current value is kept
     until the user rules on it. See Tasks/01-design-tokens. */
  --accent-hover: #C3D0FF;

  /* Native system stack (kit section 3). */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", system-ui, Roboto, "Helvetica Neue", Arial, sans-serif;

  /* [AG2] Brand face, kit section 3: "Geist is used only on brand surfaces
     (sign-up brand panel, marketing site), loaded only there." Nothing is
     downloaded anywhere in this app, so Geist is only ever honoured if the
     OS already has it; otherwise the stack falls straight through to the
     native UI font. Declared here because kit section 22 names the token
     and nothing defined it — var(--font-brand) was an undefined reference
     waiting to drop a whole declaration (Patterns 5). Brand surfaces only:
     never the product UI. */
  --font-brand: "Geist", var(--font);

  /* Spacing scale, 4px grid (kit section 4.1). */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-9: 36px;
}

/* The light theme needs no block here: every alias above resolves through
   --tb-*, and theme_b.css already re-points those for :root[data-theme="light"].
   --rail-hover is the one exception the kit treats differently per theme. */
:root[data-theme="light"] {
  --rail-hover: rgba(255,255,255,.06);
}


/* ----------------------------------------------------------------------
   [HG1 hidden-guard] The `hidden` attribute must always win.

   The UA stylesheet's [hidden]{display:none} has almost no specificity, so
   ANY author rule that sets `display` on the same element silently defeats
   it and JS can no longer hide that element. This codebase has been bitten
   by it at least five separate times, each patched one element at a time:
   app.css:889 (#med-overlay, #med-vargrid), app.css:926 (#med-cmp),
   app.css:312 (.src-tools), brandkit.css (#ctxpop, #bkp-scrim) — and the
   comment at app.css:886 spells the cause out.

   One rule ends the whole class. The !important is the point: it has to
   outrank author `display` declarations, which is exactly what the UA rule
   fails to do. Verified safe first — nothing in this app relies on CSS
   re-showing an element that still carries `hidden` (#newchat2 is the only
   markup-hidden element CSS touches, and that rule hides it too).
   ---------------------------------------------------------------------- */
[hidden] { display: none !important; }

/* [TY2 min-size] Kit section 3: "never below 12px anywhere; on Windows
   raise 12px text to 13px where it reads too small." Everything under the
   floor was lifted to 12px.

   Three elements are deliberately NOT changed: the kit specifies them below
   the floor itself (section 5 "Rail badge | 16px lime circle, text 10/800",
   "Setup group | SETUP 10/700"). That is a conflict inside the kit, so it is
   the user's call, not mine — see Lessons-Learned / Tasks. */
/* ----------------------------------------------------------------------
   Global rules for Phase-1 surfaces
   ---------------------------------------------------------------------- */
/* [FT1] #messages named explicitly: it inherits through #view-chat today,
   but the message log is the one surface a stray font-family would be most
   visible on, so it is pinned rather than left to inheritance. */
#rail, #convpanel, #chathead, #view-chat, #composer, #messages {
  font-family: var(--font);
  --dim: var(--text-dim);
  --faint: var(--text-muted);
  --accent: var(--primary);
  --accent-ink: var(--white);
  --accent-soft: var(--selected-fill);
  --accent-border: var(--selected-border);
}

/* Focus ring (keyboard only, :focus-visible): 2px --selected-border with 2px page-color gap */
#rail button:focus-visible,
#convpanel button:focus-visible,
#convpanel input:focus-visible,
#chathead button:focus-visible,
#messages button:focus-visible,
#composer button:focus-visible,
.bk-start:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--selected-border);
  transition: none;
}

/* Transitions on phase-1 controls */
#rail button,
#convpanel button,
#chathead button,
#composer button,
.conv,
.bk-start {
  transition: background 120ms ease-out, border-color 120ms ease-out, color 120ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  #rail button,
  #convpanel button,
  #chathead button,
  #composer button,
  .conv,
  .bk-start,
  .bk-start.bk-swap {
    transition: none !important;
    animation: none !important;
  }
}

/* Disabled state */
#convpanel button:disabled,
#chathead button:disabled,
#composer button:disabled {
  opacity: .45;
  cursor: not-allowed;
}

/* ======================================================================
   B. LEFT RAIL (Navigation)
   ====================================================================== */
@media (min-width: 768px) {
  :root {
    --rail-w: 84px;
    --conv-w: 272px;
  }

  #rail {
    width: var(--rail-w);
    background: var(--rail);
    border-right: 1px solid rgba(255, 255, 255, 0.08);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 12px 0 60px;
    flex: none;
  }

  #logo {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-btn);
    background: var(--primary);
    color: var(--white);
    font-weight: 700;
    font-size: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 12px;
    user-select: none;
    overflow: hidden;
    box-shadow: var(--glow-accent);
  }
  #logo img,
  #logo span { display: none; }

  .rail-btn {
    width: 68px;
    height: auto;
    min-height: 50px;
    border-radius: var(--radius-btn);        /* kit s5: rail item radius 10 */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    padding: 7px 0 6px;
    color: var(--rail-text);
    background: transparent;
    border: none;
    cursor: pointer;
    position: relative;
    user-select: none;
  }
  .rail-btn svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
    flex: none;
  }
  /* Labels always visible, stacked under icon */
  .rail-btn::before {
    content: attr(data-label);
    order: 2;
    font-size: 12px;
    line-height: 1.2;
    font-weight: 500;
    max-width: 66px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: inherit;
  }
  .rail-btn:hover {
    background: var(--rail-hover);
    color: var(--rail-text-hover);
  }
  .rail-btn.active {
    background: var(--rail-active-fill);
    color: var(--white);
  }
  .rail-btn.active svg {
    color: var(--rail-icon-active);
  }
  .rail-btn.active::before {
    font-weight: 600;
    color: var(--white);
  }
  /* Labels are permanent; suppress hover tooltip */
  .rail-btn::after {
    display: none !important;
  }

  /* Rail badge (e.g. Workflows count): 17px lime circle, --on-lime text 10/800 */
  .rail-badge {
    position: absolute;
    top: 4px;
    right: calc(50% - 19px);
    width: 17px;
    height: 17px;
    min-width: 17px;
    border-radius: 50%;
    background: var(--success);
    color: var(--on-lime);
    font-size: 10px;
    font-weight: 800;
    line-height: 17px;
    text-align: center;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2;
    border: 1.5px solid var(--rail);
  }
  .rail-badge.appr {
    background: var(--warning);
    color: var(--bg);
    left: calc(50% - 19px);
    right: auto;
  }

  /* Setup group: pinned at bottom under a 1px divider with "SETUP" label */
  .rail-spacer {
    flex: 1;
  }
  .rail-setup-label {
    width: 58px;
    margin: 6px 0 2px;
    padding-top: 8px;
    text-align: center;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: .12em;
    color: var(--rail-setup-label);
    user-select: none;
  }
  .rail-btn[data-setup] {
    min-height: 44px;
    padding: 5px 0 5px;
  }
  .rail-btn[data-setup] svg {
    width: 18px;
    height: 18px;
  }
}

/* ---- [BK5 control-truth-v1] structural control fixes (U22 / kit 7) ---- */
/* native <select> had NO base styling anywhere, so it rendered as the
   browser's white control inside the dark theme (Tools: "No session
   connected"). Base chrome on tokens; more specific rules keep winning. */
select {
  background: var(--tb-surface, var(--surface, transparent));
  color: var(--tb-text, var(--text, inherit));
  border: 1px solid var(--tb-border-strong, var(--border-2, currentColor));
  border-radius: var(--radius-input); padding: 8px 10px; font: inherit; font-size: 13px;
}
select:disabled { opacity: .45; }

/* .wf-retry gets an EXPLICIT fill (kit Secondary) so it can never fall
   through to a user-agent light render, and a visible disabled state. */
.wf-retry { background: var(--tb-surface-2, transparent); }
.wf-retry:disabled { opacity: .45; cursor: default; }

/* ---- [NAV1b report-btn-scale] the "✦ Enhanced report" offer --------------
   offerReportBtn (app.js:86) builds it as `wf-retry cap-continue report-btn`,
   and neither .cap-continue nor .report-btn has ever had a rule — so it
   inherited .wf-retry wholesale: `padding: 7px 16px; font-size: var(--f-sm)`
   (app.css:1342).

   --f-sm is 18px, declared once at app.css:39 and never corrected. That is
   the QtWebEngine desktop value Patterns.md already flags ("Base type
   --f: 21px, --f-sm: 18px | Kit value 13-15px"), which is why the button
   reads a size too large next to the message text it hangs under.

   Scoped to .report-btn on purpose: var(--f-sm) feeds 39 other declarations
   across app.css, and correcting the token itself is a separate change that
   needs its own visual pass. Radius and padding follow the kit's small-button
   pattern (.more-item, brandkit:1314). */
.report-btn {
  font-size: 13px;
  line-height: 1.3;
  padding: 7px 12px;
  border-radius: var(--radius-btn);
}

/* ---- [BK6 composer-words-v1] (U5) ---- */
/* the "· this chat" scope suffix inside the composer chips */
.chip .chip-scope {
  font-style: normal; font-size: 12px; margin-left: 5px;
  color: var(--text-muted); font-weight: 400;
}
.chip.on .chip-scope { color: var(--text-dim); opacity: .85; }
/* privacy line under the composer (brand kit 10: 12px muted, centred) */
.bk-privacy {
  margin: 8px 0 0; text-align: center; font-size: 12px;
  font-weight: 400; color: var(--text-muted);
}

/* ---- [BK9 desktop-apps-v1 + connect-dialog-v1] (U15/U16) ---- */
.cpg-sec { margin: 26px 0 10px; font-size: 16px; font-weight: 700; }
.cpg-onestep { margin: 2px 0 10px; font-size: 13px;
  color: var(--tb-text-secondary, var(--dim, inherit)); }
.cpg-dlg input[type="search"] {
  width: 100%; box-sizing: border-box; height: 38px; margin: 4px 0 10px;
  padding: 0 12px; border-radius: var(--radius-input); font: inherit; font-size: 14px;
  background: var(--tb-surface-2, transparent);
  color: var(--tb-text, inherit);
  border: 1px solid var(--tb-border-strong, currentColor);
}
#cpg-dlg-list { max-height: 50vh; overflow-y: auto; display: flex;
  flex-direction: column; gap: 4px; }
.cpg-dlg-g { font-size: 12px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--tb-text-muted, inherit);
  margin: 10px 0 2px; }
.cpg-dlg-g em { font-style: normal; color: var(--tb-success, inherit);
  text-transform: none; letter-spacing: 0; font-weight: 600; }
.cpg-dlg-item {
  display: flex; align-items: center; gap: 8px; text-align: left;
  padding: 9px 10px; border-radius: var(--radius-btn); cursor: pointer;
  background: transparent; border: 1px solid transparent;
  color: var(--tb-text, inherit); font: inherit; font-size: 14px;
}
.cpg-dlg-item:hover { background: var(--tb-surface-2, transparent);
  border-color: var(--tb-border, currentColor); }
.cpg-dlg-item b { font-weight: 600; }
.cpg-dlg-sub { font-size: 12px; color: var(--tb-text-muted, inherit); }
/* jump-to-card flash: 2px selected-border pulse, stops under reduced motion */
.cpg-flash { outline: 2px solid var(--tb-accent-border, currentColor);
  outline-offset: 2px; animation: cpg-flash 1.2s ease-out 2; }
@keyframes cpg-flash { 50% { outline-color: transparent; } }
@media (prefers-reduced-motion: reduce) { .cpg-flash { animation: none; } }

/* ---- [BK8 ai-card-v1 / brain-collapse-v1 / failure-card-v1] (U8–U10) ---- */
/* elapsed-seconds chip in the work strip (tabular digits, never jumps) */
.lw-timer {
  margin-left: auto; padding-left: 10px; flex: none;
  font-size: 12px; font-variant-numeric: tabular-nums;
  color: var(--tb-text-muted, var(--faint, inherit));
}
/* collapsed activity: one lime summary line; click shows the same rows */
.act-summary {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600; cursor: pointer;
  color: var(--tb-success, inherit); padding: 2px 0 6px;
  user-select: none;
}
.act-summary:hover { text-decoration: underline; }
.live-activity.collapsed .act-row { display: none; }

/* failure card (brand kit 13): plain words, what to do next; raw text only
   under Technical details */
.bk-fail {
  border: 1px solid var(--tb-danger, currentColor); border-radius: var(--radius-card);
  padding: 14px 16px; background: var(--tb-danger-soft, rgba(242,131,122,.12));
}
.bk-fail-t { font-size: 15px; font-weight: 600; line-height: 1.4;
  color: var(--tb-text, inherit); }
.bk-fail-b { margin-top: 6px; font-size: 14px; line-height: 1.5;
  color: var(--tb-text-secondary, var(--dim, inherit)); }
.bk-fail-det { margin-top: 8px; }
.bk-fail-det summary { cursor: pointer; font-size: 12px;
  color: var(--tb-text-muted, var(--faint, inherit)); }
.bk-fail-det pre { margin: 6px 0 0; padding: 10px; border-radius: var(--radius-input);
  background: var(--tb-surface, transparent);
  border: 1px solid var(--tb-border, currentColor);
  font-size: 12px; white-space: pre-wrap; word-break: break-word;
  max-height: 220px; overflow: auto; }
.bk-fail-actions { display: flex; gap: 8px; margin-top: 12px; }

/* ---- [FCB1] failure-card buttons -------------------------------------------
   "Try again" / "Check connectors" (app.js finishLive) and the auto-retry
   "Cancel" are built as plain .wf-retry, which app.css:424 sizes at
   `padding: 7px 16px; font-size: var(--f-sm)` = 18px - the QtWebEngine scale -
   so they read bigger than the 14px card text, and the two identical boxes
   gave no hint which one is the next step. Same cure as [NAV1b] .report-btn:
   scoped here, because .wf-retry has ~25 users and --f-sm feeds 39 rules.
   Try again is always appended first (app.js), so :first-child is the primary;
   blue means act, in both themes. */
.bk-fail-actions .wf-retry,
.bk-autoretry .wf-retry {
  display: inline-flex;
  align-items: center;
  height: 32px;
  padding: 0 14px;
  border: 1px solid var(--tb-border-strong);
  border-radius: var(--radius-btn);
  background: var(--tb-bg-panel);
  color: var(--tb-text);
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.bk-fail-actions .wf-retry:hover,
.bk-autoretry .wf-retry:hover {
  border-color: var(--tb-accent-border);
  background: var(--tb-accent-soft);
  color: var(--tb-accent-text);
}
.bk-fail-actions .wf-retry:first-child {
  border-color: var(--tb-accent);
  background: var(--tb-accent);
  color: var(--white);
}
.bk-fail-actions .wf-retry:first-child:hover {
  border-color: var(--tb-accent-hover);
  background: var(--tb-accent-hover);
  color: var(--white);
}
.bk-autoretry .wf-retry { height: 26px; padding: 0 10px; font-size: 12px; }
.bk-fail-actions .wf-retry:focus-visible,
.bk-autoretry .wf-retry:focus-visible {
  outline: 2px solid var(--tb-accent-border);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .bk-fail-actions .wf-retry,
  .bk-autoretry .wf-retry { transition: none; }
}

/* ---- [BK6 sessions-steps-v1] (U17) spacing for the reused .dc-steps ---- */
.brs-steps { margin: 12px 0 16px; max-width: 760px; }
.brs-steps li { line-height: 1.55; }
.brs-steps b { font-weight: 600; }

/* Chrome autofill paints a saved secret as a WHITE field inside the dark
   theme (live screenshot: the filled Apollo key). The inset-shadow trick is
   the only reliable override Chrome honours. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus {
  /* [BK10] !important: Chrome paints autofill with UA-important rules */
  -webkit-box-shadow: 0 0 0 1000px var(--tb-surface-2) inset !important;
  -webkit-text-fill-color: var(--tb-text) !important;
  caret-color: var(--tb-text);
  transition: background-color 999999s ease-in-out 0s;
}

/* ======================================================================
   C. LIST COLUMN (Chat List)
   ====================================================================== */
#convpanel {
  width: 272px;
  background: var(--list);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 14px 12px;
  gap: 10px;
  flex: none;
}
#convsplit {
  width: 6px;
  flex: none;
  cursor: col-resize;
  position: relative;
}
#convsplit::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 2px;
  width: 1px;
  background: transparent;
}
#convsplit:hover::after {
  background: var(--selected-border);
}

/* "New chat" button: primary variant, full width, 40px high, radius 10 */
#newchat {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 40px;
  padding: 0 16px;
  border-radius: var(--radius-btn);
  background: var(--primary);
  color: var(--white);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  border: none;
  cursor: pointer;
  flex: none;
  box-shadow: var(--glow-accent-sm);
  transition: background 120ms ease;
}
#newchat svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  flex: none;
}
#newchat:hover {
  background: var(--primary-hover);
}
#newchat:active {
  background: var(--primary-pressed);
}

/* Search input container and field */
.conv-search-wrap {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  flex: none;
}
.conv-search-ico {
  position: absolute;
  left: 11px;
  width: 15px;
  height: 15px;
  fill: none;
  stroke: var(--placeholder);
  stroke-width: 2;
  stroke-linecap: round;
  pointer-events: none;
}
#convsearch {
  width: 100%;
  height: 38px;
  border-radius: var(--radius-input);
  background: var(--surface);
  border: 1px solid var(--border-2);
  color: var(--text);
  font-size: 13.5px;
  padding: 0 12px 0 34px;
  outline: none;
  box-sizing: border-box;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}
#convsearch:hover {
  border-color: var(--border-hover);
}
#convsearch:focus {
  border-color: var(--selected-border);
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--selected-border);
}
#convsearch::placeholder {
  color: var(--placeholder);
  font-size: 13.5px;
}

/* Hide the old panel-label "Conversations" */
.panel-label {
  display: none !important;
}

/* Day group labels (TODAY / YESTERDAY / LAST 7 DAYS) */
.conv-group {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 12px 6px 4px;
  user-select: none;
}
.conv-group:first-child {
  padding-top: 2px;
}

/* Chat list and rows */
#convlist {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding-bottom: 24px;
  /* [SB1 sidebar-scrollbar] The global bar in app.css is 9px with a 5px
     radius and sits flush against the rows. Here the list pulls 6px out into
     #convpanel's own 12px right padding and gives that width back as padding,
     so the bar ends up with clear space on BOTH sides — 6px off the rows,
     6px off the panel edge — instead of crowding the titles. Rows also come
     out slightly wider than before (the old 9px bar ate more). */
  margin-right: -6px;
  padding-right: 6px;
  scrollbar-width: thin;                                  /* Firefox */
  scrollbar-color: var(--border-2) transparent;
}
#convlist::-webkit-scrollbar {
  width: 6px;
}
#convlist::-webkit-scrollbar-track {
  background: transparent;
  margin: 2px 0;              /* the thumb stops short of both ends */
}
#convlist::-webkit-scrollbar-thumb {
  background: var(--border-2);
  border-radius: 999px;
  min-height: 40px;           /* never collapses to a sliver on a long list */
}
#convlist::-webkit-scrollbar-thumb:hover {
  background: var(--border-hover);
}
.conv {
  display: flex;
  align-items: flex-start;
  padding: 8px 10px;
  border-radius: var(--radius-btn);
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
  position: relative;
  transition: background 120ms ease, border-color 120ms ease;
}
.conv:hover {
  background: var(--surface-2);
  color: var(--text);
}
.conv.active {
  background: var(--selected-fill);
  border-color: var(--selected-border);
  color: var(--text);
}

.conv-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.conv-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  width: 100%;
}
.conv .t {
  flex: 1;
  /* [PL1] Same defect as the header pill: a flex item defaults to
     min-width:auto and refuses to shrink below its text, so the ellipsis
     never fires and a long chat title pushes the timestamp out of the row
     instead. Found by scanning for the class, not by being reported. */
  min-width: 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conv.active .t {
  color: var(--text);
}

/* Running indicator pill */
.conv-run {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--primary);
  flex: none;
}
.conv-run-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
  box-shadow: 0 0 6px var(--primary);
}

/* [LIVE1] "answering" dot: blinks on a chat in the sidebar while its reply is
   streaming (app.js paintLiveDots). Same meaning family as "connected / on"
   elsewhere: lime on dark, blue on light (lime is never legible on the light
   surface). Sits at the right end of .conv-top because .conv .t is flex:1. */
.conv-live {
  flex: none;
  width: 8px;
  height: 8px;
  margin-left: 8px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 0 3px var(--tb-success-soft);
  animation: convLiveBlink 1.2s ease-in-out infinite;
}
:root[data-theme="light"] .conv-live {
  background: var(--tb-accent);
  box-shadow: 0 0 0 3px var(--tb-accent-soft);
}
/* [LIVE2] waiting for the user (workflow decision / approval asked in chat):
   amber in BOTH themes (needs-you is amber everywhere), a slower pulse so it
   reads as "waiting", not "working". Listed with the light-theme selector so
   it outranks :root[data-theme="light"] .conv-live above. */
.conv-live.ask,
:root[data-theme="light"] .conv-live.ask {
  background: var(--tb-warning);
  box-shadow: 0 0 0 3px var(--tb-warning-soft);
  animation-duration: 2.4s;
}
.conv-live[hidden] { display: none; }
/* the row's more-button (absolute, right: 6px) appears on hover / focus in
   the same spot; the dot steps aside instead of sitting under it */
.conv:hover .conv-live,
.conv:focus-within .conv-live { visibility: hidden; }
@keyframes convLiveBlink {
  0%, 100% { opacity: 1; }
  50%      { opacity: .3; }
}
@media (prefers-reduced-motion: reduce) {
  .conv-live { animation: none; }
}

.conv-sub {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-muted);
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conv.active .conv-sub {
  color: var(--text-dim);
}

/* [CM1 conv-row-menu] The row's hover control. The old bare "×" is gone —
   this opens Pin / Add to project / Delete instead. Revealed on hover AND
   on keyboard focus, so it is reachable without a mouse; it also stays
   visible while its own menu is open. */
.conv-menu-btn {
  visibility: hidden;
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: var(--radius-btn);
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
}
/* [A11] the row is a tab stop now, so it needs the same ring as everything else */
.conv:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -2px;
  border-radius: var(--radius-btn);
}
/* [KLH1-01 conv-delete-visible-v1] the hover selector used to sit in the
   focus-ring group above, so hovering a row OUTLINED the dots instead of
   showing them -- the menu (Pin / Add to project / Delete) was unreachable
   with a mouse in both browser-only and helper modes. Touch devices have no
   hover: the active row keeps its dots visible too. */
.conv:hover .conv-menu-btn,
.conv.active .conv-menu-btn,
.conv:focus-within .conv-menu-btn,
.conv-menu-btn:focus-visible,
.conv-menu-btn[aria-expanded="true"] {
  visibility: visible;
}
.conv-menu-btn:hover {
  background: var(--surface-3);
  color: var(--text);
}
.conv-menu-btn svg {
  width: 16px;
  height: 16px;
  fill: currentColor;        /* three dots are filled circles, not strokes */
  stroke: none;
  pointer-events: none;
}

/* The menu itself is a direct child of <body>, position:fixed — #convlist is
   an overflow container and would clip it. JS sets left/top. */
.conv-menu {
  position: fixed;
  z-index: 80;
  min-width: 190px;
  padding: var(--space-1);
  display: flex;
  flex-direction: column;
  gap: 2px;
  background: var(--panel);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-pop);
  box-shadow: var(--shadow-pop);
}
.conv-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  width: 100%;
  padding: 8px 10px;
  border: none;
  border-radius: var(--radius-btn);
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}
.conv-menu-item svg {
  width: 16px;
  height: 16px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.conv-menu-item:hover:not([disabled]) {
  background: var(--surface-2);
}
.conv-menu-item.danger {
  color: var(--danger);
}
.conv-menu-item.danger:hover:not([disabled]) {
  background: var(--danger-tint);
}
/* Kit section 6: a disabled control explains itself (title tooltip) rather
   than looking broken. Pin and Add to project have no backend yet. */
.conv-menu-item[disabled] {
  opacity: .45;
  cursor: not-allowed;
}
/* Pushes the "›" of a submenu item to the right edge. */
.conv-menu-chev {
  margin-left: auto;
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1;
}

/* A single consequence line should read as a sentence, not a one-item
   bullet list (the delete confirmation uses exactly one). */
.bkdlg ul:has(> li:only-child) {
  padding-left: 0;
  list-style: none;
}

/* [CM1 pinned-section] Pinned chats sit above the scrolling list, directly
   under the search box, and do NOT scroll with it. Empty and hidden until
   pinning has a backend — the structure is here so wiring it up later is a
   render change only. */
#convpinned {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
#convpinned:not([hidden]) {
  margin-bottom: var(--space-2);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
}

/* ======================================================================
   D. TOP HEADER OF THE CHAT VIEW
   ====================================================================== */
#chathead {
  height: 56px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 0 24px;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
  box-shadow: none;
  z-index: 10;
  position: relative;
}
/* [HD2 stable-header] The title sits in a FIXED-WIDTH grid track, so the
   "Working on" pill always starts at the same x. The previous shrink-to-fit
   version let the column follow the chat name, which slid the pill sideways
   on every chat switch — and made the truncation pointless, since a short
   name simply made the column narrow instead of ever truncating.
   The track is clamped to the viewport, not to the text: constant for a given
   window width, independent of whatever chat is open. */
.chathead-left {
  display: grid;
  /* [PL1 pill-stability] The second track used to be `max-content`, i.e. the
     pill sized itself from its own label. Every extra selection made it wider
     until it pushed into — and overlapped — the status chip and the header
     buttons on its right.

     This is the same defect Lessons-Learned already records for #convtitle
     ("size a flexible element from the CONTAINER, never from its content"). I
     had applied that rule to the title track and left the pill beside it still
     content-sized, which just moved the instability one element to the right.

     Both tracks are clamped now, so the pill occupies the same width whether
     nothing or everything is selected, and nothing beside it can ever move. */
  grid-template-columns: clamp(200px, 32vw, 440px) clamp(190px, 22vw, 330px);
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  flex: 1;
}
#convtitle {
  /* Kit section 4.2: header title 18 / 600. */
  font-size: 18px;
  font-weight: 600;
  line-height: 1.25;
  color: var(--text);
  margin: 0;
  min-width: 0;          /* lets the ellipsis work inside the grid track */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* The pill owns its own track and is never squeezed or wrapped. */
/* [PL2 pill-fill] These were two separate blocks saying contradictory
   things, and together they defeated the clamped track in .chathead-left:

     justify-self: start  -> the grid item does NOT stretch to its track
     display: inline-flex -> the box sizes to its content

   So the wrap shrank to the pill's text, and `#ctxpill { width: 100% }`
   resolved against the WRAP rather than the track — circular, and the pill
   went back to being content-sized. A clamped track only constrains
   anything if the item inside actually fills it.

   stretch + flex + min-width:0 makes the wrap take the track's width; the
   pill then fills the wrap, and #ctxlabel's ellipsis finally has a limit to
   work against. */
.ctxpill-wrap {
  position: relative;
  display: flex;
  justify-self: stretch;
  align-self: center;
  min-width: 0;
}
#ctxpill {
  /* Fills its clamped track rather than hugging its text — the track is what
     fixes the width, this just stops the button shrinking inside it. */
  width: 100%;
  min-width: 0;
  height: 32px;
  padding: 0 10px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text);
  font-size: 12.5px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease;
}
#ctxpill:hover {
  background: var(--surface-2);
  border-color: var(--border-hover);
}
.ctx-icon {
  width: 14px;
  height: 14px;
  stroke: var(--text-muted);
  stroke-width: 1.8;
  fill: none;
  flex: none;
}
.ctx-pre {
  color: var(--text-muted);
  font-weight: 400;
  flex: none;                /* the static word must never be the thing clipped */
}
/* The only flexible child: it absorbs the slack and takes the ellipsis.
   min-width:0 is required — a flex item defaults to min-width:auto, which
   refuses to shrink below its text and is why nothing truncated before. */
#ctxlabel {
  color: var(--text);
  font-weight: 700;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Shown only when more than one thing is selected; the badge carries the
   exact count and the pill's tooltip lists every selection in full. */
#ctxmore {
  flex: none;
  color: var(--text-muted);
  font-weight: 700;
}
#ctxmore[hidden] { display: none; }
/* The count badge is styled in app.css, which stays byte-identical, so the
   flex pin is added here: it must keep its width while #ctxlabel shrinks. */
#ctxcount {
  flex: none;
}
.ctx-chev {
  width: 12px;
  height: 12px;
  stroke: var(--text-muted);
  stroke-width: 2;
  fill: none;
  flex: none;
  margin-left: 2px;
}

#ctxpop {
  position: absolute;
  top: calc(100% + 8px);
  /* Centred on the pill rather than flush to its left edge. app.css pins it
     to `right: 44px`, which is why it used to hang off to one side. */
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-pop);
  padding: 14px 16px;
  min-width: 320px;
  z-index: 50;
  box-shadow: var(--shadow-pop);
}
/* [CP1 ctxpop-compact] Same problem the model popover had: .dd-btn,
   .dd-opt and .dd-filter inherit app.css's desktop-era `--f-sm` (18px), so
   every control in here rendered oversized. Scoped to #ctxpop — the same
   .dd-* classes are reused by the legacy Agents / Projects / Workflows
   selects, which are not phase 1. */
#ctxpop .pop-h {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--text-muted);
  margin: 0 0 var(--space-3);
}
#ctxpop .pop-l {
  width: 76px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
}
#ctxpop .dd-btn {
  height: 34px;
  padding: 0 10px;
  font-size: 13.5px;
  border-radius: var(--radius-input);
  background: var(--surface);
}
#ctxpop .dd-arr {
  font-size: 12px;
  color: var(--text-muted);
}
#ctxpop .dd-menu {
  border-radius: var(--radius-card);
  padding: var(--space-1);
  background: var(--panel);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  display: flex;
  flex-direction: column;
  max-height: none;
  overflow: visible;        /* must not clip its own open list */
}
#ctxpop .dd-filter {
  flex: none;
  font-size: 13px;
  padding: 6px 9px;
  border-radius: var(--radius-input);
}
#ctxpop .dd-list {
  max-height: 196px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-2) transparent;
}
#ctxpop .dd-list::-webkit-scrollbar { width: 6px; }
#ctxpop .dd-list::-webkit-scrollbar-track { background: transparent; margin: 4px 0; }
#ctxpop .dd-list::-webkit-scrollbar-thumb {
  background: var(--border-2);
  border-radius: 999px;
  min-height: 32px;
}
#ctxpop .dd-list::-webkit-scrollbar-thumb:hover { background: var(--border-hover); }
#ctxpop .dd-opt {
  font-size: 13.5px;
  padding: 7px 10px;
  border-radius: var(--radius-btn);
}
#ctxpop .dd-opt:hover { background: var(--surface-2); }
#ctxpop .pop-note {
  font-size: 12px;
  color: var(--text-muted);
}

#ctxpop.hidden,
#ctxpop[hidden] {
  display: none !important;
}
#ctxpop .pop-h {
  font-size: 13px;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 12px 0;
}
#ctxpop .pop-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
#ctxpop .pop-l {
  width: 66px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-muted);
  flex: none;
}
#ctxpop select {
  flex: 1;
  height: 32px;
  border-radius: var(--radius-input);
  border: 1px solid var(--border-2);
  background: var(--surface-2);
  color: var(--text);
  padding: 0 8px;
  font-size: 12.5px;
  outline: none;
}
#ctxpop .pop-note {
  font-size: 12px;
  color: var(--text-muted);
  margin: 10px 0 0;
  line-height: 1.4;
}

.chathead-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}
.head-icon-btn {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: none;
  padding: 0;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.head-icon-btn:hover {
  background: var(--surface-2);
  border-color: var(--border-hover);
  color: var(--text);
}
.head-icon-btn svg {
  width: 16px;
  height: 16px;
  stroke: currentColor;
  stroke-width: 1.8;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

#chathead #newchat2,
#chathead #ntf-bell,
#chathead > button/* ============================================================
   [UT1 undefined-token-map] 2026-10-09
   The notifications / settings / device blocks below were written against
   token names that are defined NOWHERE in the app: --mut, --fg, --acc,
   --bg2, --bg3, --line. An undefined custom property with no fallback makes
   the whole declaration invalid at computed-value time, so these were not
   "dead code" - they were live bugs:
     #ntf-pop   had no background at all (transparent popover)
     #ntf-badge had no fill (the unread count was invisible)
     muted text rendered at full strength, row hover gave no feedback
   They now point at the real tokens:
     --mut -> --text-muted   --fg  -> --text       --acc -> --accent
     --bg2 -> --panel        --bg3 -> --surface-2  --line -> --border
   ============================================================ */
#ntf-bell {
  display: none !important;
}

/* Status Pill spec (.devchip): 32px height, radius 8, green tint */
.devchip {
  height: 32px;
  /* was var(--radius-sm) — a token that does not exist anywhere, so the
     declaration was invalid and the chip rendered with square corners.
     --radius-btn (10px) gives the rounded rectangle asked for. NOTE: the kit
     specs a 999px pill for header status (section 5); the rounded rectangle
     is a deliberate product decision on top of it. */
  border-radius: var(--radius-btn);
  border: 1px solid var(--success-tint-border);
  background: var(--success-tint);
  color: var(--success-text);
  padding: 0 10px;
  font-size: 12px;
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}
:root[data-theme="dark"] .devchip {
  background: var(--success-tint);
  border-color: var(--success-tint-border);
  color: var(--success-text);
}
:root[data-theme="light"] .devchip,
:root[data-theme="light"] .devchip.tone-ok,
:root[data-theme="light"] #devchip,
:root[data-theme="light"] #devchip.tone-ok {
  background: var(--selected-fill);
  border-color: var(--selected-border);
  color: var(--tb-accent-text, var(--accent));
}
.devchip .devchip-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 6px currentColor;
  flex: none;
}
:root[data-theme="light"] .devchip .devchip-dot,
:root[data-theme="light"] .devchip.tone-ok .devchip-dot,
:root[data-theme="light"] #devchip .devchip-dot {
  background: var(--accent);
  box-shadow: 0 0 6px var(--tb-accent-soft);
}
.devchip .devchip-label {
  color: inherit;
}
.devchip:hover {
  filter: brightness(1.05);
}

/* Direct mode toggle & Gateway online light dot in global navbar */
#theme-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
}
#theme-icon svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#theme-icon .ti-sun { display: none; }
#theme-icon .ti-moon { display: block; }
#theme-icon[data-mode="dark"] .ti-sun { display: block; }
#theme-icon[data-mode="dark"] .ti-moon { display: none; }
:root[data-theme="dark"] #theme-icon .ti-sun { display: block; }
:root[data-theme="dark"] #theme-icon .ti-moon { display: none; }
:root[data-theme="light"] #theme-icon .ti-sun { display: none; }
:root[data-theme="light"] #theme-icon .ti-moon { display: block; }

/* Gateway light dot with hover tooltip */
.gwdot-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 32px;
  cursor: pointer;
  outline: none;
}
#gwdot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  transition: transform 140ms ease, box-shadow 140ms ease, background 140ms ease;
}
#gwdot.off {
  background: var(--text-muted);
  box-shadow: none;
}
#gwdot.on {
  background: var(--success);
  box-shadow: 0 0 0 2px var(--success-tint-border), 0 0 8px var(--success);
}
:root[data-theme="light"] #gwdot.on {
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--tb-accent-soft), 0 0 8px var(--accent);
}
.gwdot-wrap:hover #gwdot.on,
.gwdot-wrap:focus-visible #gwdot.on {
  transform: scale(1.25);
  box-shadow: 0 0 0 3px var(--success-tint-border), 0 0 12px var(--success);
}
.gw-tooltip {
  position: absolute;
  top: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(-2px);
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  font-size: 11.5px;
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 120ms ease, transform 120ms ease, visibility 120ms ease;
  box-shadow: var(--shadow-pop);
  z-index: 70;
}
.gwdot-wrap:hover .gw-tooltip,
.gwdot-wrap:focus-visible .gw-tooltip {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}

/* ======================================================================
   E. "NEW CHAT" SCREEN (Empty State + Composer)
   ====================================================================== */
#view-chat {
  background: var(--bg);
}
#messages {
  max-width: 1140px;
  margin: 0 auto;
  width: 100%;
  box-sizing: border-box;

  /* [MS1 chat-type-scale] Why chat always looked "zoomed in": app.css is a
     port of the QtWebEngine desktop build, where `body` is
     `font: 400 var(--f)/1.6` with `--f: 21px`, and renderer.css draws every
     markdown block at `var(--dr-f)` — also 21px. At kit scale body text is
     14-15px, so every answer rendered ~40% oversized.

     These are set HERE, on #messages, instead of on :root. Custom properties
     inherit, so this rescales only markdown rendered inside the chat.
     drRender() is also used by agents_page.js and workflows_page.js, which
     are NOT phase 1 and must keep their current size. */
  font-size: 15px;                 /* kit: body 14-15 */
  --dr-f: 15px;
  --dr-f-sm: 13.5px;
  --dr-f-code: 13.5px;             /* kit: mono 13-15 */
  --dr-f-h1: 20px;
  --dr-f-h2: 17px;                 /* kit: section 16-18 */
  --dr-f-h3: 15.5px;

  /* [MS2 idle-scrollbar] The chat bar sat on screen permanently: a styled
     ::-webkit-scrollbar never gets the OS overlay auto-hide. The thumb is
     transparent at rest and only paints while scrolling (JS adds .scrolling
     and drops it after a beat) or while the pointer is over the log. */
  scrollbar-width: thin;                              /* Firefox */
  scrollbar-color: transparent transparent;
}
/* ======================================================================
   [RS1 responsive] Phase-1 widths: 1440 / 1100 / 800.

   The arithmetic that forced this: the rail (84) and the list column (272)
   are fixed, so at 800px the work area gets 444px — while .chathead-left
   alone was reserving clamp(200,32vw,440) + clamp(190,22vw,330) = 446px,
   before the status chip and the two icon buttons on its right. The header
   overflowed its own row and the pill rode over the buttons.

   Kit 4.4 wants the list column to collapse behind a toggle from 1023px
   down. That needs a toggle control, which is a feature, not a style — so
   this pass stays CSS-only: the fixed columns and the header tracks give
   back width in steps, and the device chip (whose meaning is duplicated in
   the More menu) drops out at the narrowest step. boot/mobile.css is not
   touched, so nothing below 768px changes.
   ====================================================================== */
@media (max-width: 1280px) {
  #convpanel { width: 248px; }
  .chathead-left {
    grid-template-columns: clamp(180px, 26vw, 380px) clamp(180px, 20vw, 300px);
  }
  #messages { max-width: 980px; }
}

@media (max-width: 1100px) {
  #convpanel { width: 232px; }
  .chathead-left {
    grid-template-columns: clamp(160px, 24vw, 320px) clamp(170px, 19vw, 280px);
    gap: var(--space-2);
  }
  #chathead { padding: 0 16px; }
  #composer { padding: 12px 16px 16px; }
}

@media (max-width: 900px) {
  #convpanel { width: 208px; }
  .chathead-left {
    grid-template-columns: minmax(0, 1fr) clamp(150px, 20vw, 240px);
  }
  /* The chip is a status read-out, not an action, and the same state is in
     the More menu — it is the right thing to drop first. */
  #devchip { display: none; }
  /* [PL2] At this width the pill track is ~160px; the static "Working on"
     would eat most of it and leave nothing for the value. The button keeps
     aria-label="Working on", so the meaning survives for screen readers. */
  .ctx-pre { display: none; }
  #messages { padding-left: 16px; padding-right: 16px; }
}

/* ======================================================================
   [UM1 long-user-msg] A long pasted message used to render at full height
   and push the conversation off screen. It now clamps and offers
   "Show more", the way Claude does.

   .msg.user is `display:flex; justify-content:flex-end` in app.css, so the
   toggle would land BESIDE the bubble. Switching this wrapper to a column
   puts it underneath and keeps both right-aligned; `.bubble` itself is
   untouched, so nothing that builds or reads it changes.
   ====================================================================== */
.msg.user {
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}
.msg.user .bubble.is-clamped {
  max-height: var(--user-msg-clamp);
  overflow: hidden;
  position: relative;
}
/* Fades the cut edge into the bubble so the clamp does not look like a
   rendering glitch. pointer-events:none keeps the text selectable. */
.msg.user .bubble.is-clamped::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3.2em;
  background: linear-gradient(to bottom, transparent, var(--user-bub));
  pointer-events: none;
}
.msg-expand {
  appearance: none;
  background: none;
  border: none;
  padding: 2px 6px;
  margin: 0;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
  border-radius: var(--radius-btn);
}
.msg-expand:hover {
  color: var(--text);
  background: var(--surface-2);
}
.msg-expand:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

#messages:hover,
#messages.scrolling {
  scrollbar-color: var(--border-2) transparent;       /* Firefox */
}
#messages::-webkit-scrollbar {
  width: 8px;
}
#messages::-webkit-scrollbar-track {
  background: transparent;
}
#messages::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 999px;
  min-height: 36px;
  transition: background 260ms ease-out;
}
#messages:hover::-webkit-scrollbar-thumb,
#messages.scrolling::-webkit-scrollbar-thumb {
  background: var(--border-2);
}
#messages:hover::-webkit-scrollbar-thumb:hover {
  background: var(--border-hover);
}

/* [TY1 type-scale] Last of the desktop-era type consumers (Patterns s15).
   app.css is a QtWebEngine port: .empty-title is a hard 28.5px and
   .empty-sub / .dd-empty read --f-sm (18px). Kit scale is Display 22/700
   and body 14-15.

   .empty-* are chat-only selectors, so they are corrected outright.
   .dd-group / .dd-empty are shared with the legacy Agents / Projects /
   Workflows selects, so those stay scoped to the two phase-1 popovers -
   same reasoning as MP2 and CP1. */
.empty-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -.01em;
}
.empty-sub {
  font-size: 14px;
  line-height: 1.6;
  max-width: 420px;
}
#modelpop .dd-group,
#ctxpop .dd-group {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .05em;
  color: var(--text-muted);
}
#modelpop .dd-empty,
#ctxpop .dd-empty {
  font-size: 13px;
  padding: 8px 10px;
}

/* Empty-state title & sub-copy */
#empty {
  max-width: 1140px;
  margin: calc(14vh / var(--uz, 1)) auto 0;
  text-align: center;
  padding: 0 24px;
}
#empty .empty-title {
  font-size: 22px;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text);
  margin-bottom: 8px;
}
#empty .empty-sub {
  font-size: 14px;
  font-weight: 400;
  color: var(--text-dim);
  line-height: 1.5;
  margin-bottom: 24px;
}

/* Suggestion/starter cards: 2 per row, --surface fill, 1px --border, radius 14 */
.bk-starters {
  display: grid;
  grid-template-columns: repeat(2, minmax(240px, 340px));
  gap: 14px;
  justify-content: center;
  max-width: 720px;
  margin: 0 auto;
}
@media (max-width: 700px) {
  .bk-starters {
    grid-template-columns: 1fr;
  }
}
.bk-start {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  text-align: left;
  padding: 18px 20px;
  border-radius: var(--radius-card);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--text);
  cursor: pointer;
}
.bk-start:hover {
  border-color: var(--border-2);
  background: var(--surface);
}
.bk-start:active {
  background: var(--surface-2);
}
.bk-start b {
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
}
.bk-start span {
  font-size: 13px;
  font-weight: 400;
  color: var(--text-muted);
  line-height: 1.4;
}
/* [BK13 dyn-starters-v1] starter animations */
.bk-start.bk-swap { animation: bkStartIn .35s ease; }
@keyframes bkStartIn { from { opacity: 0; transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .bk-start.bk-swap { animation: none; } }

/* Composer card layout: unified rounded card with input and bottom bar */
#composer {
  flex: none;
  padding: 12px 24px 16px;
  background: var(--bg);
  border-top: none;
  box-shadow: none;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}
#composer-card {
  width: 100%;
  max-width: 880px;
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius-pop);
  padding: 14px 16px 12px;
  box-shadow: none;   /* kit s4.3: sticky composer carries no shadow */
  display: flex;
  flex-direction: column;
  transition: border-color 140ms ease, box-shadow 140ms ease;
  box-sizing: border-box;
}
#composer-card:focus-within {
  border-color: var(--selected-border);
  box-shadow: var(--ring-accent);
}
#inputwrap {
  width: 100%;
  margin: 0;
  padding: 0;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}
#input {
  width: 100%;
  min-height: 36px;
  max-height: 180px;
  resize: none;
  background: transparent;
  border: none !important;
  outline: none !important;
  box-shadow: none !important;
  color: var(--text);
  font-size: 14.5px;
  line-height: 1.5;
  font-family: var(--font);
  padding: 0 0 10px 0;
  box-sizing: border-box;
}
#input::placeholder {
  color: var(--placeholder);
  font-size: 14.5px;
}

#composer-card-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  width: 100%;
  margin-top: 4px;
}

/* Toolbar row outside card (#composebar) */
#composebar {
  width: 100%;
  max-width: 880px;
  margin: 8px 0 0;
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
  box-sizing: border-box;
}
.compose-left {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}
#composebar > #attachbtn {
  width: auto;
  height: 28px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--border-2);
  background: transparent;
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex: none;
  padding: 0 10px;
  transition: border-color 120ms ease, color 120ms ease, background 120ms ease;
}
#composebar > #attachbtn:hover {
  border-color: var(--border-hover);
  color: var(--text);
  background: var(--surface-2);
}
#composebar > #attachbtn svg {
  width: 14px;
  height: 14px;
  stroke: currentColor;
  stroke-width: 2.2;
  fill: none;
  stroke-linecap: round;
}
.compose-hint {
  font-size: 12.5px;
  color: var(--text-muted);
  font-weight: 400;
  user-select: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: opacity 180ms ease;
}

#composebar > .chip {
  display: none !important;
}

.compose-right {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
}
.model-wrap {
  position: relative;
  display: inline-flex;
}
.modeltag {
  height: 28px;
  padding: 0 8px;
  border: 1px solid var(--border-2);
  border-radius: var(--radius-btn);
  background: transparent;
  color: var(--text-dim);
  font-size: 12.5px;
  font-weight: 500;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 240px;
  white-space: nowrap;
  flex: none;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.modeltag:hover {
  color: var(--text);
  border-color: var(--border-hover);
  background: var(--surface-2);
}
.modeltag-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
  display: inline-block;
  vertical-align: middle;
}
.modeltag .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  display: inline-block;
  flex: none;
}
.modeltag .dot.on {
  background: var(--success);
  box-shadow: 0 0 6px var(--success-tint-border);
}
/* [CNX1 model-dot-light-v1] Lime is a dark-surface colour. --success stays
   lime in BOTH themes (theme_b keeps it as a fill token), so on the light
   composer this dot was lime-on-white: present, but reading as decoration
   rather than "the model is live". Light mode uses the accent blue, which
   is already the active colour everywhere else on that surface. The amber
   and bad states below are unchanged — they carry meaning that must not
   move with the theme. */
:root[data-theme="light"] .modeltag .dot.on {
  background: var(--accent);
  box-shadow: 0 0 6px var(--tb-accent-soft);
}
/* [CNX1] …and the same dots INSIDE the popover. theme_b.css:165 sets
   `.dot.on { background: var(--tb-success) }` globally, which is lime in both
   themes, so the rows in #modelpop stayed lime on the light surface even
   after the button's dot was corrected above. Scoped to #modelpop: the same
   .dd-* dropdown (and its .dot) is reused by Workflows, Agents and Projects,
   which are not part of this pass. */
:root[data-theme="light"] #modelpop .dot.on {
  background: var(--accent);
}
/* [BK0 model-dot-truth] the health dot is honest again (on / amber / bad),
   so both non-green states need token colours here — without these they
   fall through to app.css's literal #f59e0b / #ef4444 warm-palette hexes. */
.modeltag .dot.amber {
  background: var(--warning);
  box-shadow: 0 0 6px var(--warning-tint-border);
}
.modeltag .dot.bad {
  background: var(--danger);
  box-shadow: 0 0 6px var(--danger-tint-border);
}
.modeltag-chev {
  font-size: 12px;
  margin-left: 1px;
  color: var(--text-muted);
}

#sendbtn {
  width: 32px;
  height: 32px;
  border-radius: var(--radius-btn);
  background: var(--primary);
  color: var(--white);
  border: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  padding: 0;
  box-shadow: var(--glow-accent-sm);
  transition: background 120ms ease, transform 100ms ease;
}
#sendbtn:hover {
  background: var(--primary-hover);
}
#sendbtn:active {
  background: var(--primary-pressed);
  transform: scale(0.96);
}
#sendbtn svg {
  width: 16px;
  height: 16px;
  stroke: var(--white);
  stroke-width: 2.4;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#sendbtn:disabled {
  opacity: .45;
  cursor: not-allowed;
  box-shadow: none;
}

#cancelbtn.stop {
  height: 30px;
  padding: 0 10px;
  border-radius: var(--radius-btn);
  border: 1px solid var(--danger);
  color: var(--danger);
  background: transparent;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
#cancelbtn.stop:hover {
  background: var(--danger-tint);
}

/* Chips in composebar */
.chip {
  height: 32px;
  font-size: 13px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid var(--border-2);
  color: var(--text-muted);
  background: transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}
.chip:hover {
  color: var(--text);
  border-color: var(--border-hover);
}
.chip.on {
  background: var(--selected-fill);
  border-color: var(--selected-border);
  color: var(--text);
}

/* Privacy line under the composer */
#composer-privacy,
.bk-privacy {
  margin: 8px 0 0;
  text-align: center;
  font-size: 12px;
  font-weight: 400;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.privacy-lock {
  width: 12px;
  height: 12px;
  stroke: currentColor;
  stroke-width: 2;
  fill: none;
  flex: none;
  display: inline-block;
}

/* ---- [BK4 skeleton-v1] (U22, brand kit 12) skeleton rows + shimmer ---- */
.bk-skels { display: flex; flex-direction: column; gap: 10px; padding: 8px 2px; }
.bk-skel {
  height: 14px; border-radius: var(--radius-input);
  background: linear-gradient(90deg,
    var(--tb-surface) 0%,
    var(--tb-surface-2, rgba(127,127,127,.15)) 45%,
    var(--tb-surface) 90%);
  background-size: 200% 100%;
  animation: bk-shimmer 1.8s linear infinite;
  border: 1px solid var(--tb-border, transparent);
}
@keyframes bk-shimmer {
  from { background-position: 180% 0; }
  to   { background-position: -20% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .bk-skel { animation: none; background: var(--tb-surface-2, rgba(127,127,127,.12)); }
}

/* ---- [BK12 spinner-v1] (brand kit 12.2) one shared spinner: track border-2,
   arc accent-text, 0.9s linear. Sizes 12/16/24/32. ---- */
.bk-spin { display: inline-block; width: 16px; height: 16px; flex: none;
  border-radius: 50%; border: 2px solid var(--border-2);
  border-top-color: var(--accent-text);
  animation: bk-spin .9s linear infinite; }
.bk-spin.sm { width: 12px; height: 12px; }
.bk-spin.lg { width: 24px; height: 24px; }
.bk-spin.xl { width: 32px; height: 32px; }
@keyframes bk-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .bk-spin { animation-duration: 1.8s; } }

/* inline "Saving<Spinner>" + "check Saved" row indicator (kit 12.1 #3) */
.bk-savestate { display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--text-muted); }
.bk-savestate.ok { color: var(--success-text, var(--success)); }

/* "check Saved" mark rendered lime (kit 12.1 #2/#3): a lime check + word. */
.bk-saved { display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--success-text, var(--success)); }
.bk-saved svg { width: 12px; height: 12px; }

/* 3px cobalt page bar under the header (kit 12.1 #5 / 12.3) */
.bk-pagebar { position: fixed; top: 0; left: 0; right: 0; height: 3px;
  background: var(--primary); z-index: 65; overflow: hidden; }
.bk-pagebar::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
  animation: bk-slide 1.2s linear infinite; }
@keyframes bk-slide { from { transform: translateX(-100%); } to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .bk-pagebar::after { animation: none; } }

/* ---- [BK4 confirm-v1] (U22, brand kit 11/13) alert dialog ---- */
.bkdlg-scrim {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(6, 7, 10, .62);
  display: flex; align-items: center; justify-content: center;
}
.bkdlg {
  width: min(440px, calc(100vw - 32px));
  background: var(--tb-bg-panel);
  border: 1px solid var(--tb-border-strong, var(--border-2, currentColor));
  border-radius: var(--radius-dialog); padding: 22px;
  box-shadow: var(--shadow-dialog);
  color: var(--tb-text, inherit);
}
.bkdlg h3 { margin: 0 0 10px; font-size: 18px; font-weight: 700; line-height: 1.3; }
.bkdlg ul { margin: 0 0 6px; padding-left: 18px; }
.bkdlg li {
  font-size: 14px; line-height: 1.55;
  color: var(--tb-text-secondary, var(--dim, inherit));
  margin: 4px 0;
}
.bkdlg-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }
.bkdlg-actions button {
  height: 36px; padding: 0 16px; border-radius: var(--radius-btn);
  font-size: 14px; font-weight: 600; cursor: pointer;
}
.bkdlg-cancel {
  background: transparent; color: var(--tb-text-secondary, inherit);
  border: 1px solid var(--tb-border-strong, currentColor);
}
.bkdlg-cancel:hover { background: var(--tb-surface-2, transparent); }
.bkdlg-primary {
  background: var(--tb-accent); color: var(--white); border: none;
}
.bkdlg-primary:hover { filter: brightness(1.12); }
.bkdlg-danger {
  background: var(--tb-danger-fill); color: var(--white); border: none;
}
.bkdlg-danger:hover { filter: brightness(1.1); }

/* ---- [BK12 create-card-v1] creation card: AI mark + "Creating {name}…" +
   indeterminate bar + one real step line; at 8s -> "taking longer" + Try again ---- */
.bk-create { display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  max-width: 720px; padding: 14px 16px; border: 1px solid var(--tb-border);
  border-radius: var(--radius-card); background: var(--tb-surface);
  align-self: flex-start; margin: 4px 0; }
.bk-create .mark { width: 28px; height: 28px; border-radius: 8px; flex: none;
  background: var(--tb-accent-soft); color: var(--tb-accent-text);
  display: flex; align-items: center; justify-content: center; }
.bk-create .mark svg { width: 16px; height: 16px; }
.bk-create .t { font-size: 14px; font-weight: 600; }
.bk-create .bar { width: 100%; height: 3px; border-radius: 999px; overflow: hidden;
  background: var(--tb-surface-2, rgba(127,127,127,.12)); }
.bk-create .bar i { display: block; height: 100%; width: 40%;
  background: var(--tb-accent); animation: bk-slide 1.2s linear infinite; }
.bk-create .s { font-size: 12.5px; color: var(--tb-text-muted); line-height: 1.5; }
.bk-create .slow { display: flex; gap: 8px; }
@media (prefers-reduced-motion: reduce) { .bk-create .bar i { animation: none; } }

/* ---- [P2 C3 not-live-v1 + auto-retry-v1] ---- */
.bk-notlive {
  display: inline-flex; align-items: center; margin-top: 8px;
  font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 999px;
  background: var(--tb-surface-2, rgba(127,127,127,.12));
  color: var(--tb-text-dim, inherit);
  border: 1px solid var(--tb-border-2, var(--tb-border, currentColor));
}
.bk-autoretry {
  display: flex; align-items: center; gap: 8px; margin-top: 10px;
  font-size: 13px; color: var(--tb-text-dim, inherit);
}
.bk-ar-ring { width: 16px; height: 16px; transform: rotate(-90deg); }
.bk-ar-ring circle {
  fill: none; stroke: var(--tb-accent-text, currentColor); stroke-width: 2;
  stroke-linecap: round;
}
.bk-ar-cancel { margin-left: 2px; }

/* ---- [P2 C4 chat-search-v1] Ctrl/Cmd+K palette (brand kit 11) ---- */
#bkp-scrim {
  position: fixed; inset: 0; z-index: 60;
  background: var(--tb-scrim, rgba(6,7,10,.62));
  display: flex; align-items: flex-start; justify-content: center;
}
/* [P2 C4 palette-close-v2] the id's display:flex outranks the UA
   [hidden]{display:none} rule, so hidden=true never visually closed the
   palette -- Esc and scrim clicks "did nothing". This makes hidden win. */
#bkp-scrim[hidden] { display: none !important; }
#bkp-head { display: flex; align-items: center; gap: 8px; }
#bkp-head #bkp-input { flex: 1; }
#bkp-close {
  flex: none; width: 34px; height: 34px; border-radius: var(--radius-btn); cursor: pointer;
  background: transparent; border: 1px solid var(--tb-border-2, currentColor);
  color: var(--tb-text-muted, inherit); font-size: 16px; line-height: 1;
}
#bkp-close:hover { color: inherit; }
#bkp {
  width: 640px; max-width: calc(100vw - 32px); margin-top: 15vh;
  background: var(--tb-panel, var(--panel));
  border: 1px solid var(--tb-border-2, currentColor);
  border-radius: var(--radius-pop); padding: 10px;
  box-shadow: var(--shadow-pop);
}
#bkp-input {
  width: 100%; height: 48px; padding: 0 14px; font: inherit; font-size: 15px;
  background: var(--tb-surface, transparent); color: inherit;
  border: 1px solid var(--tb-border-2, currentColor); border-radius: var(--radius-input);
}
.bkp-group {
  font-size: 12px; font-weight: 700; letter-spacing: .08em;
  color: var(--tb-text-muted, inherit); margin: 12px 6px 6px;
}
#bkp-list { max-height: 50vh; overflow-y: auto; }
.bkp-row {
  display: flex; flex-direction: column; gap: 2px; cursor: pointer;
  padding: 9px 10px; border-radius: var(--radius-btn);
}
.bkp-row:hover, .bkp-row.sel { background: var(--tb-selected-fill, rgba(53,99,255,.12)); }
.bkp-row b { font-size: 14px; font-weight: 600; }
.bkp-row span {
  font-size: 12px; color: var(--tb-text-muted, inherit);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bkp-empty { font-size: 13px; color: var(--tb-text-muted, inherit); padding: 10px; }
.bkp-hint {
  font-size: 12px; color: var(--tb-text-muted, inherit);
  border-top: 1px solid var(--tb-border, currentColor);
  margin-top: 8px; padding: 8px 6px 2px;
}

/* ---- [P2 C13 notify-v1] header bell + inbox popover. Tokens only; the
   badge is a NUMBER and unread rows carry the word "New" (status is never
   colour alone, brand kit 8). ---- */
#ntf-bell {
  position: relative; display: inline-flex; align-items: center;
  justify-content: center; width: 30px; height: 30px; border-radius: var(--radius-btn);
  background: transparent; border: 1px solid var(--border); cursor: pointer;
  color: var(--text-muted); flex: none;
}
#ntf-bell:hover { color: var(--text); border-color: var(--text-muted); }
#ntf-bell svg { width: 16px; height: 16px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
#ntf-badge {
  position: absolute; top: -6px; right: -6px; min-width: 16px; height: 16px;
  padding: 0 4px; border-radius: 999px; background: var(--accent);
  color: var(--acc-fg, var(--white)); font-size: 10px; line-height: 16px;
  font-weight: 700; text-align: center;
}
#ntf-pop {
  position: fixed; z-index: 1200; width: min(360px, calc(100vw - 16px));
  max-height: min(60vh, 480px); overflow: auto; background: var(--panel);
  border: 1px solid var(--border); border-radius: var(--radius-pop);
  box-shadow: var(--shadow-pop); padding: 8px;
}
.ntf-head { display: flex; align-items: center; gap: 8px; padding: 4px 6px 8px;
  border-bottom: 1px solid var(--border); font-size: 13px; }
.ntf-ghost { background: transparent; border: none; color: var(--text-muted);
  font-size: 12px; cursor: pointer; padding: 2px 6px; border-radius: var(--radius-btn); }
.ntf-ghost:hover { color: var(--text); background: var(--surface-2); }
.ntf-row { padding: 8px 6px; border-bottom: 1px solid var(--border);
  cursor: pointer; border-radius: var(--radius-btn); }
.ntf-row:last-child { border-bottom: none; }
.ntf-row:hover { background: var(--surface-2); }
.ntf-line { display: flex; align-items: baseline; gap: 8px; font-size: 13px; }
.ntf-row p { margin: 2px 0 0; font-size: 12px; color: var(--text-muted); }
.ntf-new { font-size: 12px; font-weight: 700; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 999px; padding: 0 5px; }
.ntf-when { font-size: 12px; color: var(--text-muted); white-space: nowrap; }
.ntf-empty { padding: 16px 8px; font-size: 12.5px; color: var(--text-muted); }

/* ---- [P2 C8 settings-autosave-v1] per-row save note in Settings ---- */
.set-autosave { font-size: 12px; color: var(--text-muted); margin-left: 8px;
  white-space: nowrap; }

/* ---- [P2 C11 helper-perms-v1] Devices page safety switches ---- */
.dev-perm-row { display: flex; gap: 10px; align-items: flex-start;
  padding: 8px 0; font-size: 13px; cursor: pointer; }
.dev-perm-row input { margin-top: 3px; flex: none; }
.dev-perm-row span { color: var(--text-muted); }
.dev-perm-row b { color: var(--text); font-weight: 600; }
/* [CNS1 consent-inline-v1] folder-add approval inside the Allowed folders card */
.dr-ask { margin: 10px 0; padding: 10px 12px; border: 1px solid var(--tb-accent);
  background: var(--tb-accent-soft); border-radius: var(--radius-btn); display: flex;
  align-items: center; gap: 10px; flex-wrap: wrap; }
.dr-ask[hidden] { display: none; }
.dr-ask-text { margin: 0; flex: 1; min-width: 200px; word-break: break-all;
  color: var(--tb-text); font-size: 13px; font-weight: 400; }
.dr-ask-text b { font-weight: 600; }
.dr-ask .dev-acts button.dr-ask-allow { background: var(--tb-accent); border-color: var(--tb-accent); color: var(--white); }

/* ---- [P2 C1 live-steps-v1 + source-line-v1] step truth on act rows and
   the answer's sources line. Words carry the status; colour assists. ---- */
.act-step { font-size: 12px; color: var(--text-muted); margin-left: 6px;
  white-space: nowrap; }
.act-step.ok { color: var(--text); }
.act-step.bad { color: var(--warn, var(--text)); font-weight: 600; }
.bk-srcline { font-size: 12px; color: var(--text-muted); padding: 4px 2px 0;
  border-top: 1px dashed var(--border); margin-top: 6px; }


/* ---- teaching pulse support for boot/railhints.js (without icon-only override) ---- */
.rail-btn.rail-hint { background: var(--surface-2); }
.rail-btn.rail-hint svg {
  animation: railHintPulse 1.1s ease-in-out 2;
}
@keyframes railHintPulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.25); }
}
@media (prefers-reduced-motion: reduce) {
  .rail-btn.rail-hint svg { animation: none; }
}


/* ---- [t4_04 chat-scroll-pin-v1] the "come back down" button ----------- */
/* #messages' parent (#view-chat / any .view) was not positioned, so the
   absolute button needs this anchor; harmless for every other view. */
.view { position: relative; }
#scroll-latest {
  position: absolute; right: 26px; bottom: 18px; z-index: 40;
  padding: 7px 14px; border-radius: 999px;
  background: var(--panel-2, var(--surface));
  color: var(--text, inherit);
  border: 1px solid var(--border-2, var(--border, currentColor));
  font-size: 13px; font-weight: 600; cursor: pointer;
  box-shadow: var(--shadow-float);
}
#scroll-latest:hover { background: var(--panel, var(--surface)); }
#scroll-latest[hidden] { display: none; }

/* [WFX3 W8] approvals-waiting badge on the Workflows rail item: amber =
   needs the user (kit 2.2); sits under the blue running badge. */
/* [RB1 rail-badge-lime] app.css:778 sets `.rail-badge.run { background:#22c55e }`
   — a raw hex, and at (0,2,0) it outranks the brand-kit `.rail-badge` rule
   at (0,1,0), so the running-count badge rendered saturated green instead of
   the kit's lime. Brand kit section 5: "Rail badge: 16px lime circle,
   #0C0E13 text 10/800, top-right of the icon" — i.e. --success on --on-lime.
   Matching the (0,2,0) specificity is what makes this land. */
.rail-badge.run {
  background: var(--success);
  color: var(--on-lime);
}
.rail-badge.appr {
  background: var(--tb-warning);
  color: var(--tb-bg);
}
@media (min-width: 768px) {
  .rail-badge.appr { top: 4px; left: calc(50% - 20px); right: auto; }
}

/* ======================================================================
   [MP1 model-popover] "AI models" popover placement + kit sizing.

   app.css anchors #modelpop with `left: 0; min-width: 560px`, so it grows
   RIGHTWARD from a trigger that sits at the right end of the composer —
   560px of panel heading straight off the screen, taking the open select
   list with it. Anchoring to the trigger's right edge makes it grow left
   and up instead, the way a menu attached to a right-hand button should
   (and the way Claude / ChatGPT place theirs).

   Sizing follows brand kit section 11 (Popover): anchored to its trigger
   with an 8px offset, radius 14.

   NOT applied here: the kit's "max-height 420px then scroll". This popover
   is a fixed two-row form, so it never needs to scroll — and an `overflow`
   value other than `visible` CLIPS absolutely-positioned descendants, which
   silently cut the open model list off (a z-index cannot escape a clip).
   The scrolling belongs to .dd-menu below, which is the part that actually
   grows with the model catalogue.
   Scoped to #modelpop so the same .dd-* dropdown used on Workflows,
   Agents and Projects keeps exactly the look it has today.
   ====================================================================== */
#modelpop {
  left: auto;
  right: 0;                                   /* grow leftward from the trigger */
  min-width: 0;
  width: min(440px, calc(100vw - 32px));
  max-width: none;
  margin-bottom: var(--space-2);              /* kit: 8px offset */
  border-radius: var(--radius-card);          /* kit: 14 */
  padding: var(--space-3);
  background: var(--panel);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  overflow: visible;                          /* must not clip the open list */
  z-index: 60;
}
#modelpop .pop-h {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--text-muted);
  margin: 0 0 var(--space-2);
}
#modelpop .pop-row {
  gap: var(--space-2);
  margin-bottom: var(--space-2);
}
#modelpop .pop-l {
  width: 98px;                                /* fits "Thinking model" on one line */
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text);
}
#modelpop .pop-note {
  margin: var(--space-1) 0 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--text-muted);
}
/* ----------------------------------------------------------------------
   [MP2 modelpop-compact] The popover inherited desktop-era sizing: .dd-btn
   and .dd-filter in app.css are font-size:var(--f-sm), which is 18px — that
   file came from the QtWebEngine desktop build. At kit scale these controls
   are 13-14px, so everything read oversized.

   Scoped to #modelpop ONLY. The same .dd-* classes are reused by the legacy
   Agents / Projects / Workflows selects (app.js enhanceSelect at 4168 / 5044
   / 5569), which are NOT phase 1 and must not move.
   ---------------------------------------------------------------------- */
#modelpop {
  width: min(380px, calc(100vw - 32px));
}
#modelpop .dd-btn {
  height: 34px;
  padding: 0 10px;
  font-size: 13.5px;
  border-radius: var(--radius-input);
  background: var(--surface);
}
#modelpop .dd-arr {
  font-size: 12px;
  color: var(--text-muted);
}

/* The select list inside this popover, on the kit's popover spec.
   The MENU no longer scrolls — the LIST does. Scrolling the menu took the
   filter box with it, so the moment you scrolled you lost the thing you
   were typing into. overflow stays `visible` here (see Lessons-Learned:
   an overflow value clips absolutely-positioned descendants). */
#modelpop .dd-menu {
  /* NOTE: this rule sets `display`, which would defeat the `hidden`
     attribute that enhanceSelect's close() uses — [HG1] above restores it. */
  border-radius: var(--radius-card);
  padding: var(--space-1);
  background: var(--panel);
  border: 1px solid var(--border-2);
  box-shadow: var(--shadow-pop);
  display: flex;
  flex-direction: column;
  max-height: none;
  overflow: visible;
}
#modelpop .dd-filter {
  flex: none;
  font-size: 13px;
  padding: 6px 9px;
}
/* Half the old 420px, as asked: ~5 rows, so the list is scrollable without
   becoming a wall of text. */
#modelpop .dd-list {
  max-height: 196px;
  overflow-y: auto;
  /* [SB1-style scrollbar] same treatment as #convlist: a thin 6px bar with a
     fully rounded thumb and a minimum length, instead of the global 9px
     square-ish bar app.css sets for the whole document. */
  scrollbar-width: thin;                        /* Firefox */
  scrollbar-color: var(--border-2) transparent;
}
#modelpop .dd-list::-webkit-scrollbar {
  width: 6px;
}
#modelpop .dd-list::-webkit-scrollbar-track {
  background: transparent;
  margin: 4px 0;                 /* the thumb stops short of both ends */
}
#modelpop .dd-list::-webkit-scrollbar-thumb {
  background: var(--border-2);
  border-radius: 999px;
  min-height: 32px;              /* never collapses to a sliver */
}
#modelpop .dd-list::-webkit-scrollbar-thumb:hover {
  background: var(--border-hover);
}
#modelpop .dd-opt {
  font-size: 13.5px;
  padding: 7px 10px;
  border-radius: var(--radius-btn);
}
#modelpop .dd-opt:hover {
  background: var(--surface-2);
}
#modelpop .dd-group {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--text-muted);
}
#modelpop .dd-filter {
  border-radius: var(--radius-input);
  border: 1px solid var(--border-2);
  background: var(--surface);
  color: var(--text);
}
#modelpop .dd-filter::placeholder { color: var(--placeholder); }

/* ======================================================================
   [PK-COL-COLLAPSE-v1] Collapsible home columns (Agents · Projects · Workflows)
   A column carries .pk-col; .c = collapsed. The SIDE column collapses to a
   60px icon rail (labels clip, controls stay reachable/readable); the LIST
   column collapses fully to 0 width with a visible expand handle tab. Toggles
   use --radius-btn ghost/icon-button style and kit tokens only. 200ms ease-out,
   static under prefers-reduced-motion. At 768-1023px, the list column collapses
   behind a toggle by default.
   ====================================================================== */
.pk-col { transition: width .2s ease-out, min-width .2s ease-out,
    max-width .2s ease-out, flex-basis .2s ease-out, padding .2s ease-out; }

/* Side header: New button and collapse toggle on the exact same row */
.pk-sidehead { display: flex; align-items: center; gap: 8px; width: 100%; height: 36px; margin-bottom: 14px; }
.pk-sidehead > button:not(.pk-tgl) { width: auto; flex: 1 1 auto; min-width: 0; height: 36px !important; padding: 0 14px !important; font-size: 13px !important; font-weight: 600 !important; border-radius: var(--radius-btn, 8px) !important; margin-bottom: 0 !important; justify-content: center; }
.pk-sidehead .pk-tgl.side { flex: none; width: 36px; height: 36px; }

/* List header: Search input, Sort (if any), and collapse toggle on the exact same row */
.pk-listhead { display: flex; align-items: center; gap: 8px; width: 100%; height: 36px; margin-bottom: 14px; }
.pk-listhead > .prjh-search,
.pk-listhead > .agx-search,
.pk-listhead > .wfx-search { flex: 1 1 auto; min-width: 0; height: 36px !important; border-radius: var(--radius-input, 8px) !important; margin-bottom: 0 !important; }
.pk-listhead > .prjh-sort { flex: none; height: 36px; }
.pk-listhead .pk-tgl.list { flex: none; width: 36px; height: 36px; }

.pk-tgl { width: 36px; height: 36px; flex: none; padding: 0; display: inline-flex;
    align-items: center; justify-content: center; border-radius: var(--radius-btn, 8px);
    border: 1px solid transparent; background: transparent; color: var(--tb-text-secondary);
    cursor: pointer; transition: background-color 120ms ease-out, color 120ms ease-out,
    border-color 120ms ease-out; }
.pk-tgl:hover { color: var(--tb-text); background: var(--surface-2);
    border-color: var(--tb-border-strong); }
.pk-tgl:focus-visible { outline: 2px solid var(--tb-accent); outline-offset: 2px; }
.pk-tgl .pk-tgl-ico { width: 17px; height: 17px; flex: none; fill: none;
    stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
    transition: transform .2s ease-out; }
/* Chevron points left when expanded, rotates 180deg to point right when collapsed */
.pk-tgl.c .pk-tgl-ico,
.pk-col.c .pk-tgl-ico { transform: rotate(180deg); }

/* Column 1 (Filter sidebar) Collapsed State: 60px slim icon-only strip */
.pk-col.c.side { width: 60px !important; min-width: 60px !important;
  max-width: 60px !important; flex-basis: 60px !important; flex-grow: 0 !important;
  flex-shrink: 0 !important; padding: 12px 6px !important; overflow-x: hidden !important; }
.pk-col.c.side .pk-sidehead { display: flex; flex-direction: column; align-items: center;
  gap: 10px; width: 100%; margin-bottom: 12px; }
.pk-col.c.side .pk-sidehead .pk-tgl.side { order: -1; width: 34px; height: 34px; margin: 0 auto; }
/* section label ("Vertical"/"Team"/"Function") hidden in the rail */
.pk-col.c.side .agx-seclabel, .pk-col.c.side .wfx-seclabel,
.pk-col.c.side .prjh-seclabel { display: none !important; }
.pk-col.c.side button:not(.pk-tgl) { justify-content: center;
  padding-left: 6px; padding-right: 6px; }
.pk-col.c.side button .t, .pk-col.c.side button .n { display: none !important; }
/* the "+ New …" primary button collapses to its plus icon */
.pk-col.c.side .agx-new > span:not(.agx-ico),
.pk-col.c.side .wfx-new > span:not(.wfx-ico),
.pk-col.c.side .prjh-new > span:not(.prjh-ico) { display: none !important; }
.pk-col.c.side .pk-sidehead > button:not(.pk-tgl),
.pk-col.c.side .agx-new, .pk-col.c.side .wfx-new,
.pk-col.c.side .prjh-new { padding: 0 !important; width: 34px !important;
  height: 34px !important; margin: 0 auto !important; justify-content: center !important; flex: none !important; }

/* Column 2 (List column) Collapsed State: 0 width with expand handle tab */
.pk-col.c.list { width: 0 !important; min-width: 0 !important; max-width: 0 !important;
  flex-basis: 0 !important; flex-grow: 0 !important; flex-shrink: 0 !important;
  padding: 0 !important; border-right: 0 !important; overflow: visible !important;
  position: relative !important; }
.pk-col.c.list > :not(.pk-listhead) { display: none !important; }
.pk-col.c.list > .pk-listhead { position: absolute !important; top: 14px !important; left: 0 !important; z-index: 25 !important;
  width: auto !important; height: auto !important; margin: 0 !important; padding: 0 !important; border: 0 !important;
  background: transparent !important; display: block !important; }
.pk-col.c.list > .pk-listhead > :not(.pk-tgl.list) { display: none !important; }
.pk-col.c.list .pk-tgl.list { display: inline-flex !important; position: relative; left: 0;
  width: 24px; height: 34px; padding: 0; border: 1px solid var(--tb-border-strong);
  border-left: 0; border-radius: 0 var(--radius-btn) var(--radius-btn) 0;
  background: var(--tb-surface); color: var(--tb-text-secondary);
  box-shadow: 2px 0 6px rgba(0, 0, 0, 0.08); }
.pk-col.c.list .pk-tgl.list:hover { background: var(--surface-2); color: var(--tb-text);
  border-color: var(--tb-border-strong); }

@media (max-width: 767px) {
  .pk-tgl { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .pk-col, .pk-tgl, .pk-tgl .pk-tgl-ico { transition: none !important; animation: none !important; }
}

/* ==================== GLOBAL TOAST STANDARDS (Top-Right, Lime/Blue) ==================== */
.prjx-toast,
.prjx-warnbanner,
.agx-toast,
#dc-toast,
#ag-toast {
  position: fixed !important;
  top: 24px !important;
  right: 24px !important;
  left: auto !important;
  bottom: auto !important;
  z-index: 99999 !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 10px !important;
  padding: 11px 18px !important;
  border-radius: 12px !important;
  font-size: 13.5px !important;
  font-weight: 500 !important;
  font-family: var(--font, sans-serif) !important;
  max-width: min(440px, calc(100vw - 32px)) !important;
  box-shadow: 0 12px 28px -4px rgba(0, 0, 0, 0.38), 0 4px 12px rgba(0, 0, 0, 0.2) !important;
  backdrop-filter: blur(14px) !important;
  -webkit-backdrop-filter: blur(14px) !important;
}

/* Success Toasts: Lime in Dark mode */
.prjx-toast,
.agx-toast:not(.err),
#dc-toast:not(.bad),
#ag-toast {
  background: color-mix(in srgb, #84cc16 13%, #14171f) !important;
  border: 1px solid color-mix(in srgb, #84cc16 38%, transparent) !important;
  color: #d9f99d !important;
}

/* Success Toasts: Blue in Light theme */
:root[data-theme="light"] .prjx-toast,
:root[data-theme="light"] .agx-toast:not(.err),
:root[data-theme="light"] #dc-toast:not(.bad),
:root[data-theme="light"] #ag-toast {
  background: color-mix(in srgb, #2563eb 8%, #ffffff) !important;
  border: 1px solid #bfdbfe !important;
  color: #1d4ed8 !important;
  box-shadow: 0 12px 28px -4px rgba(37, 99, 235, 0.15), 0 2px 8px rgba(0, 0, 0, 0.05) !important;
}

/* Warning / Failure Toasts: Red in Dark mode */
.prjx-warnbanner,
.agx-toast.err,
#dc-toast.bad {
  background: color-mix(in srgb, #ef4444 14%, #14171f) !important;
  border: 1px solid color-mix(in srgb, #ef4444 40%, transparent) !important;
  color: #fca5a5 !important;
}

/* Warning / Failure Toasts: Red in Light mode */
:root[data-theme="light"] .prjx-warnbanner,
:root[data-theme="light"] .agx-toast.err,
:root[data-theme="light"] #dc-toast.bad {
  background: #fef2f2 !important;
  border: 1px solid #fecaca !important;
  color: #b91c1c !important;
  box-shadow: 0 12px 28px -4px rgba(239, 68, 68, 0.15), 0 2px 8px rgba(0, 0, 0, 0.05) !important;
}
