anentrypoint-design 0.0.205 → 0.0.207

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/app-shell.css CHANGED
@@ -41,7 +41,7 @@ body {
41
41
  -webkit-font-smoothing: antialiased;
42
42
  text-rendering: optimizeLegibility;
43
43
  }
44
- ::selection { background: var(--mascot); color: var(--ink); }
44
+ ::selection { background: color-mix(in oklab, var(--accent) 24%, var(--bg-2)); color: var(--fg); }
45
45
 
46
46
  /* Every root has a CQ container so fluid type can resolve to a meaningful inline-size. */
47
47
  .app, [class*="kit-"], .ds-stage {
@@ -578,12 +578,17 @@ body.canvas-host { background: transparent !important; }
578
578
  .row.rail-purple::before { background: var(--purple-2, #7F18A4); }
579
579
  .row.rail-flame::before { background: var(--flame); }
580
580
  .row-grid { /* explicit grid-template-columns set inline */ }
581
+ /* A row with no leading code/index drops the empty first column so the title
582
+ takes the full width instead of wrapping in the narrow code gutter. */
583
+ .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
581
584
 
582
585
  .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; }
583
586
  .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; }
584
587
  .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
585
588
  .row .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
586
589
  .row .meta { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; align-self: center; }
590
+ /* WorksList meta pairs a label with a disclosure chevron, inline-aligned. */
591
+ .ds-works-meta { display: inline-flex; align-items: center; gap: .4em; }
587
592
 
588
593
  a.row { text-decoration: none; }
589
594
 
@@ -1935,36 +1940,43 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1935
1940
  .chat-msg:nth-child(n+4) { animation-delay: 0.15s; }
1936
1941
  }
1937
1942
 
1943
+ /* Calm composer (claude.ai/code): ONE bordered rounded-rect shell holding the
1944
+ context line, a borderless textarea, the hint, and an inline send button -
1945
+ not a stadium pill + a floating round send. The shell carries the border and
1946
+ the focus ring; the textarea fills it transparently. flex-wrap lets the
1947
+ context line and hint occupy their own rows above/below the input row. */
1938
1948
  .chat-composer {
1939
- display: flex; align-items: flex-end; gap: 8px;
1940
- padding: var(--space-3) 0 0;
1941
- border-top: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
1949
+ display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--space-2);
1950
+ padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
1951
+ background: var(--bg);
1952
+ border: var(--bw-hair) solid var(--rule);
1953
+ border-radius: var(--r-2);
1942
1954
  flex-shrink: 0;
1955
+ transition: border-color var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease);
1956
+ }
1957
+ .chat-composer:focus-within {
1958
+ border-color: var(--accent);
1959
+ box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent);
1943
1960
  }
1944
1961
  .chat-composer textarea {
1945
- flex: 1; padding: 12px 16px;
1946
- background: var(--bg-2); color: var(--fg);
1947
- border: 1px solid transparent; border-radius: var(--r-pill);
1962
+ flex: 1; min-width: 0; padding: 8px 4px;
1963
+ background: none; color: var(--fg);
1964
+ border: none; border-radius: 0;
1948
1965
  font-family: inherit; font-size: var(--fs-sm);
1949
- line-height: 1.4; resize: none;
1950
- min-height: 44px; max-height: 200px;
1966
+ line-height: 1.45; resize: none;
1967
+ min-height: 28px; max-height: 200px;
1951
1968
  box-sizing: border-box; overflow-y: auto;
1952
1969
  scrollbar-width: thin;
1953
1970
  }
1954
1971
  .chat-composer textarea::placeholder { color: var(--fg-3); }
1955
- .chat-composer textarea:focus {
1956
- background: var(--bg-2);
1957
- border-color: var(--accent);
1958
- box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 20%, transparent);
1959
- outline: none;
1960
- }
1972
+ .chat-composer textarea:focus { background: none; border: none; box-shadow: none; outline: none; }
1961
1973
  .chat-composer .send {
1962
- width: 44px; height: 44px; border-radius: 50%;
1974
+ width: 36px; height: 36px; border-radius: var(--r-1);
1963
1975
  background: var(--accent); color: var(--accent-fg);
1964
1976
  border: 0; cursor: pointer;
1965
1977
  display: inline-flex; align-items: center; justify-content: center;
1966
1978
  flex-shrink: 0;
1967
- transition: background var(--dur-snap, .15s) var(--ease, ease), transform .1s ease;
1979
+ transition: background var(--dur-snap, .15s) var(--ease, ease);
1968
1980
  }
1969
1981
  .chat-composer .send:disabled { opacity: .5; cursor: not-allowed; }
1970
1982
  /* Ghost icon buttons in the toolbar (attach / emoji / more) — NOT the round
@@ -1978,8 +1990,8 @@ table tr.clickable:focus-visible td { background: var(--bg-2); }
1978
1990
  transition: background var(--dur-snap, .15s) var(--ease, ease), color var(--dur-snap, .15s) var(--ease, ease);
1979
1991
  }
1980
1992
  .composer-btn:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
1981
- .chat-composer .send:hover { transform: scale(1.04); }
1982
- .chat-composer .send:active { transform: scale(0.96); }
1993
+ .chat-composer .send:hover { filter: brightness(1.08); }
1994
+ .chat-composer .send:active { filter: brightness(0.94); }
1983
1995
  .chat-composer .send:focus-visible,
1984
1996
  .composer-btn:focus-visible {
1985
1997
  outline: 2px solid var(--accent);
@@ -2836,6 +2848,12 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2836
2848
  .ws-shell.ws-no-pane.ws-pane-collapsed.ws-no-sessions { grid-template-columns: var(--ws-rail-w) 1fr var(--ws-pane-w); grid-template-areas: "rail content pane"; }
2837
2849
  .ws-shell.ws-rail-collapsed { --ws-rail-w: var(--ws-rail-w-collapsed); }
2838
2850
  .ws-shell.ws-pane-collapsed { --ws-pane-w: 0px; }
2851
+ /* Ease the rail/pane collapse. Track COUNT stays stable on collapse (only a
2852
+ width var flips), so grid-template-columns is animatable; reduced-motion
2853
+ drops it to an instant swap. */
2854
+ @media (prefers-reduced-motion: no-preference) {
2855
+ .ws-shell { transition: grid-template-columns var(--dur-base) var(--ease); }
2856
+ }
2839
2857
 
