/* @layer components — Phase 31 (DDR-123) ACP chat sidepanel.
 *
 * Ported from `.design/ui/ChatPanel.css` (the approved mock), styling only the
 * canvas-LOCAL `chat-*` content inside the `st-rpanel` Assistant tab. Every value
 * is a maude token from `1-tokens-maude.css` / a component class from
 * `4-components-maude.css`. Differences from the mock: the feed scrolls live
 * (`overflow-y:auto`, not the mock's static `hidden`) and a few wrappers
 * (`.chat-thread`, `.st-rp-body--chat`, `.chat-tool-path`) the live panel needs.
 */
@layer components {
  /* Menubar Assistant button (sparkle) — mirrors .st-whatsnew; the ✦ now opens
     the Assistant and What's New moved to a megaphone. Busy = pulse while a turn
     runs; unseen = a violet dot when a reply landed while the panel was hidden. */
  .st-assistant {
    position: relative;
    appearance: none;
    border: 0;
    background: transparent;
    cursor: pointer;
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    border-radius: var(--radius-sm);
    color: var(--fg-1);
  }
  .st-assistant:hover {
    background: var(--bg-3);
    color: var(--fg-0);
  }
  .st-assistant[data-active='true'] {
    background: var(--bg-3);
    color: var(--accent);
  }
  .st-assistant[data-busy='true'] {
    color: var(--presence-agent);
    animation: chat-pip 1.2s var(--ease-out) infinite;
  }
  .st-assistant[data-unseen='true'] {
    color: var(--presence-agent);
  }
  .st-assistant[data-unseen='true']::after {
    content: '';
    position: absolute;
    top: 3px;
    right: 3px;
    width: 7px;
    height: 7px;
    border-radius: var(--radius-pill);
    background: var(--presence-agent);
    border: 1.5px solid var(--bg-1);
  }

  .st-rp-body--chat {
    padding: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .chat-panel {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }
  .chat-thread {
    flex: 1;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  /* Chat switcher bar — recents dropdown + New chat (repo-level history). */
  .chat-bar {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    border-bottom: 1px solid var(--border-subtle);
  }
  /* Custom chat dropdown — status dot (running/open/saved) + delete per row. */
  .chat-switch {
    position: relative;
    flex: 1;
    min-width: 0;
  }
  .chat-switch-trigger {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    width: 100%;
    appearance: none;
    border: 1px solid var(--border-default);
    background: var(--bg-3);
    color: var(--fg-1);
    font-family: var(--font-body);
    font-size: var(--type-xs);
    border-radius: var(--radius-sm);
    padding: 4px var(--space-3);
    cursor: pointer;
    transition: border-color var(--dur-soft) var(--ease-out);
  }
  .chat-switch-trigger:hover {
    border-color: var(--border-strong);
  }
  .chat-switch-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: left;
  }
  .chat-switch-caret {
    color: var(--fg-3);
    flex-shrink: 0;
  }
  .chat-menu-backdrop {
    position: fixed;
    inset: 0;
    z-index: 50;
  }
  .chat-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 51;
    max-height: 260px;
    overflow-y: auto;
    background: var(--bg-2);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    padding: var(--space-1);
  }
  .chat-menu-row {
    position: relative;
    display: flex;
    align-items: center;
    border-radius: var(--radius-xs);
  }
  .chat-menu-row:hover,
  .chat-menu-row.is-active {
    background: var(--bg-3);
  }
  .chat-menu-open {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: var(--space-2);
    appearance: none;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--fg-1);
    font-family: var(--font-body);
    font-size: var(--type-xs);
    padding: var(--space-2);
    text-align: left;
  }
  .chat-menu-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  /* Inline rename input (Task C5) — same box model as .chat-menu-open so the
     row doesn't jump when switching between the button and the input. */
  .chat-menu-rename-input {
    flex: 1;
    min-width: 0;
    appearance: none;
    border: 1px solid var(--accent);
    border-radius: var(--radius-xs);
    background: var(--bg-1);
    color: var(--fg-0);
    font-family: var(--font-body);
    font-size: var(--type-xs);
    padding: var(--space-2);
    margin: 2px;
    outline: none;
  }

  /* Per-chat overflow (⋯ → Rename / Archive / Copy transcript / Delete). */
  .chat-menu-overflow-wrap {
    position: relative;
    flex-shrink: 0;
  }
  .chat-menu-more {
    appearance: none;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--fg-3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    border-radius: var(--radius-xs);
    flex-shrink: 0;
    font-size: var(--type-sm);
  }
  .chat-menu-more:hover {
    background: var(--bg-4, var(--bg-3));
    color: var(--fg-0);
  }
  .chat-menu-overflow {
    position: absolute;
    top: calc(100% + 2px);
    right: 0;
    z-index: 52;
    display: flex;
    flex-direction: column;
    min-width: 150px;
    padding: var(--space-1);
    background: var(--bg-2);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
  }
  .chat-menu-overflow button {
    appearance: none;
    border: 0;
    background: transparent;
    text-align: left;
    cursor: pointer;
    color: var(--fg-1);
    font-family: var(--font-body);
    font-size: var(--type-xs);
    padding: var(--space-2);
    border-radius: var(--radius-xs);
  }
  .chat-menu-overflow button:hover {
    background: var(--bg-3);
  }
  .chat-menu-overflow-danger {
    color: var(--status-error);
  }
  .chat-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-pill);
    flex-shrink: 0;
  }
  .chat-dot--busy {
    background: var(--presence-agent);
    animation: chat-pip 1s var(--ease-out) infinite;
  }
  .chat-dot--idle {
    background: var(--status-success);
  }
  .chat-dot--off {
    background: var(--border-strong);
  }
  /* Transcript view label (Task C4/C5) — a bare unlabeled select read as
     unexplained UI in dogfooding; this small caption fixes that. */
  .chat-view-label {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
  }
  .chat-view-label-tx {
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-3);
    white-space: nowrap;
  }
  .chat-newbtn {
    appearance: none;
    border: 1px solid var(--border-default);
    background: var(--bg-2);
    color: var(--fg-1);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    border-radius: var(--radius-sm);
    padding: 3px var(--space-3);
    cursor: pointer;
    white-space: nowrap;
    transition:
      border-color var(--dur-soft) var(--ease-out),
      background var(--dur-soft) var(--ease-out);
  }
  .chat-newbtn:hover {
    border-color: var(--border-strong);
    background: var(--bg-3);
  }
  .chat-newbtn:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }

  /* Connection status strip */
  .chat-statusrow {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-4);
    border-bottom: 1px solid var(--border-subtle);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-2);
  }
  .chat-statusrow-sep {
    color: var(--fg-3);
  }
  .chat-statusrow-cc {
    color: var(--fg-1);
  }
  .chat-statusrow-spacer {
    flex: 1;
  }
  .chat-status-dot {
    width: 7px;
    height: 7px;
    border-radius: var(--radius-pill);
    background: var(--presence-offline);
  }
  .chat-status-dot--ready {
    background: var(--status-success);
  }
  .chat-status-dot--working {
    background: var(--presence-agent);
    animation: chat-pip 1s var(--ease-out) infinite;
  }
  @keyframes chat-pip {
    0%,
    100% {
      opacity: 1;
    }
    50% {
      opacity: 0.35;
    }
  }

  /* "Still working" indicator — inline under the latest message in the feed. */
  .chat-activity {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--presence-agent);
  }
  .chat-activity-spin {
    width: 10px;
    height: 10px;
    flex-shrink: 0;
    border: 1.5px solid var(--presence-agent);
    border-top-color: transparent;
    border-radius: var(--radius-pill);
    animation: chat-spin 0.7s linear infinite;
  }
  @keyframes chat-spin {
    to {
      transform: rotate(360deg);
    }
  }
  .chat-activity-text {
    font-weight: 600;
    color: var(--presence-agent);
  }
  /* Live elapsed counter — dimmer than the label; tabular so it doesn't jitter. */
  .chat-activity-elapsed {
    font-variant-numeric: tabular-nums;
    color: var(--fg-2);
    opacity: 0.8;
  }

  /* Feed (scrolls live) */
  .chat-feed {
    flex: 1;
    overflow-y: auto;
    padding: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
  }

  /* Empty state */
  .chat-empty {
    margin: auto 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-3);
    text-align: center;
    padding: var(--space-4) var(--space-2);
  }
  .chat-empty-mark {
    color: var(--accent-muted);
  }
  .chat-empty-title {
    font-size: var(--type-base);
    font-weight: 600;
    color: var(--fg-0);
  }
  .chat-empty-sub {
    font-size: var(--type-sm);
    color: var(--fg-2);
    line-height: var(--lh-sm);
    max-width: 240px;
  }
  /* One-time "Create new design system" CTA — the prominent accent button in the
     empty state (prefills /design:setup-ds). Sits above the muted suggestion list. */
  .chat-empty-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    width: 100%;
    margin-top: var(--space-2);
    font-family: var(--font-body);
    font-size: var(--type-sm);
    font-weight: 600;
    color: var(--accent-fg);
    background: var(--accent);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-4);
    cursor: pointer;
    transition:
      background var(--dur-soft) var(--ease-out),
      border-color var(--dur-soft) var(--ease-out);
  }
  .chat-empty-cta:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
  }
  .chat-empty-cta:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }
  .chat-empty-cta-ic {
    display: inline-flex;
    color: currentColor;
  }
  .chat-sugs {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    width: 100%;
    margin-top: var(--space-2);
  }
  .chat-sug {
    text-align: left;
    width: 100%;
    font-family: var(--font-body);
    font-size: var(--type-sm);
    color: var(--fg-1);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    cursor: pointer;
    transition:
      border-color var(--dur-soft) var(--ease-out),
      background var(--dur-soft) var(--ease-out);
  }
  .chat-sug:hover {
    border-color: var(--border-strong);
    background: var(--bg-3);
  }
  .chat-sug:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
  }

  /* Messages */
  .chat-msg {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    animation: chat-msg-in var(--dur-soft) var(--ease-out) both;
  }
  @keyframes chat-msg-in {
    from {
      opacity: 0;
      transform: translateY(4px);
    }
    to {
      opacity: 1;
      transform: none;
    }
  }
  .chat-msg-role {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--fg-2);
  }
  .chat-msg-spark {
    color: var(--presence-agent);
    display: inline-flex;
  }
  .chat-msg--user .chat-bubble {
    align-self: flex-start;
    max-width: 100%;
    font-size: var(--type-sm);
    color: var(--fg-0);
    background: var(--bg-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    padding: var(--space-3) var(--space-4);
    white-space: pre-wrap;
  }
  .chat-bubble code {
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--accent);
  }
  .chat-msg--assistant .chat-bubble {
    font-size: var(--type-sm);
    color: var(--fg-1);
    line-height: var(--lh-base);
  }

  /* Continuation bubble — background work (subagent results / consolidation)
     that streamed in after the turn's premature settle (RCA F2). A dashed rule
     marks it as a continuation of the message above, not a fresh reply. */
  .chat-msg--continued {
    border-top: 1px dashed var(--border-subtle);
    padding-top: var(--space-3);
  }

  /* Per-message hover actions (Task C2 — Copy / Retry). Absolutely positioned
     so it never reflows the bubble; hover- AND focus-revealed (keyboard users
     tab to the buttons, which triggers :focus-within even without a pointer). */
  .chat-msg-actions {
    position: absolute;
    top: calc(-1 * var(--space-2));
    right: 0;
    display: flex;
    gap: 2px;
    padding: 2px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--dur-fast, 120ms) ease;
  }
  .chat-msg:hover .chat-msg-actions,
  .chat-msg:focus-within .chat-msg-actions {
    opacity: 1;
    pointer-events: auto;
  }
  .chat-msg-action {
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--fg-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--radius-xs);
    cursor: pointer;
  }
  .chat-msg-action:hover {
    background: var(--bg-3);
    color: var(--fg-0);
  }
  .chat-msg-action:disabled {
    opacity: 0.4;
    cursor: default;
  }
  .chat-msg-action[data-copied='true'] {
    color: var(--status-success);
  }
  @media (prefers-reduced-motion: reduce) {
    .chat-msg-actions {
      transition: none;
    }
  }

  /* Rendered markdown inside the assistant bubble (chat-markdown.jsx) */
  .chat-msg--assistant .chat-bubble > * + * {
    margin-top: var(--space-2);
  }
  .chat-md-p {
    margin: 0;
    white-space: pre-wrap;
  }
  .chat-md-h {
    margin: 0;
    font-weight: 600;
    color: var(--fg-0);
  }
  .chat-md-list {
    margin: 0;
    padding-left: var(--space-4);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-md-list li {
    font-size: var(--type-sm);
  }
  .chat-code {
    margin: 0;
    padding: var(--space-3);
    background: var(--bg-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    overflow-x: auto;
  }
  .chat-md-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
  }
  .chat-md-table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--type-xs);
  }
  .chat-md-table th,
  .chat-md-table td {
    padding: var(--space-2) var(--space-3);
    text-align: left;
    border-bottom: 1px solid var(--border-subtle);
    white-space: pre-wrap;
  }
  .chat-md-table th {
    background: var(--bg-2);
    font-weight: 600;
    color: var(--fg-0);
  }
  .chat-md-table td {
    color: var(--fg-1);
  }
  .chat-md-table tbody tr:last-child td {
    border-bottom: none;
  }
  .chat-code code {
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-1);
    white-space: pre;
  }
  .chat-bubble strong {
    font-weight: 600;
    color: var(--fg-0);
  }
  .chat-bubble em {
    font-style: italic;
  }
  .chat-bubble a {
    color: var(--accent);
    text-decoration: underline;
  }

  /* Collapsed "Thinking" disclosure (extended-thinking / reasoning parts) */
  .chat-think {
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    overflow: hidden;
  }
  .chat-think-sum {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-2);
    cursor: pointer;
    user-select: none;
    list-style: none;
  }
  .chat-think-sum::-webkit-details-marker {
    display: none;
  }
  .chat-think-sum::after {
    content: '▸';
    margin-left: auto;
    transition: transform var(--dur-soft) var(--ease-out);
  }
  .chat-think[open] .chat-think-sum::after {
    transform: rotate(90deg);
  }
  .chat-think-spark {
    color: var(--presence-agent);
    display: inline-flex;
  }
  .chat-think[open] .chat-think-sum {
    border-bottom: 1px solid var(--border-subtle);
  }
  .chat-think-body {
    padding: var(--space-3);
    font-size: var(--type-xs);
    color: var(--fg-2);
    line-height: var(--lh-base);
  }
  .chat-think-body .chat-md-p {
    white-space: pre-wrap;
  }

  /* Collapsed consecutive-tool-call group (Task C1) — mirrors .chat-think's
     <details>/<summary> disclosure pattern exactly. */
  .chat-toolgroup {
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    overflow: hidden;
  }
  .chat-toolgroup-sum {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-1);
    cursor: pointer;
    user-select: none;
    list-style: none;
  }
  .chat-toolgroup-sum::-webkit-details-marker {
    display: none;
  }
  .chat-toolgroup-sum::after {
    content: '▸';
    margin-left: auto;
    color: var(--fg-3);
    transition: transform var(--dur-soft) var(--ease-out);
  }
  .chat-toolgroup[open] .chat-toolgroup-sum::after {
    transform: rotate(90deg);
  }
  .chat-toolgroup[open] .chat-toolgroup-sum {
    border-bottom: 1px solid var(--border-subtle);
  }
  .chat-toolgroup-body {
    display: flex;
    flex-direction: column;
  }
  /* Flat accordion row (Task C1 revision) — a bordered card-in-a-card per
     tool read as "divné" (weird) in dogfooding; a group's individual tool
     calls are now plain rows separated by a hairline, not their own
     `.chat-tool` card, so the whole group stays one lightweight shape. */
  .chat-tool-row {
    padding: var(--space-2) var(--space-3);
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-tool-row + .chat-tool-row {
    border-top: 1px solid var(--border-subtle);
  }
  .chat-tool-row-main {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-1);
  }
  .chat-tool-row-main b {
    color: var(--accent);
    font-weight: 600;
  }
  .chat-tool-row-status {
    margin-left: auto;
    color: var(--fg-3);
  }
  .chat-tool-row-status.del {
    color: var(--status-error);
  }

  /* Tool-call card (standalone — a lone tool call outside a group). */
  .chat-tool {
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    overflow: hidden;
  }
  .chat-tool-hd {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-1);
    border-bottom: 1px solid var(--border-subtle);
  }
  .chat-tool-hd b {
    color: var(--accent);
    font-weight: 600;
  }
  .chat-tool-path {
    color: var(--fg-2);
  }
  .chat-tool-dot {
    width: 6px;
    height: 6px;
    border-radius: var(--radius-pill);
    margin-left: auto;
  }
  .chat-tool-dot--run {
    background: var(--presence-agent);
    animation: chat-pip 1s var(--ease-out) infinite;
  }
  .chat-tool-dot--done {
    background: var(--status-success);
  }
  .chat-tool-body {
    padding: var(--space-3);
    display: grid;
    gap: var(--space-1);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
  }
  .chat-tool-line {
    display: flex;
    gap: var(--space-2);
    color: var(--fg-1);
  }
  .chat-tool-line.add {
    color: var(--status-success);
  }
  .chat-tool-line.del {
    color: var(--status-error);
  }
  /* Raw args/result preview — Verbose transcript view only (Task C4). */
  .chat-tool-detail {
    margin: 0;
    padding: var(--space-2);
    background: var(--bg-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs);
    color: var(--fg-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }

  /* Permission approve/deny card (Milestone B — retires DDR-125 F2's blanket
     auto-approve). Sits between the feed and the composer, one at a time. */
  .chat-perm {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0 var(--space-4);
    padding: var(--space-3);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
  }
  .chat-perm:focus-visible {
    outline: none;
  }
  .chat-perm-hd {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-1);
  }
  /* SECURITY (ethical-hacker finding) — the title is adapter/model-controlled
     (for Bash, it's the raw shell command) with no length bound; without a
     clamp a crafted/long command could push its dangerous tail off-screen in
     a card whose entire point is "you can see what you're approving". Clamps
     to one legible line; the full string is still reachable via the native
     title-attribute tooltip (see PermissionPrompt.jsx). */
  .chat-perm-hd b {
    display: block;
    min-width: 0;
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--accent);
    font-weight: 600;
  }
  .chat-perm-queue {
    flex-shrink: 0;
    color: var(--fg-3);
    font-weight: 400;
  }
  .chat-perm-body {
    margin: 0;
    font-size: var(--type-xs);
    color: var(--fg-2);
  }
  .chat-perm-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  /* feature-acp-write-path-scope Task 4 — the out-of-project WRITE variant.
     Distinguished from an ordinary permission card because the two ask
     materially different questions: the ordinary one is "do you want this
     tool to run", this one is "do you want a file written somewhere your
     project's history stack cannot roll back". The danger tint is the whole
     point — a card that looks identical to the routine one gets clicked
     through at the same rate. */
  .chat-perm--outside {
    border-color: var(--danger, #d9534f);
  }
  .chat-perm--outside .chat-perm-hd b {
    color: var(--danger, #d9534f);
  }
  .chat-perm-outside {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  /* The resolved absolute paths. Monospaced + wrapping at any character: these
     are the one string on the card the user actually has to READ, and a path
     that overflows or ellipsizes is a path whose dangerous tail is hidden —
     the same failure the .chat-perm-hd b clamp above exists to prevent, but
     with the opposite fix, because here truncation is what would be unsafe. */
  .chat-perm-paths {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-perm-path {
    padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-xs);
    background: var(--bg-1);
    color: var(--fg-0);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    overflow-wrap: anywhere;
  }
  .chat-perm-scope,
  .chat-perm-note {
    margin: 0;
    font-size: var(--type-xs);
    color: var(--fg-3);
  }
  .chat-perm-root {
    font-family: var(--font-mono);
    overflow-wrap: anywhere;
  }

  /* Form-elicitation card (feature-acp-ask-user-question — AskUserQuestion +
     generic MCP form input). Same slot + shape as .chat-perm, mutually
     exclusive with it — see the mount site in ChatPanel.jsx. */
  .chat-elicit {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    margin: 0 var(--space-4);
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--border-default);
    border-left: 2px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
  }
  .chat-elicit:focus-visible {
    outline: none;
  }
  .chat-elicit-hd {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-elicit-hd b {
    color: var(--fg-0);
    font-size: var(--type-sm);
    font-weight: 600;
    line-height: var(--lh-sm);
  }
  .chat-elicit-meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-3);
  }
  .chat-elicit-meta > span + span::before {
    content: '·';
    margin-right: var(--space-2);
  }
  .chat-elicit-question {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0;
    padding: 0;
    border: none;
  }
  .chat-elicit-question-hd {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: 0;
    font-size: var(--type-sm);
    color: var(--fg-0);
    line-height: var(--lh-sm);
  }
  .chat-elicit-question-chip {
    align-self: flex-start;
    padding: 2px var(--space-2);
    border-radius: var(--radius-pill);
    background: var(--bg-3);
    color: var(--accent);
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
  }
  .chat-elicit-options {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-elicit-option {
    display: flex;
    align-items: flex-start;
    gap: var(--space-2);
    font-size: var(--type-xs);
    color: var(--fg-1);
    cursor: pointer;
    accent-color: var(--accent);
  }
  /* "Other" rides in the radio group itself (single-select only — see
     ElicitationPrompt.jsx) rather than a separate link below it, so the
     either/or truth (one field, one answer) is visible for free through
     native radio-group exclusivity. Styled as a peer option, not a
     secondary action — no visual demotion, it's a real 4th choice. */
  .chat-elicit-option--other {
    color: var(--fg-2);
  }
  .chat-elicit-custom--inline {
    margin-left: calc(16px + var(--space-2)); /* aligns under the "Other" label, not the radio dot */
  }
  .chat-elicit-option-body {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-elicit-option-desc {
    color: var(--fg-2);
  }
  .chat-elicit-option-preview {
    margin: 0;
    padding: var(--space-1) var(--space-2);
    background: var(--bg-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs);
    color: var(--fg-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  .chat-elicit-text {
    width: 100%;
    padding: var(--space-1) var(--space-2);
    background: var(--bg-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs);
    color: var(--fg-0);
    font-size: var(--type-xs);
    font-family: inherit;
  }
  .chat-elicit-custom-toggle {
    align-self: flex-start;
    padding: 0;
    background: none;
    border: none;
    color: var(--accent);
    font-size: var(--type-xs);
    cursor: pointer;
    text-decoration: underline;
  }
  .chat-elicit-custom-wrap {
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
  }
  .chat-elicit-custom-note {
    margin: 0;
    color: var(--fg-2);
    font-size: var(--type-xs);
  }
  /* Credential-shaped question warning (ethical-hacker finding — see
     acp-elicitation.js's looksLikeSecretRequest). Border/left-accent carries
     the warning color; TEXT stays on --fg-1 rather than --status-warn
     directly — that token fails AA contrast at this size (bit the a11y
     review once already, per DDR-097's file-tree badge fix). */
  .chat-elicit-secret-warning {
    margin: 0;
    padding: var(--space-1) var(--space-2);
    border: 1px solid var(--status-warn);
    border-radius: var(--radius-xs);
    background: color-mix(in oklab, var(--status-warn) 12%, transparent);
    color: var(--fg-1);
    font-size: var(--type-xs);
  }
  /* SECURITY (ethical-hacker finding) — shown when a question reads as a
     credential ask; pairs with the masked input in ElicitationPrompt.jsx. */
  .chat-elicit-secret-warning {
    margin: 0;
    color: var(--warn, hsl(38 92% 50%));
    font-size: var(--type-xs);
  }
  .chat-elicit-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
  }
  .chat-elicit-actions-spacer {
    flex: 1 1 auto;
  }

  /* Connection-problem error card (Task C3) — transient bridge/socket failure,
     recoverable with a retry. Same slot as .chat-perm (mutually exclusive). */
  .chat-error-card {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin: 0 var(--space-4);
    padding: var(--space-3);
    border: 1px solid var(--status-error);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
  }
  .chat-error-hd {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--status-error);
  }
  .chat-error-detail {
    margin: 0;
    font-size: var(--type-xs);
    color: var(--fg-2);
  }
  .chat-error-detail--muted {
    color: var(--fg-3);
  }
  .chat-error-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
  }

  /* Usage (Milestone D) — context-window bar, rendered inside .chat-foot-popover. */
  .chat-usage-bar {
    display: inline-block;
    width: 32px;
    height: 4px;
    border-radius: var(--radius-pill);
    background: var(--bg-4, var(--bg-3));
    overflow: hidden;
    flex-shrink: 0;
  }
  .chat-usage-bar-fill {
    display: block;
    height: 100%;
    background: var(--accent);
    border-radius: var(--radius-pill);
  }
  /* Full-width variant for the .chat-foot-popover context section (the
     32px pill above is sized for an inline ambient indicator, not a form
     bar). */
  .chat-usage-bar--wide {
    display: block;
    width: 100%;
    height: 5px;
  }

  /* Event-driven single-window rate-limit banner — rendered INSIDE
     .chat-composer's own padding (unlike .chat-perm/.chat-error-card, which
     are siblings of the composer at the thread-root level), so no extra
     horizontal margin here. */
  .chat-usage-banner {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 0 var(--space-3);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    color: var(--fg-1);
    font-size: var(--type-xs);
  }
  .chat-usage-banner-x {
    margin-left: auto;
    flex-shrink: 0;
    appearance: none;
    border: 0;
    background: transparent;
    color: var(--fg-3);
    cursor: pointer;
    font-size: var(--type-sm);
    line-height: 1;
    padding: 0 var(--space-1);
  }
  .chat-usage-banner-x:hover {
    color: var(--fg-0);
  }

  /* Quick-action row */
  .chat-quick {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-4) 0;
  }
  .chat-qa {
    font-family: var(--font-mono);
  }
  /* Issue #74 — the "Implement N comments" action. Its siblings are literal
     slash commands (hence mono); this one is prose ABOUT the canvas's current
     state and only appears when there is something to act on, so it reads as
     the row's contextual action: proportional type + a light accent tint. */
  .chat-qa--comments {
    font-family: inherit;
    border-color: var(--accent-muted);
    color: var(--accent);
  }
  .chat-qa--comments:hover {
    background: var(--accent-tint);
  }

  /* Composer */
  .chat-composer {
    padding: var(--space-3) var(--space-4) var(--space-4);
    border-top: 1px solid var(--border-subtle);
    margin-top: var(--space-3);
  }
  .chat-ctx {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    margin-bottom: var(--space-3);
    font-size: var(--type-xs);
    color: var(--fg-2);
  }
  .chat-ctx b {
    color: var(--fg-1);
    font-weight: 600;
  }
  /* Context attachment chip (feature-acp-context-hardening) — the visible
     reveal of the frozen <maude-context> block; label + a remove ×. */
  .chat-ctx-label {
    display: inline-block;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding: 2px var(--space-2);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    color: var(--fg-1);
  }
  .chat-ctx--stale .chat-ctx-label {
    border-color: var(--warn, hsl(38 92% 50%));
    color: var(--warn, hsl(38 92% 50%));
  }
  .chat-ctx-x {
    flex: none;
    padding: 0 var(--space-1);
    border: 0;
    background: none;
    color: var(--fg-2);
    font-size: var(--type-sm);
    line-height: 1;
    cursor: pointer;
  }
  .chat-ctx-x:hover {
    color: var(--fg-0);
  }

  /* Composer box — textarea on top, a bottom toolbar (model · effort · send),
     Zed-style. One border + focus ring around the whole box. */
  .chat-box {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--bg-3);
    overflow: hidden;
    transition:
      border-color var(--dur-soft) var(--ease-out),
      box-shadow var(--dur-soft) var(--ease-out);
  }
  .chat-box:focus-within {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }
  .chat-input {
    appearance: none;
    border: none;
    background: transparent;
    resize: none;
    width: 100%;
    min-height: 54px;
    padding: var(--space-3) var(--space-4);
    font-family: var(--font-body);
    font-size: var(--type-sm);
    color: var(--fg-0);
    outline: none;
  }
  .chat-input::placeholder {
    color: var(--fg-3);
  }
  .chat-toolbar {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-2);
  }
  .chat-toolbar-spacer {
    flex: 1;
  }
  /* Model/effort/mode picker row (feature-acp-panel-dynamic-claude-code-
     capabilities) — a flex row of .chat-select dropdowns inside .chat-toolbar. */
  .chat-caps {
    display: flex;
    align-items: center;
    gap: var(--space-1);
    flex-wrap: wrap;
  }
  .chat-caps--connecting {
    font-family: var(--font-body);
    font-size: var(--type-xs);
    color: var(--fg-3);
    padding: 2px var(--space-2);
  }
  /* Compact toolbar dropdowns — borderless, hover-revealed (Zed-style).
     Without `field-sizing`, a closed <select> sizes itself to its WIDEST
     option (not the one it's currently showing) — Model ends up as wide as
     its longest model name even while displaying "Sonnet". That's what made
     2-3 short picks unable to share a row in a narrow panel — each one was
     wider than it looked and forced onto its own wrapped line. `field-sizing:
     content` sizes it to what's actually shown instead; it degrades
     harmlessly where unsupported (the max-width + ellipsis below is that
     fallback net), and `flex-shrink: 0` keeps the (now much smaller) content
     width from being squeezed further by the toolbar row. */
  .chat-select {
    appearance: none;
    font-family: var(--font-body);
    font-size: var(--type-xs);
    color: var(--fg-2);
    background: transparent;
    border: 1px solid transparent;
    border-radius: var(--radius-xs);
    padding: 2px var(--space-2);
    cursor: pointer;
    flex-shrink: 0;
    field-sizing: content;
    min-width: 44px;
    max-width: 140px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition:
      border-color var(--dur-soft) var(--ease-out),
      background var(--dur-soft) var(--ease-out),
      color var(--dur-soft) var(--ease-out);
  }
  .chat-select:hover {
    border-color: var(--border-default);
    background: var(--bg-2);
    color: var(--fg-1);
  }
  .chat-select:focus-visible {
    outline: none;
    border-color: var(--accent);
  }
  .chat-send {
    width: 28px;
    height: 28px;
    padding: 0;
    border: none;
    border-radius: var(--radius-sm);
    background: var(--accent);
    color: var(--accent-fg);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    cursor: pointer;
    transition: background var(--dur-soft) var(--ease-out);
  }
  .chat-send:hover {
    background: var(--accent-hover);
  }
  .chat-send:disabled {
    opacity: 0.45;
    cursor: default;
  }
  /* Attachment reveal strip — shows what each paste chip expands to BEFORE send,
     so a collapsed [file-1]/[link-1]/[image-N] can never carry a value the user
     can't see into the auto-approving agent (DDR-140 / security-review mitigation). */
  .chat-attach {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: var(--space-2);
  }
  .chat-attach-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    min-width: 0;
    font-size: var(--type-xs);
  }
  .chat-attach-tok {
    flex-shrink: 0;
    font-family: var(--font-mono);
    color: var(--fg-1);
    background: var(--bg-4, var(--bg-3));
    border-radius: var(--radius-xs);
    padding: 0 4px;
  }
  .chat-attach-arrow {
    flex-shrink: 0;
    color: var(--fg-3);
  }
  .chat-attach-val {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--fg-2);
    font-family: var(--font-mono);
  }
  .chat-foot-spacer {
    flex: 1;
  }
  /* Composer footer info (Milestone D, revised twice after dogfooding — the
     keyboard hint + context gauge + mode footnote + subscription note first
     collapsed behind an icon on its own row, then that icon moved INTO
     .chat-toolbar next to Send so it costs no extra vertical space). The
     popover is grouped into labeled sections (context / cost / mode /
     meta) with dividers, rather than a flat stack of unrelated lines. */
  .chat-foot-info {
    position: relative;
    display: inline-flex;
  }
  .chat-foot-info-btn {
    appearance: none;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--fg-3);
    font-size: var(--type-sm);
    line-height: 1;
    padding: 2px var(--space-1);
    border-radius: var(--radius-xs);
  }
  .chat-foot-info-btn:hover,
  .chat-foot-info-btn[aria-expanded='true'] {
    color: var(--fg-1);
    background: var(--bg-3);
  }
  .chat-foot-info-btn:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }
  /* `position: fixed` (not absolute) — `.chat-foot-info` sits inside
     `.chat-box`, which clips its content with `overflow: hidden` for the
     composer's rounded-corner focus ring. An absolutely-positioned popover
     anchored there got clipped to that box instead of floating above the
     whole composer. `bottom`/`right` are computed from the button's own
     rect and set inline (see ChatFootInfo in ChatPanel.jsx). */
  .chat-foot-popover {
    position: fixed;
    z-index: 52;
    display: flex;
    flex-direction: column;
    min-width: 240px;
    padding: var(--space-3);
    background: var(--bg-2);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-2);
  }
  .chat-foot-popover-section {
    display: flex;
    flex-direction: column;
    gap: 6px;
  }
  .chat-foot-popover-sep {
    height: 1px;
    background: var(--border-subtle);
    margin: var(--space-2) calc(var(--space-3) * -1);
  }
  .chat-foot-popover-label-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    color: var(--fg-0);
    font-weight: 600;
  }
  .chat-foot-popover-row--muted {
    color: var(--fg-3);
  }
  .chat-foot-popover-foot {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }

  /* ── Slash-command autocomplete + inline highlight ────────────────────────
     The composer becomes command-aware: typing "/" opens `.chat-cmd-menu`
     (populated from the static list ∪ the live ACP catalogue), and a recognized
     command renders as a `.chat-cmd-pill` INSIDE the input via a mirror overlay. */

  /* Relative anchor so the popover floats above the composer box. */
  .chat-cmd-anchor {
    position: relative;
  }

  /* Mirror-overlay: a text layer behind a transparent-text textarea. The mirror
     is the visible text; the textarea owns the caret + input. Their box models
     MUST stay identical (padding / font / line-height / wrap) or the pill drifts. */
  .chat-input-wrap {
    position: relative;
    display: block;
  }
  .chat-input-mirror {
    position: absolute;
    inset: 0;
    z-index: 0;
    padding: var(--space-3) var(--space-4);
    font-family: var(--font-body);
    font-size: var(--type-sm);
    line-height: var(--lh-base);
    letter-spacing: 0;
    color: var(--fg-0);
    white-space: pre-wrap;
    overflow-wrap: break-word;
    word-break: break-word;
    overflow: hidden;
    pointer-events: none;
  }
  .chat-input--overlay {
    position: relative;
    z-index: 1;
    line-height: var(--lh-base);
    letter-spacing: 0;
    color: transparent;
    caret-color: var(--fg-0);
    background: transparent;
  }
  /* The recognized-command pill. NO padding/margin/letter-spacing — those would
     change glyph advance and desync the mirror from the textarea caret. The 2px
     box-shadow fakes padding without touching layout. */
  .chat-cmd-pill {
    background: var(--accent-tint);
    color: var(--accent);
    border-radius: var(--radius-xs);
    box-shadow: 0 0 0 2px var(--accent-tint);
  }

  /* Pasted-path / URL chip ([image-1] / [file-1] / [link-1]). Same zero-advance
     discipline as .chat-cmd-pill (no padding/margin/letter-spacing → the mirror
     stays glyph-aligned with the textarea caret). Neutral tint so it reads as an
     attachment badge, distinct from the accent command pill. Reused verbatim in
     the sent-message bubble, where the box-shadow padding is harmless. */
  .chat-paste-chip {
    background: var(--bg-4, var(--bg-3));
    color: var(--fg-1);
    border-radius: var(--radius-xs);
    box-shadow: 0 0 0 2px var(--bg-4, var(--bg-3));
  }
  .chat-msg--user .chat-paste-chip {
    color: var(--accent);
  }

  /* Autocomplete popover — opens upward (composer sits at the panel bottom). */
  .chat-cmd-menu {
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + var(--space-2));
    z-index: 20;
    max-height: 280px;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: var(--space-1);
    background: var(--bg-2);
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-lg);
  }
  .chat-cmd-item {
    display: flex;
    align-items: baseline;
    gap: var(--space-2);
    width: 100%;
    text-align: left;
    appearance: none;
    border: 0;
    background: transparent;
    border-radius: var(--radius-xs);
    padding: var(--space-2) var(--space-3);
    cursor: pointer;
    color: var(--fg-1);
  }
  .chat-cmd-item:hover,
  .chat-cmd-item.is-active {
    background: var(--bg-3);
  }
  .chat-cmd-name {
    flex-shrink: 0;
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--accent);
  }
  .chat-cmd-name--flow {
    color: var(--presence-agent);
  }
  .chat-cmd-desc {
    flex: 1;
    min-width: 0;
    font-size: var(--type-xs);
    color: var(--fg-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .chat-cmd-arg {
    flex-shrink: 0;
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-3);
  }

  /* Streaming → Stop bar */
  .chat-stopbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
  }
  .chat-stop-meta {
    font-size: var(--type-xs);
    color: var(--fg-2);
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
  }

  /* Not-connected explainer */
  .chat-disabled {
    margin: auto 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    padding: var(--space-4);
  }
  .chat-disabled-mark {
    color: var(--fg-3);
    align-self: center;
  }
  .chat-disabled-title {
    font-size: var(--type-base);
    font-weight: 600;
    color: var(--fg-0);
    text-align: center;
  }
  .chat-disabled-sub {
    font-size: var(--type-sm);
    color: var(--fg-2);
    line-height: var(--lh-base);
    text-align: center;
  }
  .chat-disabled-sub code {
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-0);
    background: var(--bg-3);
    padding: 1px 5px;
    border-radius: var(--radius-xs);
  }
  .chat-trust {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3);
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
  }
  .chat-trust-row {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--type-xs);
    color: var(--fg-2);
  }
  .chat-trust-row svg {
    color: var(--status-success);
    flex-shrink: 0;
  }

  /* Pasted-image thumbnail — a focusable button in the user bubble; clicking
     opens the lightbox. Sized like a chip row, never dominating the bubble. */
  .chat-thumb-btn {
    appearance: none;
    display: inline-block;
    padding: 0;
    margin: 2px 0;
    border: 0;
    background: transparent;
    border-radius: var(--radius-sm);
    cursor: zoom-in;
    line-height: 0;
    vertical-align: middle;
  }
  .chat-thumb {
    display: block;
    max-width: 180px;
    max-height: 140px;
    object-fit: cover;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    transition: border-color var(--dur-fast, 120ms) ease;
  }
  .chat-thumb-btn:hover .chat-thumb {
    border-color: var(--border-strong);
  }
  .chat-thumb-btn:focus-visible {
    outline: none;
  }
  .chat-thumb-btn:focus-visible .chat-thumb {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }

  /* Thumbnail strip under an assistant bubble — every designRoot image path the
     agent mentioned (DDR-145), previewed without leaving the chat. */
  .chat-thumbrow {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin-top: var(--space-2);
  }
  /* A REFERENCED image (assistant merely named the path) — captioned with its
     filename so it reads as "a file that was referenced", not first-class agent
     media (attacker F2, DDR-145). */
  .chat-thumb-fig {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-width: 180px;
  }
  .chat-thumb-cap {
    font-family: var(--font-mono);
    font-size: var(--type-xs);
    color: var(--fg-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* Lightbox — single fixed overlay above the whole shell (ESC / backdrop / ×).
     Scrim mixes the base background so it tracks light/dark themes. z sits above
     the shell modal band (.gi-modal 9600) but below the tour/topmost layer
     (10050+) — an enlarged image must never bury the guided tour. */
  .chat-lightbox {
    position: fixed;
    inset: 0;
    z-index: 9700;
    display: grid;
    place-items: center;
    background: color-mix(in oklch, var(--bg-0) 80%, transparent);
    animation: chat-lightbox-in 120ms ease;
  }
  .chat-lightbox img {
    max-width: 90vw;
    max-height: 90vh;
    object-fit: contain;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--bg-1);
    box-shadow: var(--shadow-lg);
  }
  .chat-lightbox-close {
    position: absolute;
    top: var(--space-4);
    right: var(--space-4);
    appearance: none;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    color: var(--fg-1);
    font-size: var(--type-base);
    line-height: 1;
    cursor: pointer;
  }
  .chat-lightbox-close:hover {
    color: var(--fg-0);
    background: var(--bg-3);
  }
  .chat-lightbox-close:focus-visible {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-tint);
  }
  @keyframes chat-lightbox-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .chat-status-dot--working,
    .chat-tool-dot--run,
    .chat-activity-spin,
    .st-assistant[data-busy='true'],
    .chat-dot--busy,
    .chat-msg,
    .chat-lightbox {
      animation: none;
    }
    .chat-thumb {
      transition: none;
    }
  }
}

