anentrypoint-design 1.0.2 → 1.0.3

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.
package/dist/247420.css CHANGED
@@ -189,6 +189,16 @@
189
189
  --ff-body: system-ui, sans-serif;
190
190
  --ff-mono: ui-monospace, Menlo, Consolas, monospace;
191
191
 
192
+ /* Weight scale — regular is the default voice for body/UI text everywhere;
193
+ medium/semibold/bold are reserved for genuine emphasis (active state,
194
+ unread counts, own-message author, section headers). Never reach for a
195
+ hardcoded 600/700 in a component rule — use these so the whole surface
196
+ can be re-tuned in one place instead of drifting per-component. */
197
+ --fw-regular: 400;
198
+ --fw-medium: 500;
199
+ --fw-semibold: 600;
200
+ --fw-bold: 700;
201
+
192
202
  /* Sub-12px tiers exist ONLY for dense OS/data chrome — taskbar strips,
193
203
  session chips, tool-call headers, file-row metadata, ID/stat columns.
194
204
  Never use them for body copy or ordinary UI text: at these sizes the
@@ -1649,9 +1659,19 @@
1649
1659
  workspace rail item-count badge (atoms.js Badge size="sm"). */
1650
1660
  .ds-247420 .ds-badge.ds-badge--sm { min-width: var(--icon-xs); height: var(--icon-xs); padding: 0 var(--space-1); font-size: var(--fs-nano); }
1651
1661
  .ds-247420 .ds-badge.ds-badge--lg { min-width: 22px; height: 22px; padding: 0 var(--space-2); font-size: var(--fs-tiny); }
1652
- .ds-247420 .ds-badge.tone-green, .ds-247420 .ds-badge.tone-live, .ds-247420 .ds-badge.tone-success {
1662
+ .ds-247420 .ds-badge.tone-green, .ds-247420 .ds-badge.tone-success {
1653
1663
  background: var(--green-tint); color: var(--green-deep);
1654
1664
  }
1665
+ /* tone-live is its own hue (sky), split out of the success/green group:
1666
+ "live/broadcasting now" and "operation succeeded" are different facts and
1667
+ read identically when both borrow the brand's accent green — a LIVE badge
1668
+ next to an "ok" chip must not look like the same state. --sky is already
1669
+ used for informational surfaces (ds-alert-info, audio-file icons) and is
1670
+ never pinned by the thebird brand's `--accent:var(--green)!important`
1671
+ override, so it stays visually distinct under every accent preset. */
1672
+ .ds-247420 .ds-badge.tone-live {
1673
+ background: color-mix(in oklab, var(--sky) 22%, var(--bg)); color: var(--sky);
1674
+ }
1655
1675
  .ds-247420 .ds-badge.tone-flame, .ds-247420 .ds-badge.tone-error {
1656
1676
  background: var(--flame); color: var(--on-color);
1657
1677
  }
@@ -1681,9 +1701,36 @@
1681
1701
  text-transform: none; letter-spacing: 0; font-weight: 500;
1682
1702
  border-radius: var(--r-0); padding: var(--space-half) var(--space-2);
1683
1703
  }
1684
- .ds-247420 .chip.tone-green, .ds-247420 .chip.tone-live, .ds-247420 .chip.tone-success, .ds-247420 .chip.tone-ok {
1704
+ .ds-247420 .chip.tone-green, .ds-247420 .chip.tone-success, .ds-247420 .chip.tone-ok {
1685
1705
  background: var(--green-tint); color: var(--green-deep);
1686
1706
  }
1707
+ /* tone-live: its own sky hue, split from tone-ok/tone-success — see the
1708
+ .ds-badge.tone-live comment above for the rationale. A small pulsing dot
1709
+ precedes the label so "live" reads as an active broadcast state, not a
1710
+ static status chip. */
1711
+ .ds-247420 .chip.tone-live {
1712
+ background: color-mix(in oklab, var(--sky) 16%, var(--bg));
1713
+ color: var(--sky);
1714
+ position: relative;
1715
+ padding-left: 22px;
1716
+ }
1717
+ .ds-247420 .chip.tone-live::before {
1718
+ content: '';
1719
+ position: absolute;
1720
+ left: 10px; top: 50%;
1721
+ width: 6px; height: 6px;
1722
+ border-radius: 50%;
1723
+ background: var(--sky);
1724
+ transform: translateY(-50%);
1725
+ animation: chip-live-pulse 1.6s ease-in-out infinite;
1726
+ }
1727
+ @keyframes chip-live-pulse {
1728
+ 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in oklab, var(--sky) 50%, transparent); }
1729
+ 50% { opacity: 0.7; box-shadow: 0 0 0 4px transparent; }
1730
+ }
1731
+ @media (prefers-reduced-motion: reduce) {
1732
+ .ds-247420 .chip.tone-live::before { animation: none; }
1733
+ }
1687
1734
  .ds-247420 .chip.tone-flame, .ds-247420 .chip.tone-error, .ds-247420 .chip.tone-miss {
1688
1735
  background: var(--flame); color: var(--on-color);
1689
1736
  }
