anentrypoint-design 0.0.478 → 0.0.481

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.
Files changed (38) hide show
  1. package/chat.css +4 -4
  2. package/colors_and_type.css +33 -3
  3. package/community.css +22 -8
  4. package/dist/247420.css +195 -59
  5. package/dist/247420.js +24 -24
  6. package/package.json +1 -1
  7. package/src/community-app.js +4 -2
  8. package/src/components/community/navigation.js +2 -2
  9. package/src/components/community/presence.js +10 -4
  10. package/src/components/community/views.js +8 -2
  11. package/src/components/content/avatar.js +30 -0
  12. package/src/components/content.js +2 -2
  13. package/src/components/overlay-primitives/emoji-picker.js +15 -3
  14. package/src/components/shell/workspace-shell.js +1 -1
  15. package/src/components/theme-toggle.js +8 -3
  16. package/src/css/app-shell/base.css +18 -0
  17. package/src/css/app-shell/catalog-theme.css +14 -2
  18. package/src/css/app-shell/chat-polish.css +12 -0
  19. package/src/css/app-shell/collab.css +5 -0
  20. package/src/css/app-shell/data-density.css +4 -0
  21. package/src/css/app-shell/files.css +1 -1
  22. package/src/css/app-shell/hero-content.css +1 -1
  23. package/src/css/app-shell/loading-alerts.css +14 -12
  24. package/src/css/app-shell/otp-input.css +2 -2
  25. package/src/css/app-shell/plugins-config.css +3 -0
  26. package/src/css/app-shell/primitives.css +13 -4
  27. package/src/css/app-shell/responsive.css +13 -0
  28. package/src/css/app-shell/responsive2-workspace.css +4 -1
  29. package/src/css/app-shell/states-interactions.css +20 -4
  30. package/src/kits/os/app-panes.css +3 -2
  31. package/src/kits/os/icons.js +16 -0
  32. package/src/kits/os/shell-geometry.js +2 -2
  33. package/src/kits/os/shell.js +24 -3
  34. package/src/kits/os/theme.css +251 -78
  35. package/src/kits/os/wm.css +19 -6
  36. package/src/kits/spoint/host-join-lobby.css +3 -3
  37. package/src/web-components/freddie-chat.js +2 -2
  38. package/types/components.d.ts +4 -0
package/dist/247420.css CHANGED
@@ -203,12 +203,24 @@
203
203
  --fs-body: 16px;
204
204
  --fs-lg: 18px;
205
205
  --fs-xl: 21px;
206
- --fs-h4: clamp(22px, 2cqi, 26px);
206
+ --fs-h4: clamp(24px, 2cqi, 28px);
207
207
  --fs-h3: clamp(25px, 2.6cqi, 34px);
208
208
  --fs-h2: clamp(28px, 3.6cqi, 44px);
209
209
  --fs-h1: clamp(34px, 5cqi, 64px);
210
210
  --fs-hero: clamp(42px, 7cqi, 96px);
211
211
  --fs-mega: clamp(56px, 11cqi, 168px);
212
+ /* Bridges the fixed --fs-* ladder (tops out at --fs-xl, 21px) and the fluid
213
+ heading clamps below it — use for fixed (non-clamping) UI text that needs
214
+ to sit between --fs-xl and a heading tier, e.g. empty-state icon glyphs. */
215
+ --fs-2xl: 28px;
216
+
217
+ /* Icon size scale — canonical sizes for glyphs/icons across the kit going
218
+ forward. Existing ad-hoc pixel values (6/7/8/10/12/14/16/18px etc.)
219
+ don't need to be migrated in this pass; new/updated icon usage should. */
220
+ --icon-xs: 12px;
221
+ --icon-sm: 16px;
222
+ --icon-md: 20px;
223
+ --icon-lg: 24px;
212
224
 
213
225
  /* App/chrome typescale: the default heading scale above is tuned for
214
226
  marketing/hero layouts (h1 up to 64px). Application chrome — page titles,
@@ -357,6 +369,9 @@
357
369
  --z-below: -1;
358
370
  --z-base: 0;
359
371
  --z-raised: 100;
372
+ --z-raised-1: calc(var(--z-raised) + 1);
373
+ --z-raised-2: calc(var(--z-raised) + 2);
374
+ --z-raised-3: calc(var(--z-raised) + 3);
360
375
  --z-sticky: 200;
361
376
  --z-header: 300;
362
377
  --z-drawer: 400;
@@ -417,6 +432,9 @@
417
432
  --focus-w: 2px;
418
433
  --focus-offset: 2px;
419
434
  --focus-ring-inset: inset 0 0 0 var(--focus-w) var(--focus-color);
435
+
436
+ /* letterbox background for video/media containers */
437
+ --media-letterbox: #000;
420
438
  }
421
439
 
422
440
  /* ============================================================
@@ -718,8 +736,20 @@
718
736
 
719
737
  /* Type-scale modifier — opt-in body/lg/xl bump for surfaces that want denser
720
738
  or larger reading sizes without a custom override. */
721
- .ds-247420[data-typescale="sm"] { --fs-body: 15px; --fs-lg: 17px; --fs-xl: 20px; }
722
- .ds-247420[data-typescale="lg"] { --fs-body: 17px; --fs-lg: 20px; --fs-xl: 24px; }
739
+ .ds-247420[data-typescale="sm"] {
740
+ --fs-body: 15px; --fs-lg: 17px; --fs-xl: 20px;
741
+ --fs-h4: clamp(22px, 1.9cqi, 24px);
742
+ --fs-h3: clamp(23px, 2.4cqi, 32px);
743
+ --fs-h2: clamp(26px, 3.4cqi, 41px);
744
+ --fs-h1: clamp(32px, 4.7cqi, 60px);
745
+ }
746
+ .ds-247420[data-typescale="lg"] {
747
+ --fs-body: 17px; --fs-lg: 20px; --fs-xl: 24px;
748
+ --fs-h4: clamp(27px, 2.2cqi, 31px);
749
+ --fs-h3: clamp(28px, 2.9cqi, 38px);
750
+ --fs-h2: clamp(31px, 4cqi, 49px);
751
+ --fs-h1: clamp(38px, 5.6cqi, 71px);
752
+ }
723
753
 