2840
2858
  /* Rail (left nav) */
2841
2859
  .ws-rail {
@@ -2906,9 +2924,17 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2906
2924
 
2907
2925
  /* Content column */
2908
2926
  .ws-content { grid-area: content; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
2909
- .ws-crumb { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-1); border-bottom: var(--bw-hair) solid var(--bg-3); }
2927
+ /* Crumb band is the top chrome of the content column: a stable height so the
2928
+ top edge aligns with the rail head, and a left gutter matching .ws-main so
2929
+ the trail text is not flush against the rail border. */
2930
+ .ws-crumb { flex: 0 0 auto; min-height: 48px; padding: 0 var(--space-4); display: flex; align-items: center; gap: var(--space-1); border-bottom: var(--bw-hair) solid var(--bg-3); }
2910
2931
  .ws-crumb-main { flex: 1 1 auto; min-width: 0; }
2911
- .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
2932
+ /* Content column gutter. Claude-Code-class calm: file grid / dashboard / event
2933
+ list / history get a generous, consistent inner gutter instead of butting
2934
+ against the 1px column borders. The chat tab opts out via .ws-main--flush
2935
+ because the chat thread carries its own --measure gutter. */
2936
+ .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; padding: var(--space-4) var(--space-5); }
2937
+ .ws-main.ws-main--flush { padding: 0; }
2912
2938
  .ws-main:focus { outline: none; }
2913
2939
 
2914
2940
  /* Right context pane */
@@ -2953,8 +2979,11 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
2953
2979
  .ws-rail-collapsed .ws-rail-item-label, .ws-rail-collapsed .ws-rail-brand { display: none; }
2954
2980
  /* Tap-scrim behind an open drawer; dismiss on click. Hidden unless a drawer
2955
2981
  is open so it never blocks the content area on desktop. */
2956
- .ws-scrim { display: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); }
2957
- .ws-shell.ws-sessions-open .ws-scrim, .ws-shell.ws-pane-open .ws-scrim { display: block; }
2982
+ /* Scrim is always present on mobile so it can FADE with the drawer instead of
2983
+ hard-appearing via a display toggle; pointer-events gate keeps it inert
2984
+ while closed. Reduced-motion users get the global transition kill -> instant. */
2985
+ .ws-scrim { display: block; opacity: 0; pointer-events: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); transition: opacity var(--dur-base) var(--ease); }
2986
+ .ws-shell.ws-sessions-open .ws-scrim, .ws-shell.ws-pane-open .ws-scrim { opacity: 1; pointer-events: auto; }
2958
2987
  /* The mobile drawer-toggle affordances live in the crumb bar. */
2959
2988
  .ws-drawer-toggle { display: inline-flex; }
2960
2989
  }