@@ -2461,6 +2508,12 @@
2461
2508
  outline-offset: -2px;
2462
2509
  }
2463
2510
  .ds-247420 table tr.clickable:focus-visible td { background: var(--bg-2); }
2511
+ /* Non-clickable (static) rows still get a subtle hover cue — most dashboard
2512
+ tables (freddie's sessions-by-platform/model, tool distribution, commands)
2513
+ never pass onRowClick, so they had zero row-hover feedback at all. A dim
2514
+ hover on ANY row (not just .clickable) reads as "you're scanning this
2515
+ row" without implying it's actionable. */
2516
+ .ds-247420 table tr:not(.clickable):hover td { background: color-mix(in oklab, var(--bg-2) 60%, transparent); }
2464
2517
 
2465
2518
  /* Table() striped/compact opt-in density modifiers (webgeist g-table parity).
2466
2519
  Scoped under .ds-table-wrap so they never leak onto an unrelated bare
@@ -2468,8 +2521,15 @@
2468
2521
  .ds-247420 .ds-table-wrap.is-striped table tr:nth-child(even) td { background: var(--bg-2); }
2469
2522
  .ds-247420 .ds-table-wrap.is-striped table tr.clickable:nth-child(even):hover td,
2470
2523
  .ds-247420 .ds-table-wrap.is-striped table tr.clickable:nth-child(even):focus-visible td { background: var(--bg-3, var(--bg-2)); }
2524
+ .ds-247420 .ds-table-wrap.is-striped table tr:not(.clickable):nth-child(even):hover td { background: color-mix(in oklab, var(--bg-3, var(--bg-2)) 60%, transparent); }
2471
2525
  .ds-247420 .ds-table-wrap.is-compact table th { padding: var(--space-1-5, 5px) var(--space-2, 8px); }
2472
2526
  .ds-247420 .ds-table-wrap.is-compact table td { padding: var(--space-1-5, 5px) var(--space-2, 8px); }
2527
+ /* Numeric-column right-alignment: Table() (content/table.js) tags a cell
2528
+ td.is-num when its raw content is a plain integer/decimal, so digit
2529
+ columns (session counts, tool counts, etc.) line up on the ones place
2530
+ instead of ragged-left like prose columns. th.is-num mirrors it on the
2531
+ matching header so the label sits over its column. */
2532
+ .ds-247420 table td.is-num, .ds-247420 table th.is-num { text-align: right; font-variant-numeric: tabular-nums; }
2473
2533
 
2474
2534
  /* ============================================================
2475
2535
  Changelog
@@ -2532,6 +2592,9 @@
2532
2592
  .ds-247420 .ds-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex-shrink: 0; vertical-align: middle; }
2533
2593
  .ds-247420 .ds-dot-on { color: var(--green-2); }
2534
2594
  .ds-247420 .ds-dot-off { color: var(--fg-3); }
2595
+ /* live is a distinct hue from a plain "on" dot — see .chip.tone-live's
2596
+ comment for the success-vs-live rationale. */
2597
+ .ds-247420 .ds-dot-live { color: var(--sky); }
2535
2598
  .ds-247420 .ds-dot-live { color: var(--green-2); }
2536
2599
  .ds-247420 .ds-dot-idle { color: var(--fg-3); }
2537
2600
 
@@ -2549,6 +2612,26 @@
2549
2612
  padding: var(--space-3);
2550
2613
  background: var(--bg-2);
2551
2614
  border-radius: var(--r-1);
2615
+ /* A thin border + hover elevation gives the tile real edges and a "this is
2616
+ a distinct object" affordance instead of a flat color patch that blends
2617
+ into the surrounding panel — matches the "no border, no hover state"
2618
+ gap named against the stat tiles. */
2619
+ border: 1px solid var(--rule);
2620
+ position: relative;
2621
+ transition: border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;
2622
+ }
2623
+ .ds-247420 .kpi-card:hover {
2624
+ border-color: color-mix(in oklab, var(--accent) 40%, var(--rule));
2625
+ transform: translateY(-1px);
2626
+ box-shadow: var(--shadow-1, 0 2px 8px rgba(0,0,0,.12));
2627
+ }
2628
+ .ds-247420 .kpi-glyph {
2629
+ position: absolute;
2630
+ top: var(--space-2);
2631
+ right: var(--space-2);
2632
+ color: var(--fg-3);
2633
+ opacity: 0.6;
2634
+ display: inline-flex;
2552
2635
  }