724
754
  /* Debug grid overlay — 8px mascot grid. Toggle via class on any container. */
725
755
  .ds-247420 .with-grid-overlay {
@@ -882,6 +912,21 @@
882
912
  scrollbar-width: thin;
883
913
  scrollbar-color: var(--bg-3) transparent;
884
914
  }
915
+ /* Firefox gets themed scrollbars via scrollbar-width/-color above; Chrome,
916
+ Safari, and Edge need the ::-webkit-scrollbar family too, or every
917
+ scrollable node in the app shell falls back to the raw OS scrollbar and
918
+ clashes with the dark UI. Same selector scope, same --bg-3 token. */
919
+ .ds-247420 .app::-webkit-scrollbar, .ds-247420 .ds-stage::-webkit-scrollbar, .ds-247420 .app *::-webkit-scrollbar, .ds-247420 .ds-stage *::-webkit-scrollbar {
920
+ width: 8px;
921
+ height: 8px;
922
+ }
923
+ .ds-247420 .app::-webkit-scrollbar-track, .ds-247420 .ds-stage::-webkit-scrollbar-track, .ds-247420 .app *::-webkit-scrollbar-track, .ds-247420 .ds-stage *::-webkit-scrollbar-track {
924
+ background: transparent;
925
+ }
926
+ .ds-247420 .app::-webkit-scrollbar-thumb, .ds-247420 .ds-stage::-webkit-scrollbar-thumb, .ds-247420 .app *::-webkit-scrollbar-thumb, .ds-247420 .ds-stage *::-webkit-scrollbar-thumb {
927
+ background: var(--bg-3);
928
+ border-radius: var(--r-pill, 999px);
929
+ }
885
930
 
886
931
  .ds-247420 h1, .ds-247420 .t-h1 { font-family: var(--ff-display); font-size: var(--fs-h1); line-height: var(--lh-snug); letter-spacing: var(--tr-tight); font-weight: 600; margin: 0; }
887
932
  .ds-247420 h2, .ds-247420 .t-h2 { font-family: var(--ff-display); font-size: var(--fs-h2); line-height: var(--lh-snug); letter-spacing: var(--tr-tight); font-weight: 600; margin: 0; }
@@ -1429,7 +1474,7 @@
1429
1474
  }
1430
1475
  .ds-247420 .btn-primary:hover { background: var(--fg); color: var(--green); transform: translateY(-1px); box-shadow: var(--shadow-2); }
1431
1476
  .ds-247420 .btn-ghost { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 2px var(--fg); }
1432
- .ds-247420 .btn-ghost:hover { background: var(--fg); color: var(--bg); transform: translateY(-1px); }
1477
+ .ds-247420 .btn-ghost:hover { background: color-mix(in oklab, var(--fg) 12%, transparent); transform: translateY(-1px); }
1433
1478
  .ds-247420 .btn:active, .ds-247420 .btn-primary:active, .ds-247420 .btn-ghost:active { transform: translateY(1px); box-shadow: none; }
1434
1479
  .ds-247420 .btn:focus-visible, .ds-247420 .btn-primary:focus-visible, .ds-247420 .btn-ghost:focus-visible, .ds-247420 .ds-icon-btn:focus-visible {
1435
1480
  outline: var(--focus-w) solid var(--focus-color);
@@ -1461,7 +1506,9 @@
1461
1506
  border-radius: var(--r-1, 6px);
1462
1507
  background: transparent; color: var(--fg);
1463
1508
  width: 32px; height: 32px;
1509
+ transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
1464
1510
  }
1511
+ .ds-247420 .ds-icon-btn:hover { background: var(--bg-2); }
1465
1512
  .ds-247420 .ds-icon-btn-xs { width: 22px; height: 22px; }
1466
1513
  .ds-247420 .ds-icon-btn-sm { width: 26px; height: 26px; }
1467
1514
  .ds-247420 .ds-icon-btn-base { width: 32px; height: 32px; }
@@ -1471,7 +1518,10 @@
1471
1518
  .ds-247420 .ds-icon-btn-ghost:hover { background: var(--fg); color: var(--bg); }
1472
1519
  .ds-247420 .ds-icon-btn-primary { background: var(--accent); color: var(--accent-fg); }
1473
1520
  .ds-247420 .ds-icon-btn-primary:hover { background: var(--fg); color: var(--accent-ink); }
1474
- .ds-247420 .ds-icon-btn-danger { background: var(--warn); color: var(--on-color); }
1521
+ /* --ink, not --on-color: --on-color is a fixed #fff, which measures 3.07:1 on
1522
+ --warn (#FF5A52) -- below the 4.5:1 AA floor. --ink measures 6.27:1. Same
1523
+ fix as .btn-primary.danger in app-shell/files.css. */
1524
+ .ds-247420 .ds-icon-btn-danger { background: var(--warn); color: var(--ink); }
1475
1525
  .ds-247420 .ds-icon-btn-danger:hover { filter: brightness(0.92); }
1476
1526
  .ds-247420 .ds-icon-btn:active { transform: translateY(1px); }
1477
1527
  .ds-247420 .ds-icon-btn:disabled, .ds-247420 .ds-icon-btn.is-disabled {
@@ -1485,7 +1535,7 @@
1485
1535
  border-radius: var(--r-pill);
1486
1536
  background: var(--bg-3); color: var(--fg-2);
1487
1537
  }
