anentrypoint-design 0.0.280 → 0.0.282

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/README.md CHANGED
@@ -52,7 +52,7 @@ mount(document.getElementById('app'), () => C.AppShell({
52
52
  - **chrome** — `Topbar`, `Crumb`, `Side`, `Status`, `AppShell`, `Brand`, `Chip`, `Btn`, `Glyph`, `Heading`, `Lede`
53
53
  - **content** — `Panel`, `Row`, `RowLink`, `Hero`, `Install`, `Receipt`, `Changelog`, `WorksList`, `WritingList`, `Manifesto`, `Section`, `Kpi`, `Table`, `HomeView`, `ProjectView`
54
54
  - **chat** — `Chat`, `ChatMessage`, `ChatComposer`, `AICat`, `AICatPortrait`
55
- - **multi-agent chat shell** — `WorkspaceShell`, `WorkspaceRail`, `ConversationList`, `AgentChat`, `SessionDashboard` — the flagship desktop-class chat-agent product surface (persistent rail + resizable columns + full turn/tool-call thread + live multi-session dashboard). See `COMPONENT_API.md` for the full prop contract; the canonical real-world wiring ships at [`agentgui`](https://github.com/AnEntrypoint/agentgui).
55
+ - **multi-agent chat shell** — `WorkspaceShell`, `WorkspaceRail`, `ConversationList`, `AgentChat`, `SessionDashboard` — the flagship desktop-class chat-agent product surface (persistent rail + resizable columns + full turn/tool-call thread + live multi-session dashboard). See `COMPONENT_API.md` for the full prop contract; a runnable mock-data demo lives at `ui_kits/workspace/`; the canonical real-world wiring ships at [`agentgui`](https://github.com/AnEntrypoint/agentgui).
56
56
  - **file browser** — `FileRow`, `FileGrid`, `FileToolbar`, `FileIcon`, `DropZone`, `UploadProgress`, `EmptyState`, `BreadcrumbPath`, plus modal pieces `FileViewer`, `FilePreviewMedia`, `FilePreviewCode`, `FilePreviewText`, `ConfirmDialog`, `PromptDialog`
57
57
  - **ui_kits** — `homepage`, `project_page`, `docs`, `blog`, `chat`, `aicat`, `file_browser`. Each is a fully-working buildless example loading the SDK from this repo.
58
58
 
package/app-shell.css CHANGED
@@ -148,7 +148,7 @@ pre {
148
148
  pre .k { color: var(--code-str-alt, var(--mascot)); }
149
149
  pre .s { color: var(--code-string, var(--green)); }
150
150
  pre .c { color: var(--fg-3); }
151
- pre .n { color: var(--green-2); }
151
+ pre .n { color: var(--code-num); }
152
152
 
153
153
  /* ============================================================
154
154
  AppShell — page frame. The topbar floats above a soft background;
@@ -427,6 +427,19 @@ body.canvas-host { background: transparent !important; }
427
427
  .app-status .item:last-of-type:not(:only-of-type) { display: none; }
428
428
  }
429
429
 
430
+ /* The "dateline" — ASCII bar used at the top of every preview/brand page.
431
+ 3-4 flex slots; a .spread filler pushes the trailing slot to the far
432
+ edge instead of every span running together with no gap. */
433
+ .dateline {
434
+ display: flex; align-items: center; gap: var(--space-3);
435
+ flex-wrap: nowrap; overflow: hidden;
436
+ font-family: var(--ff-mono); font-size: var(--fs-xs); line-height: 1.2;
437
+ letter-spacing: 0.02em;
438
+ color: var(--fg-3);
439
+ }
440
+ .dateline span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
441
+ .dateline .spread { flex: 1 1 auto; min-width: var(--space-3); }
442
+
430
443
  /* ============================================================
431
444
  Primitives
432
445
  ============================================================ */
@@ -457,15 +470,15 @@ body.canvas-host { background: transparent !important; }
457
470
  an ink block with the lead as text, a confident two-tone flip. */
458
471
  .btn-primary {
459
472
  background: var(--accent); color: var(--accent-fg);
460
- font-weight: 700; letter-spacing: var(--tr-caps);
473
+ font-weight: 700;
461
474
  }
462
475
  .btn-primary:hover { background: var(--fg); color: var(--accent-ink); transform: translateY(-1px); box-shadow: var(--shadow-2); }
463
476
  .btn-ghost { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 2px var(--fg); }
464
477
  .btn-ghost:hover { background: var(--fg); color: var(--bg); transform: translateY(-1px); }
465
478
  .btn:active, .btn-primary:active, .btn-ghost:active { transform: translateY(1px); box-shadow: none; }
466
479
  .btn:focus-visible, .btn-primary:focus-visible, .btn-ghost:focus-visible, .ds-icon-btn:focus-visible {
467
- outline: 2px solid var(--accent-ink);
468
- outline-offset: 2px;
480
+ outline: var(--focus-w) solid var(--focus-color);
481
+ outline-offset: var(--focus-offset);
469
482
  }
470
483
 
471
484
  /* ============================================================
@@ -484,12 +497,12 @@ body.canvas-host { background: transparent !important; }
484
497
  .ds-icon-btn-lg { width: 40px; height: 40px; }
485
498
  .ds-icon-btn-xl { width: 48px; height: 48px; }
486
499
  .ds-icon-btn-ghost { background: transparent; }
487
- .ds-icon-btn-ghost:hover { background: var(--bg-2); }
500
+ .ds-icon-btn-ghost:hover { background: var(--fg); color: var(--bg); }
488
501
  .ds-icon-btn-primary { background: var(--accent); color: var(--accent-fg); }
489
502
  .ds-icon-btn-primary:hover { background: var(--fg); color: var(--bg); }
490
503
  /* warn = destructive ACTION tone; flame stays exclusively error STATUS. */
491
504
  .ds-icon-btn-danger { background: var(--warn); color: var(--on-color); }
492
- .ds-icon-btn-danger:hover { filter: brightness(1.1); }
505
+ .ds-icon-btn-danger:hover { filter: brightness(0.92); }
493
506
  .ds-icon-btn:active { transform: translateY(1px); }
494
507
  .ds-icon-btn:disabled, .ds-icon-btn.is-disabled {
495
508
  opacity: 0.5; cursor: not-allowed; pointer-events: none;
@@ -639,7 +652,7 @@ body.canvas-host { background: transparent !important; }
639
652
  white-space: pre-wrap;
640
653
  font-family: var(--ff-mono);
641
654
  font-size: var(--fs-sm);
642
- line-height: var(--lh-snug, 1.3);
655
+ line-height: var(--lh-snug);
643
656
  margin-top: 8px;
644
657
  padding: 10px 12px;
645
658
  background: var(--bg);
@@ -695,7 +708,7 @@ a.row:hover .meta, .row[role="button"]:hover .meta { color: var(--accent-ink); t
695
708
  .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
696
709
 
697
710
  .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; }
698
- .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; }
711
+ .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); line-height: var(--lh-snug); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
699
712
  .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
700
713
  /* App typescale: list rows are quiet working chrome (the 18px/600 default is a
701
714
  marketing-surface voice). One size for ALL app list rows - matches
@@ -1139,6 +1152,10 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1139
1152
  flex: 1 1 100%; margin-left: 0; order: 3; min-width: 0; max-width: 100%;
1140
1153
  display: flex; gap: 2px; flex-wrap: nowrap;
1141
1154
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
1155
+ /* Fade the trailing edge so a clipped last item (e.g. "source ->" cut to
1156
+ "sour") reads as scrollable content, not a broken/truncated label. */
1157
+ mask-image: linear-gradient(90deg, var(--fg) 0 calc(100% - 28px), transparent 100%);
1158
+ -webkit-mask-image: linear-gradient(90deg, var(--fg) 0 calc(100% - 28px), transparent 100%);
1142
1159
  }
1143
1160
  .app-topbar nav::-webkit-scrollbar { display: none; }
1144
1161
  .app-topbar nav a {
@@ -1192,8 +1209,12 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1192
1209
  font-size: var(--fs-xs);
1193
1210
  }
1194
1211
  .ds-file-open { gap: 10px; }
1195
- /* On mobile, fold meta under the title and keep actions inline. */
1196
- .ds-file-row .ds-file-meta { font-size: var(--fs-micro); }
1212
+ /* At mobile row widths, a fixed-size meta column (date/size) plus the
1213
+ always-visible action buttons leave the flexible title only a few px —
1214
+ not enough for even one legible character before the two collide. Drop
1215
+ the metadata column here; the title + actions still fully identify and
1216
+ operate on the row, and meta stays available in the file viewer. */
1217
+ .ds-file-row .ds-file-meta { display: none; }
1197
1218
  .ds-file-row .ds-file-actions { opacity: 1; }
1198
1219
  /* H4: floor finger-sized controls so file actions/sort/filter/breadcrumb are
1199
1220
  reachable by touch (cohesion sweep). */
@@ -1495,6 +1516,12 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1495
1516
  .ds-file-row .ds-file-meta {
1496
1517
  font-family: var(--ff-mono); font-size: var(--fs-xs);
1497
1518
  color: var(--fg-3); white-space: nowrap;
1519
+ /* Never shrink below content: a flex sibling with white-space:nowrap and
1520
+ the default flex-shrink:1 silently overflows its own box (no ellipsis)
1521
+ when the row runs out of width, painting the date/size over the title
1522
+ and action icons at mobile widths. Fixed-size the meta column instead
1523
+ and let .title (flex:1, min-width:0, ellipsis) absorb the squeeze. */
1524
+ flex-shrink: 0;
1498
1525
  }
1499
1526
 
1500
1527
  /* File icon — glyph chip, tinted per type. */
@@ -1964,6 +1991,7 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1964
1991
  border-color: var(--warn);
1965
1992
  color: var(--on-color);
1966
1993
  }
1994
+ .btn-primary.danger:hover { filter: brightness(0.92); border-color: var(--warn); }
1967
1995
 
1968
1996
  /* -- Preview ------------------------------------------------ */
1969
1997
  .ds-preview-head {
@@ -2773,6 +2801,14 @@ input[type="checkbox"], input[type="radio"] {
2773
2801
  transform var(--dur-snap) var(--ease);
2774
2802
  }
2775
2803
 
2804
+ /* Native checkbox/radio tint — browser default is UA blue, which fights the
2805
+ single lime lead accent wherever a raw control lands outside a bespoke
2806
+ toggle (e.g. signin's "remember me"). accent-color re-tints the native
2807
+ control box without hand-drawing a replacement. */
2808
+ input[type="checkbox"], input[type="radio"] {
2809
+ accent-color: var(--accent-ink);
2810
+ }
2811
+
2776
2812
  /* Prevent double-tap zoom on buttons (iOS) */
2777
2813
  .btn, .btn-primary, .btn-ghost, button {
2778
2814
  -webkit-user-select: none;
@@ -2936,6 +2972,52 @@ textarea::placeholder {
2936
2972
  color: var(--fg-3);
2937
2973
  }
2938
2974
 
2975
+ /* Rubber-stamp motif — a bordered, uppercase, letter-spaced badge with a
2976
+ slight built-in rotation (variants may override via inline transform for
2977
+ a stronger tilt). Max 1 per page per the component's own caption. */
2978
+ .stamp {
2979
+ display: inline-block;
2980
+ font-family: var(--ff-mono); font-size: var(--fs-xs); font-weight: 700;
2981
+ text-transform: uppercase; letter-spacing: 0.08em;
2982
+ padding: var(--space-1-5, var(--space-2)) var(--space-3);
2983
+ border: 2px solid var(--fg);
2984
+ border-radius: var(--r-hair);
2985
+ color: var(--fg);
2986
+ transform: rotate(-2deg);
2987
+ white-space: nowrap;
2988
+ }
2989
+ .stamp.ink { background: var(--ink); border-color: var(--ink); color: var(--paper); }
2990
+ .stamp.acid { background: var(--accent); border-color: var(--accent-ink); color: var(--accent-ink); }
2991
+
2992
+ /* Structural hairlines — "no boxes, no cards, structure comes from rules."
2993
+ Three weights: .rule (default separator), .rule-double (major section
2994
+ break), .rule-dotted (optional/skippable). Applied to a bare <hr>, which
2995
+ otherwise falls back to the browser's default inset groove line. */
2996
+ hr.rule, hr.rule-double, hr.rule-dotted {
2997
+ width: 100%; height: 0; border: 0;
2998
+ }
2999
+ hr.rule { border-top: 1px solid var(--rule); }
3000
+ hr.rule-double { border-top: 3px double var(--rule-strong); }
3001
+ hr.rule-dotted { border-top: 1px dotted var(--rule-strong); }
3002
+
3003
+ /* Hairline-only text input — no box, no fill. A single bottom rule that
3004
+ thickens to 2px on focus, matching the row/rule zero-border aesthetic
3005
+ instead of a browser-default boxed field. */
3006
+ .input {
3007
+ display: block; width: 100%; box-sizing: border-box;
3008
+ border: 0; border-bottom: 1px solid var(--rule-strong);
3009
+ border-radius: var(--r-0);
3010
+ background: transparent;
3011
+ padding: var(--space-2) var(--space-1);
3012
+ font: inherit; color: var(--fg);
3013
+ }
3014
+ .input::placeholder { color: var(--fg-3); }
3015
+ .input:focus-visible {
3016
+ outline: none;
3017
+ border-bottom-width: 2px;
3018
+ border-bottom-color: var(--accent-ink);
3019
+ }
3020
+
2939
3021
  /* -- Field controls: themed base for TextField / Select / SearchInput --
2940
3022
  Root fix: previously only `transition` was set, so themed apps got
2941
3023
  browser-default white boxes in dark mode and labels collided with inputs
@@ -439,7 +439,7 @@ select:focus-visible {
439
439
  --fg: var(--ink); --fg-2: var(--ink-2); --fg-3: var(--ink-3);
440
440
  --accent: var(--acid); --accent-fg: var(--ink); --accent-ink: var(--acid-deep);
441
441
  /* A paper island under a dark ancestor must not inherit the dark signal pair. */
442
- --flame: #C53E00; --amber: #8A6512; --warn: #E0241A; --sky: #3A6EFF;
442
+ --flame: #C53E00; --amber: #7C570F; --warn: #E0241A; --sky: #3A6EFF;
443
443
  }
444
444
 
445
445
  /* thebird — warm-paper brand preset. A first-class swappable theme: it lives
package/community.css CHANGED
@@ -353,9 +353,9 @@
353
353
  }
354
354
 
355
355
  .cm-channel-item.voice-active {
356
- color: var(--green-2);
356
+ color: var(--green);
357
357
  }
358
- .cm-channel-item.voice-active .cm-ch-icon { color: var(--green-2); }
358
+ .cm-channel-item.voice-active .cm-ch-icon { color: var(--green); }
359
359
  .cm-channel-item.voice-active:hover {
360
360
  background: color-mix(in oklab, var(--green) 12%, transparent);
361
361
  }
@@ -401,7 +401,7 @@
401
401
  }
402
402
 
403
403
  .cm-ch-icon.voice-active-badge {
404
- color: var(--green-2);
404
+ color: var(--green);
405
405
  text-shadow: 0 0 8px var(--green-2);
406
406
  }
407
407
 
@@ -508,7 +508,7 @@
508
508
  color: var(--fg);
509
509
  }
510
510
  .cm-ch-voice-user.speaking {
511
- color: var(--green-2);
511
+ color: var(--green);
512
512
  }
513
513
  .cm-ch-voice-user.speaking .cm-ch-voice-user-avatar {
514
514
  box-shadow: 0 0 0 2px var(--green-2);
@@ -564,7 +564,7 @@
564
564
  font-size: var(--fs-micro);
565
565
  text-transform: uppercase;
566
566
  letter-spacing: var(--tr-caps);
567
- color: var(--green-2);
567
+ color: var(--green);
568
568
  font-weight: 700;
569
569
  display: inline-flex;
570
570
  align-items: center;
package/dist/247420.css CHANGED
@@ -441,7 +441,7 @@
441
441
  --fg: var(--ink); --fg-2: var(--ink-2); --fg-3: var(--ink-3);
442
442
  --accent: var(--acid); --accent-fg: var(--ink); --accent-ink: var(--acid-deep);
443
443
  /* A paper island under a dark ancestor must not inherit the dark signal pair. */
444
- --flame: #C53E00; --amber: #8A6512; --warn: #E0241A; --sky: #3A6EFF;
444
+ --flame: #C53E00; --amber: #7C570F; --warn: #E0241A; --sky: #3A6EFF;
445
445
  }
446
446
 
447
447
  /* thebird — warm-paper brand preset. A first-class swappable theme: it lives
@@ -664,7 +664,7 @@
664
664
  .ds-247420 pre .k { color: var(--code-str-alt, var(--mascot)); }
665
665
  .ds-247420 pre .s { color: var(--code-string, var(--green)); }
666
666
  .ds-247420 pre .c { color: var(--fg-3); }
667
- .ds-247420 pre .n { color: var(--green-2); }
667
+ .ds-247420 pre .n { color: var(--code-num); }
668
668
 
669
669
  /* ============================================================
670
670
  AppShell — page frame. The topbar floats above a soft background;
@@ -943,6 +943,19 @@
943
943
  .ds-247420 .app-status .item:last-of-type:not(:only-of-type) { display: none; }
944
944
  }
945
945
 
946
+ /* The "dateline" — ASCII bar used at the top of every preview/brand page.
947
+ 3-4 flex slots; a .spread filler pushes the trailing slot to the far
948
+ edge instead of every span running together with no gap. */
949
+ .ds-247420 .dateline {
950
+ display: flex; align-items: center; gap: var(--space-3);
951
+ flex-wrap: nowrap; overflow: hidden;
952
+ font-family: var(--ff-mono); font-size: var(--fs-xs); line-height: 1.2;
953
+ letter-spacing: 0.02em;
954
+ color: var(--fg-3);
955
+ }
956
+ .ds-247420 .dateline span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
957
+ .ds-247420 .dateline .spread { flex: 1 1 auto; min-width: var(--space-3); }
958
+
946
959
  /* ============================================================
947
960
  Primitives
948
961
  ============================================================ */
@@ -973,15 +986,15 @@
973
986
  an ink block with the lead as text, a confident two-tone flip. */
974
987
  .ds-247420 .btn-primary {
975
988
  background: var(--accent); color: var(--accent-fg);
976
- font-weight: 700; letter-spacing: var(--tr-caps);
989
+ font-weight: 700;
977
990
  }
978
991
  .ds-247420 .btn-primary:hover { background: var(--fg); color: var(--accent-ink); transform: translateY(-1px); box-shadow: var(--shadow-2); }
979
992
  .ds-247420 .btn-ghost { background: transparent; color: var(--fg); box-shadow: inset 0 0 0 2px var(--fg); }
980
993
  .ds-247420 .btn-ghost:hover { background: var(--fg); color: var(--bg); transform: translateY(-1px); }
981
994
  .ds-247420 .btn:active, .ds-247420 .btn-primary:active, .ds-247420 .btn-ghost:active { transform: translateY(1px); box-shadow: none; }
982
995
  .ds-247420 .btn:focus-visible, .ds-247420 .btn-primary:focus-visible, .ds-247420 .btn-ghost:focus-visible, .ds-247420 .ds-icon-btn:focus-visible {
983
- outline: 2px solid var(--accent-ink);
984
- outline-offset: 2px;
996
+ outline: var(--focus-w) solid var(--focus-color);
997
+ outline-offset: var(--focus-offset);
985
998
  }
986
999
 
987
1000
  /* ============================================================
@@ -1000,12 +1013,12 @@
1000
1013
  .ds-247420 .ds-icon-btn-lg { width: 40px; height: 40px; }
1001
1014
  .ds-247420 .ds-icon-btn-xl { width: 48px; height: 48px; }
1002
1015
  .ds-247420 .ds-icon-btn-ghost { background: transparent; }
1003
- .ds-247420 .ds-icon-btn-ghost:hover { background: var(--bg-2); }
1016
+ .ds-247420 .ds-icon-btn-ghost:hover { background: var(--fg); color: var(--bg); }
1004
1017
  .ds-247420 .ds-icon-btn-primary { background: var(--accent); color: var(--accent-fg); }
1005
1018
  .ds-247420 .ds-icon-btn-primary:hover { background: var(--fg); color: var(--bg); }
1006
1019
  /* warn = destructive ACTION tone; flame stays exclusively error STATUS. */
1007
1020
  .ds-247420 .ds-icon-btn-danger { background: var(--warn); color: var(--on-color); }
1008
- .ds-247420 .ds-icon-btn-danger:hover { filter: brightness(1.1); }
1021
+ .ds-247420 .ds-icon-btn-danger:hover { filter: brightness(0.92); }
1009
1022
  .ds-247420 .ds-icon-btn:active { transform: translateY(1px); }
1010
1023
  .ds-247420 .ds-icon-btn:disabled, .ds-247420 .ds-icon-btn.is-disabled {
1011
1024
  opacity: 0.5; cursor: not-allowed; pointer-events: none;
@@ -1155,7 +1168,7 @@
1155
1168
  white-space: pre-wrap;
1156
1169
  font-family: var(--ff-mono);
1157
1170
  font-size: var(--fs-sm);
1158
- line-height: var(--lh-snug, 1.3);
1171
+ line-height: var(--lh-snug);
1159
1172
  margin-top: 8px;
1160
1173
  padding: 10px 12px;
1161
1174
  background: var(--bg);
@@ -1211,7 +1224,7 @@
1211
1224
  .ds-247420 .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
1212
1225
 
1213
1226
  .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; }
1214
- .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; }
1227
+ .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); line-height: var(--lh-snug); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
1215
1228
  .ds-247420 .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
1216
1229
  /* App typescale: list rows are quiet working chrome (the 18px/600 default is a
1217
1230
  marketing-surface voice). One size for ALL app list rows - matches
@@ -1655,6 +1668,10 @@
1655
1668
  flex: 1 1 100%; margin-left: 0; order: 3; min-width: 0; max-width: 100%;
1656
1669
  display: flex; gap: 2px; flex-wrap: nowrap;
1657
1670
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
1671
+ /* Fade the trailing edge so a clipped last item (e.g. "source ->" cut to
1672
+ "sour") reads as scrollable content, not a broken/truncated label. */
1673
+ mask-image: linear-gradient(90deg, var(--fg) 0 calc(100% - 28px), transparent 100%);
1674
+ -webkit-mask-image: linear-gradient(90deg, var(--fg) 0 calc(100% - 28px), transparent 100%);
1658
1675
  }