2553
2636
  .ds-247420 .kpi-card .num {
2554
2637
  font-family: var(--ff-body); font-weight: 600;
@@ -8437,7 +8520,7 @@
8437
8520
  justify-content: center;
8438
8521
  font-family: var(--ff-body);
8439
8522
  font-size: var(--fs-lg);
8440
- font-weight: 600;
8523
+ font-weight: var(--fw-medium);
8441
8524
  letter-spacing: var(--tr-tight);
8442
8525
  cursor: pointer;
8443
8526
  overflow: hidden;
@@ -8494,7 +8577,7 @@
8494
8577
  color: var(--ink);
8495
8578
  font-family: var(--ff-mono);
8496
8579
  font-size: var(--fs-micro);
8497
- font-weight: 700;
8580
+ font-weight: var(--fw-bold);
8498
8581
  border-radius: var(--r-pill);
8499
8582
  display: flex;
8500
8583
  align-items: center;
@@ -8513,7 +8596,7 @@
8513
8596
  align-items: center;
8514
8597
  justify-content: center;
8515
8598
  font-size: var(--fs-xl);
8516
- font-weight: 400;
8599
+ font-weight: var(--fw-regular);
8517
8600
  cursor: pointer;
8518
8601
  border: 0;
8519
8602
  transition:
@@ -8559,7 +8642,7 @@
8559
8642
  padding: var(--space-2-75) var(--space-3);
8560
8643
  background: var(--bg-2);
8561
8644
  box-shadow: 0 1px 0 color-mix(in oklab, var(--fg) 8%, transparent);
8562
- font-weight: 600;
8645
+ font-weight: var(--fw-medium);
8563
8646
  font-size: var(--fs-sm);
8564
8647
  letter-spacing: -0.01em;
8565
8648
  /* No cursor:pointer, no :hover background, no user-select:none. This is a
@@ -8614,7 +8697,7 @@
8614
8697
  padding: var(--space-1) var(--space-2);
8615
8698
  font-family: var(--ff-body);
8616
8699
  font-size: var(--fs-micro);
8617
- font-weight: 600;
8700
+ font-weight: var(--fw-medium);
8618
8701
  color: var(--fg-3);
8619
8702
  letter-spacing: var(--tr-caps);
8620
8703
  text-transform: uppercase;
@@ -8653,7 +8736,7 @@
8653
8736
  font-family: var(--ff-mono);
8654
8737
  font-size: var(--fs-micro);
8655
8738
  color: var(--fg-3);
8656
- font-weight: 500;
8739
+ font-weight: var(--fw-medium);
8657
8740
  letter-spacing: 0;
8658
8741
  text-transform: none;
8659
8742
  }
@@ -8723,7 +8806,7 @@
8723
8806
  .ds-247420 .cm-channel-item.active {
8724
8807
  background: color-mix(in oklab, var(--fg) 10%, transparent);
8725
8808
  color: var(--fg);
8726
- font-weight: 500;
8809
+ font-weight: var(--fw-medium);
8727
8810
  }
8728
8811
  .ds-247420 .cm-channel-item.active::before {
8729
8812
  content: '';
@@ -8829,7 +8912,7 @@
8829
8912
  color: var(--ink);
8830
8913
  font-family: var(--ff-mono);
8831
8914
  font-size: var(--fs-micro);
8832
- font-weight: 700;
8915
+ font-weight: var(--fw-bold);
8833
8916
  border-radius: var(--r-pill);
8834
8917
  display: inline-flex;
8835
8918
  align-items: center;
@@ -8913,7 +8996,7 @@
8913
8996
  align-items: center;
8914
8997
  justify-content: center;
8915
8998
  font-size: var(--fs-pico);
8916
- font-weight: 600;
8999
+ font-weight: var(--fw-medium);
8917
9000
  overflow: hidden;
8918
9001
  transition: box-shadow var(--dur-snap) var(--ease);
8919
9002
  }
@@ -8952,7 +9035,7 @@
8952
9035
  a pulsing dot and must read as the loudest thing in the strip). */
8953
9036
  .ds-247420 .cm-vs-label {
8954
9037
  color: var(--green);
8955
- font-weight: 700;
9038
+ font-weight: var(--fw-bold);
8956
9039
  display: inline-flex;
8957
9040
  align-items: center;
8958
9041
  gap: var(--space-1-75);
@@ -8978,7 +9061,7 @@
8978
9061
 
8979
9062
  .ds-247420 .cm-vs-channel {
8980
9063
  font-size: var(--fs-sm);
8981
- font-weight: 600;
9064
+ font-weight: var(--fw-medium);
8982
9065
  color: var(--fg);
8983
9066
  overflow: hidden;
8984
9067
  text-overflow: ellipsis;
@@ -9006,7 +9089,7 @@
9006
9089
  border-radius: var(--r-1);
9007
9090
  font-family: var(--ff-body);
9008
9091
  font-size: var(--fs-xs);
9009
- font-weight: 600;
9092
+ font-weight: var(--fw-medium);
9010
9093
  cursor: pointer;
9011
9094
  transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
9012
9095
  }
@@ -9048,7 +9131,7 @@
9048
9131
  align-items: center;
9049
9132
  justify-content: center;
9050
9133
  font-size: var(--fs-xs);
9051
- font-weight: 600;
9134
+ font-weight: var(--fw-medium);
9052
9135
  overflow: hidden;
9053
9136
  }
9054
9137
  .ds-247420 .cm-user-avatar img {
@@ -9078,7 +9161,7 @@
9078
9161
  }
9079
9162
  .ds-247420 .cm-user-name {
9080
9163
  font-size: var(--fs-xs);
9081
- font-weight: 600;
9164
+ font-weight: var(--fw-medium);
9082
9165
  color: var(--fg);
9083
9166
  overflow: hidden;
9084
9167
  text-overflow: ellipsis;
@@ -9159,7 +9242,7 @@
9159
9242
  pinned weight/size/colour, but a bare h1 also brings a UA block margin
9160
9243
  that would break this flex row — so the margin is zeroed explicitly. */
9161
9244
  margin: 0;
9162
- font-weight: 600;
9245
+ font-weight: var(--fw-medium);
9163
9246
  font-size: var(--fs-sm);
9164
9247
  color: var(--fg);
9165
9248
  letter-spacing: -0.01em;
@@ -9223,7 +9306,7 @@
9223
9306
  padding: var(--space-2-75) var(--space-3) var(--space-1-75);
9224
9307
  font-family: var(--ff-body);
9225
9308
  font-size: var(--fs-micro);
9226
- font-weight: 600;
9309
+ font-weight: var(--fw-medium);
9227
9310
  color: var(--fg-3);
9228
9311
  letter-spacing: var(--tr-caps);
9229
9312
  text-transform: uppercase;
@@ -9259,7 +9342,7 @@
9259
9342
  align-items: center;
9260
9343
  justify-content: center;
9261
9344
  font-size: var(--fs-micro);
9262
- font-weight: 600;
9345
+ font-weight: var(--fw-medium);
9263
9346
  overflow: hidden;
9264
9347
  }
9265
9348
  .ds-247420 .cm-member-avatar img {
@@ -9320,7 +9403,7 @@
9320
9403
  align-items: center;
9321
9404
  justify-content: center;
9322
9405
  font-size: var(--fs-lg);
9323
- font-weight: 600;
9406
+ font-weight: var(--fw-medium);
9324
9407
  overflow: hidden;
9325
9408
  }
9326
9409
  .ds-247420 .cm-voice-user-avatar img {
@@ -9336,7 +9419,7 @@
9336
9419
  .ds-247420 .cm-voice-user-name {
9337
9420
  font-size: var(--fs-xs);
9338
9421
  color: var(--fg);
9339
- font-weight: 500;
9422
+ font-weight: var(--fw-medium);
9340
9423
  max-width: 100px;
9341
9424
  overflow: hidden;
9342
9425
  text-overflow: ellipsis;
@@ -9531,7 +9614,7 @@
9531
9614
  flex: 1 1 auto;
9532
9615
  min-width: 0;
9533
9616
  font-family: var(--font-mono, monospace);
9534
- font-weight: 600;
9617
+ font-weight: var(--fw-medium);
9535
9618
  color: var(--fg);
9536
9619
  white-space: nowrap;
9537
9620
  overflow: hidden;
@@ -9554,7 +9637,7 @@
9554
9637
  font-size: var(--fs-xs);
9555
9638
  }
9556
9639
  .ds-247420 .cm-rb-label { flex: none; color: var(--fg-2); }
9557
- .ds-247420 .cm-rb-author { color: var(--accent); font-weight: 600; }
9640
+ .ds-247420 .cm-rb-author { color: var(--accent); font-weight: var(--fw-medium); }
9558
9641
  .ds-247420 .cm-rb-preview {
9559
9642
  flex: 1 1 auto;
9560
9643
  min-width: 0;
@@ -9586,7 +9669,7 @@
9586
9669
  width: 100%;
9587
9670
  padding: var(--space-2) var(--space-3);
9588
9671
  font-size: var(--fs-xs);
9589
- font-weight: 500;
9672
+ font-weight: var(--fw-medium);
9590
9673
  }
9591
9674
  .ds-247420 .cm-banner.clickable { cursor: pointer; }
9592
9675
  .ds-247420 .cm-banner.clickable:hover { background: color-mix(in oklab, currentColor 10%, transparent); }
@@ -9597,7 +9680,7 @@
9597
9680
  background: transparent;
9598
9681
  color: inherit;
9599
9682
  font: inherit;
9600
- font-weight: 600;
9683
+ font-weight: var(--fw-semibold);
9601
9684
  padding: var(--space-hair) var(--space-2);
9602
9685
  border-radius: var(--r-1);
9603
9686
  cursor: pointer;
@@ -9659,7 +9742,7 @@
9659
9742
  color: var(--fg);
9660
9743
  font-family: var(--ff-body);
9661
9744
  font-size: var(--fs-sm);
9662
- font-weight: 600;
9745
+ font-weight: var(--fw-medium);
9663
9746
  cursor: pointer;
9664
9747
  user-select: none;
9665
9748
  -webkit-user-select: none;
@@ -9781,7 +9864,7 @@
9781
9864
  color: var(--fg);
9782
9865
  font-family: var(--ff-body);
9783
9866
  font-size: var(--fs-sm);
9784
- font-weight: 600;
9867
+ font-weight: var(--fw-semibold);
9785
9868
  cursor: pointer;
9786
9869
  transition: background var(--dur-base) var(--ease);
9787
9870
  }
@@ -9811,7 +9894,7 @@
9811
9894
  padding: var(--space-3);
9812
9895
  border-bottom: var(--bw-hair) solid var(--rule);
9813
9896
  }