1488
- .ds-247420 .ds-badge.ds-badge--sm { min-width: 14px; height: 14px; padding: 0 var(--space-1); font-size: 10px; }
1538
+ .ds-247420 .ds-badge.ds-badge--sm { min-width: 14px; height: 14px; padding: 0 var(--space-1); font-size: var(--fs-pico); }
1489
1539
  .ds-247420 .ds-badge.ds-badge--lg { min-width: 22px; height: 22px; padding: 0 var(--space-2); font-size: var(--fs-tiny); }
1490
1540
  .ds-247420 .ds-badge.tone-green, .ds-247420 .ds-badge.tone-live, .ds-247420 .ds-badge.tone-success {
1491
1541
  background: var(--green-tint); color: var(--green-deep);
@@ -1502,7 +1552,7 @@
1502
1552
  background: var(--sun); color: var(--ink);
1503
1553
  }
1504
1554
  .ds-247420 .ds-badge.tone-blue { background: var(--accent-tint); color: var(--accent-ink); }
1505
- .ds-247420 .ds-badge.tone-orange { background: color-mix(in oklab, var(--flame) 30%, var(--sun) 70%); color: var(--ink); }
1555
+ .ds-247420 .ds-badge.tone-orange { background: color-mix(in oklab, var(--flame) 22%, var(--bg)); color: color-mix(in oklab, var(--flame) 65%, black); }
1506
1556
 