/* DDR-128 — AI-editing readiness list (ReadinessList.jsx). Shared by the onboarding
   readiness strip and the ChatPanel not-connected explainer. Detect-and-guide:
   present rows reassure, missing rows carry a copy-paste fix, optional rows stay
   muted (never alarming). */
@layer components {
  .rdy { display: flex; flex-direction: column; gap: var(--space-3); }
  .rdy-list {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: var(--space-2);
  }
  .rdy-row {
    display: flex; gap: var(--space-2); align-items: flex-start;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    background: var(--bg-2); text-align: left;
  }
  .rdy-ic { flex-shrink: 0; margin-top: 1px; }
  .rdy-row--present .rdy-ic { color: var(--status-success); }
  .rdy-row--missing .rdy-ic { color: var(--status-error); }
  .rdy-row--unknown .rdy-ic { color: var(--status-info); }
  /* optional, missing → muted, not alarming */
  .rdy-row--opt.rdy-row--missing .rdy-ic { color: var(--fg-3); }
  .rdy-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .rdy-label { font-size: var(--type-sm); font-weight: 600; color: var(--fg-0); }
  .rdy-detail { font-size: var(--type-xs); color: var(--fg-2); line-height: var(--lh-xs); }
  .rdy-fix {
    margin-top: var(--space-2); display: flex; gap: var(--space-2);
    align-items: flex-start;
    font-size: var(--type-xs); color: var(--fg-1); line-height: var(--lh-xs);
  }
  .rdy-fix-tx { min-width: 0; }
  .rdy code {
    font-family: var(--font-mono); font-size: var(--type-xs);
    color: var(--fg-0); background: var(--bg-3);
    padding: 1px 5px; border-radius: var(--radius-xs);
    overflow-wrap: anywhere;
  }
  .rdy-copy {
    flex-shrink: 0; cursor: pointer;
    font-size: var(--type-xs); color: var(--fg-2);
    background: transparent; border: 1px solid var(--border-subtle);
    border-radius: var(--radius-xs); padding: 1px 6px;
  }
  .rdy-copy:hover { color: var(--fg-0); background: var(--bg-3); }
  .rdy-foot { display: flex; justify-content: flex-end; }
  /* DDR-166 T0c/T0d — verbatim install command + Sign-in action rows. */
  .rdy-cmd {
    margin-top: var(--space-2); display: flex; gap: var(--space-2);
    align-items: center; flex-wrap: wrap;
  }
  .rdy-cmd-tx {
    font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-0);
    background: var(--bg-3); padding: var(--space-1) var(--space-2);
    border-radius: var(--radius-xs); overflow-wrap: anywhere; flex: 1 1 auto;
  }
  .rdy-fix-tx--err { color: var(--status-error); }
  .rdy-fallback-label { display: block; margin-top: var(--space-2); color: var(--fg-3); }
  /* DDR-166 Decision 3 — the resolved-binary disclosure shown before Sign-in. */
  .rdy-resolved-path { display: block; margin-top: var(--space-2); color: var(--fg-3); word-break: break-all; }
  .rdy-resolved-path code { font-family: var(--font-mono); color: var(--fg-1); }
  .rdy-signin {
    flex-shrink: 0; cursor: pointer;
    font-size: var(--type-xs); font-weight: 600; color: var(--bg-0);
    background: var(--accent); border: 1px solid var(--accent);
    border-radius: var(--radius-xs); padding: 3px 10px;
  }
  .rdy-signin:hover { filter: brightness(1.08); }
  /* Help ▸ Check AI editing readiness… modal (reuses .help-modal chrome). */
  .rdy-modal { max-width: 520px; }
  .rdy-modal-note { margin: 0 0 var(--space-3); color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
  /* DDR-166 Decision 5 — auto-setup opt-out, mirrors .ob-crash-optin. */
  .rdy-autosetup-toggle { display: flex; align-items: flex-start; gap: var(--space-2); margin-top: var(--space-3); color: var(--fg-2); font-size: var(--type-xs); line-height: var(--lh-md); cursor: pointer; text-align: left; }
  .rdy-autosetup-toggle input { margin-top: 2px; flex: 0 0 auto; accent-color: var(--accent); cursor: pointer; }
}