9814
- .ds-247420 .vx-modal-title { margin: 0; font-size: var(--fs-lg); font-weight: 600; }
9897
+ .ds-247420 .vx-modal-title { margin: 0; font-size: var(--fs-lg); font-weight: var(--fw-semibold); }
9815
9898
  .ds-247420 .vx-modal-x {
9816
9899
  border: 0; background: transparent; color: var(--fg-3);
9817
9900
  font-size: var(--fs-xl); line-height: 1; cursor: pointer; padding: 0 var(--space-1);
@@ -9835,7 +9918,7 @@
9835
9918
  color: var(--fg);
9836
9919
  font-family: var(--ff-body);
9837
9920
  font-size: var(--fs-tiny);
9838
- font-weight: 600;
9921
+ font-weight: var(--fw-medium);
9839
9922
  letter-spacing: var(--tr-caps);
9840
9923
  cursor: pointer;
9841
9924
  }
@@ -9893,13 +9976,13 @@
9893
9976
  .ds-247420 .vx-chip-current { border-color: var(--accent); background: color-mix(in oklab, var(--accent) 16%, var(--bg-3)); }
9894
9977
  .ds-247420 .vx-chip-live { border-color: var(--green-2); }
9895
9978
  .ds-247420 .vx-chip-dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--fg-3); flex-shrink: 0; }