1507
1557
  .ds-247420 .chip {
1508
1558
  display: inline-flex; align-items: center; gap: var(--space-1-75);
@@ -1570,6 +1620,10 @@
1570
1620
  .ds-247420 .ds-pill.tone-accent { background: var(--accent-tint); color: var(--accent-ink); }
1571
1621
  .ds-247420 .ds-pill.tone-muted { background: transparent; color: var(--fg-3); box-shadow: inset 0 0 0 1px var(--rule); }
1572
1622
 
1623
+ /* .glyph-* sizes (14/18/22px) are for small inline text-adjacent glyphs
1624
+ (single characters/icons sitting in a text flow), a different scale and
1625
+ purpose than the .ds-icon-btn-* tap-target scale (22/26/32/40/48px) below --
1626
+ the -sm/-lg naming overlap is coincidental, not a shared system. */
1573
1627
  .ds-247420 .glyph {
1574
1628
  display: inline-flex; align-items: center; justify-content: center;
1575
1629
  width: 18px; height: 18px;
@@ -2383,7 +2437,7 @@
2383
2437
  Form
2384
2438
  ============================================================ */
2385
2439
  .ds-247420 .row-form {
2386
- display: grid; gap: 12px;
2440
+ display: grid; gap: var(--space-2-75);
2387
2441
  padding: var(--space-5);
2388
2442
  background: var(--bg-2);
2389
2443
  border-radius: var(--r-3);
@@ -2416,6 +2470,19 @@
2416
2470
  Responsive Design — Mobile (480px), Tablet (1024px), Desktop (1440px+)
2417
2471
  ============================================================ */
2418
2472
 
2473
+ /* Breakpoint reference (CSS custom properties can't be used in @media queries,
2474
+ so these are documented here for consistency — always use these exact values):
2475
+ - Mobile/tablet boundary: 768px (max-width) — used for compact nav/sidebar
2476
+ collapse (catalog-theme.css, sidebar-misc.css). Note: kits-appended.css
2477
+ uses 760px for the same kind of collapse in a few places — a near-miss
2478
+ of this value, worth aligning to 768px when touched.
2479
+ - Tablet/desktop boundary: 900px (max-width) / 901px (min-width) — used for
2480
+ main layout reflow (hero-content.css, responsive2-workspace.css)
2481
+ - Legacy tablet band: 481px–1024px (min-width 481px / max-width 1025px) —
2482
+ used in this file (responsive.css) for a specific tablet treatment,
2483
+ consider migrating to the 768/900 pair
2484
+ */
2485
+
2419
2486
  /* --------------------------------------------------------------------
2420
2487
  Mobile Portrait Breakpoint (480px and below)
2421
2488
  ---------------------------------------------------------------------- */
@@ -3461,7 +3528,7 @@
3461
3528
  .ds-247420 .ds-preview-code::-webkit-scrollbar,
3462
3529
  .ds-247420 .ds-preview-text::-webkit-scrollbar,
3463
3530
  .ds-247420 .ds-preview-body::-webkit-scrollbar,
3464
- .ds-247420 .ds-modal-body::-webkit-scrollbar { width: 10px; height: 10px; }
3531
+ .ds-247420 .ds-modal-body::-webkit-scrollbar { width: 8px; height: 8px; }
3465
3532
  .ds-247420 .ds-preview-code::-webkit-scrollbar-thumb,
3466
3533
  .ds-247420 .ds-preview-text::-webkit-scrollbar-thumb {
3467
3534
  background: color-mix(in oklab, var(--paper) 28%, transparent);
@@ -3636,13 +3703,25 @@
3636
3703
  font-family: var(--ff-mono); font-size: var(--fs-xs);
3637
3704
  display: inline-flex; align-items: center; gap: 6px;
3638
3705
  }
3639
- /* CSS-drawn half-disc mark on the compact theme toggle: keeps the control
3640
- legible when its text label is hidden (icon-only rail strip). */
3706
+ /* CSS-drawn disc mark on the compact theme toggle: keeps the control
3707
+ legible when its text label is hidden (icon-only rail strip). Per-mode
3708
+ fill gives the icon itself a distinct look for auto/light/dark, so state
3709
+ reads without relying on the title tooltip alone. */
3641
3710
  .ds-247420 .ds-theme-disc {
3642
3711
  flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%;
3643
3712
  border: var(--bw-hair) solid var(--fg-3);
3713
+ /* auto: half-and-half, matches default (no data-mode) for safety */
3644
3714
  background: linear-gradient(90deg, var(--fg-3) 0 50%, transparent 50% 100%);
3645
3715
  }
3716
+ .ds-247420 .ds-theme-disc[data-mode="auto"] {
3717
+ background: linear-gradient(90deg, var(--fg-3) 0 50%, transparent 50% 100%);
3718
+ }
3719
+ .ds-247420 .ds-theme-disc[data-mode="paper"] {
3720
+ background: var(--bg); border-color: var(--fg-3);
3721
+ }
3722
+ .ds-247420 .ds-theme-disc[data-mode="ink"] {
3723
+ background: var(--fg-3); border-color: var(--fg-3);
3724
+ }
3646
3725
 
3647
3726
  /* ============================================================
3648
3727
  Chat kit polish — styles every class emitted by Chat /
@@ -3715,6 +3794,18 @@
3715
3794
  background: color-mix(in oklab, var(--mascot) 26%, var(--bg-2));
3716
3795
  color: var(--mascot-deep);
3717
3796
  }
3797
+ /* Plain assistant turns ('them', no aicat persona) previously fell through to
3798
+ the bare .chat-avatar gray disc with no role identity at all — 'you' and
3799
+ 'aicat' both got a tinted background + ring, the default assistant got
3800
+ nothing. Give it the same tinted-background treatment via --color-success
3801
+ (the conventional assistant/bot association, distinct from the accent hue
3802
+ 'you' owns and the mascot hue 'aicat' owns) plus a thin identity ring so
3803
+ role is readable from the avatar alone, not just bubble position/color. */
3804
+ .ds-247420 .chat-msg.them:not(.aicat) .chat-avatar {
3805
+ background: color-mix(in oklab, var(--color-success) 20%, var(--bg-3));
3806
+ color: color-mix(in oklab, var(--color-success) 65%, var(--fg));
3807
+ box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--color-success) 35%, transparent);
3808
+ }
3718
3809
 
3719
3810
  .ds-247420 .chat-stack {
3720
3811
  display: flex; flex-direction: column; gap: var(--space-1);
@@ -4284,12 +4375,26 @@
4284
4375
  more "still looks clickable-green") and the steeper opacity drop reads as
4285
4376
  unmistakably inert at a glance, not just slightly dimmed. */
4286
4377
  .ds-247420 .btn:disabled, .ds-247420 .btn-primary:disabled, .ds-247420 .btn-ghost:disabled, .ds-247420 .btn.is-disabled, .ds-247420 .btn-primary.is-disabled, .ds-247420 .btn-ghost.is-disabled, .ds-247420 button:disabled, .ds-247420[disabled] {
4287
- opacity: 0.45;
4378
+ opacity: 0.5;
4288
4379
  filter: grayscale(60%);
4289
4380
  cursor: not-allowed;
4290
4381
  pointer-events: none;
4291
4382
  }
4292
4383
 
4384
+ /* Systemic hover fallback — button-like elements with no design-system class
4385
+ (a bare <button>, [role="button"], or a generic .row/.chip usage) get a
4386
+ `transition` declared above (line ~106) but nothing to transition to, so
4387
+ they look inert until clicked. This is a low-specificity (0,0,1)/(0,1,1)
4388
+ catch-all: any element that also carries `.btn`/`.btn-primary`/`.btn-ghost`/
4389
+ `.ds-icon-btn`/etc. keeps its own component `:hover` (those selectors are
4390
+ equal-or-higher specificity and, for the shared ones, declared later in
4391
+ the cascade), so this never overrides a deliberate per-component hover —
4392
+ it only fills the gap for elements that don't have one. */
4393
+ .ds-247420 button:not(:disabled):hover,
4394
+ .ds-247420[role="button"]:not([aria-disabled="true"]):hover {
4395
+ background-color: var(--panel-hover, var(--bg-3));
4396
+ }
4397
+
4293
4398
  /* Loading state — spinning indicator */
4294
4399
  @keyframes spinner-rotate {
4295
4400
  from { transform: rotate(0deg); }
@@ -4297,10 +4402,12 @@
4297
4402
  }
4298
4403
  /* Reusable spin utility: rotates the element (e.g. a refresh Icon used as a
4299
4404
  busy indicator) via the shared spinner-rotate keyframe. Respects reduced
4300
- motion. Use instead of a decorative rotation glyph. */
4405
+ motion. Use instead of a decorative rotation glyph.
4406
+ Ring spinner — use for larger blocking/full-region loading states. */
4301
4407
  .ds-247420 .ds-spin { animation: spinner-rotate 0.8s linear infinite; transform-origin: center; }
4302
4408
  @media (prefers-reduced-motion: reduce) { .ds-247420 .ds-spin { animation: none; } }
4303
4409
 
4410
+ /* Ring spinner — use for larger blocking/full-region loading states. */
4304
4411
  .ds-247420 .loading { position: relative; }
4305
4412
  .ds-247420 .loading::after {
4306
4413
  content: '';
@@ -4721,7 +4828,7 @@
4721
4828
  background: var(--accent-ink); border-color: var(--accent-ink);
4722
4829
  }
4723
4830
  .ds-247420 .ds-toggle[aria-checked="true"] .ds-toggle-knob {
4724
- background: var(--panel-0, #fff);
4831
+ background: var(--panel-0, var(--bg));
4725
4832
  transform: translateX(18px);
4726
4833
  }
4727
4834
  .ds-247420 .ds-toggle:disabled { opacity: 0.5; cursor: not-allowed; }
@@ -4855,7 +4962,7 @@
4855
4962
  .ds-247420 .ds-field input:not(.input):disabled,
4856
4963
  .ds-247420 .ds-field textarea:not(.input):disabled,
4857
4964
  .ds-247420 .ds-field .ds-select:disabled {
4858
- opacity: .55;
4965
+ opacity: 0.5;
4859
4966
  cursor: not-allowed;
4860
4967
  }
4861
4968
  .ds-247420 .ds-field input:not(.input)[aria-invalid="true"],
@@ -5112,15 +5219,16 @@
5112
5219
  /* ============================================================
5113
5220
  Spinner — animated loading indicator
5114
5221
  ============================================================ */
5222
+ /* Dots spinner — use for small inline/compact loading states. */
5115
5223
  .ds-247420 .ds-spinner {
5116
5224
  display: inline-flex;
5117
- gap: 4px;
5225
+ gap: var(--space-1);
5118
5226
  align-items: center;
5119
5227
  height: 16px;
5120
5228
  }
5121
5229
  .ds-247420 .ds-spinner span {
5122
- width: 4px;
5123
- height: 4px;
5230
+ width: var(--space-1);
5231
+ height: var(--space-1);
5124
5232
  border-radius: 50%;
5125
5233
  background: var(--accent);
5126
5234
  }
@@ -5131,17 +5239,17 @@
5131
5239
  .ds-247420 .ds-spinner span:nth-child(3) { animation-delay: 0.36s; }
5132
5240
  }
5133
5241
 
5134
- .ds-247420 .ds-spinner-lg { height: 24px; gap: 6px; }
5135
- .ds-247420 .ds-spinner-lg span { width: 6px; height: 6px; }
5242
+ .ds-247420 .ds-spinner-lg { height: 24px; gap: var(--space-1-75); }
5243
+ .ds-247420 .ds-spinner-lg span { width: var(--space-1-75); height: var(--space-1-75); }
5136
5244
 
5137
- .ds-247420 .ds-spinner-sm { height: 12px; gap: 2px; }
5138
- .ds-247420 .ds-spinner-sm span { width: 2px; height: 2px; }
5245
+ .ds-247420 .ds-spinner-sm { height: 12px; gap: var(--space-hair); }
5246
+ .ds-247420 .ds-spinner-sm span { width: var(--space-hair); height: var(--space-hair); }
5139
5247
 
5140
5248
  .ds-247420 .ds-spinner-xs { height: 8px; gap: 1px; }
5141
5249
  .ds-247420 .ds-spinner-xs span { width: 1.5px; height: 1.5px; }
5142
5250
 
5143
- .ds-247420 .ds-spinner-xl { height: 32px; gap: 8px; }
5144
- .ds-247420 .ds-spinner-xl span { width: 8px; height: 8px; }
5251
+ .ds-247420 .ds-spinner-xl { height: 32px; gap: var(--space-2); }
5252
+ .ds-247420 .ds-spinner-xl span { width: var(--space-2); height: var(--space-2); }
5145
5253
 
5146
5254
  @keyframes ds-bounce {
5147
5255
  0%, 80%, 100% { transform: translateY(0); }
@@ -5191,7 +5299,7 @@
5191
5299
  flex-shrink: 0;
5192
5300
  color: var(--alert-tone);
5193
5301
  font-weight: 600;
5194
- min-width: 20px;
5302
+ min-width: var(--space-3-5);
5195
5303
  text-align: center;
5196
5304
  }
5197
5305
 
@@ -5220,13 +5328,14 @@
5220
5328
  cursor: pointer;
5221
5329
  color: var(--fg-3);
5222
5330
  padding: 0;
5223
- font-size: 14px;
5331
+ font-size: var(--fs-xs);
5224
5332
  line-height: 1;
5225
- min-width: 20px;
5333
+ min-width: var(--space-3-5);
5226
5334
  text-align: center;
5227
5335
  transition: color var(--dur-snap) var(--ease);
5228
5336
  }
