agentgui 1.0.960 → 1.0.961

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -442,7 +442,7 @@
442
442
  -webkit-font-smoothing: antialiased;
443
443
  text-rendering: optimizeLegibility;
444
444
  }
445
- .ds-247420 ::selection { background: var(--mascot); color: var(--ink); }
445
+ .ds-247420 ::selection { background: color-mix(in oklab, var(--accent) 24%, var(--bg-2)); color: var(--fg); }
446
446
 
447
447
  /* Every root has a CQ container so fluid type can resolve to a meaningful inline-size. */
448
448
  .ds-247420 .app, .ds-247420[class*="kit-"], .ds-247420 .ds-stage {
@@ -555,6 +555,9 @@
555
555
  ============================================================ */
556
556
  .ds-247420 .app {
557
557
  display: flex; flex-direction: column;
558
+ /* Offset parent for the sidebar drawer/scrim/toggle, which are absolute so
559
+ they overlay THIS shell (a thebird WM window) rather than the viewport. */
560
+ position: relative;
558
561
  min-height: 100vh;
559
562
  /* Definite height so the flex column resolves height:100% for descendants
560
563
  (e.g. a full-height chat) at every breakpoint, not just where a desktop
@@ -932,41 +935,61 @@
932
935
  grid-template-columns: minmax(80px, 12ch) minmax(0, 1fr) auto;
933
936
  gap: var(--space-3);
934
937
  align-items: baseline;
935
- padding: 18px 22px;
938
+ padding: 16px 22px;
936
939
  background: var(--bg);
937
940
  border-radius: var(--r-2);
938
941
  color: var(--fg);
939
942
  position: relative;
940
- transition: background var(--dur-snap) var(--ease), padding var(--dur-base) var(--ease);
943
+ /* Only background + the leading rail animate; padding/size never change on
944
+ interaction, so they are deliberately absent (a padding transition here was
945
+ dead and misleading). */
946
+ transition: background var(--dur-snap) var(--ease);
941
947
  }
942
- .ds-247420 .row + .row { margin-top: 4px; }
948
+ .ds-247420 .row + .row { margin-top: 2px; }
943
949
  .ds-247420 .row::before {
944
950
  content: '';
945
- position: absolute; left: 6px; top: 22%; bottom: 22%; width: 3px;
946
- background: transparent; border-radius: 3px;
947
- transition: background var(--dur-snap) var(--ease);
951
+ position: absolute; left: 7px; top: 0; bottom: 0; width: 3px;
952
+ margin: auto 0;
953
+ height: 0; /* collapsed by default; reveals from centre */
954
+ background: var(--rule-strong);
955
+ border-radius: var(--r-pill);
956
+ opacity: 0;
957
+ transition: height var(--dur-base) var(--ease), opacity var(--dur-snap) var(--ease), background var(--dur-snap) var(--ease);
948
958
  }
949
959
  /* A clickable row (onClick -> role=button, or a link row) is interactive, so it
950
960
  carries a pointer cursor; without this the click affordance is invisible. */
951
961
  .ds-247420 .row[role="button"], .ds-247420 a.row { cursor: pointer; }
952
- .ds-247420 .row:hover { background: var(--bg-2); }
953
- .ds-247420 .row:hover::before { background: var(--rule-strong); }
962
+ /* Hover reveals the rail (grows from centre) only on interactive rows — a static
963
+ row should not signal an affordance it does not have. */
964
+ .ds-247420 .row[role="button"]:hover, .ds-247420 a.row:hover { background: var(--bg-2); }
965
+ .ds-247420 .row[role="button"]:hover::before, .ds-247420 a.row:hover::before { height: 56%; opacity: 1; }
954
966
  .ds-247420 .row.active { background: color-mix(in oklab, var(--accent) 10%, var(--bg-2)); }
955
- .ds-247420 .row.active::before { background: var(--accent); }
967
+ .ds-247420 .row.active::before { height: 64%; opacity: 1; background: var(--accent); }
968
+ .ds-247420 .row.active .title { color: var(--accent); }
956
969
  .ds-247420 .row.row-state-disabled { opacity: 0.5; pointer-events: none; }
957
970
  .ds-247420 .row.row-state-error { background: color-mix(in oklab, var(--flame) 10%, var(--bg-2)); }
958
- .ds-247420 .row.row-state-error::before { background: var(--flame); }
971
+ .ds-247420 .row.row-state-error::before { height: 64%; opacity: 1; background: var(--flame); }
959
972
  /* rail tones — a persistent status colour on the leading rail (the ::before
960
- bar). Active/hover/error still win via their own rules below source order. */
973
+ bar). Always shown (a status indicator, not a hover affordance). Active/error
974
+ still win via their own rules below in source order. */
975
+ .ds-247420 .row.rail-green::before,
976
+ .ds-247420 .row.rail-purple::before,
977
+ .ds-247420 .row.rail-flame::before { height: 56%; opacity: 1; }
961
978
  .ds-247420 .row.rail-green::before { background: var(--accent); }