9896
- .ds-247420 .vx-chip-name { font-weight: 600; }
9979
+ .ds-247420 .vx-chip-name { font-weight: var(--fw-medium); }
9897
9980
  .ds-247420 .vx-chip-dur { font-family: var(--ff-mono); color: var(--fg-3); }
9898
9981
  /* Joins the small-label voice above. Deliberate overrides: --green + weight 700
9899
9982
  because this is the "LIVE" badge on a session chip, same signal role as
9900
9983
  .cm-vs-label. */
9901
9984
  .ds-247420 .vx-chip-tag {
9902
- color: var(--green); font-weight: 700;
9985
+ color: var(--green); font-weight: var(--fw-bold);
9903
9986
  }
9904
9987
 
9905
9988
  /* VoiceControls — vx-vc-* */
@@ -9945,7 +10028,7 @@
9945
10028
  display: flex; align-items: center; justify-content: space-between;
9946
10029
  padding: var(--space-2); border-bottom: var(--bw-hair) solid var(--rule);
9947
10030
  }
9948
- .ds-247420 .cm-tp-title { font-weight: 700; font-size: var(--fs-xs); }
10031
+ .ds-247420 .cm-tp-title { font-weight: var(--fw-bold); font-size: var(--fs-xs); }
9949
10032
  .ds-247420 .cm-tp-head-actions { display: flex; gap: var(--space-1); }