1659
1676
  .ds-247420 .app-topbar nav::-webkit-scrollbar { display: none; }
1660
1677
  .ds-247420 .app-topbar nav a {
@@ -1708,8 +1725,12 @@
1708
1725
  font-size: var(--fs-xs);
1709
1726
  }
1710
1727
  .ds-247420 .ds-file-open { gap: 10px; }
1711
- /* On mobile, fold meta under the title and keep actions inline. */
1712
- .ds-247420 .ds-file-row .ds-file-meta { font-size: var(--fs-micro); }
1728
+ /* At mobile row widths, a fixed-size meta column (date/size) plus the
1729
+ always-visible action buttons leave the flexible title only a few px —
1730
+ not enough for even one legible character before the two collide. Drop
1731
+ the metadata column here; the title + actions still fully identify and
1732
+ operate on the row, and meta stays available in the file viewer. */
1733
+ .ds-247420 .ds-file-row .ds-file-meta { display: none; }
1713
1734
  .ds-247420 .ds-file-row .ds-file-actions { opacity: 1; }
1714
1735
  /* H4: floor finger-sized controls so file actions/sort/filter/breadcrumb are
1715
1736
  reachable by touch (cohesion sweep). */
@@ -2011,6 +2032,12 @@
2011
2032
  .ds-247420 .ds-file-row .ds-file-meta {
2012
2033
  font-family: var(--ff-mono); font-size: var(--fs-xs);
2013
2034
  color: var(--fg-3); white-space: nowrap;
2035
+ /* Never shrink below content: a flex sibling with white-space:nowrap and
2036
+ the default flex-shrink:1 silently overflows its own box (no ellipsis)
2037
+ when the row runs out of width, painting the date/size over the title
2038
+ and action icons at mobile widths. Fixed-size the meta column instead
2039
+ and let .title (flex:1, min-width:0, ellipsis) absorb the squeeze. */
2040
+ flex-shrink: 0;
2014
2041
  }