5229
5337
  .ds-247420 .ds-alert-dismiss:hover { color: var(--fg); }
5338
+ .ds-247420 .ds-alert-dismiss:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: var(--focus-offset); }
5230
5339
 
5231
5340
  /* ============================================================
5232
5341
  Responsive Perfection — Drawer rail, ultrawide cap, mobile compact
@@ -5511,7 +5620,9 @@
5511
5620
  .ds-247420 .ws-rail-item:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: -2px; }
5512
5621
  .ds-247420 .ws-rail-item.active { background: var(--accent-tint); color: var(--fg); box-shadow: inset 2px 0 0 var(--accent); }
5513
5622
  .ds-247420 .ws-rail-item-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
5514
- .ds-247420 .ws-rail-item-count { font-family: var(--ff-mono); font-size: var(--fs-tiny); color: var(--fg-3); }
5623
+ /* Shape/color come from the shared .ds-badge component (see app-shell/primitives.css);
5624
+ this class is now just the rail-item layout hook (spacing, collapsed-state targeting). */
5625
+ .ds-247420 .ws-rail-item-count { flex: none; margin-inline-start: var(--space-1); }
5515
5626
  .ds-247420 .ws-rail-item-flag { width: 6px; height: 6px; border-radius: 50%; flex: none; }
5516
5627
  .ds-247420 .ws-rail-item-flag.tone-flame { background: var(--flame); box-shadow: 0 0 0 2px color-mix(in oklab, var(--flame) 38%, transparent); }
5517
5628
  .ds-247420 .ws-rail-foot { margin-top: auto; padding-top: var(--space-2); border-top: var(--bw-hair) solid var(--bg-3); }
@@ -5554,6 +5665,7 @@
5554
5665
  because the chat thread carries its own --measure gutter. */
5555
5666
  .ds-247420 .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; padding: var(--space-4) var(--space-5); }
5556
5667
  .ds-247420 .ws-main.ws-main--flush { padding: 0; }
5668
+ /* Non-interactive scroll region (content column), not a focusable control — outline intentionally suppressed. */
5557
5669
  .ds-247420 .ws-main:focus { outline: none; }