9950
10033
  .ds-247420 .cm-tp-new, .ds-247420 .cm-tp-close {
9951
10034
  border: none; background: transparent; color: var(--fg-2, var(--fg));
@@ -9963,7 +10046,7 @@
9963
10046
  }
9964
10047
  .ds-247420 .cm-tp-item:hover { background: var(--bg-3); }
9965
10048
  .ds-247420 .cm-tp-item.is-active { background: var(--bg-3); box-shadow: inset 3px 0 0 var(--accent); }
9966
- .ds-247420 .cm-tp-item.is-unread .cm-tp-item-title { font-weight: 700; }
10049
+ .ds-247420 .cm-tp-item.is-unread .cm-tp-item-title { font-weight: var(--fw-bold); }
9967
10050
  .ds-247420 .cm-tp-dot { position: absolute; left: 4px; top: 50%; transform: translateY(-50%); width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
9968
10051
  .ds-247420 .cm-tp-item-title { font-size: var(--fs-xs); }
9969
10052
  .ds-247420 .cm-tp-item-snippet { font-size: var(--fs-micro); color: var(--fg-2, var(--fg)); opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -10017,7 +10100,7 @@
10017
10100
  .ds-247420 .cm-forum-item { display: flex; flex-direction: column; gap: var(--space-1); width: 100%; text-align: left; cursor: pointer; padding: var(--space-2) var(--space-3); border: none; background: transparent; border-bottom: var(--bw-hair) solid var(--rule); color: var(--fg); }
10018
10101
  .ds-247420 .cm-forum-item:hover { background: var(--bg-3); }
10019
10102
  .ds-247420 .cm-forum-item-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
10020
- .ds-247420 .cm-forum-item-title { font-weight: 700; font-size: var(--fs-xs); }
10103
+ .ds-247420 .cm-forum-item-title { font-weight: var(--fw-bold); font-size: var(--fs-xs); }
10021
10104
  .ds-247420 .cm-forum-item-replies { font-size: var(--fs-micro); color: var(--fg-2, var(--fg)); opacity: .8; white-space: nowrap; }
10022
10105
  .ds-247420 .cm-forum-item-snippet { font-size: var(--fs-micro); color: var(--fg-2, var(--fg)); opacity: .85; }
10023
10106
  .ds-247420 .cm-forum-item-meta { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; font-size: var(--fs-micro); color: var(--fg-2, var(--fg)); opacity: .7; }
@@ -10030,9 +10113,9 @@
10030
10113
  .ds-247420 .cm-page { display: flex; flex-direction: column; height: 100%; min-height: 0; overflow-y: auto; background: var(--bg-1, var(--bg-2)); color: var(--fg); }
10031
10114
  .ds-247420 .cm-page-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-3); border-bottom: var(--bw-hair) solid var(--rule); }
10032
10115
  .ds-247420 .cm-page-head-title { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
10033
- .ds-247420 .cm-page-title { margin: 0; font-size: var(--fs-xl); font-weight: 700; }
10116
+ .ds-247420 .cm-page-title { margin: 0; font-size: var(--fs-xl); font-weight: var(--fw-bold); }
10034
10117
  .ds-247420 .cm-page-meta { display: flex; align-items: center; gap: var(--space-2); font-size: var(--fs-xs); color: var(--fg-2, var(--fg)); }
10035
- .ds-247420 .cm-page-author { font-weight: 500; }
10118
+ .ds-247420 .cm-page-author { font-weight: var(--fw-medium); }
10036
10119
  .ds-247420 .cm-page-time { opacity: .75; }
10037
10120
  .ds-247420 .cm-page-edit { padding: var(--space-1) var(--space-2); border: var(--bw-hair) solid var(--rule-strong); border-radius: var(--r-1); background: var(--bg-3); color: var(--fg); cursor: pointer; }
10038
10121
  .ds-247420 .cm-page-body { padding: var(--space-3); line-height: 1.6; }
@@ -10071,9 +10154,105 @@
10071
10154
  }
10072
10155
 
10073
10156
  /* chat.css */