2015
2042
 
2016
2043
  /* File icon — glyph chip, tinted per type. */
@@ -2480,6 +2507,7 @@
2480
2507
  border-color: var(--warn);
2481
2508
  color: var(--on-color);
2482
2509
  }
2510
+ .ds-247420 .btn-primary.danger:hover { filter: brightness(0.92); border-color: var(--warn); }
2483
2511
 
2484
2512
  /* -- Preview ------------------------------------------------ */
2485
2513
  .ds-247420 .ds-preview-head {
@@ -3281,6 +3309,14 @@
3281
3309
  transform var(--dur-snap) var(--ease);
3282
3310
  }
3283
3311
 
3312
+ /* Native checkbox/radio tint — browser default is UA blue, which fights the
3313
+ single lime lead accent wherever a raw control lands outside a bespoke
3314
+ toggle (e.g. signin's "remember me"). accent-color re-tints the native
3315
+ control box without hand-drawing a replacement. */
3316
+ .ds-247420 input[type="checkbox"], .ds-247420 input[type="radio"] {
3317
+ accent-color: var(--accent-ink);
3318
+ }
3319
+
3284
3320
  /* Prevent double-tap zoom on buttons (iOS) */
3285
3321
  .ds-247420 .btn, .ds-247420 .btn-primary, .ds-247420 .btn-ghost, .ds-247420 button {
3286
3322
  -webkit-user-select: none;
@@ -3444,6 +3480,52 @@
3444
3480
  color: var(--fg-3);
3445
3481
  }