5558
5670
 
5559
5671
  /* Right context pane */
@@ -5837,6 +5949,10 @@
5837
5949
 
5838
5950
  /* PhaseWalk */
5839
5951
  .ds-247420 .ds-phasewalk { display: inline-flex; gap: var(--space-hair); vertical-align: middle; }
5952
+ /* NOTE: a second toggle-switch-shaped implementation exists in
5953
+ plugins-config.css:91 (.ds-plugins-toggle) at a different scale (40x22 vs
5954
+ this 18x10) — consider consolidating into a shared .ds-switch primitive
5955
+ with a size modifier. */
5840
5956
  .ds-247420 .ds-phasewalk-seg {
5841
5957
  width: 18px; height: 10px; border-radius: var(--r-hair);
5842
5958
  background: var(--bg-3); position: relative;
@@ -7245,6 +7361,9 @@
7245
7361
  }
7246
7362
  .ds-247420 .ds-plugins-version { font-size: var(--fs-micro); color: var(--fg-3); }
7247
7363
 
7364
+ /* NOTE: a second toggle-switch implementation exists in data-density.css:18
7365
+ (.ds-phasewalk-seg) at a different scale (18x10 vs this 40x22) — consider
7366
+ consolidating into a shared .ds-switch primitive with a size modifier. */
7248
7367
  .ds-247420 .ds-plugins-toggle {
7249
7368
  flex: 0 0 auto; width: 40px; height: 22px; border-radius: 11px; border: none; padding: 0;
7250
7369
  background: var(--rule); position: relative; cursor: pointer;
@@ -7487,11 +7606,11 @@
7487
7606
  .ds-247420 .ds-otp-box:focus-visible {
7488
7607
  outline: none;
7489
7608
  border-color: var(--accent);
7490
- box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 40%, transparent);
7609
+ box-shadow: var(--focus-ring-inset);
7491
7610
  }
7492
7611
  .ds-247420 .ds-otp-box-filled { border-color: var(--rule-strong); background: var(--bg-3); }
7493
7612
  .ds-247420 .ds-otp-box-error { border-color: var(--red); }
7494
- .ds-247420 .ds-otp-box-error:focus-visible { box-shadow: 0 0 0 3px color-mix(in oklab, var(--red) 40%, transparent); }
7613
+ .ds-247420 .ds-otp-box-error:focus-visible { box-shadow: var(--focus-ring-inset); }
7495
7614
  .ds-247420 .ds-otp-box:disabled { opacity: 0.5; cursor: default; }
7496
7615
 
7497
7616
  @media (prefers-reduced-motion: reduce) {
@@ -7755,6 +7874,11 @@
7755
7874
  border-radius: var(--r-pill);
7756
7875
  background: var(--bg-2);
7757
7876
  }
7877
+ /* .ds-collab-chip-avatar (24px identity circle) and .ds-collab-chip-status
7878
+ (8px status dot) below are both circular via border-radius: 50% but are
7879
+ intentionally distinct: different sizes, different content (initial vs.
7880
+ plain fill), different positioning role (layout box vs. absolute badge).
7881
+ Not extracting a shared class -- there's nothing substantive to share. */
7758
7882
  .ds-247420 .ds-collab-chip-avatar {
7759
7883
  position: relative;
7760
7884
  width: 24px;
@@ -7919,6 +8043,9 @@
7919
8043
  min-width: 18px;
7920
8044
  height: 18px;
7921
8045
  padding: 0 var(--space-1-5);
8046
+ /* TODO(a11y): --paper is a fixed near-white on --warn (#FF5A52) -- likely
8047
+ ~3:1, below the 4.5:1 AA floor (same defect fixed via --ink elsewhere
8048
+ for --warn text). Small numeric badge; needs contrast audit. */
7922
8049
  background: var(--warn);
7923
8050
  color: var(--paper);
7924
8051
  font-family: var(--ff-mono);
@@ -8251,6 +8378,9 @@
8251
8378
  min-width: 16px;
8252
8379
  height: 16px;
8253
8380
  padding: 0 var(--space-1-5);
8381
+ /* TODO(a11y): --paper is a fixed near-white on --warn (#FF5A52) -- likely
8382
+ ~3:1, below the 4.5:1 AA floor (same defect fixed via --ink elsewhere
8383
+ for --warn text). Small numeric badge; needs contrast audit. */
8254
8384
  background: var(--warn);
8255
8385
  color: var(--paper);
8256
8386
  font-family: var(--ff-mono);
@@ -8334,7 +8464,7 @@
8334
8464
  height: 20px;
8335
8465
  border-radius: 50%;
8336
8466
  background: var(--avatar-bg, var(--bg-3));
8337
- color: var(--fg-2);
8467
+ color: var(--avatar-fg, var(--fg-2));
8338
8468
  display: inline-flex;
8339
8469
  align-items: center;
8340
8470
  justify-content: center;
@@ -8440,8 +8570,11 @@
8440
8570
  background: color-mix(in oklab, var(--fg) 18%, transparent);
8441
8571
  }
8442
8572
  .ds-247420 .cm-vs-btn.danger {
8573
+ /* --ink, not --paper: --paper is a fixed near-white, which measures ~3:1 on
8574
+ --warn (#FF5A52) -- below the 4.5:1 AA floor. Same fix pattern as
8575
+ .btn-primary.danger in app-shell/files.css. */
8443
8576
  background: var(--warn);
8444
- color: var(--paper);
8577
+ color: var(--ink);
8445
8578
  }