package/chat.css CHANGED
@@ -464,7 +464,10 @@ button.chat-composer-context:focus-visible { outline: 2px solid var(--accent); o
464
464
  /* --- C5: active dashboard card (current conversation). --- */
465
465
  .ds-dash-card.is-active { box-shadow: inset 2px 0 0 var(--accent); }
466
466
  .ds-dash-card.is-selected { background: var(--accent-tint); }
467
- .ds-dash-card.is-stale { opacity: .92; }
467
+ /* Stale/idle card: a positive amber inset bar (mirrors is-active) so a stuck
468
+ agent is flagged in a dense grid, not merely faded near-invisibly. The word
469
+ 'idle' co-carries state, so this stays colour-blind safe. */
470
+ .ds-dash-card.is-stale { box-shadow: inset 2px 0 0 var(--amber, #d9a93a); }
468
471
 
469
472
  /* --- H3: dashboard live disc pulses; stale/error do not (handled by H1). --- */
470
473
 
@@ -550,7 +553,7 @@ button.chat-composer-context:focus-visible { outline: 2px solid var(--accent); o
550
553
  /* Enter-to-send hint: visible while the composer is focused or carries a
551
554
  draft; hidden under 420px to save rows. */
552
555
  .chat-composer-hint {
553
- display: none; padding: 2px var(--space-3) 0;
556
+ display: none; width: 100%; order: 5; padding: 2px var(--space-1) 0;
554
557
  font-size: var(--fs-micro); color: var(--fg-3);
555
558
  }
556
559
  .chat-composer:focus-within .chat-composer-hint,
@@ -632,3 +635,137 @@ button.chat-composer-context:focus-visible { outline: 2px solid var(--accent); o
632
635
 
633
636
  /* One connection vocabulary: offline (is-lost kept as legacy alias). */
634
637
  .ds-dash-stream.is-offline { color: var(--flame); }
638
+
639
+ /* ============================================================
640
+ 10th run - Claude-Code-web design-language parity
641
+ ============================================================ */
642
+
643
+ /* Flat full-width chat turns (claude.ai/code), replacing the messenger
644
+ avatar-disc + colored-bubble layout. AgentChat passes flat:true; the demo
645
+ Chat keeps the bubble layout. Turns are full-width to --measure; the user vs
646
+ assistant distinction is a role label + a faint assistant background. */
647
+ .chat-msg-flat { display: block; padding: var(--space-3) var(--space-4); margin: 0; background: none; border-radius: var(--r-2); }
648
+ .chat-msg-flat.them { background: color-mix(in oklab, var(--fg) 3%, transparent); }
649
+ .chat-msg-flat.you { background: none; }
650
+ .chat-msg-flat .chat-stack { max-width: var(--measure); width: 100%; margin: 0; align-items: stretch; }
651
+ .chat-msg-flat.you .chat-stack { align-items: stretch; }
652
+ .chat-role { font-size: var(--fs-tiny); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); margin-bottom: var(--space-1); }
653
+ .chat-msg-flat.you .chat-role { color: var(--accent); }
654
+ .chat-msg-flat .chat-bubble { background: none; border: none; border-radius: 0; padding: 0; max-width: 100%; box-shadow: none; transform: none; }
655
+ .chat-msg-flat.you .chat-bubble { background: none; color: inherit; }
656
+ .chat-msg-flat:hover { background: color-mix(in oklab, var(--fg) 3%, transparent); }
657
+ .chat-msg-flat.you:hover { background: color-mix(in oklab, var(--fg) 2%, transparent); }
658
+ .chat-msg-flat:hover .chat-bubble { transform: none; box-shadow: none; background: none; }
659
+ .chat-msg-flat .chat-avatar { display: none; }
660
+
661
+ /* Tool-call card: a bordered, status-toned, scannable card (claude.ai/code),
662
+ not the raw mascot-tinted details dump. The node keeps the .chat-bubble
663
+ class, so these rules de-frame it and restyle. Placed after the flat-bubble
664
+ reset so they win on equal specificity. */
665
+ .chat-msg .chat-tool {
666
+ display: block; max-width: 100%; padding: 0; margin: var(--space-1) 0;
667
+ background: var(--bg); color: var(--fg);
668
+ border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
669
+ box-shadow: none; overflow: hidden;
670
+ }
671
+ .chat-msg .chat-tool[open] { background: var(--bg); }
672
+ .chat-msg .chat-tool .chat-tool-head {
673
+ display: flex; align-items: center; gap: var(--space-2);
674
+ padding: var(--space-2) var(--space-3); cursor: pointer;
675
+ font-size: var(--fs-sm); list-style: none;
676
+ }
677
+ .chat-msg .chat-tool .chat-tool-head::-webkit-details-marker { display: none; }
678
+ .chat-msg .chat-tool .chat-tool-head:hover { background: var(--bg-2); }
679
+ .chat-tool-icon { display: inline-flex; color: var(--fg-3); }
680
+ .chat-tool-name { font-family: var(--ff-mono); font-weight: 600; color: var(--fg); }
681
+ .chat-tool-label { color: var(--fg-3); font-size: var(--fs-tiny); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
682
+ .chat-tool-status {
683
+ margin-left: auto; flex: 0 0 auto;
684
+ font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
685
+ color: var(--fg-3);
686
+ padding: 2px var(--space-2); border-radius: var(--r-pill);
687
+ background: color-mix(in oklab, var(--fg) 6%, transparent);
688
+ }
689
+ .chat-msg .chat-tool.tool-running .chat-tool-status { color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, transparent); }
690
+ .chat-msg .chat-tool.tool-error .chat-tool-status { color: var(--flame); background: color-mix(in oklab, var(--flame) 12%, transparent); }
691
+ .chat-tool-body { border-top: var(--bw-hair) solid var(--rule); padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
692
+ .chat-tool-section { display: flex; flex-direction: column; gap: var(--space-1); }
693
+ .chat-tool-section-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-3); }
694
+ .chat-tool-pre { margin: 0; padding: var(--space-2); background: var(--bg-2); border-radius: var(--r-1); font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1.45; overflow-x: auto; max-height: 320px; overflow-y: auto; }
695
+ .chat-tool-pre.is-error { color: var(--flame); }
696
+ .chat-tool-pre.chat-tool-empty { color: var(--fg-3); }
697
+
698
+ /* Fenced-code language tab on every rendered-markdown block (not just the
699
+ structured CodeNode). injectCodeCopy reads the language- class. */
700
+ .chat-code-block { position: relative; }
701
+ .chat-code-lang {
702
+ position: absolute; top: 0; left: 0; z-index: 2;
703
+ padding: 2px var(--space-2); border-bottom-right-radius: var(--r-1);
704
+ font-family: var(--ff-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .04em;
705
+ color: var(--fg-3); background: color-mix(in oklab, var(--fg) 6%, transparent);
706
+ pointer-events: none;
707
+ }
708
+ .chat-code-block pre { padding-top: calc(var(--space-3) + 4px); }
709
+
710
+ /* Motion + microinteraction polish (all reduced-motion guarded). */
711
+ .ds-session-row { transition: background var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease); }
712
+ @media (prefers-reduced-motion: no-preference) {
713
+ .agentchat-thread { scroll-behavior: smooth; }
714
+ .ds-alert { animation: ds-alert-in var(--dur-base) var(--ease); }
715
+ }
716
+ @keyframes ds-alert-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
717
+ .chat-code-copy { transition: opacity var(--dur-snap, .12s) var(--ease, ease), color var(--dur-snap) var(--ease), border-color var(--dur-snap) var(--ease), background var(--dur-snap) var(--ease); }
718
+ .chat-msg-action { transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease); }
719
+ .agentchat-install-copy { transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease); }
720
+ @media (prefers-reduced-motion: no-preference) {
721
+ .btn.is-armed, .btn-primary.is-armed { animation: ds-arm-pulse var(--dur-slow) var(--ease); }
722
+ }
723
+ @keyframes ds-arm-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--warn) 55%, transparent); } 100% { box-shadow: 0 0 0 6px color-mix(in oklab, var(--warn) 0%, transparent); } }
724
+ .ds-dash-card.is-new { box-shadow: inset 2px 0 0 var(--accent), 0 0 0 1px color-mix(in oklab, var(--accent) 40%, transparent); }
725
+ @media (prefers-reduced-motion: no-preference) {
726
+ .ds-dash-card.is-new { animation: ds-card-in var(--dur-slow) var(--ease); }
727
+ }
728
+ @keyframes ds-card-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
729
+
730
+ /* Live command-center: status-bucket groups + header breakdown + heartbeat. */
731
+ .ds-dash-group { display: flex; flex-direction: column; gap: var(--space-2); }
732
+ .ds-dash-group-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); padding: 0 var(--space-1); }
733
+ .ds-dash-breakdown { display: flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); color: var(--fg-2); }
734
+ .ds-dash-breakdown .seg.is-running { color: var(--green); font-weight: 600; }
735
+ .ds-dash-breakdown .seg.is-error { color: var(--flame); font-weight: 600; }
736
+ .ds-dash-breakdown .seg.is-idle { color: var(--amber, #d9a93a); }
737
+ .ds-dash-stream-disc { display: inline-flex; align-items: center; gap: var(--space-1); }
738
+ .ds-dash-selectall { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-tiny); color: var(--fg-2); cursor: pointer; background: none; border: none; padding: var(--space-1); }
739
+ .ds-dash-selectall:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
740
+ .ds-dash-clear { background: none; border: none; color: var(--fg-3); cursor: pointer; font-size: var(--fs-tiny); text-decoration: underline dotted; padding: var(--space-1); }
741
+
742
+ /* Conversation-rail loading skeleton (cold ccsniff walk). */
743
+ .ds-session-row-skeleton { display: flex; flex-direction: column; gap: 6px; padding: var(--space-2) var(--space-3); }
744
+ .ds-session-row-skeleton .ds-skel { background: var(--bg-3); border-radius: var(--r-1); }
745
+ .ds-session-row-skeleton .ds-skel-title { height: 12px; width: 70%; }
746
+ .ds-session-row-skeleton .ds-skel-meta { height: 9px; width: 45%; }
747
+ @media (prefers-reduced-motion: no-preference) {
748
+ .ds-session-row-skeleton .ds-skel { animation: ds-skel-shimmer 1.3s ease-in-out infinite; background: linear-gradient(90deg, var(--bg-3) 0%, var(--bg-2) 50%, var(--bg-3) 100%); background-size: 200% 100%; }
749
+ }
750
+ @keyframes ds-skel-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
751
+
752
+ /* File code preview: paint Prism tokens (the bundle scoped them to the chat
753
+ block only) + an optional non-selectable line-number gutter. */
754
+ .ds-preview-code code { color: var(--fg); }
755
+ .ds-preview-code .token.comment, .ds-preview-code .token.prolog, .ds-preview-code .token.doctype, .ds-preview-code .token.cdata { color: var(--fg-3); }
756
+ .ds-preview-code .token.punctuation { color: var(--fg-2); }
757
+ .ds-preview-code .token.property, .ds-preview-code .token.tag, .ds-preview-code .token.boolean, .ds-preview-code .token.number, .ds-preview-code .token.constant, .ds-preview-code .token.symbol { color: var(--purple-2, #7F18A4); }
758
+ .ds-preview-code .token.selector, .ds-preview-code .token.attr-name, .ds-preview-code .token.string, .ds-preview-code .token.char, .ds-preview-code .token.builtin { color: var(--green-2, #3A9A34); }
759
+ .ds-preview-code .token.atrule, .ds-preview-code .token.attr-value, .ds-preview-code .token.keyword { color: var(--sky, #3A6EFF); }
760
+ .ds-preview-code .token.function, .ds-preview-code .token.class-name { color: var(--flame); }
761
+ .ds-preview-code.has-gutter { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--space-2); }
762
+ .ds-preview-code.has-gutter code { display: block; min-width: 0; overflow-x: auto; }
763
+ .ds-preview-gutter { user-select: none; text-align: right; padding: 0 var(--space-2) 0 0; color: var(--fg-3); border-right: var(--bw-hair) solid var(--rule); font-family: var(--ff-mono); white-space: pre; line-height: inherit; }
764
+
765
+ /* Image preview: fit/actual control + alpha checkerboard. */
766
+ .ds-preview-media-controls { display: flex; gap: var(--space-2); padding: var(--space-2); justify-content: center; }
767
+ .ds-preview-media-alpha {
768
+ background-image: linear-gradient(45deg, var(--bg-3) 25%, transparent 25%), linear-gradient(-45deg, var(--bg-3) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--bg-3) 75%), linear-gradient(-45deg, transparent 75%, var(--bg-3) 75%);
769
+ background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0;
770
+ }
771
+ .ds-preview-media.is-actual { max-width: none; max-height: none; }
package/dist/247420.css CHANGED
@@ -442,7 +442,7 @@
442
442
  -webkit-font-smoothing: antialiased;
443
443
  text-rendering: optimizeLegibility;
444
444
  }
445
- .ds-247420 ::selection { background: var(--mascot); color: var(--ink); }
445
+ .ds-247420 ::selection { background: color-mix(in oklab, var(--accent) 24%, var(--bg-2)); color: var(--fg); }
446
446
 
447
447
  /* Every root has a CQ container so fluid type can resolve to a meaningful inline-size. */
448
448
  .ds-247420 .app, .ds-247420[class*="kit-"], .ds-247420 .ds-stage {
@@ -979,12 +979,17 @@
979
979
  .ds-247420 .row.rail-purple::before { background: var(--purple-2, #7F18A4); }
980
980
  .ds-247420 .row.rail-flame::before { background: var(--flame); }
981
981
  .ds-247420 .row-grid { /* explicit grid-template-columns set inline */ }
982
+ /* A row with no leading code/index drops the empty first column so the title
983
+ takes the full width instead of wrapping in the narrow code gutter. */
984
+ .ds-247420 .row.row-nocode { grid-template-columns: minmax(0, 1fr) auto; }
982
985
 
983
986
  .ds-247420 .row .code { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); font-variant-numeric: tabular-nums; letter-spacing: 0.01em; }
984
987
  .ds-247420 .row .title { font-family: var(--ff-body); font-weight: 600; font-size: var(--fs-lg); line-height: var(--lh-snug, 1.3); display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; min-width: 0; }
985
988
  .ds-247420 .row .title .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
986
989
  .ds-247420 .row .sub { font-family: var(--ff-body); font-weight: 400; font-size: var(--fs-sm); color: var(--fg-3); }
987
990
  .ds-247420 .row .meta { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; align-self: center; }
991
+ /* WorksList meta pairs a label with a disclosure chevron, inline-aligned. */
992
+ .ds-247420 .ds-works-meta { display: inline-flex; align-items: center; gap: .4em; }
988
993
 
989
994
  .ds-247420 a.row { text-decoration: none; }
990
995
 
@@ -2336,36 +2341,43 @@
2336
2341
  .ds-247420 .chat-msg:nth-child(n+4) { animation-delay: 0.15s; }
2337
2342
  }
2338
2343
 
2344
+ /* Calm composer (claude.ai/code): ONE bordered rounded-rect shell holding the
2345
+ context line, a borderless textarea, the hint, and an inline send button -
2346
+ not a stadium pill + a floating round send. The shell carries the border and
2347
+ the focus ring; the textarea fills it transparently. flex-wrap lets the
2348
+ context line and hint occupy their own rows above/below the input row. */
2339
2349
  .ds-247420 .chat-composer {
2340
- display: flex; align-items: flex-end; gap: 8px;
2341
- padding: var(--space-3) 0 0;
2342
- border-top: 1px solid color-mix(in oklab, var(--fg) 8%, transparent);
2350
+ display: flex; align-items: flex-end; flex-wrap: wrap; gap: var(--space-2);
2351
+ padding: var(--space-2) var(--space-2) var(--space-2) var(--space-3);
2352
+ background: var(--bg);
2353
+ border: var(--bw-hair) solid var(--rule);
2354
+ border-radius: var(--r-2);
2343
2355
  flex-shrink: 0;
2356
+ transition: border-color var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease);
2357
+ }
2358
+ .ds-247420 .chat-composer:focus-within {
2359
+ border-color: var(--accent);
2360
+ box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 18%, transparent);
2344
2361
  }
2345
2362
  .ds-247420 .chat-composer textarea {
2346
- flex: 1; padding: 12px 16px;
2347
- background: var(--bg-2); color: var(--fg);
2348
- border: 1px solid transparent; border-radius: var(--r-pill);
2363
+ flex: 1; min-width: 0; padding: 8px 4px;
2364
+ background: none; color: var(--fg);
2365
+ border: none; border-radius: 0;
2349
2366
  font-family: inherit; font-size: var(--fs-sm);
2350
- line-height: 1.4; resize: none;
2351
- min-height: 44px; max-height: 200px;
2367
+ line-height: 1.45; resize: none;
2368
+ min-height: 28px; max-height: 200px;
2352
2369
  box-sizing: border-box; overflow-y: auto;
2353
2370
  scrollbar-width: thin;
2354
2371
  }
2355
2372
  .ds-247420 .chat-composer textarea::placeholder { color: var(--fg-3); }
2356
- .ds-247420 .chat-composer textarea:focus {
2357
- background: var(--bg-2);
2358
- border-color: var(--accent);
2359
- box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent) 20%, transparent);
2360
- outline: none;
2361
- }
2373
+ .ds-247420 .chat-composer textarea:focus { background: none; border: none; box-shadow: none; outline: none; }
2362
2374
  .ds-247420 .chat-composer .send {
2363
- width: 44px; height: 44px; border-radius: 50%;
2375
+ width: 36px; height: 36px; border-radius: var(--r-1);
2364
2376
  background: var(--accent); color: var(--accent-fg);
2365
2377
  border: 0; cursor: pointer;
2366
2378
  display: inline-flex; align-items: center; justify-content: center;
2367
2379
  flex-shrink: 0;
2368
- transition: background var(--dur-snap, .15s) var(--ease, ease), transform .1s ease;
2380
+ transition: background var(--dur-snap, .15s) var(--ease, ease);
2369
2381
  }
2370
2382
  .ds-247420 .chat-composer .send:disabled { opacity: .5; cursor: not-allowed; }
2371
2383
  /* Ghost icon buttons in the toolbar (attach / emoji / more) — NOT the round
@@ -2379,8 +2391,8 @@
2379
2391
  transition: background var(--dur-snap, .15s) var(--ease, ease), color var(--dur-snap, .15s) var(--ease, ease);
2380
2392
  }
2381
2393
  .ds-247420 .composer-btn:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
2382
- .ds-247420 .chat-composer .send:hover { transform: scale(1.04); }
2383
- .ds-247420 .chat-composer .send:active { transform: scale(0.96); }
2394
+ .ds-247420 .chat-composer .send:hover { filter: brightness(1.08); }
2395
+ .ds-247420 .chat-composer .send:active { filter: brightness(0.94); }
2384
2396
  .ds-247420 .chat-composer .send:focus-visible,
2385
2397
  .ds-247420 .composer-btn:focus-visible {
2386
2398
  outline: 2px solid var(--accent);
@@ -3228,6 +3240,12 @@
3228
3240
  .ds-247420 .ws-shell.ws-no-pane.ws-pane-collapsed.ws-no-sessions { grid-template-columns: var(--ws-rail-w) 1fr var(--ws-pane-w); grid-template-areas: "rail content pane"; }
3229
3241
  .ds-247420 .ws-shell.ws-rail-collapsed { --ws-rail-w: var(--ws-rail-w-collapsed); }
3230
3242
  .ds-247420 .ws-shell.ws-pane-collapsed { --ws-pane-w: 0px; }
3243
+ /* Ease the rail/pane collapse. Track COUNT stays stable on collapse (only a
3244
+ width var flips), so grid-template-columns is animatable; reduced-motion
3245
+ drops it to an instant swap. */
3246
+ @media (prefers-reduced-motion: no-preference) {
3247
+ .ds-247420 .ws-shell { transition: grid-template-columns var(--dur-base) var(--ease); }
3248
+ }
3231
3249
 
3232
3250
  /* Rail (left nav) */
3233
3251
  .ds-247420 .ws-rail {
@@ -3298,9 +3316,17 @@
3298
3316
 
3299
3317
  /* Content column */
3300
3318
  .ds-247420 .ws-content { grid-area: content; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
3301
- .ds-247420 .ws-crumb { flex: 0 0 auto; display: flex; align-items: center; gap: var(--space-1); border-bottom: var(--bw-hair) solid var(--bg-3); }
3319
+ /* Crumb band is the top chrome of the content column: a stable height so the
3320
+ top edge aligns with the rail head, and a left gutter matching .ws-main so
3321
+ the trail text is not flush against the rail border. */
3322
+ .ds-247420 .ws-crumb { flex: 0 0 auto; min-height: 48px; padding: 0 var(--space-4); display: flex; align-items: center; gap: var(--space-1); border-bottom: var(--bw-hair) solid var(--bg-3); }
3302
3323
  .ds-247420 .ws-crumb-main { flex: 1 1 auto; min-width: 0; }
3303
- .ds-247420 .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
3324
+ /* Content column gutter. Claude-Code-class calm: file grid / dashboard / event
3325
+ list / history get a generous, consistent inner gutter instead of butting
3326
+ against the 1px column borders. The chat tab opts out via .ws-main--flush
3327
+ because the chat thread carries its own --measure gutter. */
3328
+ .ds-247420 .ws-main { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; padding: var(--space-4) var(--space-5); }
3329
+ .ds-247420 .ws-main.ws-main--flush { padding: 0; }
3304
3330
  .ds-247420 .ws-main:focus { outline: none; }
3305
3331
 
3306
3332
  /* Right context pane */
@@ -3345,8 +3371,11 @@
3345
3371
  .ds-247420 .ws-rail-collapsed .ws-rail-item-label, .ds-247420 .ws-rail-collapsed .ws-rail-brand { display: none; }
3346
3372
  /* Tap-scrim behind an open drawer; dismiss on click. Hidden unless a drawer
3347
3373
  is open so it never blocks the content area on desktop. */
3348
- .ds-247420 .ws-scrim { display: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); }
3349
- .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { display: block; }
3374
+ /* Scrim is always present on mobile so it can FADE with the drawer instead of
3375
+ hard-appearing via a display toggle; pointer-events gate keeps it inert
3376
+ while closed. Reduced-motion users get the global transition kill -> instant. */
3377
+ .ds-247420 .ws-scrim { display: block; opacity: 0; pointer-events: none; position: fixed; inset: 0; z-index: 41; background: color-mix(in srgb, var(--fg) 38%, transparent); transition: opacity var(--dur-base) var(--ease); }
3378
+ .ds-247420 .ws-shell.ws-sessions-open .ws-scrim, .ds-247420 .ws-shell.ws-pane-open .ws-scrim { opacity: 1; pointer-events: auto; }
3350
3379
  /* The mobile drawer-toggle affordances live in the crumb bar. */
3351
3380
  .ds-247420 .ws-drawer-toggle { display: inline-flex; }
3352
3381
  }
@@ -5393,7 +5422,10 @@
5393
5422
  /* --- C5: active dashboard card (current conversation). --- */
5394
5423
  .ds-247420 .ds-dash-card.is-active { box-shadow: inset 2px 0 0 var(--accent); }
5395
5424
  .ds-247420 .ds-dash-card.is-selected { background: var(--accent-tint); }
5396
- .ds-247420 .ds-dash-card.is-stale { opacity: .92; }
5425
+ /* Stale/idle card: a positive amber inset bar (mirrors is-active) so a stuck
5426
+ agent is flagged in a dense grid, not merely faded near-invisibly. The word
5427
+ 'idle' co-carries state, so this stays colour-blind safe. */
5428
+ .ds-247420 .ds-dash-card.is-stale { box-shadow: inset 2px 0 0 var(--amber, #d9a93a); }
5397
5429
 
5398
5430
  /* --- H3: dashboard live disc pulses; stale/error do not (handled by H1). --- */
5399
5431
 
@@ -5479,7 +5511,7 @@
5479
5511
  /* Enter-to-send hint: visible while the composer is focused or carries a
5480
5512
  draft; hidden under 420px to save rows. */
5481
5513
  .ds-247420 .chat-composer-hint {
5482
- display: none; padding: 2px var(--space-3) 0;
5514
+ display: none; width: 100%; order: 5; padding: 2px var(--space-1) 0;
5483
5515
  font-size: var(--fs-micro); color: var(--fg-3);
5484
5516
  }
5485
5517
  .ds-247420 .chat-composer:focus-within .chat-composer-hint,
@@ -5562,6 +5594,140 @@
5562
5594
  /* One connection vocabulary: offline (is-lost kept as legacy alias). */
5563
5595
  .ds-247420 .ds-dash-stream.is-offline { color: var(--flame); }
5564
5596
 
5597
+ /* ============================================================
5598
+ 10th run - Claude-Code-web design-language parity
5599
+ ============================================================ */
5600
+
5601
+ /* Flat full-width chat turns (claude.ai/code), replacing the messenger
5602
+ avatar-disc + colored-bubble layout. AgentChat passes flat:true; the demo
5603
+ Chat keeps the bubble layout. Turns are full-width to --measure; the user vs
5604
+ assistant distinction is a role label + a faint assistant background. */
5605
+ .ds-247420 .chat-msg-flat { display: block; padding: var(--space-3) var(--space-4); margin: 0; background: none; border-radius: var(--r-2); }
5606
+ .ds-247420 .chat-msg-flat.them { background: color-mix(in oklab, var(--fg) 3%, transparent); }
5607
+ .ds-247420 .chat-msg-flat.you { background: none; }
5608
+ .ds-247420 .chat-msg-flat .chat-stack { max-width: var(--measure); width: 100%; margin: 0; align-items: stretch; }
5609
+ .ds-247420 .chat-msg-flat.you .chat-stack { align-items: stretch; }
5610
+ .ds-247420 .chat-role { font-size: var(--fs-tiny); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); margin-bottom: var(--space-1); }
5611
+ .ds-247420 .chat-msg-flat.you .chat-role { color: var(--accent); }
5612
+ .ds-247420 .chat-msg-flat .chat-bubble { background: none; border: none; border-radius: 0; padding: 0; max-width: 100%; box-shadow: none; transform: none; }
5613
+ .ds-247420 .chat-msg-flat.you .chat-bubble { background: none; color: inherit; }
5614
+ .ds-247420 .chat-msg-flat:hover { background: color-mix(in oklab, var(--fg) 3%, transparent); }
5615
+ .ds-247420 .chat-msg-flat.you:hover { background: color-mix(in oklab, var(--fg) 2%, transparent); }
5616
+ .ds-247420 .chat-msg-flat:hover .chat-bubble { transform: none; box-shadow: none; background: none; }
5617
+ .ds-247420 .chat-msg-flat .chat-avatar { display: none; }
5618
+
5619
+ /* Tool-call card: a bordered, status-toned, scannable card (claude.ai/code),
5620
+ not the raw mascot-tinted details dump. The node keeps the .chat-bubble
5621
+ class, so these rules de-frame it and restyle. Placed after the flat-bubble
5622
+ reset so they win on equal specificity. */
5623
+ .ds-247420 .chat-msg .chat-tool {
5624
+ display: block; max-width: 100%; padding: 0; margin: var(--space-1) 0;
5625
+ background: var(--bg); color: var(--fg);
5626
+ border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
5627
+ box-shadow: none; overflow: hidden;
5628
+ }
5629
+ .ds-247420 .chat-msg .chat-tool[open] { background: var(--bg); }
5630
+ .ds-247420 .chat-msg .chat-tool .chat-tool-head {
5631
+ display: flex; align-items: center; gap: var(--space-2);
5632
+ padding: var(--space-2) var(--space-3); cursor: pointer;
5633
+ font-size: var(--fs-sm); list-style: none;
5634
+ }
5635
+ .ds-247420 .chat-msg .chat-tool .chat-tool-head::-webkit-details-marker { display: none; }
5636
+ .ds-247420 .chat-msg .chat-tool .chat-tool-head:hover { background: var(--bg-2); }
5637
+ .ds-247420 .chat-tool-icon { display: inline-flex; color: var(--fg-3); }
5638
+ .ds-247420 .chat-tool-name { font-family: var(--ff-mono); font-weight: 600; color: var(--fg); }
5639
+ .ds-247420 .chat-tool-label { color: var(--fg-3); font-size: var(--fs-tiny); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
5640
+ .ds-247420 .chat-tool-status {
5641
+ margin-left: auto; flex: 0 0 auto;
5642
+ font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
5643
+ color: var(--fg-3);
5644
+ padding: 2px var(--space-2); border-radius: var(--r-pill);
5645
+ background: color-mix(in oklab, var(--fg) 6%, transparent);
5646
+ }
5647
+ .ds-247420 .chat-msg .chat-tool.tool-running .chat-tool-status { color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, transparent); }
5648
+ .ds-247420 .chat-msg .chat-tool.tool-error .chat-tool-status { color: var(--flame); background: color-mix(in oklab, var(--flame) 12%, transparent); }
5649
+ .ds-247420 .chat-tool-body { border-top: var(--bw-hair) solid var(--rule); padding: var(--space-2) var(--space-3); display: flex; flex-direction: column; gap: var(--space-2); }
5650
+ .ds-247420 .chat-tool-section { display: flex; flex-direction: column; gap: var(--space-1); }
5651
+ .ds-247420 .chat-tool-section-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-3); }
5652
+ .ds-247420 .chat-tool-pre { margin: 0; padding: var(--space-2); background: var(--bg-2); border-radius: var(--r-1); font-family: var(--ff-mono); font-size: var(--fs-tiny); line-height: 1.45; overflow-x: auto; max-height: 320px; overflow-y: auto; }
5653
+ .ds-247420 .chat-tool-pre.is-error { color: var(--flame); }
5654
+ .ds-247420 .chat-tool-pre.chat-tool-empty { color: var(--fg-3); }
5655
+
5656
+ /* Fenced-code language tab on every rendered-markdown block (not just the
5657
+ structured CodeNode). injectCodeCopy reads the language- class. */
5658
+ .ds-247420 .chat-code-block { position: relative; }
5659
+ .ds-247420 .chat-code-lang {
5660
+ position: absolute; top: 0; left: 0; z-index: 2;
5661
+ padding: 2px var(--space-2); border-bottom-right-radius: var(--r-1);
5662
+ font-family: var(--ff-mono); font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: .04em;
5663
+ color: var(--fg-3); background: color-mix(in oklab, var(--fg) 6%, transparent);
5664
+ pointer-events: none;
5665
+ }
5666
+ .ds-247420 .chat-code-block pre { padding-top: calc(var(--space-3) + 4px); }
5667
+
5668
+ /* Motion + microinteraction polish (all reduced-motion guarded). */
5669
+ .ds-247420 .ds-session-row { transition: background var(--dur-snap) var(--ease), box-shadow var(--dur-snap) var(--ease); }
5670
+ @media (prefers-reduced-motion: no-preference) {
5671
+ .ds-247420 .agentchat-thread { scroll-behavior: smooth; }
5672
+ .ds-247420 .ds-alert { animation: ds-alert-in var(--dur-base) var(--ease); }
5673
+ }
5674
+ @keyframes ds-alert-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
5675
+ .ds-247420 .chat-code-copy { transition: opacity var(--dur-snap, .12s) var(--ease, ease), color var(--dur-snap) var(--ease), border-color var(--dur-snap) var(--ease), background var(--dur-snap) var(--ease); }
5676
+ .ds-247420 .chat-msg-action { transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease); }
5677
+ .ds-247420 .agentchat-install-copy { transition: background var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease); }
5678
+ @media (prefers-reduced-motion: no-preference) {
5679
+ .ds-247420 .btn.is-armed, .ds-247420 .btn-primary.is-armed { animation: ds-arm-pulse var(--dur-slow) var(--ease); }
5680
+ }
5681
+ @keyframes ds-arm-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--warn) 55%, transparent); } 100% { box-shadow: 0 0 0 6px color-mix(in oklab, var(--warn) 0%, transparent); } }
5682
+ .ds-247420 .ds-dash-card.is-new { box-shadow: inset 2px 0 0 var(--accent), 0 0 0 1px color-mix(in oklab, var(--accent) 40%, transparent); }
5683
+ @media (prefers-reduced-motion: no-preference) {
5684
+ .ds-247420 .ds-dash-card.is-new { animation: ds-card-in var(--dur-slow) var(--ease); }
5685
+ }
5686
+ @keyframes ds-card-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
5687
+
5688
+ /* Live command-center: status-bucket groups + header breakdown + heartbeat. */
5689
+ .ds-247420 .ds-dash-group { display: flex; flex-direction: column; gap: var(--space-2); }
5690
+ .ds-247420 .ds-dash-group-label { font-size: var(--fs-micro); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-3); padding: 0 var(--space-1); }
5691
+ .ds-247420 .ds-dash-breakdown { display: flex; align-items: center; gap: var(--space-1); font-size: var(--fs-sm); color: var(--fg-2); }
5692
+ .ds-247420 .ds-dash-breakdown .seg.is-running { color: var(--green); font-weight: 600; }
5693
+ .ds-247420 .ds-dash-breakdown .seg.is-error { color: var(--flame); font-weight: 600; }
5694
+ .ds-247420 .ds-dash-breakdown .seg.is-idle { color: var(--amber, #d9a93a); }
5695
+ .ds-247420 .ds-dash-stream-disc { display: inline-flex; align-items: center; gap: var(--space-1); }
5696
+ .ds-247420 .ds-dash-selectall { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--fs-tiny); color: var(--fg-2); cursor: pointer; background: none; border: none; padding: var(--space-1); }
5697
+ .ds-247420 .ds-dash-selectall:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
5698
+ .ds-247420 .ds-dash-clear { background: none; border: none; color: var(--fg-3); cursor: pointer; font-size: var(--fs-tiny); text-decoration: underline dotted; padding: var(--space-1); }
5699
+
5700
+ /* Conversation-rail loading skeleton (cold ccsniff walk). */
5701
+ .ds-247420 .ds-session-row-skeleton { display: flex; flex-direction: column; gap: 6px; padding: var(--space-2) var(--space-3); }
5702
+ .ds-247420 .ds-session-row-skeleton .ds-skel { background: var(--bg-3); border-radius: var(--r-1); }
5703
+ .ds-247420 .ds-session-row-skeleton .ds-skel-title { height: 12px; width: 70%; }
5704
+ .ds-247420 .ds-session-row-skeleton .ds-skel-meta { height: 9px; width: 45%; }
5705
+ @media (prefers-reduced-motion: no-preference) {
5706
+ .ds-247420 .ds-session-row-skeleton .ds-skel { animation: ds-skel-shimmer 1.3s ease-in-out infinite; background: linear-gradient(90deg, var(--bg-3) 0%, var(--bg-2) 50%, var(--bg-3) 100%); background-size: 200% 100%; }
5707
+ }
5708
+ @keyframes ds-skel-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
5709
+
5710
+ /* File code preview: paint Prism tokens (the bundle scoped them to the chat
5711
+ block only) + an optional non-selectable line-number gutter. */
5712
+ .ds-247420 .ds-preview-code code { color: var(--fg); }
5713
+ .ds-247420 .ds-preview-code .token.comment, .ds-247420 .ds-preview-code .token.prolog, .ds-247420 .ds-preview-code .token.doctype, .ds-247420 .ds-preview-code .token.cdata { color: var(--fg-3); }
5714
+ .ds-247420 .ds-preview-code .token.punctuation { color: var(--fg-2); }
5715
+ .ds-247420 .ds-preview-code .token.property, .ds-247420 .ds-preview-code .token.tag, .ds-247420 .ds-preview-code .token.boolean, .ds-247420 .ds-preview-code .token.number, .ds-247420 .ds-preview-code .token.constant, .ds-247420 .ds-preview-code .token.symbol { color: var(--purple-2, #7F18A4); }
5716
+ .ds-247420 .ds-preview-code .token.selector, .ds-247420 .ds-preview-code .token.attr-name, .ds-247420 .ds-preview-code .token.string, .ds-247420 .ds-preview-code .token.char, .ds-247420 .ds-preview-code .token.builtin { color: var(--green-2, #3A9A34); }
5717
+ .ds-247420 .ds-preview-code .token.atrule, .ds-247420 .ds-preview-code .token.attr-value, .ds-247420 .ds-preview-code .token.keyword { color: var(--sky, #3A6EFF); }
5718
+ .ds-247420 .ds-preview-code .token.function, .ds-247420 .ds-preview-code .token.class-name { color: var(--flame); }
5719
+ .ds-247420 .ds-preview-code.has-gutter { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 var(--space-2); }
5720
+ .ds-247420 .ds-preview-code.has-gutter code { display: block; min-width: 0; overflow-x: auto; }
5721
+ .ds-247420 .ds-preview-gutter { user-select: none; text-align: right; padding: 0 var(--space-2) 0 0; color: var(--fg-3); border-right: var(--bw-hair) solid var(--rule); font-family: var(--ff-mono); white-space: pre; line-height: inherit; }
5722
+
5723
+ /* Image preview: fit/actual control + alpha checkerboard. */
5724
+ .ds-247420 .ds-preview-media-controls { display: flex; gap: var(--space-2); padding: var(--space-2); justify-content: center; }
5725
+ .ds-247420 .ds-preview-media-alpha {
5726
+ background-image: linear-gradient(45deg, var(--bg-3) 25%, transparent 25%), linear-gradient(-45deg, var(--bg-3) 25%, transparent 25%), linear-gradient(45deg, transparent 75%, var(--bg-3) 75%), linear-gradient(-45deg, transparent 75%, var(--bg-3) 75%);
5727
+ background-size: 16px 16px; background-position: 0 0, 0 8px, 8px -8px, -8px 0;
5728
+ }
5729
+ .ds-247420 .ds-preview-media.is-actual { max-width: none; max-height: none; }
5730
+
5565
5731
  /* editor-primitives.css */
5566
5732
  /* editor-primitives.css — chrome for in-engine editors, inspectors, IDEs,
5567
5733
  debug HUDs. All rules under .ds-247420 scope (build prefixes). Tokens