10074
- /* chat.css — chat-specific styles. Most chat styles live in app-shell.css under
10075
- the .chat-* prefix. This file carries the AgentChat kit styles (the reusable
10076
- multi-agent orchestration chat surface). */
10157
+ /* chat.css — chat-specific styles, including the base .chat-* rules used by
10158
+ Chat()/ChatMessage() (chat/threads.js, chat/message.js): .chat, .chat-head,
10159
+ .chat-thread, .chat-msg, .chat-avatar, .chat-bubble, .chat-stack,
10160
+ .chat-empty. This file also carries the AgentChat kit styles (the reusable
10161
+ multi-agent orchestration chat surface, .agentchat-*). */
10162
+
10163
+ /* Base chat surface — the default (non-flat) messenger layout: left/right
10164
+ avatar-disc + colored-bubble turns. .chat-msg-flat further down overrides
10165
+ these to the claude.ai/code full-width turn style; these are the rules it
10166
+ overrides FROM, and were previously entirely undefined, so the default
10167
+ layout rendered on raw flex/browser defaults (unstyled bubble shape, no
10168
+ avatar depth, no defined thread padding) until a Chat() consumer supplied
10169
+ its own colliding class names. */
10170
+ .ds-247420 .chat {
10171
+ display: flex;
10172
+ flex-direction: column;
10173
+ flex: 1;
10174
+ min-height: 0;
10175
+ }
10176
+ .ds-247420 .chat-head {
10177
+ display: flex;
10178
+ align-items: center;
10179
+ gap: var(--space-2);
10180
+ padding: var(--space-2-75) var(--space-3);
10181
+ border-bottom: 1px solid var(--panel-3, color-mix(in oklab, var(--fg) 10%, transparent));
10182
+ flex-shrink: 0;
10183
+ }
10184
+ .ds-247420 .chat-head .ds-chat-title { font-size: var(--fs-sm); font-weight: var(--fw-medium); margin: 0; }
10185
+ .ds-247420 .chat-head .sub { font-size: var(--fs-tiny); color: var(--fg-3); }
10186
+ .ds-247420 .chat-head .spread { flex: 1; }
10187
+ .ds-247420 .chat-thread {
10188
+ flex: 1;
10189
+ min-height: 0;
10190
+ overflow-y: auto;
10191
+ display: flex;
10192
+ flex-direction: column;
10193
+ gap: var(--space-3);
10194
+ padding: var(--space-3) var(--space-3) var(--space-4);
10195
+ /* A short thread must not stretch its one message across the whole
10196
+ viewport height — pack content to the bottom (where the composer is)
10197
+ instead of centering it in a sea of empty space above and below. */
10198
+ justify-content: flex-end;
10199
+ }
10200
+ .ds-247420 .chat-empty {
10201
+ margin: auto;
10202
+ max-width: var(--measure-narrow, 60ch);
10203
+ text-align: center;
10204
+ padding: var(--space-5) var(--space-3);
10205
+ color: var(--fg-3);
10206
+ }
10207
+ .ds-247420 .chat-empty-title { font-size: var(--fs-lg); font-weight: var(--fw-medium); color: var(--fg-2); margin: 0 0 var(--space-1); }
10208
+ .ds-247420 .chat-empty-sub { font-size: var(--fs-sm); margin: 0; }
10209
+ .ds-247420 .chat-msg {
10210
+ display: flex;
10211
+ gap: var(--space-2);
10212
+ align-items: flex-start;
10213
+ max-width: 100%;
10214
+ }
10215
+ .ds-247420 .chat-msg.you { flex-direction: row-reverse; }
10216
+ .ds-247420 .chat-msg.centered { justify-content: center; text-align: center; }
10217
+ .ds-247420 .chat-avatar {
10218
+ width: 32px;
10219
+ height: 32px;
10220
+ flex-shrink: 0;
10221
+ border-radius: 50%;
10222
+ background: var(--bg-3);
10223
+ color: var(--fg);
10224
+ display: inline-flex;
10225
+ align-items: center;
10226
+ justify-content: center;
10227
+ font-size: var(--fs-tiny);
10228
+ font-weight: var(--fw-medium);
10229
+ /* Depth over a flat solid-color disc: a hairline inset ring plus the same
10230
+ soft shadow --panel-shadow uses elsewhere, so avatars read as a real
10231
+ surface element instead of a wireframe placeholder. */
10232
+ box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fg) 10%, transparent), 0 1px 2px color-mix(in oklab, var(--fg) 10%, transparent);
10233
+ }
10234
+ .ds-247420 .chat-stack {
10235
+ display: flex;
10236
+ flex-direction: column;
10237
+ gap: var(--space-1);
10238
+ max-width: 70%;
10239
+ min-width: 0;
10240
+ }
10241
+ .ds-247420 .chat-msg.you .chat-stack { align-items: flex-end; }
10242
+ .ds-247420 .chat-bubble {
10243
+ padding: var(--space-2) var(--space-2-75);
10244
+ background: var(--bg-2);
10245
+ color: var(--fg);
10246
+ /* r-2, not a pill — a pill-capsule bubble read as a generic chat-template
10247
+ shape inconsistent with every other rounded element in the app (which
10248
+ all use the r-0..r-3 scale, never 999px). */
10249
+ border-radius: var(--r-2);
10250
+ line-height: var(--lh-base, 1.5);
10251
+ word-break: break-word;
10252
+ font-size: var(--fs-sm);
10253
+ }
10254
+ .ds-247420 .chat-msg.you .chat-bubble { background: var(--accent); color: var(--accent-fg); }
10255
+ .ds-247420 .chat-meta { display: flex; gap: var(--space-1-5); font-size: var(--fs-nano); color: var(--fg-3); padding: 0 var(--space-1); }
10077
10256
 