8446
8579
  .ds-247420 .cm-vs-btn.danger:hover {
8447
8580
  background: color-mix(in oklab, var(--warn) 80%, var(--ink));
@@ -8466,7 +8599,7 @@
8466
8599
  height: 32px;
8467
8600
  border-radius: 50%;
8468
8601
  background: var(--avatar-bg, var(--bg-3));
8469
- color: var(--fg-2);
8602
+ color: var(--avatar-fg, var(--fg-2));
8470
8603
  display: inline-flex;
8471
8604
  align-items: center;
8472
8605
  justify-content: center;
@@ -8677,7 +8810,7 @@
8677
8810
  height: 28px;
8678
8811
  border-radius: 50%;
8679
8812
  background: var(--avatar-bg, var(--bg-3));
8680
- color: var(--fg-2);
8813
+ color: var(--avatar-fg, var(--fg-2));
8681
8814
  display: inline-flex;
8682
8815
  align-items: center;
8683
8816
  justify-content: center;
@@ -8738,7 +8871,7 @@
8738
8871
  height: 56px;
8739
8872
  border-radius: 50%;
8740
8873
  background: var(--avatar-bg, var(--bg-3));
8741
- color: var(--fg-2);
8874
+ color: var(--avatar-fg, var(--fg-2));
8742
8875
  display: inline-flex;
8743
8876
  align-items: center;
8744
8877
  justify-content: center;
@@ -9449,10 +9582,14 @@
9449
9582
  /* PageView — cm-page / cm-page-* */
9450
9583
  .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); }
9451
9584
  .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); }
9585
+ .ds-247420 .cm-page-head-title { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
9452
9586
  .ds-247420 .cm-page-title { margin: 0; font-size: var(--fs-xl); font-weight: 700; }
9587
+ .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)); }
9588
+ .ds-247420 .cm-page-author { font-weight: 500; }
9589
+ .ds-247420 .cm-page-time { opacity: .75; }
9453
9590
  .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; }
9454
9591
  .ds-247420 .cm-page-body { padding: var(--space-3); line-height: 1.6; }
9455
- .ds-247420 .cm-page-empty { color: var(--fg-2, var(--fg)); opacity: .7; }
9592
+ .ds-247420 .cm-page-empty { color: var(--fg-2, var(--fg)); opacity: .82; }
9456
9593
 
9457
9594
  /* ============================================================
9458
9595
  freddie pages — layout for FREDDIE_PAGES renderers.
@@ -9465,8 +9602,9 @@
9465
9602
  .ds-247420 .fd-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-2, 10px); padding: var(--space-5, 32px) var(--space-3, 16px); color: var(--fg-2, var(--fg)); text-align: center; }
9466
9603
  /* 28px is an ICON size (empty-state mark), not a type tier — the --fs-* ladder
9467
9604
  tops out at --fs-xl (21px) before every remaining rung becomes a fluid
9468
- heading clamp, so neither substitutes without visibly resizing the mark. */
9469
- .ds-247420 .fd-empty-glyph { font-size: 28px; opacity: .55; line-height: 1; }
9605
+ heading clamp, so neither substitutes without visibly resizing the mark.
9606
+ --fs-2xl bridges that gap as a fixed 28px token. */
9607
+ .ds-247420 .fd-empty-glyph { font-size: var(--fs-2xl); opacity: .55; line-height: 1; }
9470
9608
  .ds-247420 .fd-pre { margin: 0; padding: var(--space-2, 10px); background: var(--bg-3, var(--panel-bg-2)); border: var(--bw-hair, 1px) solid var(--rule, var(--panel-accent)); border-radius: var(--r-1, 6px); overflow: auto; max-height: 460px; white-space: pre-wrap; overflow-wrap: anywhere; word-break: break-word; font-family: var(--font-mono, ui-monospace, monospace); font-size: var(--fs-micro); line-height: 1.5; }
9471
9609
  .ds-247420 .fd-skill-body { max-height: 320px; }
9472
9610
  .ds-247420 .fd-row-actions { display: inline-flex; gap: var(--space-1, 6px); align-items: center; }
@@ -10052,7 +10190,7 @@
10052
10190
  background: var(--bg); border: var(--border-w) solid var(--accent); border-radius: var(--r-1);
10053
10191
  padding: var(--space-1) var(--space-2);
10054
10192
  }
10055
- .ds-247420 .ds-session-rename-input:focus { outline: none; }
10193
+ .ds-247420 .ds-session-rename-input:focus { outline: none; box-shadow: var(--focus-ring-inset); }
10056
10194
 
10057
10195
  /* Inline delete confirm — same row height, two flat buttons, no modal;
10058
10196
  mirrors SessionDashboard's arm-then-confirm bulk-stop control. */
@@ -10929,7 +11067,7 @@
10929
11067
  /* Minimap internal order: centerline < viewport < dot < tooltip. All four
10930
11068
  live inside the one raised widget, so they share its rung and differ
10931
11069
  only by a local offset. */
10932
- z-index: calc(var(--z-raised) + 1);
11070
+ z-index: var(--z-raised-1);
10933
11071
  }
10934
11072
  .ds-247420 .chat-minimap-centerline {
10935
11073
  position: absolute;
@@ -10949,7 +11087,7 @@
10949
11087
  border-radius: var(--r-pill, 999px);
10950
11088
  transform: translate(-50%, -50%) scale(1);
10951
11089
  transition: transform 0.1s;
10952
- z-index: calc(var(--z-raised) + 2);
11090
+ z-index: var(--z-raised-2);
10953
11091
  }
10954
11092
  .ds-247420 .chat-minimap-dot.is-user {
10955
11093
  background: color-mix(in oklab, var(--accent) 18%, transparent);
@@ -10974,7 +11112,7 @@
10974
11112
  /* Top of the minimap's internal order. Deliberately NOT --z-tooltip: it is
10975
11113
  clipped to the minimap rail rather than floating over the app, so it must
10976
11114
  not outrank real overlays that may cover the rail. */
10977
- z-index: calc(var(--z-raised) + 3);
11115
+ z-index: var(--z-raised-3);
10978
11116
  pointer-events: none;
10979
11117
  opacity: 0.45;
10980
11118
  font-size: var(--fs-tiny);
@@ -12345,6 +12483,14 @@
12345
12483
  box-shadow: var(--shadow-3);
12346
12484
  outline: none; overflow: hidden;
12347
12485
  }