962
979
  .ds-247420 .row.rail-purple::before { background: var(--purple-2, #7F18A4); }
963
980
  .ds-247420 .row.rail-flame::before { background: var(--flame); }
964
981
  .ds-247420 .row-grid { /* explicit grid-template-columns set inline */ }
982
+ /* A row with no leading code/index drops the empty first column so the title
983
+ takes the full width instead of wrapping in the narrow code gutter. */
984
+ .ds-247420 .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
965
985
 
966
- .ds-247420 .row .code { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
967
- .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
986
+ .ds-247420 .row .code { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
987
+ .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); line-height: var(--lh-snug, 1.3); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
988
+ .ds-247420 .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
968
989
  .ds-247420 .row .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
969
- .ds-247420 .row .meta { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-align: right; }
990
+ .ds-247420 .row .meta { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; align-self: center; }
991
+ /* WorksList meta pairs a label with a disclosure chevron, inline-aligned. */
992
+ .ds-247420 .ds-works-meta { display: inline-flex; align-items: center; gap: .4em; }
970
993
 
971
994
  .ds-247420 a.row { text-decoration: none; }
972
995
 
@@ -2318,36 +2341,43 @@
2318
2341
  .ds-247420 .chat-msg:nth-child(n+4) { animation-delay: 0.15s; }
2319
2342
  }
2320
2343
 
2344
+ /* Calm composer (claude.ai/code): ONE bordered rounded-rect shell holding the
2345
+ context line, a borderless textarea, the hint, and an inline send button -
2346
+ not a stadium pill + a floating round send. The shell carries the border and
2347
+ the focus ring; the textarea fills it transparently. flex-wrap lets the
2348
+ context line and hint occupy their own rows above/below the input row. */
2321
2349
  .ds-247420 .chat-composer {
2322
- display: flex; align-items: flex-end; gap: 8px;
2323
- padding: var(--space-3) 0 0;
2324
- border-top: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
2350
+ display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--space-2);
2351
+ padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
2352
+ background: var(--bg);
2353
+ border: var(--bw-hair) solid var(--rule);
2354
+ border-radius: var(--r-2);
2325
2355
  flex-shrink: 0;
2356
+ transition: border-color var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease);
2357
+ }
2358
+ .ds-247420 .chat-composer:focus-within {
2359
+ border-color: var(--accent);
2360
+ box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent);
2326
2361
  }
2327
2362
  .ds-247420 .chat-composer textarea {
2328
- flex: 1; padding: 12px 16px;
2329
- background: var(--bg-2); color: var(--fg);
2330
- border: 1px solid transparent; border-radius: var(--r-pill);
2363
+ flex: 1; min-width: 0; padding: 8px 4px;
2364
+ background: none; color: var(--fg);
2365
+ border: none; border-radius: 0;
2331
2366
  font-family: inherit; font-size: var(--fs-sm);
2332
- line-height: 1.4; resize: none;
2333
- min-height: 44px; max-height: 200px;
2367
+ line-height: 1.45; resize: none;
2368
+ min-height: 28px; max-height: 200px;
2334
2369
  box-sizing: border-box; overflow-y: auto;
2335
2370
  scrollbar-width: thin;
2336
2371
  }
2337
2372
  .ds-247420 .chat-composer textarea::placeholder { color: var(--fg-3); }