10078
10257
  .ds-247420 .agentchat {
10079
10258
  display: flex;
@@ -13437,6 +13616,48 @@
13437
13616
  padding: 0;
13438
13617
  }
13439
13618
 
13619
+ /* app topbar — mountCommunityApp's own sole chrome above the chat-head; had
13620
+ no rules anywhere (relying on raw flex defaults), which read as unaligned
13621
+ default spacing rather than a designed header row. */
13622
+ .ds-247420.ds-247420 .app-topbar {
13623
+ display: flex;
13624
+ align-items: center;
13625
+ gap: var(--space-3);
13626
+ height: 48px;
13627
+ flex-shrink: 0;
13628
+ padding: 0 var(--space-3);
13629
+ background: var(--bg-2);
13630
+ border-bottom: 1px solid var(--panel-3, color-mix(in oklab, var(--fg) 10%, transparent));
13631
+ }
13632
+ .ds-247420.ds-247420 .app-topbar .brand {
13633
+ display: flex;
13634
+ align-items: baseline;
13635
+ gap: var(--space-1);
13636
+ min-width: 0;
13637
+ font-weight: var(--fw-medium, 500);
13638
+ font-size: var(--fs-sm);
13639
+ color: var(--fg);
13640
+ overflow: hidden;
13641
+ white-space: nowrap;
13642
+ text-overflow: ellipsis;
13643
+ }
13644
+ .ds-247420.ds-247420 .app-topbar .brand .slash { color: var(--fg-3); }
13645
+ .ds-247420.ds-247420 .app-topbar nav {
13646
+ display: flex;
13647
+ align-items: center;
13648
+ gap: var(--space-2);
13649
+ }
13650
+ .ds-247420.ds-247420 .app-topbar nav a {
13651
+ color: var(--fg-2);
13652
+ font-size: var(--fs-tiny);
13653
+ text-decoration: none;
13654
+ padding: var(--space-1) var(--space-1-5);
13655
+ border-radius: var(--r-1);
13656
+ transition: background var(--dur-snap, .12s) var(--ease, ease), color var(--dur-snap, .12s) var(--ease, ease);
13657
+ }
13658
+ .ds-247420.ds-247420 .app-topbar nav a:hover { color: var(--fg); background: color-mix(in oklab, var(--fg) 8%, transparent); }
13659
+ .ds-247420.ds-247420 .app-topbar nav a:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 2px; }
13660
+
13440
13661
  /* server + channel rail */
13441
13662
  .ds-247420.ds-247420 .ca-rail {
13442
13663
  display: flex;
@@ -13452,7 +13673,7 @@
13452
13673
  }
13453
13674
  .ds-247420.ds-247420 .ca-rail .group {
13454
13675
  font-size: 11px;
13455
- font-weight: 600;
13676
+ font-weight: var(--fw-semibold, 600);
13456
13677
  letter-spacing: 0.04em;
13457
13678
  text-transform: uppercase;
13458
13679
  color: var(--fg-3, color-mix(in oklab, var(--fg) 55%, transparent));
@@ -13512,7 +13733,7 @@
13512
13733
  background: var(--accent);
13513
13734
  color: var(--on-accent);
13514
13735
  font-size: 11px;
13515
- font-weight: 600;
13736
+ font-weight: var(--fw-semibold, 600);
13516
13737
  text-align: center;
13517
13738
  }
13518
13739
  .ds-247420.ds-247420 .ca-rail .rail-empty {