12486
+ .ds-247420 .ov-emoji-search {
12487
+ flex-shrink: 0; margin: var(--space-2, 8px); margin-bottom: 0;
12488
+ padding: var(--space-1-5, 6px) var(--space-2, 8px);
12489
+ border: 1px solid var(--rule); border-radius: var(--r-1, 10px);
12490
+ background: var(--bg-1, var(--bg-3)); color: var(--fg);
12491
+ font: inherit; font-size: var(--fs-sm, 13px);
12492
+ }
12493
+ .ds-247420 .ov-emoji-search:focus-visible { outline: var(--focus-w) solid var(--focus-color); outline-offset: 1px; }
12348
12494
  .ds-247420 .ov-emoji-tabs {
12349
12495
  display: flex; flex-shrink: 0;
12350
12496
  border-bottom: 1px solid var(--rule);
@@ -12503,7 +12649,7 @@
12503
12649
  .ds-247420 .ov-lightbox-x { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border: none; border-radius: 50%; background: color-mix(in oklab, var(--on-color) 12%, transparent); color: var(--on-color); font-size: 24px; line-height: 1; cursor: pointer; }
12504
12650
  .ds-247420 .ov-lightbox-x:hover { background: color-mix(in oklab, var(--on-color) 24%, transparent); }
12505
12651
  .ds-247420 .ov-lightbox-stage { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); max-width: 92vw; max-height: 90vh; }
12506
- .ds-247420 .ov-lightbox-video { max-width: 92vw; max-height: 82vh; border-radius: var(--r-1); background: #000; /* true black media letterbox, intentional */ }
12652
+ .ds-247420 .ov-lightbox-video { max-width: 92vw; max-height: 82vh; border-radius: var(--r-1); background: var(--media-letterbox); /* true black media letterbox, intentional */ }
12507
12653
  .ds-247420 .ov-lightbox-label { color: var(--on-color); font-size: var(--fs-tiny); opacity: .85; }
12508
12654
 
12509
12655
  /* ---------------------------------------------------------------
@@ -12608,16 +12754,6 @@
12608
12754
  color: var(--panel-text);
12609
12755
  overflow: hidden;
12610
12756
  }
12611
- /* prefers-reduced-transparency: the dock's whole "non-occluding" idiom (see
12612
- the comment above this block) relies on translucency + blur to let the
12613
- viewport read through behind it; a user who has disabled see-through
12614
- panel chrome gets a fully solid --panel-1 backing instead, same layout. */
12615
- @media (prefers-reduced-transparency: reduce) {
12616
- .ds-247420 .ds-ep-dock {
12617
- background: var(--panel-1);
12618
- -webkit-backdrop-filter: none; backdrop-filter: none;
12619
- }
12620
- }
12621
12757
  .ds-247420 .ds-ep-dock-left { left: 8px; }
12622
12758
  .ds-247420 .ds-ep-dock-right { right: 8px; }
12623
12759
  /* Collapsed: shrink to just the header strip, freeing the viewport. */
@@ -13547,14 +13683,14 @@
13547
13683
  * prefixer leaves it untouched (consumers mount on <html class="ds-247420">).
13548
13684
  * All values read kit tokens — no hardcoded hex, no inline design in the app. */
13549
13685
 
13550
- .ds-247420 .site-panel { margin: var(--space-2); }
13686
+ .ds-247420 .site-panel { margin: var(--space-2); max-width: 1100px; padding: var(--space-3, 16px); }
13551
13687
 
13552
13688
  /* Hero block */
13553
13689
  .ds-247420 .site-hero { padding: var(--space-4); }
13554
13690
  .ds-247420 .site-hero-h { margin: 0 0 var(--space-2); }
13555
13691
  .ds-247420 .site-hero-body { margin: var(--space-2) 0 var(--space-3); color: var(--fg-2); max-width: 64ch; }
13556
- .ds-247420 .site-chip-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 var(--space-3); }
13557
- .ds-247420 .site-cta-row { display: flex; gap: var(--space-2); flex-wrap: wrap; }
13692
+ .ds-247420 .site-chip-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 0 0 var(--space-3); }
13693
+ .ds-247420 .site-cta-row { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
13558
13694
 
13559
13695
  /* Quickstart CLI block — these .cli/.prompt/.cmd nodes were previously unstyled. */
13560
13696
  .ds-247420 .site-cli { padding: var(--space-3); background: var(--bg); border: var(--bw-hair, 1px) solid var(--rule); border-radius: var(--r-1); }
@@ -13769,12 +13905,12 @@
13769
13905
  background: var(--bg);
13770
13906
  color: var(--fg);
13771
13907
  border: 1px solid var(--bw-rule, var(--rule));
13772
- border-radius: var(--r-1, 6px);
13773
- padding: 8px 10px;
13908
+ border-radius: var(--r-1, 8px);
13909
+ padding: var(--space-2) var(--space-2-5);
13774
13910
  font: var(--fs-body) var(--ff-mono);
13775
13911
  outline: none;
13776
13912
  }
13777
- .ds-247420 .sp-lobby-input:focus { border-color: var(--accent); }
13913
+ .ds-247420 .sp-lobby-input:focus-visible { border-color: var(--accent); box-shadow: var(--focus-ring-inset); }
13778
13914
  .ds-247420 .sp-lobby-link { font-size: var(--fs-small, 11px); }
13779
13915
  .ds-247420 .sp-lobby-code {
13780
13916
  font-family: var(--ff-display);