/* DDR-166 plan, Phase 2 (T7/T8) — design-setup checklist (SetupChecklist.jsx).
   Mirrors .rdy-* above (same present/missing two-state shape, no remediation
   copy — this probe never offers an automated fix, just progress). */
@layer components {
  .setup-cl { display: flex; flex-direction: column; gap: var(--space-3); }
  .setup-cl-list {
    list-style: none; margin: 0; padding: 0;
    display: flex; flex-direction: column; gap: var(--space-2);
  }
  .setup-cl-row {
    display: flex; gap: var(--space-2); align-items: flex-start;
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
    background: var(--bg-2); text-align: left;
  }
  .setup-cl-ic { flex-shrink: 0; margin-top: 1px; }
  .setup-cl-row--present .setup-cl-ic { color: var(--status-success); }
  .setup-cl-row--missing .setup-cl-ic { color: var(--fg-3); }
  .setup-cl-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .setup-cl-label { font-size: var(--type-sm); font-weight: 600; color: var(--fg-0); }
  .setup-cl-detail { font-size: var(--type-xs); color: var(--fg-2); line-height: var(--lh-xs); }
  .setup-cl-foot { display: flex; justify-content: flex-end; gap: var(--space-2); flex-wrap: wrap; }
  .setup-cl-brand { text-decoration: none; }
  .setup-cl-modal { max-width: 520px; }
  .setup-cl-note { margin: 0 0 var(--space-3); color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
}

/* T12 (DDR-173) — the in-app Brand-upload panel (BrandUploadPanel.jsx).
   Reuses .help-modal-* chrome; new rules cover the pick/result content only. */
@layer components {
  .brand-up-modal { max-width: 480px; }
  .brand-up-note { margin: 0 0 var(--space-4); color: var(--fg-2); font-size: var(--type-sm); line-height: var(--lh-md); }
  .brand-up-pick { display: flex; justify-content: center; padding: var(--space-5) 0; }
  .brand-up-error { margin: var(--space-2) 0 0; color: var(--status-error); font-size: var(--type-sm); }
  .brand-up-empty { margin: 0; color: var(--fg-3); font-size: var(--type-xs); line-height: var(--lh-sm); }
  .brand-up-preview {
    display: block; max-width: 100%; max-height: 120px; margin: 0 auto var(--space-4);
    border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); background: var(--bg-3);
    padding: var(--space-3);
  }
  .brand-up-sechd {
    margin: var(--space-4) 0 var(--space-2); font-size: var(--type-xs); font-weight: 600;
    text-transform: uppercase; letter-spacing: var(--tracking-wide); color: var(--fg-2);
  }
  .brand-up-swatches { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .brand-up-swatch { display: flex; align-items: center; gap: var(--space-2); }
  .brand-up-swatch-chip {
    display: inline-block; width: 20px; height: 20px; border-radius: var(--radius-xs);
    border: 1px solid var(--border-default);
  }
  .brand-up-swatch-value { font-family: var(--font-mono); font-size: var(--type-xs); color: var(--fg-2); }
  .brand-up-fonts { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .brand-up-font-chip {
    padding: 2px var(--space-2); border-radius: var(--radius-pill); border: 1px solid var(--border-default);
    background: var(--bg-2); font-size: var(--type-xs); color: var(--fg-1);
  }
  .brand-up-nextstep { margin: var(--space-4) 0 0; font-size: var(--type-sm); color: var(--fg-1); line-height: var(--lh-md); }
  .brand-up-nextstep code { font-family: var(--font-mono); background: var(--bg-3); padding: 1px 4px; border-radius: var(--radius-xs); }
  .brand-up-actions { display: flex; gap: var(--space-2); margin-top: var(--space-3); }

  /* DDR-184 #3 — loud top-of-thread alert while the current mode can't edit
     (Plan / Don't-Ask). Warn-toned so it reads as "you're blocked", distinct
     from the neutral usage banner. One-click hop back to an editing mode. */
  .chat-mode-banner {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    margin: 0 var(--space-4) var(--space-2);
    padding: var(--space-2) var(--space-3);
    border: 1px solid var(--warn, hsl(38 92% 50%));
    border-radius: var(--radius-sm);
    background: var(--bg-2);
    color: var(--fg-1);
    font-size: var(--type-xs);
    line-height: var(--lh-md);
  }
  .chat-mode-banner-icon {
    flex-shrink: 0;
    color: var(--warn, hsl(38 92% 50%));
  }
  .chat-mode-banner-text {
    flex: 1 1 auto;
  }
  .chat-mode-banner-text b {
    color: var(--fg-0);
  }
  .chat-mode-banner-cta {
    flex-shrink: 0;
    appearance: none;
    cursor: pointer;
    border: 1px solid var(--border-default);
    border-radius: var(--radius-xs);
    background: var(--bg-3);
    color: var(--fg-0);
    font-size: var(--type-xs);
    padding: 2px var(--space-2);
  }
  .chat-mode-banner-cta:hover {
    background: var(--bg-4);
  }
}