2338
- .ds-247420 .chat-composer textarea:focus {
2339
- background: var(--bg-2);
2340
- border-color: var(--accent);
2341
- box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 20%, transparent);
2342
- outline: none;
2343
- }
2373
+ .ds-247420 .chat-composer textarea:focus { background: none; border: none; box-shadow: none; outline: none; }
2344
2374
  .ds-247420 .chat-composer .send {
2345
- width: 44px; height: 44px; border-radius: 50%;
2375
+ width: 36px; height: 36px; border-radius: var(--r-1);
2346
2376
  background: var(--accent); color: var(--accent-fg);
2347
2377
  border: 0; cursor: pointer;
2348
2378
  display: inline-flex; align-items: center; justify-content: center;
2349
2379
  flex-shrink: 0;
2350
- transition: background var(--dur-snap, .15s) var(--ease, ease), transform .1s ease;
2380
+ transition: background var(--dur-snap, .15s) var(--ease, ease);
2351
2381
  }
2352
2382
  .ds-247420 .chat-composer .send:disabled { opacity: .5; cursor: not-allowed; }
2353
2383
  /* Ghost icon buttons in the toolbar (attach / emoji / more) — NOT the round
@@ -2361,8 +2391,8 @@
2361
2391
  transition: background var(--dur-snap, .15s) var(--ease, ease), color var(--dur-snap, .15s) var(--ease, ease);
2362
2392
  }
2363
2393
  .ds-247420 .composer-btn:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
2364
- .ds-247420 .chat-composer .send:hover { transform: scale(1.04); }
2365
- .ds-247420 .chat-composer .send:active { transform: scale(0.96); }
2394
+ .ds-247420 .chat-composer .send:hover { filter: brightness(1.08); }
2395
+ .ds-247420 .chat-composer .send:active { filter: brightness(0.94); }
2366
2396
  .ds-247420 .chat-composer .send:focus-visible,
2367
2397
  .ds-247420 .composer-btn:focus-visible {
2368
2398
  outline: 2px solid var(--accent);
@@ -2472,6 +2502,12 @@
2472
2502
  from { transform: rotate(0deg); }
2473
2503
  to { transform: rotate(360deg); }
2474
2504
  }
2505
+ /* Reusable spin utility: rotates the element (e.g. a refresh Icon used as a
2506
+ busy indicator) via the shared spinner-rotate keyframe. Respects reduced
2507
+ motion. Use instead of a decorative rotation glyph. */
2508
+ .ds-247420 .ds-spin { animation: spinner-rotate 0.8s linear infinite; transform-origin: center; }
2509
+ @media (prefers-reduced-motion: reduce) { .ds-247420 .ds-spin { animation: none; } }
2510
+
2475
2511
  .ds-247420 .loading { position: relative; }