3446
3482
 
3483
+ /* Rubber-stamp motif — a bordered, uppercase, letter-spaced badge with a
3484
+ slight built-in rotation (variants may override via inline transform for
3485
+ a stronger tilt). Max 1 per page per the component's own caption. */
3486
+ .ds-247420 .stamp {
3487
+ display: inline-block;
3488
+ font-family: var(--ff-mono); font-size: var(--fs-xs); font-weight: 700;
3489
+ text-transform: uppercase; letter-spacing: 0.08em;
3490
+ padding: var(--space-1-5, var(--space-2)) var(--space-3);
3491
+ border: 2px solid var(--fg);
3492
+ border-radius: var(--r-hair);
3493
+ color: var(--fg);
3494
+ transform: rotate(-2deg);
3495
+ white-space: nowrap;
3496
+ }
3497
+ .ds-247420 .stamp.ink { background: var(--ink); border-color: var(--ink); color: var(--paper); }
3498
+ .ds-247420 .stamp.acid { background: var(--accent); border-color: var(--accent-ink); color: var(--accent-ink); }
3499
+
3500
+ /* Structural hairlines — "no boxes, no cards, structure comes from rules."
3501
+ Three weights: .rule (default separator), .rule-double (major section
3502
+ break), .rule-dotted (optional/skippable). Applied to a bare <hr>, which
3503
+ otherwise falls back to the browser's default inset groove line. */
3504
+ .ds-247420 hr.rule, .ds-247420 hr.rule-double, .ds-247420 hr.rule-dotted {
3505
+ width: 100%; height: 0; border: 0;
3506
+ }
3507
+ .ds-247420 hr.rule { border-top: 1px solid var(--rule); }
3508
+ .ds-247420 hr.rule-double { border-top: 3px double var(--rule-strong); }
3509
+ .ds-247420 hr.rule-dotted { border-top: 1px dotted var(--rule-strong); }
3510
+
3511
+ /* Hairline-only text input — no box, no fill. A single bottom rule that
3512
+ thickens to 2px on focus, matching the row/rule zero-border aesthetic
3513
+ instead of a browser-default boxed field. */
3514
+ .ds-247420 .input {
3515
+ display: block; width: 100%; box-sizing: border-box;
3516
+ border: 0; border-bottom: 1px solid var(--rule-strong);
3517
+ border-radius: var(--r-0);
3518
+ background: transparent;
3519
+ padding: var(--space-2) var(--space-1);
3520
+ font: inherit; color: var(--fg);
3521
+ }
3522
+ .ds-247420 .input::placeholder { color: var(--fg-3); }
3523
+ .ds-247420 .input:focus-visible {
3524
+ outline: none;
3525
+ border-bottom-width: 2px;
3526
+ border-bottom-color: var(--accent-ink);
3527
+ }
3528
+
3447
3529
  /* -- Field controls: themed base for TextField / Select / SearchInput --
3448
3530
  Root fix: previously only `transition` was set, so themed apps got
3449
3531
  browser-default white boxes in dark mode and labels collided with inputs
@@ -5262,9 +5344,9 @@
5262
5344
  }
5263
5345
 
5264
5346
  .ds-247420 .cm-channel-item.voice-active {
5265
- color: var(--green-2);
5347
+ color: var(--green);
5266
5348
  }
5267
- .ds-247420 .cm-channel-item.voice-active .cm-ch-icon { color: var(--green-2); }
5349
+ .ds-247420 .cm-channel-item.voice-active .cm-ch-icon { color: var(--green); }
5268
5350
  .ds-247420 .cm-channel-item.voice-active:hover {
5269
5351
  background: color-mix(in oklab, var(--green) 12%, transparent);
5270
5352
  }
@@ -5310,7 +5392,7 @@
5310
5392
  }
5311
5393
 
5312
5394
  .ds-247420 .cm-ch-icon.voice-active-badge {
5313
- color: var(--green-2);
5395
+ color: var(--green);
5314
5396
  text-shadow: 0 0 8px var(--green-2);
5315
5397
  }
5316
5398
 
@@ -5417,7 +5499,7 @@
5417
5499
  color: var(--fg);
5418
5500
  }
5419
5501
  .ds-247420 .cm-ch-voice-user.speaking {
5420
- color: var(--green-2);
5502
+ color: var(--green);
5421
5503
  }
5422
5504
  .ds-247420 .cm-ch-voice-user.speaking .cm-ch-voice-user-avatar {
5423
5505
  box-shadow: 0 0 0 2px var(--green-2);
@@ -5473,7 +5555,7 @@
5473
5555
  font-size: var(--fs-micro);
5474
5556
  text-transform: uppercase;
5475
5557
  letter-spacing: var(--tr-caps);
5476
- color: var(--green-2);
5558
+ color: var(--green);
5477
5559
  font-weight: 700;
5478
5560
  display: inline-flex;
5479
5561
  align-items: center;