2476
2512
  .ds-247420 .loading::after {
2477
2513
  content: '';
@@ -3054,14 +3090,20 @@
3054
3090
  ============================================================ */
3055
3091
 
3056
3092
  /* Tablet + Mobile: side rail becomes off-canvas drawer (≤900px) */
3057
- @media (max-width: 900px) {
3093
+ /* Sidebar drawer collapse keys on the SHELL width (@container on .app, which is
3094
+ container-type:inline-size) — NOT the viewport. Full-page (freddie) the shell
3095
+ == viewport so this is identical to the old @media(max-width:900px); embedded
3096
+ in a thebird WM window the drawer + hamburger appear when the WINDOW is narrow
3097
+ even on a wide desktop. Drawer/scrim/toggle are absolute (anchored to .app), so
3098
+ they overlay the window, not the page. */
3099
+ @container (max-width: 900px) {
3058
3100
  .ds-247420 .app-body,
3059
3101
  .ds-247420 .app-body.no-side { grid-template-columns: 1fr !important; }
3060
3102
  .ds-247420 .app-side-shell {
3061
- position: fixed;
3103
+ position: absolute;
3062
3104
  left: 0; top: var(--app-topbar-h);
3063
- height: calc(100vh - var(--app-topbar-h) - var(--app-status-h));
3064
- width: 280px; max-width: 80vw;
3105
+ height: calc(100% - var(--app-topbar-h) - var(--app-status-h));
3106
+ width: 280px; max-width: 80%;
3065
3107
  transform: translateX(-100%);
3066
3108
  transition: transform var(--dur-base, 240ms) var(--ease, ease);
3067
3109
  z-index: 50;
@@ -3095,21 +3137,24 @@
3095
3137
  .ds-247420 .app-main { padding-left: var(--space-3); padding-right: var(--space-3); }
3096
3138
  }
3097
3139
 
3098
- /* Drawer scrim — lives inside .app-body, shown when drawer open ≤900px */
3140
+ /* Drawer scrim — absolute so it covers THIS shell, shown when drawer open and
3141
+ the shell is narrow (@container on .app). */
3099
3142
  .ds-247420 .app-side-scrim {
3100
3143
  display: none;
3101
- position: fixed; inset: 0;
3144
+ position: absolute; inset: 0;
3102
3145
  background: color-mix(in oklab, var(--bg) 60%, transparent);
3103
3146
  z-index: 49;
3104
3147
  }
3105
- @media (max-width: 900px) {
3148
+ @container (max-width: 900px) {
3106
3149
  .ds-247420 .app-body.side-open .app-side-scrim { display: block; }
3107
3150
  }
3108
3151
 
3109
- /* Mobile nav toggle (hamburger) — hidden on desktop, shown ≤900px */
3152
+ /* Nav toggle (hamburger) — hidden when the shell is wide, shown when the shell
3153
+ itself is narrow (@container on .app). Absolute so it sits in THIS shell's
3154
+ topbar, not pinned to the viewport corner. */
3110
3155
  .ds-247420 .app-side-toggle {
3111
3156
  display: none;
3112
- position: fixed; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
3157
+ position: absolute; top: calc((var(--app-topbar-h) - 44px) / 2); left: 10px;
3113
3158
  z-index: 51;
3114
3159
  /* 44x44 minimum hit area (WCAG 2.5.5 / Apple HIG) - 36px is below the
3115
3160
  reliable-tap threshold on touch. */
@@ -3122,7 +3167,7 @@
3122
3167
  cursor: pointer;
3123
3168
  }
3124
3169
  .ds-247420 .app-side-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
3125
- @media (max-width: 900px) {
3170
+ @container (max-width: 900px) {
3126
3171
  .ds-247420 .app-side-toggle { display: inline-flex; }
3127
3172
  .ds-247420 .app-topbar .brand { margin-left: 44px; }
3128
3173
  }
@@ -3195,6 +3240,12 @@
3195
3240
  .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed.ws-no-sessions { grid-template-columns: var(--ws-rail-w) 1fr var(--ws-pane-w); grid-template-areas: "rail content pane"; }
3196
3241
  .ds-247420 .ws-shell.ws-rail-collapsed { --ws-rail-w: var(--ws-rail-w-collapsed); }
3197
3242
  .ds-247420 .ws-shell.ws-pane-collapsed { --ws-pane-w: 0px; }
3243
+ /* Ease the rail/pane collapse. Track COUNT stays stable on collapse (only a
3244
+ width var flips), so grid-template-columns is animatable; reduced-motion
3245
+ drops it to an instant swap. */
3246
+ @media (prefers-reduced-motion: no-preference) {
3247
+ .ds-247420 .ws-shell { transition: grid-template-columns var(--dur-base) var(--ease); }
3248
+ }
3198
3249
 
3199
3250
  /* Rail (left nav) */
3200
3251
  .ds-247420 .ws-rail {
@@ -3265,9 +3316,17 @@
3265
3316
 
3266
3317
  /* Content column */
3267
3318
  .ds-247420 .ws-content { grid-area: content; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
3268
- .ds-247420 .ws-crumb { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-1); border-bottom: var(--bw-hair) solid var(--bg-3); }
3319
+ /* Crumb band is the top chrome of the content column: a stable height so the
3320
+ top edge aligns with the rail head, and a left gutter matching .ws-main so
3321
+ the trail text is not flush against the rail border. */
3322
+ .ds-247420 .ws-crumb { flex: 0 0 auto; min-height: 48px; padding: 0 var(--space-4); display: flex; align-items: center; gap: var(--space-1); border-bottom: var(--bw-hair) solid var(--bg-3); }
3269
3323
  .ds-247420 .ws-crumb-main { flex: 1 1 auto; min-width: 0; }
3270
- .ds-247420 .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
3324
+ /* Content column gutter. Claude-Code-class calm: file grid / dashboard / event
3325
+ list / history get a generous, consistent inner gutter instead of butting
3326
+ against the 1px column borders. The chat tab opts out via .ws-main--flush
3327
+ because the chat thread carries its own --measure gutter. */
3328
+ .ds-247420 .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; padding: var(--space-4) var(--space-5); }
3329
+ .ds-247420 .ws-main.ws-main--flush { padding: 0; }
3271
3330
  .ds-247420 .ws-main:focus { outline: none; }
3272
3331
 
3273
3332
  /* Right context pane */
@@ -3312,8 +3371,11 @@
3312
3371
  .ds-247420 .ws-rail-collapsed .ws-rail-item-label, .ds-247420 .ws-rail-collapsed .ws-rail-brand { display: none; }
3313
3372
  /* Tap-scrim behind an open drawer; dismiss on click. Hidden unless a drawer
3314
3373
  is open so it never blocks the content area on desktop. */
3315
- .ds-247420 .ws-scrim { display: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); }
3316
- .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { display: block; }
3374
+ /* Scrim is always present on mobile so it can FADE with the drawer instead of
3375
+ hard-appearing via a display toggle; pointer-events gate keeps it inert
3376
+ while closed. Reduced-motion users get the global transition kill -> instant. */
3377
+ .ds-247420 .ws-scrim { display: block; opacity: 0; pointer-events: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); transition: opacity var(--dur-base) var(--ease); }
3378
+ .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { opacity: 1; pointer-events: auto; }
3317
3379
  /* The mobile drawer-toggle affordances live in the crumb bar. */
3318
3380
  .ds-247420 .ws-drawer-toggle { display: inline-flex; }
3319
3381
  }
@@ -5360,7 +5422,10 @@
5360
5422
  /* --- C5: active dashboard card (current conversation). --- */
5361
5423
  .ds-247420 .ds-dash-card.is-active { box-shadow: inset 2px 0 0 var(--accent); }
5362
5424
  .ds-247420 .ds-dash-card.is-selected { background: var(--accent-tint); }
5363
- .ds-247420 .ds-dash-card.is-stale { opacity: .92; }
5425
+ /* Stale/idle card: a positive amber inset bar (mirrors is-active) so a stuck
5426
+ agent is flagged in a dense grid, not merely faded near-invisibly. The word
5427
+ 'idle' co-carries state, so this stays colour-blind safe. */
5428
+ .ds-247420 .ds-dash-card.is-stale { box-shadow: inset 2px 0 0 var(--amber, #d9a93a); }
5364
5429
 
5365
5430
  /* --- H3: dashboard live disc pulses; stale/error do not (handled by H1). --- */
5366
5431
 
@@ -5446,7 +5511,7 @@
5446
5511
  /* Enter-to-send hint: visible while the composer is focused or carries a
5447
5512
  draft; hidden under 420px to save rows. */
5448
5513
  .ds-247420 .chat-composer-hint {
5449
- display: none; padding: 2px var(--space-3) 0;
5514
+ display: none; width: 100%; order: 5; padding: 2px var(--space-1) 0;
5450
5515
  font-size: var(--fs-micro); color: var(--fg-3);
5451
5516
  }
5452
5517
  .ds-247420 .chat-composer:focus-within .chat-composer-hint,
@@ -5529,6 +5594,140 @@
5529
5594
  /* One connection vocabulary: offline (is-lost kept as legacy alias). */
5530
5595
  .ds-247420 .ds-dash-stream.is-offline { color: var(--flame); }
5531
5596
 
5597
+ /* ============================================================
5598
+ 10th run - Claude-Code-web design-language parity
5599
+ ============================================================ */
5600
+
5601
+ /* Flat full-width chat turns (claude.ai/code), replacing the messenger
5602
+ avatar-disc + colored-bubble layout. AgentChat passes flat:true; the demo
5603
+ Chat keeps the bubble layout. Turns are full-width to --measure; the user vs
5604
+ assistant distinction is a role label + a faint assistant background. */
5605
+ .ds-247420 .chat-msg-flat { display: block; padding: var(--space-3) var(--space-4); margin: 0; background: none; border-radius: var(--r-2); }
5606
+ .ds-247420 .chat-msg-flat.them { background: color-mix(in oklab, var(--fg) 3%, transparent); }
5607
+ .ds-247420 .chat-msg-flat.you { background: none; }
5608
+ .ds-247420 .chat-msg-flat .chat-stack { max-width: var(--measure); width: 100%; margin: 0; align-items: stretch; }
5609
+ .ds-247420 .chat-msg-flat.you .chat-stack { align-items: stretch; }
5610
+ .ds-247420 .chat-role { font-size: var(--fs-tiny); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); margin-bottom: var(--space-1); }
5611
+ .ds-247420 .chat-msg-flat.you .chat-role { color: var(--accent); }
5612
+ .ds-247420 .chat-msg-flat .chat-bubble { background: none; border: none; border-radius: 0; padding: 0; max-width: 100%; box-shadow: none; transform: none; }
5613
+ .ds-247420 .chat-msg-flat.you .chat-bubble { background: none; color: inherit; }
5614
+ .ds-247420 .chat-msg-flat:hover { background: color-mix(in oklab, var(--fg) 3%, transparent); }
5615
+ .ds-247420 .chat-msg-flat.you:hover { background: color-mix(in oklab, var(--fg) 2%, transparent); }
5616
+ .ds-247420 .chat-msg-flat:hover .chat-bubble { transform: none; box-shadow: none; background: none; }
5617
+ .ds-247420 .chat-msg-flat .chat-avatar { display: none; }
5618
+
5619
+ /* Tool-call card: a bordered, status-toned, scannable card (claude.ai/code),
5620
+ not the raw mascot-tinted details dump. The node keeps the .chat-bubble
5621
+ class, so these rules de-frame it and restyle. Placed after the flat-bubble
5622
+ reset so they win on equal specificity. */
5623
+ .ds-247420 .chat-msg .chat-tool {
5624
+ display: block; max-width: 100%; padding: 0; margin: var(--space-1) 0;
5625
+ background: var(--bg); color: var(--fg);
5626
+ border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
5627
+ box-shadow: none; overflow: hidden;
5628
+ }
5629
+ .ds-247420 .chat-msg .chat-tool[open] { background: var(--bg); }
5630
+ .ds-247420 .chat-msg .chat-tool .chat-tool-head {
5631
+ display: flex; align-items: center; gap: var(--space-2);
5632
+ padding: var(--space-2) var(--space-3); cursor: pointer;
5633
+ font-size: var(--fs-sm); list-style: none;
5634
+ }
5635
+ .ds-247420 .chat-msg .chat-tool .chat-tool-head::-webkit-details-marker { display: none; }
5636
+ .ds-247420 .chat-msg .chat-tool .chat-tool-head:hover { background: var(--bg-2); }
5637
+ .ds-247420 .chat-tool-icon { display: inline-flex; color: var(--fg-3); }
5638
+ .ds-247420 .chat-tool-name { font-family: var(--ff-mono); font-weight: 600; color: var(--fg); }
5639
+ .ds-247420 .chat-tool-label { color: var(--fg-3); font-size: var(--fs-tiny); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
5640
+ .ds-247420 .chat-tool-status {
5641
+ margin-left: auto; flex: 0 0 auto;
5642
+ font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
5643
+ color: var(--fg-3);
5644
+ padding: 2px var(--space-2); border-radius: var(--r-pill);
5645
+ background: color-mix(in oklab, var(--fg) 6%, transparent);
5646
+ }
5647
+ .ds-247420 .chat-msg .chat-tool.tool-running .chat-tool-status { color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, transparent); }
5648
+ .ds-247420 .chat-msg .chat-tool.tool-error .chat-tool-status { color: var(--flame); background: color-mix(in oklab, var(--flame) 12%, transparent); }
5649
+ .ds-247420 .chat-tool-body { border-top: var(--bw-hair) solid var(--rule); padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
5650
+ .ds-247420 .chat-tool-section { display: flex; flex-direction: column; gap: var(--space-1); }
5651
+ .ds-247420 .chat-tool-section-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-3); }
5652
+ .ds-247420 .chat-tool-pre { margin: 0; padding: var(--space-2); background: var(--bg-2); border-radius: var(--r-1); font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1.45; overflow-x: auto; max-height: 320px; overflow-y: auto; }
5653
+ .ds-247420 .chat-tool-pre.is-error { color: var(--flame); }
5654
+ .ds-247420 .chat-tool-pre.chat-tool-empty { color: var(--fg-3); }
5655
+
5656
+ /* Fenced-code language tab on every rendered-markdown block (not just the
5657
+ structured CodeNode). injectCodeCopy reads the language- class. */
5658
+ .ds-247420 .chat-code-block { position: relative; }
5659
+ .ds-247420 .chat-code-lang {
5660
+ position: absolute; top: 0; left: 0; z-index: 2;
5661
+ padding: 2px var(--space-2); border-bottom-right-radius: var(--r-1);
5662
+ font-family: var(--ff-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .04em;
5663
+ color: var(--fg-3); background: color-mix(in oklab, var(--fg) 6%, transparent);
5664
+ pointer-events: none;
5665
+ }
5666
+ .ds-247420 .chat-code-block pre { padding-top: calc(var(--space-3) + 4px); }
5667
+
5668
+ /* Motion + microinteraction polish (all reduced-motion guarded). */
5669
+ .ds-247420 .ds-session-row { transition: background var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease); }
5670
+ @media (prefers-reduced-motion: no-preference) {
5671
+ .ds-247420 .agentchat-thread { scroll-behavior: smooth; }
5672
+ .ds-247420 .ds-alert { animation: ds-alert-in var(--dur-base) var(--ease); }
5673
+ }
5674
+ @keyframes ds-alert-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
5675
+ .ds-247420 .chat-code-copy { transition: opacity var(--dur-snap, .12s) var(--ease, ease), color var(--dur-snap) var(--ease), border-color var(--dur-snap) var(--ease), background var(--dur-snap) var(--ease); }
5676
+ .ds-247420 .chat-msg-action { transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease); }
5677
+ .ds-247420 .agentchat-install-copy { transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease); }
5678
+ @media (prefers-reduced-motion: no-preference) {
5679
+ .ds-247420 .btn.is-armed, .ds-247420 .btn-primary.is-armed { animation: ds-arm-pulse var(--dur-slow) var(--ease); }
5680
+ }
5681
+ @keyframes ds-arm-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--warn) 55%, transparent); } 100% { box-shadow: 0 0 0 6px color-mix(in oklab, var(--warn) 0%, transparent); } }
5682
+ .ds-247420 .ds-dash-card.is-new { box-shadow: inset 2px 0 0 var(--accent), 0 0 0 1px color-mix(in oklab, var(--accent) 40%, transparent); }
5683
+ @media (prefers-reduced-motion: no-preference) {
5684
+ .ds-247420 .ds-dash-card.is-new { animation: ds-card-in var(--dur-slow) var(--ease); }
5685
+ }
5686
+ @keyframes ds-card-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
5687
+
5688
+ /* Live command-center: status-bucket groups + header breakdown + heartbeat. */
5689
+ .ds-247420 .ds-dash-group { display: flex; flex-direction: column; gap: var(--space-2); }
5690
+ .ds-247420 .ds-dash-group-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); padding: 0 var(--space-1); }
5691
+ .ds-247420 .ds-dash-breakdown { display: flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); color: var(--fg-2); }
5692
+ .ds-247420 .ds-dash-breakdown .seg.is-running { color: var(--green); font-weight: 600; }
5693
+ .ds-247420 .ds-dash-breakdown .seg.is-error { color: var(--flame); font-weight: 600; }
5694
+ .ds-247420 .ds-dash-breakdown .seg.is-idle { color: var(--amber, #d9a93a); }
5695
+ .ds-247420 .ds-dash-stream-disc { display: inline-flex; align-items: center; gap: var(--space-1); }
5696
+ .ds-247420 .ds-dash-selectall { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-tiny); color: var(--fg-2); cursor: pointer; background: none; border: none; padding: var(--space-1); }
5697
+ .ds-247420 .ds-dash-selectall:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
5698
+ .ds-247420 .ds-dash-clear { background: none; border: none; color: var(--fg-3); cursor: pointer; font-size: var(--fs-tiny); text-decoration: underline dotted; padding: var(--space-1); }
5699
+
5700
+ /* Conversation-rail loading skeleton (cold ccsniff walk). */
5701
+ .ds-247420 .ds-session-row-skeleton { display: flex; flex-direction: column; gap: 6px; padding: var(--space-2) var(--space-3); }
5702
+ .ds-247420 .ds-session-row-skeleton .ds-skel { background: var(--bg-3); border-radius: var(--r-1); }
5703
+ .ds-247420 .ds-session-row-skeleton .ds-skel-title { height: 12px; width: 70%; }
5704
+ .ds-247420 .ds-session-row-skeleton .ds-skel-meta { height: 9px; width: 45%; }
5705
+ @media (prefers-reduced-motion: no-preference) {
5706
+ .ds-247420 .ds-session-row-skeleton .ds-skel { animation: ds-skel-shimmer 1.3s ease-in-out infinite; background: linear-gradient(90deg, var(--bg-3) 0%, var(--bg-2) 50%, var(--bg-3) 100%); background-size: 200% 100%; }
5707
+ }
5708
+ @keyframes ds-skel-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
5709
+
5710
+ /* File code preview: paint Prism tokens (the bundle scoped them to the chat
5711
+ block only) + an optional non-selectable line-number gutter. */
5712
+ .ds-247420 .ds-preview-code code { color: var(--fg); }
5713
+ .ds-247420 .ds-preview-code .token.comment, .ds-247420 .ds-preview-code .token.prolog, .ds-247420 .ds-preview-code .token.doctype, .ds-247420 .ds-preview-code .token.cdata { color: var(--fg-3); }
5714
+ .ds-247420 .ds-preview-code .token.punctuation { color: var(--fg-2); }
5715
+ .ds-247420 .ds-preview-code .token.property, .ds-247420 .ds-preview-code .token.tag, .ds-247420 .ds-preview-code .token.boolean, .ds-247420 .ds-preview-code .token.number, .ds-247420 .ds-preview-code .token.constant, .ds-247420 .ds-preview-code .token.symbol { color: var(--purple-2, #7F18A4); }
5716
+ .ds-247420 .ds-preview-code .token.selector, .ds-247420 .ds-preview-code .token.attr-name, .ds-247420 .ds-preview-code .token.string, .ds-247420 .ds-preview-code .token.char, .ds-247420 .ds-preview-code .token.builtin { color: var(--green-2, #3A9A34); }
5717
+ .ds-247420 .ds-preview-code .token.atrule, .ds-247420 .ds-preview-code .token.attr-value, .ds-247420 .ds-preview-code .token.keyword { color: var(--sky, #3A6EFF); }
5718
+ .ds-247420 .ds-preview-code .token.function, .ds-247420 .ds-preview-code .token.class-name { color: var(--flame); }
5719
+ .ds-247420 .ds-preview-code.has-gutter { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--space-2); }
5720
+ .ds-247420 .ds-preview-code.has-gutter code { display: block; min-width: 0; overflow-x: auto; }
5721
+ .ds-247420 .ds-preview-gutter { user-select: none; text-align: right; padding: 0 var(--space-2) 0 0; color: var(--fg-3); border-right: var(--bw-hair) solid var(--rule); font-family: var(--ff-mono); white-space: pre; line-height: inherit; }
5722
+
5723
+ /* Image preview: fit/actual control + alpha checkerboard. */
5724
+ .ds-247420 .ds-preview-media-controls { display: flex; gap: var(--space-2); padding: var(--space-2); justify-content: center; }
5725
+ .ds-247420 .ds-preview-media-alpha {
5726
+ background-image: linear-gradient(45deg, var(--bg-3) 25%, transparent 25%), linear-gradient(-45deg, var(--bg-3) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--bg-3) 75%), linear-gradient(-45deg, transparent 75%, var(--bg-3) 75%);
5727
+ background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0;
5728
+ }
5729
+ .ds-247420 .ds-preview-media.is-actual { max-width: none; max-height: none; }
5730
+
5532
5731
  /* editor-primitives.css */
5533
5732
  /* editor-primitives.css — chrome for in-engine editors, inspectors, IDEs,
5534
5733
  debug HUDs. All rules under .ds-247420 scope (build prefixes). Tokens