dsh-claude-desktop-theme 0.4.1 → 0.4.2

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/lib/client.js CHANGED
@@ -44,7 +44,7 @@ var FEATURE_IDS = [
44
44
  ];
45
45
  var APPEARANCE_FIELDS = ["canvas", "sidebar"];
46
46
  var FONT_FIELDS = ["uiLatin", "uiCjk", "code"];
47
- var VIEW_FIELDS = ["showEmptyGroups"];
47
+ var VIEW_FIELDS = ["showEmptyGroups", "groupByStatus", "showHeaderSubagents", "showHeaderTeam"];
48
48
  var DEFAULT_FEATURES = Object.freeze({
49
49
  shell: true,
50
50
  sidebar: true,
@@ -66,7 +66,10 @@ var DEFAULT_FONTS = Object.freeze({
66
66
  code: ""
67
67
  });
68
68
  var DEFAULT_VIEW = Object.freeze({
69
- showEmptyGroups: false
69
+ showEmptyGroups: false,
70
+ groupByStatus: false,
71
+ showHeaderSubagents: false,
72
+ showHeaderTeam: false
70
73
  });
71
74
  var HEX_COLOUR = /^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i;
72
75
  var FONT_NAME = /^[\p{L}\p{N} ._-]+$/u;
@@ -521,6 +524,8 @@ var HOST = Object.freeze({
521
524
  /** WorkspaceBrowser.module.css: the tree's own scroller — the one element
522
525
  whose scroll distance the parked header band follows. */
523
526
  browserList: "._7514NG_list",
527
+ /** FlatList is the only native body the status presentation reorders. */
528
+ browserFlatList: "._7514NG_flatList",
524
529
  /** Rows.module.css: one Workspace's row, the line the merged header shares,
525
530
  and its trailing action group (`sidebar.css` parks both). */
526
531
  workspaceRow: ".jJkEga_projectRow",
@@ -4429,16 +4434,16 @@ function resolveThemeTokens(config) {
4429
4434
  }
4430
4435
 
4431
4436
  // src/client/theme/composer.css
4432
- var composer_default = '/*\n * Shared composer geometry.\n *\n * Both the blank-session page and the conversation page must place the official\n * Composer at the same width and shape, so the geometry lives here instead of\n * being duplicated in two features (siblings never import each other). The\n * upstream structure is kept: the resident Composer card stays the single\n * editable root, and only where its parts sit changes.\n *\n * Reference geometry (@2x reference screenshots, logical px at 1374x871):\n * - input surface: 770x42, 1px border, radius 10, text line 24px at 8/14 padding\n * - the send control is the return arrow *inside* that surface, 24px, 14px in\n * from the right border and anchored to the bottom text line\n * - control row: outside the surface, 4px below it, ~28px tall\n * - window edge: 8px below the row\n *\n * Host classes are pinned in src/client/compat/host-dom.ts.\n */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_body {\n --dsh-chat-content-width: var(--ccd-composer-width);\n --dsh-composer-card-max-width: var(--ccd-composer-width);\n --dsh-composer-side-clearance: 16px;\n}\n\n/* The card becomes a transparent column: the input surface draws the border. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card {\n gap: 0;\n padding-top: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n}\n\n/* Without a workspace the host makes the whole card a workspace picker and\n draws a dashed ::after around it. Move that state cue to the input surface\n that owns our border, while keeping the host\'s picker behavior. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_cardWorkspaceTrigger::after {\n content: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_scroll {\n box-sizing: border-box;\n min-height: var(--ccd-composer-min-height);\n margin-right: 0;\n padding: var(--ccd-composer-padding);\n border: 1px solid var(--ccd-border-strong);\n border-radius: var(--ccd-composer-radius);\n background: var(--ccd-card);\n box-shadow: var(--ccd-shadow-card);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_cardWorkspaceTrigger .yhfFVG_scroll {\n border-style: dashed;\n}\n\n/* The editor owns the focus cue. Model/effort menus live in this card too,\n so :focus-within would leave the ring on while a menu has keyboard focus.\n Darken the existing 1px border without changing the surface geometry. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_input:focus) .yhfFVG_scroll {\n border-color: var(--ccd-composer-focus-border);\n}\n\n/* Attachments: the `ui-attachment` plugin renders the draft-image rail as a\n sibling of the input panel inside the card (`conversation.input.attachments`\n slot, class pinned in src/client/compat/host-dom.ts \u2014 ComposerAttachments\n .module.css, `dVdiKa_`). With the card transparent the previews would float\n on the page above the surface, and the send control, pinned to the card\'s\n top-right corner, would leave the surface with them. When the rail is\n present the two merge back into one surface: the rail draws the top cap and\n the panel drops its own, while the card\'s zero gap keeps the 1px side\n borders touching so no seam shows. The host\'s unstyled card pulled the rail\n 6px into the panel (`margin-bottom: -6px`); that belongs to the old card and\n is dropped. The send control stays beside the bottom text line, so the rail\n needs only the same side padding as the input. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.dVdiKa_rail) .dVdiKa_rail {\n box-sizing: border-box;\n margin-bottom: 0;\n padding: 10px var(--ccd-composer-padding-inline) 0;\n border: 1px solid var(--ccd-border-strong);\n border-bottom: 0;\n border-radius: var(--ccd-composer-radius) var(--ccd-composer-radius) 0 0;\n background: var(--ccd-card);\n box-shadow: var(--ccd-shadow-card);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.dVdiKa_rail) .yhfFVG_scroll {\n border-top: 0;\n border-radius: 0 0 var(--ccd-composer-radius) var(--ccd-composer-radius);\n}\n\n/* The attachment cap shares the editor\'s focused border colour. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_input:focus) .dVdiKa_rail {\n border-color: var(--ccd-composer-focus-border);\n}\n\n/* Match the image tile to the outer editable surface, including its clipping. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card .dVdiKa_thumbnail {\n border-radius: var(--ccd-composer-radius);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_input,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_hero .yhfFVG_input {\n box-sizing: border-box;\n min-height: 24px;\n /* Keep text clear of the controls, including when the editor scrolls. */\n padding: 0 var(--ccd-send-reserve) 0 0;\n font-family: var(--ccd-font-ui);\n font-size: var(--dsh-content-font-size, 14px);\n line-height: 24px;\n color: var(--ccd-text);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_placeholder {\n /* Hero copy is longer than chat copy. Limit only the placeholder, leaving\n the actual editor\'s wrapping and multiline growth untouched. */\n inset: 0 0 auto 0;\n box-sizing: border-box;\n padding-right: var(--ccd-send-reserve);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--ccd-text-placeholder);\n font-size: var(--dsh-content-font-size, 14px);\n line-height: 24px;\n}\n\n/* Send / stop stay beside the input\'s bottom line. The row is their containing\n block: its top follows the input\'s bottom even if the row itself wraps.\n The host still owns both buttons, their state, labels and click handlers. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary {\n /* The user agent\'s `1px 6px` button padding is asymmetric against a 24px box\n only in the sense that it steals the content box; drop it and centre. */\n padding: 0;\n position: absolute;\n top: auto;\n bottom: calc(100% + var(--ccd-composer-row-gap) + var(--ccd-composer-padding-block) + 1px);\n right: var(--ccd-composer-padding-inline);\n width: var(--ccd-send-size);\n height: var(--ccd-send-size);\n border-radius: var(--ccd-send-radius);\n background: transparent;\n color: var(--ccd-text-nav);\n transform: none;\n transition: background-color 0.1s, color 0.1s;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary:hover:not(:disabled) {\n background: var(--ccd-hover);\n color: var(--ccd-text);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary:disabled {\n background: transparent;\n opacity: 0.4;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary svg {\n display: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary::before {\n content: "";\n width: 16px;\n height: 16px;\n background-color: currentColor;\n mask: var(--ccd-icon-send) center / 16px 16px no-repeat;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary:has(rect)::before {\n mask-image: var(--ccd-icon-stop);\n}\n\n/* DSH exposes both stop and send when a new draft is entered while running. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_row .yhfFVG_primary:has(+ .yhfFVG_primary) {\n right: calc(var(--ccd-composer-padding-inline) + var(--ccd-send-size) + 6px);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_primary + .yhfFVG_primary) .yhfFVG_input {\n padding-right: calc(var(--ccd-send-reserve) + var(--ccd-send-size) + 6px);\n}\n\n/* Tool row: outside the surface, directly below it, and one rhythm end to end.\n The row\'s own gap is the host\'s 12px, which the leading groups kept while the\n trailing cluster was already on `--ccd-cluster-gap`; the rule below hands the\n same 6px to every container in the bar, so the leading pair, the trailing\n cluster, the statistics dock and the ring read as one row.\n\n One line, at every width. The host\'s row wraps\n (`InputBar.module.css`: `.yhfFVG_row { flex-wrap: wrap }`) and breaks before\n it shrinks anything: a flex container decides its lines from the children\'s\n *base* sizes, so a column too narrow for the leading pair and the whole\n trailing cluster put \u2014 and the cluster lands on a second line of its own, a\n row lower, while the model chip that could have given up the space is still\n drawn at its cap. The reference draws the bar as one line\n at every window width (its `DeepSeek V4.1 Fl\u2026` is the model name clipped by\n the chip\'s own ellipsis, not a wrapped row), and the Composer\'s bottom inset\n is measured for that one line: two lines push the row over the window edge.\n So the wrap goes and the squeeze lands where the reference puts it \u2014 the\n model name, whose chip is the one item here that can shorten without\n losing its reading (`min-width: 0` and the host\'s own ellipsis on\n `.cl2Rlq_triggerLabel`), while the leading controls keep their boxes\n (`.yhfFVG_tools` below), the effort keeps its `flex-shrink: 0` and the ring\n keeps its reserved seat. Standing in the way of that squeeze is the trailing\n group\'s own `flex: none` (the host\'s, under `.yhfFVG_trailing`): the group is\n sized from the model chip\'s budget, and the budget\n (`compat/stats-values.ts` publishes the row\'s measured remainder as\n `--ccd-model-max-width`) is what the row has *left over* \u2014 not what the chip\n may take from a line that also carries the leading pair. Left unshrinkable\n the cluster would simply run past the Composer\'s right edge with the chip at\n its cap; allowed to shrink, the chip settles on what is actually there and\n ellipsizes, which is the one reading the reference is willing to shorten. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_row {\n position: relative;\n flex-wrap: nowrap;\n gap: var(--ccd-cluster-gap);\n min-height: var(--ccd-control-row-height);\n margin-top: var(--ccd-composer-row-gap);\n padding: 0 var(--ccd-composer-row-inset);\n color: var(--ccd-text-secondary);\n font-size: var(--ccd-font-size-muted);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_row button {\n color: var(--ccd-text-secondary);\n}\n\n/* The model selector\'s two texts \u2014 the model name and the reasoning effort \u2014\n are the row\'s chosen values, not chrome, so they carry the chosen-value ink\n instead of the row\'s label grey; the host\'s own `font-weight: 400` stays.\n Each text is its own span, so the colour lands on the spans rather than on\n the button the rule above paints, and this plugin\'s own model/effort pair\n (features/model-controls) follows the same token. Host classes are pinned in\n src/client/compat/host-dom.ts (`ui-model-selection`\'s\n ModelSelect.module.css, `cl2Rlq_`). */\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_triggerLabel,\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_triggerEffort {\n color: var(--ccd-text-strong);\n}\n\n/* Budget the complete row: the native model-collapse check cannot see the\n sibling statistics dock. Keep the effort readable and give the name the\n remaining space, instead of hiding either at a fixed column breakpoint. */\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_trigger {\n box-sizing: border-box;\n max-width: min(360px, var(--ccd-model-max-width, 45cqw));\n}\n\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_triggerEffort {\n flex-shrink: 0;\n}\n\n/* The command button is a bare glyph in the reference, not a filled circle \u2014\n and it is a chip like every other control in the row: 20px tall, its 14px\n glyph plus one chip padding on each side, so the box is the same 28px the\n host drew and only its height and corner move. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_add {\n width: calc(var(--ccd-row-icon-size) + 2 * var(--ccd-chip-padding-inline));\n height: var(--ccd-chip-height);\n border-radius: var(--ccd-chip-radius);\n background: transparent;\n color: var(--ccd-text-secondary);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_add:hover:not(:disabled) {\n background: var(--ccd-hover);\n color: var(--ccd-text);\n}\n\n/* The leading pair keeps its boxes: the row no longer wraps, so the only item\n it may take the slack from is the model chip beside it. The permission chip\'s\n label is the whole control (`composer.css`, above), so a shrunk tools group\n would be a control with its own reading cut off rather than a shorter one. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_tools {\n flex: none;\n align-items: center;\n}\n\n/* The trailing group\'s half of the same trade: it stays at its own size where\n there is room (the host\'s `flex: none`), and gives the model chip up to the\n line\'s real remainder where there is not. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing {\n min-width: 0;\n flex-shrink: 1;\n}\n\n/* Statistics cluster and context ring: the dock is a sibling of the card inside\n the Composer root, so it is laid over the tool row instead of taking a line of\n its own. Every readout keeps its own icon and its click-open detail panel;\n only the narrow-column labels go. The root becomes the containing block, and\n the offsets below walk back in from the column edge to the card\'s own right\n edge, which the dock cannot see from where it sits.\n\n The dock now owns the row\'s *last* seat rather than the one before the model:\n the statistics cluster still stops one cluster gap short of the trailing\n group, and the context ring hangs past it, on the row\'s right content edge.\n Both offsets are built from `--ccd-ring-offset` \u2014 the trailing cluster\'s live\n width, one cluster gap and the ring\'s own seat \u2014 so the ring lands on that\n edge whatever the cluster measures, and the trailing group\'s `margin-right`\n below keeps the model/effort pair clear of it. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root {\n position: relative;\n container: ccd-composer / inline-size;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock {\n position: absolute;\n --ccd-ring-offset: calc(var(--ccd-trailing-width, 120px) + var(--ccd-cluster-gap)\n + var(--ccd-context-ring-seat));\n right: calc((100% - min(100% - 32px, var(--ccd-composer-width))) / 2\n + var(--ccd-composer-row-inset) + var(--ccd-ring-offset));\n bottom: var(--ccd-composer-bottom-gap);\n height: var(--ccd-control-row-height);\n /* Never measure narrower than the ring\'s own trigger box: compat/stats-values.ts\n subtracts this dock from the model\'s budget, and an empty dock would\n otherwise hand the model the ring\'s seat as well. */\n min-width: var(--ccd-context-ring-trigger);\n padding: 0;\n gap: var(--ccd-cluster-gap);\n align-items: center;\n justify-content: flex-end;\n /* The box is an overlay: only its occupants take pointer input, so an empty\n dock never shadows the row underneath. */\n pointer-events: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock > * {\n pointer-events: auto;\n}\n\n/* The context ring\'s seat: the status bar\'s last one, where the voice control\n used to sit. The ring is the host\'s own element \u2014 `ContextMeter` renders\n `span.y0jqnG_root` as the dock\'s last child \u2014 and is placed rather than\n re-parented: the host unmounts that ring whenever the voice control expands,\n and React would then remove it from a parent it no longer belongs to. The\n plugin\'s empty-state ring below shares this box exactly, so a session gaining\n its first tokens hands the seat over without moving or resizing anything. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock > .y0jqnG_root,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock::after {\n position: absolute;\n right: calc(-1 * var(--ccd-ring-offset));\n top: 0;\n width: var(--ccd-context-ring-trigger);\n height: var(--ccd-control-row-height);\n flex: none;\n}\n\n/* The seat is the row\'s own 28px line and the ring\'s trigger inside it is a\n chip like every other control, so the artwork has to be centred in the seat\n rather than laid out from its top edge: `align-items: stretch` does not\n stretch an item that states its own height, it parks it at the line\'s start. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock > .y0jqnG_root {\n align-items: center;\n justify-content: center;\n}\n\n/* A session with no usage renders no `ContextMeter` at all: the component\n returns null until the token meter knows both a numerator and the context\n window, so the empty state is not something the host hides \u2014 there is nothing\n to show. This draws the ring\'s own track in the seat above, at the host\'s own\n geometry (`ContextMeter.module.css`: 14px box, r 5.5, 2px stroke), and\n withdraws the moment the host\'s ring exists or the voice control\'s capture row\n takes the bar \u2014 exactly the states in which the host unmounts its own ring. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock::after {\n content: "";\n background-color: var(--ccd-context-ring-track);\n mask: var(--ccd-icon-context-ring) center / var(--ccd-context-ring-size) var(--ccd-context-ring-size) no-repeat;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock:has(.y0jqnG_root)::after,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root:has(.yhfFVG_trailingActive) .yhfFVG_dock::after {\n content: none;\n}\n\n/* The trailing cluster stops one ring seat short of the row\'s right content\n edge, so the model/effort pair never lands under the ring. While the voice\n control\'s capture row owns the bar the ring is unmounted and the seat is given\n back, leaving the host\'s own capture layout whole. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing {\n margin-right: var(--ccd-context-ring-seat);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root:has(.yhfFVG_trailingActive) .yhfFVG_trailing {\n margin-right: 0;\n}\n\n/* The host hides a hero-phase dock that has nothing in it; the ring\'s seat is\n drawn through a pseudo-element, which `:empty` does not see. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_hero .yhfFVG_dock:empty {\n display: flex;\n}\n\n/*\n * The whole status row reads on one pitch \u2014 not just the trailing cluster. The\n * host separates its groups with 12px (`InputBar.module.css`: the row itself,\n * `.yhfFVG_tools` and `.yhfFVG_modes`) while the plugin\'s trailing cluster\n * already ran on 6px, which put the leading pair, the model/effort pair and the\n * ring on two different rhythms; every container in the bar now takes its gap\n * from `--ccd-cluster-gap` (tokens.css).\n *\n * The group\'s last seat is the native activity control (speech to text). While\n * no occupant is mounted, its wrapper is still a box \u2014 the renderer seats every\n * entry in a `display: contents` wrapper, so the host\'s own `:empty` rule cannot\n * see that it is empty \u2014 and the group\'s gap then held the model/effort pair\n * 12px off the row\'s right content edge. Hiding the empty wrapper moves the pair\n * (and, through `--ccd-trailing-width`, the whole cluster) back onto that edge.\n * An expanded activity control carries the other class and keeps its seat.\n *\n * The control itself no longer lives in this group: flex `order` cannot cross\n * the two containers, so compat/composer-status-order.ts moves the seat into the\n * leading group\'s modes cluster, immediately after the permission control. The\n * same empty-seat rule is repeated for that parent below.\n */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_tools,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_modes,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_standardControls {\n gap: var(--ccd-cluster-gap);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing > .yhfFVG_activity:not(:has(> :not([data-slot]))):not(:has([data-slot] > *)),\nhtml[data-dsh-ccd-style="true"] .yhfFVG_modes > .yhfFVG_activity:not(:has(> :not([data-slot]))):not(:has([data-slot] > *)) {\n display: none;\n}\n\n/* Voice input. The glyph is addressed through the control\'s own slot outlet \u2014\n the one stable name the seat has \u2014 so its size holds whether the seat still\n sits in the trailing group or already beside the permission control, which is\n where compat/composer-status-order.ts moves it; the `data-ccd-voice-seat` mark\n that module leaves on a relocated seat is what the placement rule reads. The\n host draws the microphone at 18px, while every other glyph in the status bar\n (command plus, statistics readouts, context ring) is 14px artwork, so the\n mic takes that size and stays centred in its box. Only `button > svg` is\n resized: the recording row\'s waveform is a direct child of its own row and\n keeps the host\'s sizing. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_modes > [data-ccd-voice-seat] {\n align-items: center;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-slot="conversation.input.activity"] button > svg {\n width: var(--ccd-row-icon-size);\n height: var(--ccd-row-icon-size);\n}\n\n/* The mic\'s own hit box is the row\'s glyph box, not the host\'s 28\xD714 strip: a\n chip of the row\'s height around the 14px mark, the same box the command plus\n beside it carries. The capture layout is left alone \u2014 the host hands that row\n its own round buttons and its own geometry. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root:not(:has(.yhfFVG_trailingActive))\n [data-slot="conversation.input.activity"] button {\n box-sizing: border-box;\n display: inline-flex;\n width: calc(var(--ccd-row-icon-size) + 2 * var(--ccd-chip-padding-inline));\n height: var(--ccd-chip-height);\n align-items: center;\n justify-content: center;\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_root {\n gap: var(--ccd-cluster-gap);\n align-items: center;\n}\n\n/* The readouts are opted into (`features.composer-stats`, off by default);\n `compat/stats-values.ts` publishes that state on the root. Off, the host\'s\n whole cluster leaves the line \u2014 each pill and the counts it prints \u2014 and the\n mirroring rules below have nothing to draw on. Nothing moves when it goes:\n the cluster and the context ring are both occupants of the dock, which is\n right-aligned, so the ring keeps the edge it already had, and the model\n button\'s budget is re-measured from the dock\'s own width by that same module.\n `[data-composer-stats]` is the host\'s stable marker for the cluster, so this\n rule outlives a build whose class hashes move. */\nhtml[data-dsh-ccd-style="true"][data-ccd-composer-stats="off"] [data-composer-stats] {\n display: none;\n}\n\n/* Same control shape as the model and permission selectors next to them: the\n host draws these readouts as full pills (`border-radius: 999px`) on its own\n 28px line, which reads as a different family of control in the same row. They\n take the row\'s chip box \u2014 height, corner and the readouts\' own 6px inline\n padding \u2014 and the row\'s own hover step, because the host paints its pill\n hover from `--dsw-alias-interactive-bg-hover` (a 6% bluish grey) while every\n other control in the bar sits in this palette\'s warm `--ccd-hover`. */\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill,\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger {\n gap: 4px;\n height: var(--ccd-chip-height);\n padding: 0 6px;\n border-radius: var(--ccd-chip-radius);\n color: var(--ccd-text-secondary);\n font-size: var(--ccd-font-size-muted);\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill:hover,\nhtml[data-dsh-ccd-style="true"] button.OpZ85W_pill[aria-expanded="true"],\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger:hover,\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger[aria-expanded="true"] {\n background: var(--ccd-hover);\n}\n\n/* Wide columns show one short readout per icon, derived from host text.\n Original aria-labels and click handlers stay on the host buttons. */\nhtml[data-dsh-ccd-style="true"] .OpZ85W_label,\nhtml[data-dsh-ccd-style="true"] .OpZ85W_sep {\n display: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill::after {\n content: var(--ccd-stat-value, "");\n font-variant-numeric: tabular-nums;\n}\n\n@container ccd-composer (max-width: 700px) {\n html[data-dsh-ccd-style="true"] .OpZ85W_pill::after {\n content: none;\n }\n}\n\n/* The ring carries no reading: the arc is the reading. The host\'s own text\n (`span` inside the trigger) goes, while the trigger keeps its box so the\n seat\'s geometry is unchanged. The hover panel keeps its numbers, and the\n accessible name keeps its wording \u2014 compat/composer-status-order.ts strips\n only the percentage from that. */\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger > span {\n display: none;\n}\n\n/* The consumed arc is the one reading this control exists to show, so it takes\n the interface\'s accent blue instead of the host\'s tertiary label grey, which\n painted it the same ink as the percentage beside it. Only the colour moves:\n the host\'s 14px box, 2px stroke and round cap are untouched, and the track\n underneath keeps `--dsw-alias-border-l3` (already a theme override), so the\n two arcs stay clearly apart. The blue holds at every percentage \u2014 the\n reference draws no warning step, and a hue that changed near the limit would\n leave the ring\'s own reading ambiguous. */\nhtml[data-dsh-ccd-style="true"] .y0jqnG_fill {\n stroke: var(--ccd-context-ring-fill);\n}\n\n/* The permission control is the row\'s other text chip: the host draws it on the\n row\'s full 28px with a 4px/8px inline padding, so beside the model chip it kept\n a taller fill and a different ink rhythm. It takes the chip box and the chip\'s\n own 7px padding on both sides \u2014 the host\'s asymmetry was the two marks it\n reserved room for, and neither of them is drawn (below), so the label sits on\n the chip\'s even padding. Its hover fill is the row\'s warm step for the same\n reason the readouts above are. Host class pinned in\n src/client/compat/host-dom.ts (`ui-permission-presets`\'s\n PermissionSelect.module.css, `wXeviG_`). */\nhtml[data-dsh-ccd-style="true"] .wXeviG_trigger {\n box-sizing: border-box;\n height: var(--ccd-chip-height);\n padding: 0 var(--ccd-chip-padding-inline);\n border-radius: var(--ccd-chip-radius);\n}\n\nhtml[data-dsh-ccd-style="true"] .wXeviG_trigger:hover:not(:disabled) {\n background: var(--ccd-hover);\n}\n\n/* The chip is its text, and nothing else. The host leads the control with the\n mode\'s own glyph \u2014 `PermissionIconReadOnlyRegular` / `...WorkspaceWrite` /\n `...FullAccess`, the same 14px artwork the command plus beside it draws \u2014 and\n closes it with `IconChevronDownOutlineRegular`. Neither says anything the chip\n does not: the glyph repeats the mode the label already spells out, and this\n row\'s other menu controls (the two hero chips) draw no disclosure mark either.\n Both come out of the line, and with them the host\'s two 4px gaps and the\n 4px/8px asymmetry they reserved. The control keeps the host\'s `aria-label`\n ("\u6A21\u5F0F \u2026") and its `title`, so a screen reader still hears the mode in full,\n and the button keeps its own name \u2014 it is the same control, drawn shorter.\n Its open state has no mark left to turn; the row\'s one fill already answers\n the pointer that opened it. */\nhtml[data-dsh-ccd-style="true"] .wXeviG_triggerIcon,\nhtml[data-dsh-ccd-style="true"] .wXeviG_chevron {\n display: none;\n}\n\n/* The label is what is left, so it is drawn at every width. The host\'s own\n container query drops it below 460px\n (`.wXeviG_trigger:has(.wXeviG_triggerIcon) .wXeviG_triggerLabel`), reading the\n glyph as the reading that survives the narrow column; with that glyph\n withdrawn the rule would leave a chip that still answers a click and shows\n nothing. `:has()` plus the child combinator is what outranks the host\'s rule\n \u2014 the sheet order does not decide it. */\nhtml[data-dsh-ccd-style="true"] .wXeviG_trigger:has(.wXeviG_triggerIcon) > .wXeviG_triggerLabel {\n display: inline;\n}\n\n/* Narrow columns tighten the readouts\' side padding and the ring\'s seat; the\n permission chip keeps its label, because the label is the whole control. */\n@container ccd-composer (max-width: 560px) {\n html[data-dsh-ccd-style="true"] .OpZ85W_pill,\n html[data-dsh-ccd-style="true"] .y0jqnG_trigger {\n padding-inline: 4px;\n }\n\n /* The ring\'s trigger keeps the chip\'s height but drops 7px of side padding to\n 4px, so the seat it occupies is 22px wide; the empty-state ring follows it\n (the seat the row reserves stays the authored 32px, a hair generous). */\n html[data-dsh-ccd-style="true"] .yhfFVG_dock {\n --ccd-context-ring-trigger: 22px;\n }\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill,\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger {\n flex-shrink: 0;\n white-space: nowrap;\n}\n\n/* Hero keeps the workspace row above the composer, as the reference does. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_composerHero {\n gap: 6px;\n padding-bottom: 0;\n}\n\n/* Bottom inset: row \u2192 window edge. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_hero {\n padding-bottom: var(--ccd-composer-bottom-gap);\n}\n\n/* The chips row starts on the input surface\'s own left edge: the Composer root\n insets that surface by the side clearance, so the row carries exactly that\n inset and nothing more. The reference measures the chip\'s border within 1px\n of the input\'s border, so a chip that sat any further right would read as a\n second, misaligned column. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow {\n justify-content: flex-start;\n height: 26px;\n padding: 0 var(--dsh-composer-side-clearance, 16px);\n}\n\n/* Both chips in that row are menu controls \u2014 the workspace picker and the\n agent-preset picker \u2014 and the reference draws each of them as a bordered\n card on the page rather than as a bare label: 1px `--ccd-border`, the row\n radius, a hairline shadow, and no fill until hover. The input surface below\n keeps the stronger border, because it is the editable surface. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"],\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace {\n box-sizing: border-box;\n height: 26px;\n min-height: 26px;\n padding: 0 8px;\n border: 1px solid var(--ccd-border);\n border-radius: var(--ccd-radius-row);\n background: transparent;\n box-shadow: var(--ccd-shadow-card);\n color: var(--ccd-text-secondary);\n font-size: var(--ccd-font-size-muted);\n}\n\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"]:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"][aria-expanded="true"],\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace[aria-expanded="true"] {\n background: var(--ccd-hover);\n color: var(--ccd-text);\n}\n\n/* The chip\'s leading mark. The host picks that glyph from the chip\'s own state:\n `IconFolderOpenRegular` \u2014 a slanted front panel over a translucent back panel\n \u2014 as soon as a workspace is chosen, and a closed folder only while the chip\n carries its placeholder. The reference leads with one closed folder either\n way, so the host\'s svg is taken out of the line and the mark is painted in\n its place from `--ccd-icon-folder`, on the same 16px box, with the chip\'s own\n `currentColor` \u2014 which is the ink the label beside it uses, and the ink the\n chip already steps up on hover, so the mark follows both for free.\n\n `::before` on the button is the first flex item of its own `inline-flex`\n line, exactly where the host\'s svg sat: the button\'s 4px gap and its 8px\n leading padding keep measuring from a 16px box, so the label\'s x does not\n move. `flex: none` is the host\'s own declaration on that svg, restated\n because the seat is now a pseudo-element: left shrinkable, a long workspace\n name would take its width out of the mark\'s 16px box as well as its own. */\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace .bocITq_folder {\n display: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace::before {\n content: "";\n flex: none;\n width: 16px;\n height: 16px;\n background-color: currentColor;\n mask: var(--ccd-icon-folder) center / 16px 16px no-repeat;\n}\n\n/* Neither chip in the row closes on a disclosure mark. The reference draws the\n two cards as a mark, a label and nothing else, where both host controls end\n their line with `IconChevronDownOutlineRegular`: the workspace chip through\n `HeroShell.module.css`, the mode chip through `AgentPresetSeat.module.css`.\n The first selector names the workspace chip\'s own mark; the second is what\n reaches the seat, whose module prefix is not in `host-builds.ts` and so\n cannot be written down here at all \u2014 its chevron is matched on the artwork\n itself, the way this stylesheet already matches the panel glyphs. Both are\n the same 12px `M4 6L7.29289\u2026` path; the seat\'s other mark is the preset\n glyph and the workspace chip\'s is the folder, so neither can be caught here.\n\n `display: none` is the whole change: the 12px box and the 4px gap leave the\n line with it, and each label ends on the chip\'s own 8px trailing padding.\n Nothing is taken from the controls themselves \u2014 both keep `aria-haspopup`\n and `aria-expanded`, so a menu is still announced as a menu. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"] > .bocITq_chevron,\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"] > svg:has(> path[d^="M4 6L7.29289"]) {\n display: none;\n}\n\n/* Both chips in the hero row open a card from the host\'s `Menu` primitive, and\n every other host popup \u2014 the workspace `\u22EF` and session `\u22EF` menus, view\n options, the permission picker, the account card, the command palette \u2014 is\n built from the same two pieces. Their card chrome and their 24px flat cells\n are drawn once for the whole interface in [menus.css](menus.css) (DESIGN.md\n \xA76.7), so this sheet keeps only what belongs to the Composer it lays out.\n\n What is genuinely the mode card\'s own is the second line of its rows: */\n\n/* The mode card\'s second line, and the reason its rows were not flat cells in\n the first place: `ui-agent-preset` renders each row\'s label as a stack of a\n name and a description (`AgentPresetSeat.module.css`: `.item` is a column\n flex with a 2px gap, `.itemName` 13px/20px, `.itemDesc` a 12px/16px caption),\n which makes one row 66px tall and stretches the card to its longest\n description\'s measure \u2014 324px for the four shipped presets, where the flat\n cell needs a fraction of that. The design document\'s popup row is "text plus\n a trailing mark" (DESIGN.md \xA76.7) and its height is one 20px line, so the\n description is not drawn: the row then draws its name alone, and the card\n falls back to the primitive\'s own 144px minimum width.\n\n The line is reached structurally, not by class name: those two spans are the\n label wrapper\'s only children and that wrapper is the row label\'s only child,\n so "everything after the first span of the label\'s own span" is the\n description on every row of this card. The classes in that pane (`m0vb0q_*`)\n are a per-build hash of a desktop package \u2014 the same fact `host-builds.ts`\n records for `_3li69W_` from the same package \u2014 so naming one would leave the\n Windows build\'s rows two lines tall, silently, because that build has no\n counterpart to alias it to. The guard is the preset seat\'s own expanded\n state: the workspace chip beside it is the row\'s other `aria-haspopup`\n button, and `:not(.bocITq_workspace)` keeps this rule on the mode card (the\n workspace chip\'s class is pinned in `compat/host-dom.ts`). */\nhtml[data-dsh-ccd-style="true"]:has(.ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"]:not(.bocITq_workspace)[aria-expanded="true"])\n [role="menu"] > ._viewport_4ub78_19 > ._itemWrap_4ub78_90 > ._item_4ub78_90 > ._itemLabel_4ub78_190 > span > :not(:first-child) {\n display: none;\n}\n';
4437
+ var composer_default = '/*\n * Shared composer geometry.\n *\n * Both the blank-session page and the conversation page must place the official\n * Composer at the same width and shape, so the geometry lives here instead of\n * being duplicated in two features (siblings never import each other). The\n * upstream structure is kept: the resident Composer card stays the single\n * editable root, and only where its parts sit changes.\n *\n * Reference geometry (@2x reference screenshots, logical px at 1374x871):\n * - input surface: 770x42, 1px border, radius 10, text line 24px at 8/14 padding\n * - the send control is the return arrow *inside* that surface, 24px, 14px in\n * from the right border and anchored to the bottom text line\n * - control row: outside the surface, 4px below it, ~28px tall\n * - window edge: 8px below the row\n *\n * Host classes are pinned in src/client/compat/host-dom.ts.\n */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_body {\n --dsh-chat-content-width: var(--ccd-composer-width);\n --dsh-composer-card-max-width: var(--ccd-composer-width);\n --dsh-composer-side-clearance: 16px;\n}\n\n/* The card becomes a transparent column: the input surface draws the border. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card {\n --ccd-composer-add-reserve: calc(var(--ccd-send-size) + var(--ccd-cluster-gap));\n gap: 0;\n padding-top: 0;\n border: 0;\n border-radius: 0;\n background: transparent;\n box-shadow: none;\n}\n\n/* Capture mode hides the native tools group, including the plus. Let its text\n reclaim the leading inset without changing the voice seat or its layout. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_tools[hidden]) {\n --ccd-composer-add-reserve: 0px;\n}\n\n/* Without a workspace the host makes the whole card a workspace picker and\n draws a dashed ::after around it. Move that state cue to the input surface\n that owns our border, while keeping the host\'s picker behavior. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_cardWorkspaceTrigger::after {\n content: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_scroll {\n box-sizing: border-box;\n min-height: var(--ccd-composer-min-height);\n margin-right: 0;\n padding: var(--ccd-composer-padding);\n border: 1px solid var(--ccd-border-strong);\n border-radius: var(--ccd-composer-radius);\n background: var(--ccd-card);\n box-shadow: var(--ccd-shadow-card);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_cardWorkspaceTrigger .yhfFVG_scroll {\n border-style: dashed;\n}\n\n/* The editor owns the focus cue. Model/effort menus live in this card too,\n so :focus-within would leave the ring on while a menu has keyboard focus.\n Darken the existing 1px border without changing the surface geometry. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_input:focus) .yhfFVG_scroll {\n border-color: var(--ccd-composer-focus-border);\n}\n\n/* Attachments: the `ui-attachment` plugin renders the draft-image rail as a\n sibling of the input panel inside the card (`conversation.input.attachments`\n slot, class pinned in src/client/compat/host-dom.ts \u2014 ComposerAttachments\n .module.css, `dVdiKa_`). With the card transparent the previews would float\n on the page above the surface, and the send control, pinned to the card\'s\n top-right corner, would leave the surface with them. When the rail is\n present the two merge back into one surface: the rail draws the top cap and\n the panel drops its own, while the card\'s zero gap keeps the 1px side\n borders touching so no seam shows. The host\'s unstyled card pulled the rail\n 6px into the panel (`margin-bottom: -6px`); that belongs to the old card and\n is dropped. The send control stays beside the bottom text line, so the rail\n needs only the same side padding as the input. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.dVdiKa_rail) .dVdiKa_rail {\n box-sizing: border-box;\n margin-bottom: 0;\n padding: 10px var(--ccd-composer-padding-inline) 0;\n border: 1px solid var(--ccd-border-strong);\n border-bottom: 0;\n border-radius: var(--ccd-composer-radius) var(--ccd-composer-radius) 0 0;\n background: var(--ccd-card);\n box-shadow: var(--ccd-shadow-card);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.dVdiKa_rail) .yhfFVG_scroll {\n border-top: 0;\n border-radius: 0 0 var(--ccd-composer-radius) var(--ccd-composer-radius);\n}\n\n/* The attachment cap shares the editor\'s focused border colour. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_input:focus) .dVdiKa_rail {\n border-color: var(--ccd-composer-focus-border);\n}\n\n/* Match the image tile to the outer editable surface, including its clipping. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card .dVdiKa_thumbnail {\n border-radius: var(--ccd-composer-radius);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_input,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_hero .yhfFVG_input {\n box-sizing: border-box;\n min-height: 24px;\n /* Keep text clear of the controls, including when the editor scrolls. */\n padding: 0 var(--ccd-send-reserve) 0 var(--ccd-composer-add-reserve);\n font-family: var(--ccd-font-ui);\n font-size: var(--dsh-content-font-size, 14px);\n line-height: 24px;\n color: var(--ccd-text);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_placeholder {\n /* Hero copy is longer than chat copy. Limit only the placeholder, leaving\n the actual editor\'s wrapping and multiline growth untouched. */\n inset: 0 0 auto 0;\n box-sizing: border-box;\n padding-right: var(--ccd-send-reserve);\n padding-left: var(--ccd-composer-add-reserve);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--ccd-text-placeholder);\n font-size: var(--dsh-content-font-size, 14px);\n line-height: 24px;\n}\n\n/* Send / stop stay beside the input\'s bottom line. The row is their containing\n block: its top follows the input\'s bottom even if the row itself wraps.\n The host still owns both buttons, their state, labels and click handlers. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary {\n /* The user agent\'s `1px 6px` button padding is asymmetric against a 24px box\n only in the sense that it steals the content box; drop it and centre. */\n padding: 0;\n position: absolute;\n top: auto;\n bottom: calc(100% + var(--ccd-composer-row-gap) + var(--ccd-composer-padding-block) + 1px);\n right: var(--ccd-composer-padding-inline);\n width: var(--ccd-send-size);\n height: var(--ccd-send-size);\n border-radius: var(--ccd-send-radius);\n background: transparent;\n color: var(--ccd-text-nav);\n transform: none;\n transition: background-color 0.1s, color 0.1s;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary:hover:not(:disabled) {\n background: var(--ccd-hover);\n color: var(--ccd-text);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary:disabled {\n background: transparent;\n opacity: 0.4;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary svg {\n display: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary::before {\n content: "";\n width: 16px;\n height: 16px;\n background-color: currentColor;\n mask: var(--ccd-icon-send) center / 16px 16px no-repeat;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_primary:has(rect)::before {\n mask-image: var(--ccd-icon-stop);\n}\n\n/* DSH exposes both stop and send when a new draft is entered while running. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_row .yhfFVG_primary:has(+ .yhfFVG_primary) {\n right: calc(var(--ccd-composer-padding-inline) + var(--ccd-send-size) + 6px);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_card:has(.yhfFVG_primary + .yhfFVG_primary) .yhfFVG_input {\n padding-right: calc(var(--ccd-send-reserve) + var(--ccd-send-size) + 6px);\n}\n\n/* Tool row: outside the surface, directly below it, and one rhythm end to end.\n The row\'s own gap is the host\'s 12px, which the leading groups kept while the\n trailing cluster was already on `--ccd-cluster-gap`; the rule below hands the\n same 6px to every container in the bar, so the leading pair, the trailing\n cluster, the statistics dock and the ring read as one row.\n\n One line, at every width. The host\'s row wraps\n (`InputBar.module.css`: `.yhfFVG_row { flex-wrap: wrap }`) and breaks before\n it shrinks anything: a flex container decides its lines from the children\'s\n *base* sizes, so a column too narrow for the leading pair and the whole\n trailing cluster put \u2014 and the cluster lands on a second line of its own, a\n row lower, while the model chip that could have given up the space is still\n drawn at its cap. The reference draws the bar as one line\n at every window width (its `DeepSeek V4.1 Fl\u2026` is the model name clipped by\n the chip\'s own ellipsis, not a wrapped row), and the Composer\'s bottom inset\n is measured for that one line: two lines push the row over the window edge.\n So the wrap goes and the squeeze lands where the reference puts it \u2014 the\n model name, whose chip is the one item here that can shorten without\n losing its reading (`min-width: 0` and the host\'s own ellipsis on\n `.cl2Rlq_triggerLabel`), while the leading controls keep their boxes\n (`.yhfFVG_tools` below), the effort keeps its `flex-shrink: 0` and the ring\n keeps its reserved seat. Standing in the way of that squeeze is the trailing\n group\'s own `flex: none` (the host\'s, under `.yhfFVG_trailing`): the group is\n sized from the model chip\'s budget, and the budget\n (`compat/stats-values.ts` publishes the row\'s measured remainder as\n `--ccd-model-max-width`) is what the row has *left over* \u2014 not what the chip\n may take from a line that also carries the leading pair. Left unshrinkable\n the cluster would simply run past the Composer\'s right edge with the chip at\n its cap; allowed to shrink, the chip settles on what is actually there and\n ellipsizes, which is the one reading the reference is willing to shorten. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_row {\n position: relative;\n flex-wrap: nowrap;\n gap: var(--ccd-cluster-gap);\n min-height: var(--ccd-control-row-height);\n margin-top: var(--ccd-composer-row-gap);\n padding: 0 var(--ccd-composer-row-inset);\n color: var(--ccd-text-secondary);\n font-size: var(--ccd-font-size-muted);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_row button {\n color: var(--ccd-text-secondary);\n}\n\n/* The model selector\'s two texts \u2014 the model name and the reasoning effort \u2014\n are the row\'s chosen values, not chrome, so they carry the chosen-value ink\n instead of the row\'s label grey; the host\'s own `font-weight: 400` stays.\n Each text is its own span, so the colour lands on the spans rather than on\n the button the rule above paints, and this plugin\'s own model/effort pair\n (features/model-controls) follows the same token. Host classes are pinned in\n src/client/compat/host-dom.ts (`ui-model-selection`\'s\n ModelSelect.module.css, `cl2Rlq_`). */\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_triggerLabel,\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_triggerEffort {\n color: var(--ccd-text-strong);\n}\n\n/* Budget the complete row: the native model-collapse check cannot see the\n sibling statistics dock. Keep the effort readable and give the name the\n remaining space, instead of hiding either at a fixed column breakpoint. */\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_trigger {\n box-sizing: border-box;\n max-width: min(360px, var(--ccd-model-max-width, 45cqw));\n}\n\nhtml[data-dsh-ccd-style="true"] .cl2Rlq_triggerEffort {\n flex-shrink: 0;\n}\n\n/* Move only the native command button\'s painted box into the input surface.\n Like send/stop, it follows the last visible text line from the row\'s top, so\n multiline growth, editor scrolling and attachment caps cannot displace it.\n It remains inside the tools group: the host\'s hidden attribute still removes\n it during voice capture, and its focus/selection-aware launcher stays intact. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_add {\n box-sizing: border-box;\n position: absolute;\n bottom: calc(100% + var(--ccd-composer-row-gap) + var(--ccd-composer-padding-block) + 1px);\n left: var(--ccd-composer-padding-inline);\n width: var(--ccd-send-size);\n height: var(--ccd-send-size);\n padding: 0;\n border-radius: var(--ccd-chip-radius);\n background: transparent;\n color: var(--ccd-text-secondary);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_add:hover:not(:disabled) {\n background: var(--ccd-hover);\n color: var(--ccd-text);\n}\n\n/* The leading pair keeps its boxes: the row no longer wraps, so the only item\n it may take the slack from is the model chip beside it. The permission chip\'s\n label is the whole control (`composer.css`, above), so a shrunk tools group\n would be a control with its own reading cut off rather than a shorter one. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_tools {\n flex: none;\n align-items: center;\n}\n\n/* The trailing group\'s half of the same trade: it stays at its own size where\n there is room (the host\'s `flex: none`), and gives the model chip up to the\n line\'s real remainder where there is not. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing {\n min-width: 0;\n flex-shrink: 1;\n}\n\n/* Statistics cluster and context ring: the dock is a sibling of the card inside\n the Composer root, so it is laid over the tool row instead of taking a line of\n its own. Every readout keeps its own icon and its click-open detail panel;\n only the narrow-column labels go. The root becomes the containing block, and\n the offsets below walk back in from the column edge to the card\'s own right\n edge, which the dock cannot see from where it sits.\n\n The dock now owns the row\'s *last* seat rather than the one before the model:\n the statistics cluster still stops one cluster gap short of the trailing\n group, and the context ring hangs past it, on the row\'s right content edge.\n Both offsets are built from `--ccd-ring-offset` \u2014 the trailing cluster\'s live\n width, one cluster gap and the ring\'s own seat \u2014 so the ring lands on that\n edge whatever the cluster measures, and the trailing group\'s `margin-right`\n below keeps the model/effort pair clear of it. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root {\n position: relative;\n container: ccd-composer / inline-size;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock {\n position: absolute;\n --ccd-ring-offset: calc(var(--ccd-trailing-width, 120px) + var(--ccd-cluster-gap)\n + var(--ccd-context-ring-seat));\n right: calc((100% - min(100% - 32px, var(--ccd-composer-width))) / 2\n + var(--ccd-composer-row-inset) + var(--ccd-ring-offset));\n bottom: var(--ccd-composer-bottom-gap);\n height: var(--ccd-control-row-height);\n /* Never measure narrower than the ring\'s own trigger box: compat/stats-values.ts\n subtracts this dock from the model\'s budget, and an empty dock would\n otherwise hand the model the ring\'s seat as well. */\n min-width: var(--ccd-context-ring-trigger);\n padding: 0;\n gap: var(--ccd-cluster-gap);\n align-items: center;\n justify-content: flex-end;\n /* The box is an overlay: only its occupants take pointer input, so an empty\n dock never shadows the row underneath. */\n pointer-events: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock > * {\n pointer-events: auto;\n}\n\n/* The context ring\'s seat: the status bar\'s last one, where the voice control\n used to sit. The ring is the host\'s own element \u2014 `ContextMeter` renders\n `span.y0jqnG_root` as the dock\'s last child \u2014 and is placed rather than\n re-parented: the host unmounts that ring whenever the voice control expands,\n and React would then remove it from a parent it no longer belongs to. The\n plugin\'s empty-state ring below shares this box exactly, so a session gaining\n its first tokens hands the seat over without moving or resizing anything. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock > .y0jqnG_root,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock::after {\n position: absolute;\n right: calc(-1 * var(--ccd-ring-offset));\n top: 0;\n width: var(--ccd-context-ring-trigger);\n height: var(--ccd-control-row-height);\n flex: none;\n}\n\n/* The seat is the row\'s own 28px line and the ring\'s trigger inside it is a\n chip like every other control, so the artwork has to be centred in the seat\n rather than laid out from its top edge: `align-items: stretch` does not\n stretch an item that states its own height, it parks it at the line\'s start. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock > .y0jqnG_root {\n align-items: center;\n justify-content: center;\n}\n\n/* A session with no usage renders no `ContextMeter` at all: the component\n returns null until the token meter knows both a numerator and the context\n window, so the empty state is not something the host hides \u2014 there is nothing\n to show. This draws the ring\'s own track in the seat above, at the host\'s own\n geometry (`ContextMeter.module.css`: 14px box, r 5.5, 2px stroke), and\n withdraws the moment the host\'s ring exists or the voice control\'s capture row\n takes the bar \u2014 exactly the states in which the host unmounts its own ring. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock::after {\n content: "";\n background-color: var(--ccd-context-ring-track);\n mask: var(--ccd-icon-context-ring) center / var(--ccd-context-ring-size) var(--ccd-context-ring-size) no-repeat;\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_dock:has(.y0jqnG_root)::after,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root:has(.yhfFVG_trailingActive) .yhfFVG_dock::after {\n content: none;\n}\n\n/* The trailing cluster stops one ring seat short of the row\'s right content\n edge, so the model/effort pair never lands under the ring. While the voice\n control\'s capture row owns the bar the ring is unmounted and the seat is given\n back, leaving the host\'s own capture layout whole. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing {\n margin-right: var(--ccd-context-ring-seat);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root:has(.yhfFVG_trailingActive) .yhfFVG_trailing {\n margin-right: 0;\n}\n\n/* The host hides a hero-phase dock that has nothing in it; the ring\'s seat is\n drawn through a pseudo-element, which `:empty` does not see. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_hero .yhfFVG_dock:empty {\n display: flex;\n}\n\n/*\n * The whole status row reads on one pitch \u2014 not just the trailing cluster. The\n * host separates its groups with 12px (`InputBar.module.css`: the row itself,\n * `.yhfFVG_tools` and `.yhfFVG_modes`) while the plugin\'s trailing cluster\n * already ran on 6px, which put the leading pair, the model/effort pair and the\n * ring on two different rhythms; every container in the bar now takes its gap\n * from `--ccd-cluster-gap` (tokens.css).\n *\n * The group\'s last seat is the native activity control (speech to text). While\n * no occupant is mounted, its wrapper is still a box \u2014 the renderer seats every\n * entry in a `display: contents` wrapper, so the host\'s own `:empty` rule cannot\n * see that it is empty \u2014 and the group\'s gap then held the model/effort pair\n * 12px off the row\'s right content edge. Hiding the empty wrapper moves the pair\n * (and, through `--ccd-trailing-width`, the whole cluster) back onto that edge.\n * An expanded activity control carries the other class and keeps its seat.\n *\n * The control itself no longer lives in this group: flex `order` cannot cross\n * the two containers, so compat/composer-status-order.ts moves the seat into the\n * leading group\'s modes cluster, immediately after the permission control. The\n * same empty-seat rule is repeated for that parent below.\n */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_tools,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_modes,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_standardControls {\n gap: var(--ccd-cluster-gap);\n}\n\nhtml[data-dsh-ccd-style="true"] .yhfFVG_trailing > .yhfFVG_activity:not(:has(> :not([data-slot]))):not(:has([data-slot] > *)),\nhtml[data-dsh-ccd-style="true"] .yhfFVG_modes > .yhfFVG_activity:not(:has(> :not([data-slot]))):not(:has([data-slot] > *)) {\n display: none;\n}\n\n/* Voice input. The glyph is addressed through the control\'s own slot outlet \u2014\n the one stable name the seat has \u2014 so its size holds whether the seat still\n sits in the trailing group or already beside the permission control, which is\n where compat/composer-status-order.ts moves it; the `data-ccd-voice-seat` mark\n that module leaves on a relocated seat is what the placement rule reads. The\n host draws the microphone at 18px, while every other glyph in the status bar\n (command plus, statistics readouts, context ring) is 14px artwork, so the\n mic takes that size and stays centred in its box. Only `button > svg` is\n resized: the recording row\'s waveform is a direct child of its own row and\n keeps the host\'s sizing. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_modes > [data-ccd-voice-seat] {\n align-items: center;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-slot="conversation.input.activity"] button > svg {\n width: var(--ccd-row-icon-size);\n height: var(--ccd-row-icon-size);\n}\n\n/* The mic\'s own hit box is the row\'s glyph box, not the host\'s 28\xD714 strip: a\n chip of the row\'s height around the 14px mark, the same box the command plus\n beside it carries. The capture layout is left alone \u2014 the host hands that row\n its own round buttons and its own geometry. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root:not(:has(.yhfFVG_trailingActive))\n [data-slot="conversation.input.activity"] button {\n box-sizing: border-box;\n display: inline-flex;\n width: calc(var(--ccd-row-icon-size) + 2 * var(--ccd-chip-padding-inline));\n height: var(--ccd-chip-height);\n align-items: center;\n justify-content: center;\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_root {\n gap: var(--ccd-cluster-gap);\n align-items: center;\n}\n\n/* The readouts are opted into (`features.composer-stats`, off by default);\n `compat/stats-values.ts` publishes that state on the root. Off, the host\'s\n whole cluster leaves the line \u2014 each pill and the counts it prints \u2014 and the\n mirroring rules below have nothing to draw on. Nothing moves when it goes:\n the cluster and the context ring are both occupants of the dock, which is\n right-aligned, so the ring keeps the edge it already had, and the model\n button\'s budget is re-measured from the dock\'s own width by that same module.\n `[data-composer-stats]` is the host\'s stable marker for the cluster, so this\n rule outlives a build whose class hashes move. */\nhtml[data-dsh-ccd-style="true"][data-ccd-composer-stats="off"] [data-composer-stats] {\n display: none;\n}\n\n/* Same control shape as the model and permission selectors next to them: the\n host draws these readouts as full pills (`border-radius: 999px`) on its own\n 28px line, which reads as a different family of control in the same row. They\n take the row\'s chip box \u2014 height, corner and the readouts\' own 6px inline\n padding \u2014 and the row\'s own hover step, because the host paints its pill\n hover from `--dsw-alias-interactive-bg-hover` (a 6% bluish grey) while every\n other control in the bar sits in this palette\'s warm `--ccd-hover`. */\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill,\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger {\n gap: 4px;\n height: var(--ccd-chip-height);\n padding: 0 6px;\n border-radius: var(--ccd-chip-radius);\n color: var(--ccd-text-secondary);\n font-size: var(--ccd-font-size-muted);\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill:hover,\nhtml[data-dsh-ccd-style="true"] button.OpZ85W_pill[aria-expanded="true"],\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger:hover,\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger[aria-expanded="true"] {\n background: var(--ccd-hover);\n}\n\n/* Wide columns show one short readout per icon, derived from host text.\n Original aria-labels and click handlers stay on the host buttons. */\nhtml[data-dsh-ccd-style="true"] .OpZ85W_label,\nhtml[data-dsh-ccd-style="true"] .OpZ85W_sep {\n display: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill::after {\n content: var(--ccd-stat-value, "");\n font-variant-numeric: tabular-nums;\n}\n\n@container ccd-composer (max-width: 700px) {\n html[data-dsh-ccd-style="true"] .OpZ85W_pill::after {\n content: none;\n }\n}\n\n/* The ring carries no reading: the arc is the reading. The host\'s own text\n (`span` inside the trigger) goes, while the trigger keeps its box so the\n seat\'s geometry is unchanged. The hover panel keeps its numbers, and the\n accessible name keeps its wording \u2014 compat/composer-status-order.ts strips\n only the percentage from that. */\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger > span {\n display: none;\n}\n\n/* The consumed arc is the one reading this control exists to show, so it takes\n the interface\'s accent blue instead of the host\'s tertiary label grey, which\n painted it the same ink as the percentage beside it. Only the colour moves:\n the host\'s 14px box, 2px stroke and round cap are untouched, and the track\n underneath keeps `--dsw-alias-border-l3` (already a theme override), so the\n two arcs stay clearly apart. The blue holds at every percentage \u2014 the\n reference draws no warning step, and a hue that changed near the limit would\n leave the ring\'s own reading ambiguous. */\nhtml[data-dsh-ccd-style="true"] .y0jqnG_fill {\n stroke: var(--ccd-context-ring-fill);\n}\n\n/* The permission control is the row\'s other text chip: the host draws it on the\n row\'s full 28px with a 4px/8px inline padding, so beside the model chip it kept\n a taller fill and a different ink rhythm. It takes the chip box and the chip\'s\n own 7px padding on both sides \u2014 the host\'s asymmetry was the two marks it\n reserved room for, and neither of them is drawn (below), so the label sits on\n the chip\'s even padding. Its hover fill is the row\'s warm step for the same\n reason the readouts above are. Host class pinned in\n src/client/compat/host-dom.ts (`ui-permission-presets`\'s\n PermissionSelect.module.css, `wXeviG_`). */\nhtml[data-dsh-ccd-style="true"] .wXeviG_trigger {\n box-sizing: border-box;\n height: var(--ccd-chip-height);\n padding: 0 var(--ccd-chip-padding-inline);\n border-radius: var(--ccd-chip-radius);\n}\n\nhtml[data-dsh-ccd-style="true"] .wXeviG_trigger:hover:not(:disabled) {\n background: var(--ccd-hover);\n}\n\n/* The chip is its text, and nothing else. The host leads the control with the\n mode\'s own glyph \u2014 `PermissionIconReadOnlyRegular` / `...WorkspaceWrite` /\n `...FullAccess`, the same 14px artwork the command plus beside it draws \u2014 and\n closes it with `IconChevronDownOutlineRegular`. Neither says anything the chip\n does not: the glyph repeats the mode the label already spells out, and this\n row\'s other menu controls (the two hero chips) draw no disclosure mark either.\n Both come out of the line, and with them the host\'s two 4px gaps and the\n 4px/8px asymmetry they reserved. The control keeps the host\'s `aria-label`\n ("\u6A21\u5F0F \u2026") and its `title`, so a screen reader still hears the mode in full,\n and the button keeps its own name \u2014 it is the same control, drawn shorter.\n Its open state has no mark left to turn; the row\'s one fill already answers\n the pointer that opened it. */\nhtml[data-dsh-ccd-style="true"] .wXeviG_triggerIcon,\nhtml[data-dsh-ccd-style="true"] .wXeviG_chevron {\n display: none;\n}\n\n/* The label is what is left, so it is drawn at every width. The host\'s own\n container query drops it below 460px\n (`.wXeviG_trigger:has(.wXeviG_triggerIcon) .wXeviG_triggerLabel`), reading the\n glyph as the reading that survives the narrow column; with that glyph\n withdrawn the rule would leave a chip that still answers a click and shows\n nothing. `:has()` plus the child combinator is what outranks the host\'s rule\n \u2014 the sheet order does not decide it. */\nhtml[data-dsh-ccd-style="true"] .wXeviG_trigger:has(.wXeviG_triggerIcon) > .wXeviG_triggerLabel {\n display: inline;\n}\n\n/* Narrow columns tighten the readouts\' side padding and the ring\'s seat; the\n permission chip keeps its label, because the label is the whole control. */\n@container ccd-composer (max-width: 560px) {\n html[data-dsh-ccd-style="true"] .OpZ85W_pill,\n html[data-dsh-ccd-style="true"] .y0jqnG_trigger {\n padding-inline: 4px;\n }\n\n /* The ring\'s trigger keeps the chip\'s height but drops 7px of side padding to\n 4px, so the seat it occupies is 22px wide; the empty-state ring follows it\n (the seat the row reserves stays the authored 32px, a hair generous). */\n html[data-dsh-ccd-style="true"] .yhfFVG_dock {\n --ccd-context-ring-trigger: 22px;\n }\n}\n\nhtml[data-dsh-ccd-style="true"] .OpZ85W_pill,\nhtml[data-dsh-ccd-style="true"] .y0jqnG_trigger {\n flex-shrink: 0;\n white-space: nowrap;\n}\n\n/* The native workspace row is conditional on the hero phase: React removes it\n when a conversation starts. Reorder the paired workspace/preset row with CSS\n instead of moving its DOM node out of the parent React will remove it from.\n Overlay its native row on the status line and reserve its width in tools.\n Keep this stack unpositioned: positioning it changes the containing block\n of the absolute hero greeting and can place that content over the editor.\n The workspace row anchors to the host\'s positioned composer seat instead. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_composerHero {\n --ccd-workspace-seat: clamp(140px, 25vw, 260px);\n gap: 0;\n padding-bottom: 0;\n reading-flow: flex-visual;\n}\n\n/* Bottom inset: row \u2192 window edge. */\nhtml[data-dsh-ccd-style="true"] .yhfFVG_root,\nhtml[data-dsh-ccd-style="true"] .yhfFVG_hero {\n padding-bottom: var(--ccd-composer-bottom-gap);\n}\n\n/* The chips row starts on the input surface\'s own left edge: the Composer root\n insets that surface by the side clearance, so the row carries exactly that\n inset and nothing more. The reference measures the chip\'s border within 1px\n of the input\'s border, so a chip that sat any further right would read as a\n second, misaligned column. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow {\n position: absolute;\n /* The later, positioned InputBar spans this row, including the empty tools\n padding reserved for these chips. Keep native buttons above that hit box. */\n z-index: 2;\n bottom: var(--ccd-composer-bottom-gap);\n left: calc((100% - min(100%, calc(var(--ccd-composer-width) + 32px))) / 2\n + var(--dsh-composer-side-clearance, 16px) + var(--ccd-composer-row-inset));\n box-sizing: border-box;\n width: var(--ccd-workspace-seat);\n min-width: 0;\n flex-wrap: nowrap;\n gap: var(--ccd-cluster-gap);\n justify-content: flex-start;\n height: var(--ccd-control-row-height);\n margin-top: 0;\n padding: 0;\n}\n\nhtml[data-dsh-ccd-style="true"] .ST7X_W_composerHero:has(.ST7X_W_heroWorkspaceRow) .yhfFVG_tools {\n padding-left: calc(var(--ccd-workspace-seat) + var(--ccd-cluster-gap));\n}\n\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow .bocITq_workspace {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n}\n\nhtml[data-dsh-ccd-style="true"] .bocITq_workspaceLabel {\n min-width: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"]:not(.bocITq_workspace) {\n flex: none;\n white-space: nowrap;\n}\n\n/* Keep the workspace picker and the existing preset seat as the same native\n menu controls, with the lightweight chip geometry of the lower tool row. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"],\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace {\n box-sizing: border-box;\n height: var(--ccd-chip-height);\n min-height: var(--ccd-chip-height);\n padding: 0 var(--ccd-chip-padding-inline);\n border: 0;\n border-radius: var(--ccd-chip-radius);\n background: transparent;\n box-shadow: none;\n color: var(--ccd-text-secondary);\n font-size: var(--ccd-font-size-muted);\n}\n\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"]:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"][aria-expanded="true"],\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace[aria-expanded="true"] {\n background: var(--ccd-hover);\n color: var(--ccd-text);\n}\n\n/* The chip\'s leading mark. The host picks that glyph from the chip\'s own state:\n `IconFolderOpenRegular` \u2014 a slanted front panel over a translucent back panel\n \u2014 as soon as a workspace is chosen, and a closed folder only while the chip\n carries its placeholder. The reference leads with one closed folder either\n way, so the host\'s svg is taken out of the line and the mark is painted in\n its place from `--ccd-icon-folder`, on the same 16px box, with the chip\'s own\n `currentColor` \u2014 which is the ink the label beside it uses, and the ink the\n chip already steps up on hover, so the mark follows both for free.\n\n `::before` on the button is the first flex item of its own `inline-flex`\n line, exactly where the host\'s svg sat: the button\'s 4px gap and its chip\n padding keep measuring from a 16px box. `flex: none` is the host\'s own\n declaration on that svg, restated\n because the seat is now a pseudo-element: left shrinkable, a long workspace\n name would take its width out of the mark\'s 16px box as well as its own. */\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace .bocITq_folder {\n display: none;\n}\n\nhtml[data-dsh-ccd-style="true"] .bocITq_workspace::before {\n content: "";\n flex: none;\n width: 16px;\n height: 16px;\n background-color: currentColor;\n mask: var(--ccd-icon-folder) center / 16px 16px no-repeat;\n}\n\n/* Neither chip in the row closes on a disclosure mark. The reference draws the\n two controls as a mark, a label and nothing else, where both host controls end\n their line with `IconChevronDownOutlineRegular`: the workspace chip through\n `HeroShell.module.css`, the mode chip through `AgentPresetSeat.module.css`.\n The first selector names the workspace chip\'s own mark; the second is what\n reaches the seat, whose module prefix is not in `host-builds.ts` and so\n cannot be written down here at all \u2014 its chevron is matched on the artwork\n itself, the way this stylesheet already matches the panel glyphs. Both are\n the same 12px `M4 6L7.29289\u2026` path; the seat\'s other mark is the preset\n glyph and the workspace chip\'s is the folder, so neither can be caught here.\n\n `display: none` is the whole change: the 12px box and the 4px gap leave the\n line with it, and each label ends on the chip\'s own 8px trailing padding.\n Nothing is taken from the controls themselves \u2014 both keep `aria-haspopup`\n and `aria-expanded`, so a menu is still announced as a menu. */\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"] > .bocITq_chevron,\nhtml[data-dsh-ccd-style="true"] .ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"] > svg:has(> path[d^="M4 6L7.29289"]) {\n display: none;\n}\n\n/* Both chips in the hero row open a card from the host\'s `Menu` primitive, and\n every other host popup \u2014 the workspace `\u22EF` and session `\u22EF` menus, view\n options, the permission picker, the account card, the command palette \u2014 is\n built from the same two pieces. Their card chrome and their 24px flat cells\n are drawn once for the whole interface in [menus.css](menus.css) (DESIGN.md\n \xA76.7), so this sheet keeps only what belongs to the Composer it lays out.\n\n What is genuinely the mode card\'s own is the second line of its rows: */\n\n/* The mode card\'s second line, and the reason its rows were not flat cells in\n the first place: `ui-agent-preset` renders each row\'s label as a stack of a\n name and a description (`AgentPresetSeat.module.css`: `.item` is a column\n flex with a 2px gap, `.itemName` 13px/20px, `.itemDesc` a 12px/16px caption),\n which makes one row 66px tall and stretches the card to its longest\n description\'s measure \u2014 324px for the four shipped presets, where the flat\n cell needs a fraction of that. The design document\'s popup row is "text plus\n a trailing mark" (DESIGN.md \xA76.7) and its height is one 20px line, so the\n description is not drawn: the row then draws its name alone, and the card\n falls back to the primitive\'s own 144px minimum width.\n\n The line is reached structurally, not by class name: those two spans are the\n label wrapper\'s only children and that wrapper is the row label\'s only child,\n so "everything after the first span of the label\'s own span" is the\n description on every row of this card. The classes in that pane (`m0vb0q_*`)\n are a per-build hash of a desktop package \u2014 the same fact `host-builds.ts`\n records for `_3li69W_` from the same package \u2014 so naming one would leave the\n Windows build\'s rows two lines tall, silently, because that build has no\n counterpart to alias it to. The guard is the preset seat\'s own expanded\n state: the workspace chip beside it is the row\'s other `aria-haspopup`\n button, and `:not(.bocITq_workspace)` keeps this rule on the mode card (the\n workspace chip\'s class is pinned in `compat/host-dom.ts`). */\nhtml[data-dsh-ccd-style="true"]:has(.ST7X_W_heroWorkspaceRow button[aria-haspopup="menu"]:not(.bocITq_workspace)[aria-expanded="true"])\n [role="menu"] > ._viewport_4ub78_19 > ._itemWrap_4ub78_90 > ._item_4ub78_90 > ._itemLabel_4ub78_190 > span > :not(:first-child) {\n display: none;\n}\n';
4433
4438
 
4434
4439
  // src/client/theme/menus.css
4435
- var menus_default = '/*\n * Host popup surfaces \u2014 menus and panels (DESIGN.md \xA76.7).\n *\n * The document draws one popup for the whole interface: a 12px card with a 1px\n * outline, the three-layer hairline shadow and the card fill, and one flat 24px\n * cell per row \u2014 the host\'s own 13px label on a 20px line with 2px above and\n * below, a 6px corner, and no leading icon seat, because a row is text plus a\n * trailing mark.\n *\n * Every host popup is built from two shared pieces, so this sheet is two\n * families of rules rather than one per menu:\n *\n * - **The card** is `MenuSurface` (`ui-primitives`), which tags itself\n * `data-menu-material`; that node is the same whichever primitive renders\n * inside it \u2014 a `Menu` list, a submenu, the signed-in account card, or the\n * Composer\'s command palette. Its own skin is a translucent material: a 16px\n * `--dsw-radius-lg` corner, a 0.5px elevation stroke and the\n * `--dsw-elevation-prominent` shadow on the card, plus a `.material` child\n * covering its padding box with `--dsw-menu-surface-fill` (a 58%-alpha\n * near-white) under a `blur(40px) saturate(150%)` backdrop.\n *\n * - **The rows** belong to whichever primitive renders them. `ui-primitives`\'\n * `Menu` renders `button[role="menuitem"]` \u2014 `Menu.js` `MenuItemButton`: an\n * optional `.itemIcon` seat, the label and an optional trailing shortcut \u2014\n * and the Composer\'s command palette renders `button[role="option"]` inside a\n * `[role="listbox"]` viewport whose classes are a frontend asset hash\n * `compat/host-dom.ts` does not pin, so those rows are reached through ARIA\n * and structure instead of a class name.\n *\n * Until this sheet existed the document\'s chrome was written per menu: the two\n * hero chips\' pickers in `composer.css`, the account card in\n * `features/sidebar/account-menu.css`. The workspace `\u22EF`, session `\u22EF`,\n * view-options and permission menus \u2014 which open from the sidebar and from the\n * Composer\'s own status bar \u2014 therefore still drew the host\'s translucent 16px\n * material with 34px cells and a leading glyph, next to hero pickers that drew\n * this one. The rules below are now the single place that draws a host popup;\n * the sheets that used to carry a copy keep only what is genuinely theirs.\n *\n * Deliberately outside those rules:\n *\n * - the **account menu** (`compat/account-menu.ts` tags the card\n * `data-ccd-account-menu`) keeps its own row rhythm and its leading glyphs:\n * the reference for that card draws them\n * (`features/sidebar/account-menu.css`), and it is a wide account card rather\n * than a list of choices. Its *card* is still the document\'s popup and takes\n * the rule below; only the row rules step around it.\n * - the plugin\'s own **model and effort cards** (`features/model-controls`) are\n * not `MenuSurface` nodes at all \u2014 they already draw this chrome from their\n * own sheets and answer to their own tests.\n * - the **permission card** (`compat/permission-menu.ts` tags the card\n * `data-ccd-permission-menu` and each row it drew a second line for) keeps the\n * card rule and steps out of the row rule: its rows are the family\'s one\n * two-line cell, and the block at the end of this sheet is that cell. It is\n * here rather than in a sheet of its own because the card, the row group and\n * the trailing check are all this family\'s, and only the line heights differ.\n *\n * Host classes are pinned in src/client/compat/host-dom.ts.\n */\n\n/* The card.\n *\n * Three of the material\'s four values move here: the corner, the outline and\n * the shadow. The fourth, the fill, moves through the token the `.material`\n * layer reads rather than by naming that layer\'s class \u2014 one less hash to pin,\n * and the layer keeps its own `inset: 0`, so its arc still follows the card.\n *\n * The card states `--ccd-card` beside the token for the one pixel the material\n * cannot cover: the material is inset by the card\'s border, so without a\n * background of its own the corner arc would leave a sliver of the page showing\n * through. `--dsw-menu-backdrop-filter` is withdrawn with the fill: the palette\n * fill is opaque, so the 40px blur would only cost compositing.\n *\n * Everything else the surface decides for itself \u2014 its 4px padding, the\n * scrollable viewport, the footer\'s pinned row, the card\'s own\n * `--dsh-scrollbar-*` rebinding \u2014 stays the host\'s. (That rebinding still\n * stands; `theme/scrollbars.css` is the one sheet that moves the two thumb\n * colours it resolves to.) */\nhtml[data-dsh-ccd-style="true"] [data-menu-material] {\n box-sizing: border-box;\n border: 1px solid var(--ccd-border);\n border-radius: var(--ccd-radius-panel);\n background: var(--ccd-card);\n box-shadow: var(--ccd-effort-shadow);\n --dsw-menu-surface-fill: var(--ccd-card);\n --dsw-menu-backdrop-filter: none;\n}\n\n/* One row, one cell.\n *\n * The host\'s cell is 34px \u2014 a 13px label on a 20px line under a 34px minimum\n * with 6px of block padding \u2014 and its dense variant is 30px; the reference\n * measures one row as 48 device px at @2x, the same line in a 24px box. Cutting\n * the minimum and the block padding to that row\'s own 2px is the whole change:\n * the 8px inline padding, the 6px gap, the 13px/20px label and the 14px\n * trailing mark are still the host\'s, so the label\'s x and measure do not move.\n *\n * `min-height` and `padding-block` are one decision \u2014 2px around that 20px line\n * is exactly the 24px the reference draws \u2014 and they only add up under\n * `border-box`, which the renderer\'s own button default supplies and nothing the\n * host\'s cell declares. Stating it keeps the row at 24px whatever the page does\n * with padding instead of resting the arithmetic on a default.\n *\n * The corner follows the height: the reference\'s highlight fits a 12-device-px\n * curve at @2x, the same 6px the transcript\'s table and code cards carry. The\n * host\'s row radius is 12px, exactly half of a 24px row, so every hover and\n * focus fill would round into a pill instead of the reference\'s soft rectangle.\n *\n * The command palette\'s rows are `[role="option"]`, not `[role="menuitem"]`,\n * and they answer to the same cell: its row is the same 34px box with the same\n * 12px corner, and one row per command is what the reference draws there too.\n *\n * The account card is named out: its rows are its reference\'s own\n * (`features/sidebar/account-menu.css`, 28px rows with their leading glyphs), and\n * that sheet mounts after this one, so an exclusion is a decision rather than a\n * race. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"],\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"] {\n box-sizing: border-box;\n min-height: 24px;\n padding-block: 2px;\n border-radius: var(--ccd-table-radius);\n}\n\n/* No leading icon seat.\n *\n * A row is a label and a trailing mark, so the seat is removed rather than\n * reserved: out of the flex line it leaves neither itself nor the row\'s 6px gap\n * behind, and the label falls back to the row\'s own 8px start padding inside the\n * card\'s 4px \u2014 12px from the card\'s left edge, the same x on every row of every\n * popup, and the same x the hero pickers\' rows already had.\n *\n * Both seats are named by the fact that makes them seats rather than by a class\n * this sheet cannot pin: `ui-primitives`\' `Menu.js` gives its icon span the\n * `.itemIcon` class (`_4ub78_` is in `compat/host-dom.ts`), while the command\n * palette renders its icon as the row\'s first child span with\n * `aria-hidden="true"` \u2014 a decorative seat, and the palette\'s own class prefix\n * is not pinned anywhere. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"] > ._itemIcon_4ub78_148,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"] > span[aria-hidden="true"]:first-child {\n display: none;\n}\n\n/* One fill for the row\'s states.\n *\n * The pointer gets the fill every other control in this palette gets \u2014 one\n * hover step for the whole interface rather than the host\'s 6%-bluish\n * `--dsw-alias-interactive-bg-hover` inside a popup \u2014 and the keyboard walk\n * takes the same fill, because the host already reads focus that way and the\n * ring that would have told the two apart is not drawn in this family (below).\n * The destructive row is the one exception: it takes a red fill with white ink\n * (below), in every state, so the danger action reads apart from the rest of\n * the card. Selection is not a fill in this document \u2014 it is the accent check\n * the trailing seat draws (`theme/tokens.css`) and that the host\'s `.selected`\n * class already leaves transparent.\n *\n * The command palette\'s active row is its keyboard cursor (the listbox keeps DOM\n * focus and publishes `aria-activedescendant`), so it takes the fill by\n * `aria-selected` rather than by a pseudo-class. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]:focus-visible:not(:disabled),\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"]:hover,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"][aria-selected="true"] {\n background: var(--ccd-hover);\n}\n\n/* The host\'s destructive row (`Menu.module.css` `.danger`, the `_4ub78_` build\n * the rest of this sheet names) rests in the host\'s red ink. Hover and the\n * keyboard walk fill it with the red and white ink, label and shortcut included.\n * It sits after the hover rule above and is more specific, so the host\'s own\n * danger hover tint loses to it. The header session menu\'s Delete row takes the\n * same fill in `features/conversation/header-actions/header-menus.css`. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:focus-visible:not(:disabled) {\n background: var(--ccd-menu-danger);\n color: var(--ccd-menu-danger-ink);\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:hover:not(:disabled) span,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:focus-visible:not(:disabled) span {\n color: inherit;\n}\n\n/* Filling the row is the whole state: no emphasis ring on a popup row.\n *\n * \xA7\u4E03\'s ring was drawn here first and taken out again. It is a box on a 24px\n * cell, so it cannot sit still: at the first and the last row the scrolling\n * viewport cuts it open (the rows sit on its edge \u2014 measured in the running\n * interface, the top stroke of `\u91CD\u547D\u540D` and the bottom stroke of `\u5220\u9664\u5DE5\u4F5C\u533A`\n * both lost their line), and on any row between them it paints 2px into the\n * neighbour\'s cell. The host\'s own keyboard walk answers focus with the fill\n * for the same reason (`Menu.module.css` `.item:focus-visible` states\n * `outline: none`), so the family keeps one indication and the rule below is\n * the statement of that decision rather than a leftover of the host\'s. The\n * account card is left out here as everywhere else in this sheet. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]:focus-visible,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"][aria-selected="true"] {\n outline: none;\n}\n\n/* The card\'s non-option rows \u2014 group headings, and the palette\'s section and\n * group titles \u2014 are cells of the same rhythm, not blocks with a size of their\n * own: one 20px line with 2px above and below, in the control-label size (12px;\n * the document\'s scale has no 11px step) and the secondary ink. The host draws\n * them at 11px/15-16px with 5-6px of block padding and the tertiary ink, which\n * makes a heading the tallest thing in a card of 24px rows.\n *\n * They are reached structurally: both primitives render those titles as direct\n * `role="presentation"` children of the scrolling container \u2014 the `Menu` list\'s\n * `.viewport` and the palette\'s own `[role="listbox"]` viewport \u2014 while rows sit\n * one wrapper deeper and separators carry `role="separator"`. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) ._viewport_4ub78_19 > [role="presentation"],\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="listbox"] > [role="presentation"] {\n box-sizing: border-box;\n padding: 2px 8px;\n color: var(--ccd-text-secondary);\n font-size: 12px;\n line-height: 20px;\n}\n\n/* The card\'s two internal hairlines \u2014 a data separator and the pinned footer\'s\n * top edge \u2014 take the palette\'s soft line rather than the host\'s\n * `--dsw-alias-border-l2`, so a line inside a card is one step under the card\'s\n * own outline. Sizes stay the host\'s: a 0.5px hairline and its margins. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="separator"] {\n background: var(--ccd-border-soft);\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) ._footer_4ub78_62 {\n border-top-color: var(--ccd-border-soft);\n}\n\n/* The permission card: the family\'s one two-line cell.\n *\n * Every other card in this family draws a row as text plus a trailing mark, and\n * DSH\'s permission card draws its four presets that way too \u2014 `\u4EC5\u53EF\u67E5\u770B` and its\n * neighbours, one 20px line each. The reference draws the same four rows a line\n * taller: the mode\'s name over a sentence saying what the mode does, with the\n * one flagged preset carrying a badge beside its name. `compat/permission-menu.ts`\n * recognises the rows (by the name each one draws \u2014 the primitive gives a row no\n * identity of its own), writes the second line and tags the row and the card; the\n * rules below draw what it tagged, and nothing else in this sheet has to move.\n *\n * The cell is measured from that reference at @2x, the way \xA7\u4E09 measures everything\n * else: rows repeat every 80.5 device px \u2014 40px \u2014 with the name at 14px on a 20px\n * line and the sentence at 12px on a 16px line flush under it, on the family\'s own\n * 2px of block padding (20 + 16 + 4 = the measured 40). 14px is the document\'s body\n * step, one above the 13px control label a single-line menu row draws: a row that\n * carries a sentence reads as a paragraph, not as a list item.\n *\n * Two things are stated against the family rule rather than left to it. The host\'s\n * flex line becomes the grid below, which is what puts the name and the sentence on\n * two tracks instead of side by side; and `min-height` and `padding-block` are given\n * again, because the family rule sets both \u2014 at a specificity this selector beats\n * (0-5-1 to its 0-4-1), so no sheet order is relied on, and a two-line row that\n * inherited the 24px floor and the 2px padding would be clipped rather than drawn.\n * The host\'s 6px `gap` becomes the grid\'s column gap for the same reason it was a\n * flex gap: it is the distance to the trailing mark. `row-gap` is stated as 0 to\n * keep it off the two lines, which sit flush.\n *\n * The label and the check are placed by hand, because a grid without explicit\n * areas fills row-major: the name would take the first cell, the sentence the\n * second \u2014 beside it \u2014 and the check the third line. The icon seat needs no\n * placement at all: the family rule takes it out of the line with `display: none`,\n * and a `display: none` child generates no box to place. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] {\n box-sizing: border-box;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n row-gap: 0;\n min-height: 40px;\n padding-block: 2px;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] > ._itemLabel_4ub78_190 {\n grid-area: 1 / 1;\n}\n\n/* The second line, in the document\'s \u5F31\u5316\u58A8: the reference measures its sentence at\n * 137/255, which is this palette\'s muted step, a clear one below the name above it.\n * It is one line and it is not narrowed \u2014 `nowrap` is what lets the card size itself\n * to the longest sentence (its own measure lands just inside the primitive\'s 360px\n * ceiling), which is exactly what the reference does and what this family\'s rows,\n * being single lines of a name, never have to decide. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [data-ccd-permission-desc] {\n grid-area: 2 / 1;\n overflow: hidden;\n color: var(--ccd-text-muted);\n font-size: 12px;\n line-height: 16px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The trailing mark is the host\'s own selected check \u2014 an accent `\u2713` by\n * `theme/tokens.css`, never a fill \u2014 and it centres against the two lines rather\n * than against the name. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] > ._check_4ub78_179 {\n grid-area: 1 / 2 / span 2;\n align-self: center;\n}\n\n/* The one badge, as the reference draws it: a 16px pill beside the name, not the\n * 8px superscript the host sets. The host\'s own `.badge` is `font-size: 8px` at\n * weight 600 with `letter-spacing: .2px`, baseline-aligned into the name\'s line\n * (`align-self: flex-start` under a -1px pull) \u2014 every one of those is a\n * superscript\'s, and the reference\'s badge is a tag with a fill and a corner.\n *\n * The fill is the palette\'s \u5206\u6BB5\u8F68\u9053 step, which is the reference\'s measured\n * 243/255, and it is also the one fill that survives this row\'s hover: the pointer\n * fills the row `--ccd-hover` (240/255 light, 49/255 dark), and the track step\n * reads lighter than it in the light theme and darker in the dark one, so the pill\n * is never the fill it sits on. The 4px corner is the smallest in the ladder and a\n * shade rounder than the reference\'s measured 3px; 6px \u2014 the chip and card step \u2014\n * would round a 16px box towards a capsule.\n *\n * The gap the host leaves between a name and its badge (4px) is widened to the\n * reference\'s 6px here, and only here: the pair is one control, and 4px reads\n * cramped beside a 16px pill. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] .wXeviG_badge {\n align-self: center;\n margin-top: 0;\n padding: 0 5px;\n border-radius: 4px;\n background: var(--ccd-track);\n color: var(--ccd-text-secondary);\n font-size: 12px;\n font-weight: 400;\n letter-spacing: normal;\n line-height: 16px;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] .wXeviG_optionLabel {\n column-gap: 6px;\n}\n\n/* The group\'s name, above the rows.\n *\n * It is the host\'s own heading row \u2014 a `role="presentation"` div inside the row\n * group, which is what `Menu` renders for a label entry, written there by\n * `compat/permission-menu.ts` \u2014 so the family rule above already gives it the\n * 12px control-label step, the secondary ink and the 8px start padding every other\n * cell has. The one thing it does not have is this card\'s own breathing room: the\n * reference measures ~29px between the card\'s top edge and the first row, against\n * the 24px a cell of the family\'s rhythm occupies, and the 6px above it is that\n * difference. The name is a step lighter than the rows\' names, which is what a\n * heading above a card of choices should be. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] ._viewport_4ub78_19 > [data-ccd-permission-heading] {\n padding-block: 6px 2px;\n}\n';
4440
+ var menus_default = '/*\n * Host popup surfaces \u2014 menus and panels (DESIGN.md \xA76.7).\n *\n * The document draws one popup for the whole interface: a 12px card with a 1px\n * outline, the three-layer hairline shadow and the card fill, and one flat 24px\n * cell per row \u2014 the host\'s own 13px label on a 20px line with 2px above and\n * below, a 6px corner, and no leading icon seat, because a row is text plus a\n * trailing mark.\n *\n * Every host popup is built from two shared pieces, so this sheet is two\n * families of rules rather than one per menu:\n *\n * - **The card** is `MenuSurface` (`ui-primitives`), which tags itself\n * `data-menu-material`; that node is the same whichever primitive renders\n * inside it \u2014 a `Menu` list, a submenu, the signed-in account card, or the\n * Composer\'s command palette. Its own skin is a translucent material: a 16px\n * `--dsw-radius-lg` corner, a 0.5px elevation stroke and the\n * `--dsw-elevation-prominent` shadow on the card, plus a `.material` child\n * covering its padding box with `--dsw-menu-surface-fill` (a 58%-alpha\n * near-white) under a `blur(40px) saturate(150%)` backdrop.\n *\n * - **The rows** belong to whichever primitive renders them. `ui-primitives`\'\n * `Menu` renders `button[role="menuitem"]` \u2014 `Menu.js` `MenuItemButton`: an\n * optional `.itemIcon` seat, the label and an optional trailing shortcut \u2014\n * and the Composer\'s command palette renders `button[role="option"]` inside a\n * `[role="listbox"]` viewport whose classes are a frontend asset hash\n * `compat/host-dom.ts` does not pin, so those rows are reached through ARIA\n * and structure instead of a class name.\n *\n * Until this sheet existed the document\'s chrome was written per menu: the two\n * hero chips\' pickers in `composer.css`, the account card in\n * `features/sidebar/account-menu.css`. The workspace `\u22EF`, session `\u22EF`,\n * view-options and permission menus \u2014 which open from the sidebar and from the\n * Composer\'s own status bar \u2014 therefore still drew the host\'s translucent 16px\n * material with 34px cells and a leading glyph, next to hero pickers that drew\n * this one. The rules below are now the single place that draws a host popup;\n * the sheets that used to carry a copy keep only what is genuinely theirs.\n *\n * Deliberately outside those rules:\n *\n * - the **account menu** (`compat/account-menu.ts` tags the card\n * `data-ccd-account-menu`) keeps its own row rhythm and its leading glyphs:\n * the reference for that card draws them\n * (`features/sidebar/account-menu.css`), and it is a wide account card rather\n * than a list of choices. Its *card* is still the document\'s popup and takes\n * the rule below; only the row rules step around it.\n * - the plugin\'s own **model and effort cards** (`features/model-controls`) are\n * not `MenuSurface` nodes at all \u2014 they already draw this chrome from their\n * own sheets and answer to their own tests.\n * - the **permission card** (`compat/permission-menu.ts` tags the card\n * `data-ccd-permission-menu` and each row it drew a second line for) keeps the\n * card rule and steps out of the row rule: its rows are the family\'s one\n * two-line cell, and the block at the end of this sheet is that cell. It is\n * here rather than in a sheet of its own because the card, the row group and\n * the trailing check are all this family\'s, and only the line heights differ.\n *\n * Host classes are pinned in src/client/compat/host-dom.ts.\n */\n\n/* The card.\n *\n * Three of the material\'s four values move here: the corner, the outline and\n * the shadow. The fourth, the fill, moves through the token the `.material`\n * layer reads rather than by naming that layer\'s class \u2014 one less hash to pin,\n * and the layer keeps its own `inset: 0`, so its arc still follows the card.\n *\n * The card states `--ccd-card` beside the token for the one pixel the material\n * cannot cover: the material is inset by the card\'s border, so without a\n * background of its own the corner arc would leave a sliver of the page showing\n * through. `--dsw-menu-backdrop-filter` is withdrawn with the fill: the palette\n * fill is opaque, so the 40px blur would only cost compositing.\n *\n * Everything else the surface decides for itself \u2014 its 4px padding, the\n * scrollable viewport, the footer\'s pinned row, the card\'s own\n * `--dsh-scrollbar-*` rebinding \u2014 stays the host\'s. (That rebinding still\n * stands; `theme/scrollbars.css` is the one sheet that moves the two thumb\n * colours it resolves to.) */\nhtml[data-dsh-ccd-style="true"] [data-menu-material] {\n box-sizing: border-box;\n border: 1px solid var(--ccd-border);\n border-radius: var(--ccd-radius-panel);\n background: var(--ccd-card);\n box-shadow: var(--ccd-effort-shadow);\n --dsw-menu-surface-fill: var(--ccd-card);\n --dsw-menu-backdrop-filter: none;\n}\n\n/* Input-trigger menus keep their native anchor and keyboard selection. The\n * description is a separate span in MenuView; labels and aliases stay intact. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-trigger-menu] {\n width: min(280px, 100%);\n right: auto;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-trigger-menu] [role="option"] > [class$="_itemDescription"] {\n display: none;\n}\n\n/* A compact menu gives the name and alias the space descriptions used to own. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-trigger-menu] [role="option"] > [class$="_itemName"],\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-trigger-menu] [role="option"] > [class$="_itemAlias"] {\n flex-shrink: 1;\n min-width: 0;\n max-width: none;\n}\n\n/* One row, one cell.\n *\n * The host\'s cell is 34px \u2014 a 13px label on a 20px line under a 34px minimum\n * with 6px of block padding \u2014 and its dense variant is 30px; the reference\n * measures one row as 48 device px at @2x, the same line in a 24px box. Cutting\n * the minimum and the block padding to that row\'s own 2px is the whole change:\n * the 8px inline padding, the 6px gap, the 13px/20px label and the 14px\n * trailing mark are still the host\'s, so the label\'s x and measure do not move.\n *\n * `min-height` and `padding-block` are one decision \u2014 2px around that 20px line\n * is exactly the 24px the reference draws \u2014 and they only add up under\n * `border-box`, which the renderer\'s own button default supplies and nothing the\n * host\'s cell declares. Stating it keeps the row at 24px whatever the page does\n * with padding instead of resting the arithmetic on a default.\n *\n * The corner follows the height: the reference\'s highlight fits a 12-device-px\n * curve at @2x, the same 6px the transcript\'s table and code cards carry. The\n * host\'s row radius is 12px, exactly half of a 24px row, so every hover and\n * focus fill would round into a pill instead of the reference\'s soft rectangle.\n *\n * The command palette\'s rows are `[role="option"]`, not `[role="menuitem"]`,\n * and they answer to the same cell: its row is the same 34px box with the same\n * 12px corner, and one row per command is what the reference draws there too.\n *\n * The account card is named out: its rows are its reference\'s own\n * (`features/sidebar/account-menu.css`, 28px rows with their leading glyphs), and\n * that sheet mounts after this one, so an exclusion is a decision rather than a\n * race. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"],\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"] {\n box-sizing: border-box;\n min-height: 24px;\n padding-block: 2px;\n border-radius: var(--ccd-table-radius);\n}\n\n/* No leading icon seat.\n *\n * A row is a label and a trailing mark, so the seat is removed rather than\n * reserved: out of the flex line it leaves neither itself nor the row\'s 6px gap\n * behind, and the label falls back to the row\'s own 8px start padding inside the\n * card\'s 4px \u2014 12px from the card\'s left edge, the same x on every row of every\n * popup, and the same x the hero pickers\' rows already had.\n *\n * Both seats are named by the fact that makes them seats rather than by a class\n * this sheet cannot pin: `ui-primitives`\' `Menu.js` gives its icon span the\n * `.itemIcon` class (`_4ub78_` is in `compat/host-dom.ts`), while the command\n * palette renders its icon as the row\'s first child span with\n * `aria-hidden="true"` \u2014 a decorative seat, and the palette\'s own class prefix\n * is not pinned anywhere. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"] > ._itemIcon_4ub78_148,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"] > span[aria-hidden="true"]:first-child {\n display: none;\n}\n\n/* The add/command menu uses the host\'s semantic outline icons. Keep their\n * compact 14px seats and let the ink follow the row in both themes. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-trigger-menu] [role="option"] > span[aria-hidden="true"]:first-child {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 14px;\n color: inherit;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-trigger-menu] [role="option"] > span[aria-hidden="true"]:first-child svg {\n width: 14px;\n height: 14px;\n}\n\n/* One fill for the row\'s states.\n *\n * The pointer gets the fill every other control in this palette gets \u2014 one\n * hover step for the whole interface rather than the host\'s 6%-bluish\n * `--dsw-alias-interactive-bg-hover` inside a popup \u2014 and the keyboard walk\n * takes the same fill, because the host already reads focus that way and the\n * ring that would have told the two apart is not drawn in this family (below).\n * The destructive row is the one exception: it takes a red fill with white ink\n * (below), in every state, so the danger action reads apart from the rest of\n * the card. Selection is not a fill in this document \u2014 it is the accent check\n * the trailing seat draws (`theme/tokens.css`) and that the host\'s `.selected`\n * class already leaves transparent.\n *\n * The command palette\'s active row is its keyboard cursor (the listbox keeps DOM\n * focus and publishes `aria-activedescendant`), so it takes the fill by\n * `aria-selected` rather than by a pseudo-class. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]:focus-visible:not(:disabled),\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"]:hover,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"][aria-selected="true"] {\n background: var(--ccd-hover);\n}\n\n/* The host\'s destructive row (`Menu.module.css` `.danger`, the `_4ub78_` build\n * the rest of this sheet names) rests in the host\'s red ink. Hover and the\n * keyboard walk fill it with the red and white ink, label and shortcut included.\n * It sits after the hover rule above and is more specific, so the host\'s own\n * danger hover tint loses to it. The header session menu\'s Delete row takes the\n * same fill in `features/conversation/header-actions/header-menus.css`. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:hover:not(:disabled),\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:focus-visible:not(:disabled) {\n background: var(--ccd-menu-danger);\n color: var(--ccd-menu-danger-ink);\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:hover:not(:disabled) span,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]._danger_4ub78_226:focus-visible:not(:disabled) span {\n color: inherit;\n}\n\n/* Filling the row is the whole state: no emphasis ring on a popup row.\n *\n * \xA7\u4E03\'s ring was drawn here first and taken out again. It is a box on a 24px\n * cell, so it cannot sit still: at the first and the last row the scrolling\n * viewport cuts it open (the rows sit on its edge \u2014 measured in the running\n * interface, the top stroke of `\u91CD\u547D\u540D` and the bottom stroke of `\u5220\u9664\u5DE5\u4F5C\u533A`\n * both lost their line), and on any row between them it paints 2px into the\n * neighbour\'s cell. The host\'s own keyboard walk answers focus with the fill\n * for the same reason (`Menu.module.css` `.item:focus-visible` states\n * `outline: none`), so the family keeps one indication and the rule below is\n * the statement of that decision rather than a leftover of the host\'s. The\n * account card is left out here as everywhere else in this sheet. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="menuitem"]:focus-visible,\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="option"][aria-selected="true"] {\n outline: none;\n}\n\n/* The card\'s non-option rows \u2014 group headings, and the palette\'s section and\n * group titles \u2014 are cells of the same rhythm, not blocks with a size of their\n * own: one 20px line with 2px above and below, in the control-label size (12px;\n * the document\'s scale has no 11px step) and the secondary ink. The host draws\n * them at 11px/15-16px with 5-6px of block padding and the tertiary ink, which\n * makes a heading the tallest thing in a card of 24px rows.\n *\n * They are reached structurally: both primitives render those titles as direct\n * `role="presentation"` children of the scrolling container \u2014 the `Menu` list\'s\n * `.viewport` and the palette\'s own `[role="listbox"]` viewport \u2014 while rows sit\n * one wrapper deeper and separators carry `role="separator"`. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) ._viewport_4ub78_19 > [role="presentation"],\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="listbox"] > [role="presentation"] {\n box-sizing: border-box;\n padding: 2px 8px;\n color: var(--ccd-text-secondary);\n font-size: 12px;\n line-height: 20px;\n}\n\n/* The card\'s two internal hairlines \u2014 a data separator and the pinned footer\'s\n * top edge \u2014 take the palette\'s soft line rather than the host\'s\n * `--dsw-alias-border-l2`, so a line inside a card is one step under the card\'s\n * own outline. Sizes stay the host\'s: a 0.5px hairline and its margins. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) [role="separator"] {\n background: var(--ccd-border-soft);\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material]:not([data-ccd-account-menu]) ._footer_4ub78_62 {\n border-top-color: var(--ccd-border-soft);\n}\n\n/* The permission card: the family\'s one two-line cell.\n *\n * Every other card in this family draws a row as text plus a trailing mark, and\n * DSH\'s permission card draws its four presets that way too \u2014 `\u4EC5\u53EF\u67E5\u770B` and its\n * neighbours, one 20px line each. The reference draws the same four rows a line\n * taller: the mode\'s name over a sentence saying what the mode does, with the\n * one flagged preset carrying a badge beside its name. `compat/permission-menu.ts`\n * recognises the rows (by the name each one draws \u2014 the primitive gives a row no\n * identity of its own), writes the second line and tags the row and the card; the\n * rules below draw what it tagged, and nothing else in this sheet has to move.\n *\n * The cell is measured from that reference at @2x, the way \xA7\u4E09 measures everything\n * else: rows repeat every 80.5 device px \u2014 40px \u2014 with the name at 14px on a 20px\n * line and the sentence at 12px on a 16px line flush under it, on the family\'s own\n * 2px of block padding (20 + 16 + 4 = the measured 40). 14px is the document\'s body\n * step, one above the 13px control label a single-line menu row draws: a row that\n * carries a sentence reads as a paragraph, not as a list item.\n *\n * Two things are stated against the family rule rather than left to it. The host\'s\n * flex line becomes the grid below, which is what puts the name and the sentence on\n * two tracks instead of side by side; and `min-height` and `padding-block` are given\n * again, because the family rule sets both \u2014 at a specificity this selector beats\n * (0-5-1 to its 0-4-1), so no sheet order is relied on, and a two-line row that\n * inherited the 24px floor and the 2px padding would be clipped rather than drawn.\n * The host\'s 6px `gap` becomes the grid\'s column gap for the same reason it was a\n * flex gap: it is the distance to the trailing mark. `row-gap` is stated as 0 to\n * keep it off the two lines, which sit flush.\n *\n * The label and the check are placed by hand, because a grid without explicit\n * areas fills row-major: the name would take the first cell, the sentence the\n * second \u2014 beside it \u2014 and the check the third line. The icon seat needs no\n * placement at all: the family rule takes it out of the line with `display: none`,\n * and a `display: none` child generates no box to place. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] {\n box-sizing: border-box;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n row-gap: 0;\n min-height: 40px;\n padding-block: 2px;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] > ._itemLabel_4ub78_190 {\n grid-area: 1 / 1;\n}\n\n/* The second line, in the document\'s \u5F31\u5316\u58A8: the reference measures its sentence at\n * 137/255, which is this palette\'s muted step, a clear one below the name above it.\n * It is one line and it is not narrowed \u2014 `nowrap` is what lets the card size itself\n * to the longest sentence (its own measure lands just inside the primitive\'s 360px\n * ceiling), which is exactly what the reference does and what this family\'s rows,\n * being single lines of a name, never have to decide. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [data-ccd-permission-desc] {\n grid-area: 2 / 1;\n overflow: hidden;\n color: var(--ccd-text-muted);\n font-size: 12px;\n line-height: 16px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The trailing mark is the host\'s own selected check \u2014 an accent `\u2713` by\n * `theme/tokens.css`, never a fill \u2014 and it centres against the two lines rather\n * than against the name. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] > ._check_4ub78_179 {\n grid-area: 1 / 2 / span 2;\n align-self: center;\n}\n\n/* The one badge, as the reference draws it: a 16px pill beside the name, not the\n * 8px superscript the host sets. The host\'s own `.badge` is `font-size: 8px` at\n * weight 600 with `letter-spacing: .2px`, baseline-aligned into the name\'s line\n * (`align-self: flex-start` under a -1px pull) \u2014 every one of those is a\n * superscript\'s, and the reference\'s badge is a tag with a fill and a corner.\n *\n * The fill is the palette\'s \u5206\u6BB5\u8F68\u9053 step, which is the reference\'s measured\n * 243/255, and it is also the one fill that survives this row\'s hover: the pointer\n * fills the row `--ccd-hover` (240/255 light, 49/255 dark), and the track step\n * reads lighter than it in the light theme and darker in the dark one, so the pill\n * is never the fill it sits on. The 4px corner is the smallest in the ladder and a\n * shade rounder than the reference\'s measured 3px; 6px \u2014 the chip and card step \u2014\n * would round a 16px box towards a capsule.\n *\n * The gap the host leaves between a name and its badge (4px) is widened to the\n * reference\'s 6px here, and only here: the pair is one control, and 4px reads\n * cramped beside a 16px pill. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] .wXeviG_badge {\n align-self: center;\n margin-top: 0;\n padding: 0 5px;\n border-radius: 4px;\n background: var(--ccd-track);\n color: var(--ccd-text-secondary);\n font-size: 12px;\n font-weight: 400;\n letter-spacing: normal;\n line-height: 16px;\n}\n\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] [role="menuitem"][data-ccd-permission-mode] .wXeviG_optionLabel {\n column-gap: 6px;\n}\n\n/* The group\'s name, above the rows.\n *\n * It is the host\'s own heading row \u2014 a `role="presentation"` div inside the row\n * group, which is what `Menu` renders for a label entry, written there by\n * `compat/permission-menu.ts` \u2014 so the family rule above already gives it the\n * 12px control-label step, the secondary ink and the 8px start padding every other\n * cell has. The one thing it does not have is this card\'s own breathing room: the\n * reference measures ~29px between the card\'s top edge and the first row, against\n * the 24px a cell of the family\'s rhythm occupies, and the 6px above it is that\n * difference. The name is a step lighter than the rows\' names, which is what a\n * heading above a card of choices should be. */\nhtml[data-dsh-ccd-style="true"] [data-menu-material][data-ccd-permission-menu] ._viewport_4ub78_19 > [data-ccd-permission-heading] {\n padding-block: 6px 2px;\n}\n';
4436
4441
 
4437
4442
  // src/client/theme/scrollbars.css
4438
4443
  var scrollbars_default = "/*\n * Scrollbars (DESIGN.md \xA7\u4E09, \xA7\u56DB).\n *\n * DSH paints its own scrollbars. `ui-theme/src/styles/scrollbar.css` declares\n * five tokens on `body` \u2014 the thumb, its hover step, the thumb's transparent\n * border, the track's end margin and the track's width \u2014 and one un-scoped\n * `::-webkit-scrollbar` family paints them, so every scroller in the window\n * takes the same bar.\n *\n * Three of those five are geometry this sheet must not touch. The transcript's\n * `scrollbar-gutter: stable` reserves the track's width; the sidebar tree's\n * rows are padded by `--dsh-session-list-scrollbar-width` (5px, the host's own\n * value); the settings dialog's column and the menu cards widen their track to\n * 9px and 6px and inset the thumb inside it. Every one of those is measured\n * against the host's own width, so the interface keeps the host's track and\n * changes what is painted in it.\n *\n * What is painted is nothing, most of the time. The reference interface's\n * scrollbars are the platform's overlay scrollers: they appear while the reader\n * is moving something and fade again, so a window at rest carries no bar at\n * all \u2014 and the platform's own scroller, which `scrollbar-color` cannot reach,\n * is a grey pill the width of the system's. So the ink is ours and it is\n * published, not permanent: `compat/scroll-pill.ts` marks a surface\n * `data-ccd-scrolling` while it moves, and the two rules at the bottom of this\n * sheet are the whole of the state \u2014 transparent at rest, this interface's ink\n * while it is moving or while the pointer is on the bar itself.\n *\n * The five page-level surfaces the same module tracks go one step further and\n * carry no ink at all: `data-ccd-scroll-pill` takes the painted thumb out of\n * the picture and a floating pill takes its place. The painted thumb's length\n * is the content's share of the track \u2014 a short conversation, a panel with one\n * page of content, paints a bar as tall as its own viewport \u2014 while the pill is\n * a fixed short capsule that only slides. `.ccd-scroll-pill`'s own rules are at\n * the end of this sheet; the module owns its geometry.\n *\n * The reset is the half that is easy to miss. The standard `scrollbar-width`\n * and `scrollbar-color` properties *suppress* the `::-webkit-scrollbar` rules\n * whenever either is set to anything but `auto`, so one document-wide\n * `scrollbar-width: thin` \u2014 which the other skin installed beside this plugin\n * in this window makes, and which any page-global stylesheet may make \u2014 hands\n * every scroller in the window back to the platform. Stating `auto` puts the\n * host's painter back; in a document that declares neither property it is a\n * no-op. It is stated on the scrolling element itself rather than on an\n * ancestor, because the host declares the same properties on `body` and an\n * inherited value would otherwise be the one in force.\n *\n * The scope is the interface's own scroll surfaces rather than `*`. The host\n * hides the scrollbar on several horizontal rails \u2014 the draft-attachment rail,\n * the turn-nav popover, the breadcrumb trail, the dock strip and the tab strips\n * all declare `scrollbar-width: none` \u2014 and a blanket reset would give every\n * one of them a bar it does not want. This sheet adds no scrollbar anywhere, it\n * only repaints the ones the interface already shows. (The ink token does\n * inherit into whatever sits inside a scoped scroller \u2014 a custom property\n * inherits and cannot be scoped away \u2014 but a rail that hides its scrollbar\n * paints nothing to read it, and `scrollbar-width` is not inherited, so a\n * descendant keeps the value it was given.)\n *\n * The reset reaches into five of those surfaces and no more. Two of the host's\n * rails live *inside* the first list's members: `ConversationRoot` renders the\n * Composer's seat inside the page's scrolling body, and `ChatView` renders the\n * turn navigator beside the transcript column rather than inside it. A blanket\n * descendant form would reach both and put a bar on each, so the second list\n * names only the surfaces that hold scrollers of their own: the transcript\n * column (whose fenced code blocks and wide tables scroll inside it), the host's\n * popup cards (whose scrolling viewport is a child of the card) and this\n * plugin's own two. The two lists are written out in each of the three rules\n * below, because the reset, the absent ink and its reveal have to land on the\n * same elements and CSS has no way to name a set once.\n */\n\n/* The surfaces themselves, and the five whose contents scroll on their own. */\nhtml[data-dsh-ccd-style=\"true\"] :is(\n /* The Conversation page's scroller, and the transcript column inside it. */\n [data-conversation-scroll],\n .icaHSq_scroll,\n /* The sidebar's session/workspace tree, and the Files pane's. */\n ._7514NG_list,\n [data-files-body],\n /* The agent-team panel's body, the Composer's textarea, the settings\n dialog's two columns. */\n ._2tNPVa_body,\n .yhfFVG_scroll,\n .Dws9Sa_options,\n .Dws9Sa_navList,\n /* The host's popup cards. */\n [data-menu-material],\n /* This plugin's own panels and cards. */\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort,\n .ccd-context-detail,\n .ccd-settings-menu-list\n),\nhtml[data-dsh-ccd-style=\"true\"] :is(\n .icaHSq_scroll,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort\n) * {\n scrollbar-width: auto;\n scrollbar-color: auto;\n /* The thumb the host's own rule paints, in this interface's ink. Stated on\n the scroller and on everything inside one, so it also wins on the surfaces\n that rebind `--dsh-scrollbar-thumb` for themselves \u2014 a menu card, the\n settings panel and the dockkit panes all point it at another host alias,\n and an element's own declaration is the one that reaches the scroller\n there. */\n --dsh-scrollbar-thumb: var(--ccd-scrollbar-thumb);\n --dsh-scrollbar-thumb-hover: var(--ccd-scrollbar-thumb-hover);\n}\n\n/* A surface at rest carries no ink. */\nhtml[data-dsh-ccd-style=\"true\"] :is(\n [data-conversation-scroll],\n .icaHSq_scroll,\n ._7514NG_list,\n [data-files-body],\n ._2tNPVa_body,\n .yhfFVG_scroll,\n .Dws9Sa_options,\n .Dws9Sa_navList,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort,\n .ccd-context-detail,\n .ccd-settings-menu-list\n)::-webkit-scrollbar-thumb,\nhtml[data-dsh-ccd-style=\"true\"] :is(\n .icaHSq_scroll,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort\n) *::-webkit-scrollbar-thumb {\n background: transparent;\n}\n\n/*\n * The two states the ink has: while the surface moves (the module's mark, which\n * it clears again once the surface has been still), and while the pointer is on\n * the bar itself \u2014 the grab a reader makes without moving anything first.\n */\nhtml[data-dsh-ccd-style=\"true\"] :is(\n [data-conversation-scroll],\n .icaHSq_scroll,\n ._7514NG_list,\n [data-files-body],\n ._2tNPVa_body,\n .yhfFVG_scroll,\n .Dws9Sa_options,\n .Dws9Sa_navList,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort,\n .ccd-context-detail,\n .ccd-settings-menu-list\n)[data-ccd-scrolling]::-webkit-scrollbar-thumb,\nhtml[data-dsh-ccd-style=\"true\"] :is(\n .icaHSq_scroll,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort\n) *[data-ccd-scrolling]::-webkit-scrollbar-thumb,\nhtml[data-dsh-ccd-style=\"true\"] :is(\n [data-conversation-scroll],\n .icaHSq_scroll,\n ._7514NG_list,\n [data-files-body],\n ._2tNPVa_body,\n .yhfFVG_scroll,\n .Dws9Sa_options,\n .Dws9Sa_navList,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort,\n .ccd-context-detail,\n .ccd-settings-menu-list\n)::-webkit-scrollbar-thumb:hover,\nhtml[data-dsh-ccd-style=\"true\"] :is(\n .icaHSq_scroll,\n [data-menu-material],\n .ccd-model-panel,\n .ccd-model-error,\n .ccd-effort\n) *::-webkit-scrollbar-thumb:hover {\n background: var(--ccd-scrollbar-thumb);\n}\n\n/*\n * The five pill surfaces keep no ink at all \u2014 the floating capsule speaks for\n * them. They are named by the module's own mark rather than by the two lists,\n * so the sheet never has to know which of the surfaces those are. The module\n * leaves them out of the moving mark, and the two selectors that repeat it here\n * are the belt to that brace: the bar under the pointer and the bar during a\n * drag both stay empty.\n */\nhtml[data-dsh-ccd-style=\"true\"] [data-ccd-scroll-pill]::-webkit-scrollbar-thumb,\nhtml[data-dsh-ccd-style=\"true\"] [data-ccd-scroll-pill][data-ccd-scrolling]::-webkit-scrollbar-thumb,\nhtml[data-dsh-ccd-style=\"true\"] [data-ccd-scroll-pill]::-webkit-scrollbar-thumb:hover {\n background: transparent;\n}\n\n/*\n * The pill: one fixed layer for the whole window, one absolutely positioned\n * capsule per tracked surface, moved with a transform the module computes. It\n * takes no pointer events \u2014 the host's own thumb is still laid out under it, and\n * the capsule is sized and centred to sit inside it, so a drag that starts on\n * the pill grabs that bar.\n */\n[data-ccd-scroll-layer] {\n position: fixed;\n inset: 0;\n z-index: 40;\n pointer-events: none;\n}\n\n/* The macOS host excludes body > :not(#root) from native window dragging.\n This full-window decoration matches that rule even with pointer-events:\n none, so reset its app-region to avoid erasing the header's drag surface.\n Repeat :not(#root) to outrank the host's ID specificity; other portals keep\n their no-drag regions. */\nhtml[data-dsh-ccd-style=\"true\"][data-platform=\"darwin\"] body > [data-ccd-scroll-layer]:not(#root) {\n -webkit-app-region: initial;\n}\n\n[data-ccd-scroll-thumb] {\n position: absolute;\n top: 0;\n left: 0;\n box-sizing: border-box;\n width: 4px;\n border-radius: 999px;\n background: var(--ccd-scrollbar-thumb);\n opacity: 0;\n transition: opacity 140ms ease-out;\n}\n\n[data-ccd-scroll-thumb][data-ccd-scrolling] {\n opacity: 1;\n}\n\n@media (prefers-reduced-motion: reduce) {\n [data-ccd-scroll-thumb] { transition: none; }\n}\n";
4439
4444
 
4440
4445
  // src/client/theme/tokens.css
4441
- var tokens_default = "/* CCD geometry, type, artwork and light/dark colour variables.\n * Colours are centralized here; the dark palette follows the host's body marker.\n */\nhtml[data-dsh-ccd-style=\"true\"] {\n /* Geometry */\n /* Top of the blank-session greeting block. The reference puts the title a\n short step below the header instead of centring it, so the statistics card\n hanging under it still clears the Composer on a short window. */\n --ccd-hero-top: 16px;\n --ccd-sidebar-width: 264px;\n --ccd-sidebar-inline-padding: 10px;\n --ccd-sidebar-bottom-padding: 8px;\n --ccd-row-height: 28px;\n /* Workspace (group) row. The host's own 34px, pinned because the browsing\n region's merged header band is this same box: the section header parks on\n the row's line and the two have to agree to the pixel. */\n --ccd-workspace-row-height: 34px;\n /* Navigation stack. The reference's three rows measured 26px tall on a 26.5px\n pitch \u2014 contiguous, not separated \u2014 against the host's own 36px/7px row. */\n --ccd-nav-row-height: 26px;\n --ccd-nav-gap: 1px;\n --ccd-radius-row: 8px;\n --ccd-radius-panel: 12px;\n /* View-options reference: 20 device px corners at @2x. */\n --ccd-view-menu-radius: 10px;\n /* Assistant table card. The reference crop's corner curve fits a 12-device-px\n radius at @2x, so the card is rounder than the row radius it borrows its\n scale from. */\n --ccd-table-radius: 6px;\n /* Fenced code block card. The reference code block shows the same 12-device-px\n curve at @2x as the table card, so the transcript's two boxed surfaces stay\n one family. */\n --ccd-code-radius: 6px;\n --ccd-composer-width: 770px;\n --ccd-composer-min-height: 42px;\n --ccd-composer-radius: 10px;\n --ccd-composer-padding: 8px 14px;\n --ccd-composer-padding-block: 8px;\n --ccd-composer-padding-inline: 14px;\n --ccd-composer-row-gap: 4px;\n --ccd-composer-row-inset: 4px;\n --ccd-composer-bottom-gap: 5px;\n --ccd-control-row-height: 28px;\n /* Status-bar chip. The tool row's controls are all this one box: the row's\n 28px is the layout line, and every control inside it is a chip of this\n height rather than a box stretched to the line. The reference draws the\n model chip's fill as one label line \u2014 40 device px at @2x, so the row's\n 12px label sits 5.5px from the chip's top and bottom where the row itself\n would leave it 10px \u2014 and the same box now carries the command plus, the\n permission control, the voice control, the statistics readouts and the\n context ring, so a pointer crossing the row finds one fill height instead\n of three. The row keeps `--ccd-control-row-height`: the dock, the ring's\n seat and the trailing cluster are all measured from it. The corner follows\n the height \u2014 12 device px at @2x, the same curve the transcript's table and\n code cards carry, rather than the row's 8px radius, which is nearly half of\n a 20px chip and would round every fill towards a pill. */\n --ccd-chip-height: 20px;\n --ccd-chip-radius: 6px;\n /* The chip family's inline padding: the model/effort chips, the permission\n control and the two square glyph buttons (plus, voice), whose boxes are\n their 14px artwork plus one of these on each side. Six to seven px is the\n whole range in the reference; the readouts and the ring keep their own\n slightly tighter 6px, which is a 1px difference in ink and nothing in a\n fill's shape. */\n --ccd-chip-padding-inline: 7px;\n --ccd-send-size: 24px;\n --ccd-send-reserve: 30px;\n /* One gap for the whole status row: the row itself, the leading tools group,\n its modes cluster, the trailing cluster (the native readouts, the context\n ring, the model/effort pair) and the statistics dock all space their\n children with this. The host's own row ran 12px in the leading groups and\n the plugin's 6px in the trailing one, which read as two different rows in\n one bar. Each control carries its own 6-7px inner padding, so an even box\n gap also reads as an even visible rhythm. */\n --ccd-cluster-gap: 6px;\n /* Context ring. The host draws it as 14px artwork (`ContextMeter.module.css`:\n viewBox 0 0 14 14, cx=cy=7, r=5.5, 2px stroke, round cap) inside a 28px\n trigger with 6px of side padding, so the trigger's own box is 26px and the\n seat the status bar has to hold for it \u2014 that box plus one cluster gap \u2014 is\n 32px. The host's ring and this plugin's empty-state ring hang in that one\n seat, which is what keeps the ring's position and size the same before and\n after a session has usage. */\n --ccd-context-ring-size: 14px;\n --ccd-context-ring-trigger: 26px;\n --ccd-context-ring-seat: calc(var(--ccd-context-ring-trigger) + var(--ccd-cluster-gap));\n /* Context breakdown panel. Measured off the supplied reference at @2x\n (698\xD7178 for the collapsed state, 828\xD71006 for the expanded one): a 361px\n card with a 1px outline and a 12px corner, 12px inline and 8px top padding,\n a 13px/20px header, a 4px bar 5px under it, 19px value rows, 17px detail\n rows, and 10px swatches. The width is the one number the crop cut off, so\n it is the reference's own rounded value: the bar and the percentage column\n both end exactly at 360 \u2212 2 \u2212 24 = 334px, which is what the crop shows. */\n --ccd-context-panel-width: 360px;\n --ccd-context-panel-radius: 12px;\n --ccd-context-panel-padding-block: 8px;\n --ccd-context-panel-padding-inline: 12px;\n --ccd-context-panel-gap: 8px;\n --ccd-context-row-height: 19px;\n --ccd-context-detail-height: 17px;\n --ccd-context-swatch-size: 10px;\n --ccd-context-swatch-radius: 3px;\n --ccd-context-bar-height: 4px;\n --ccd-context-bar-radius: 2px;\n --ccd-context-bar-gap: 1px;\n /* 5px under the header line, and nothing below: the card's own bottom padding\n is what follows the bar in the collapsed state, and the rows state their\n own 4px above themselves in the expanded one. */\n --ccd-context-bar-margin-block: 5px 0;\n /* The buffer segment's own step away from the used group: the reference\n leaves 4px there where every used segment is 1px apart, because the grey\n block is a reservation rather than another category. */\n --ccd-context-bar-reserve-gap: 4px;\n /* Ten detail rows before a group scrolls \u2014 the reference's own visible run,\n and what keeps a session with 85 tools from drawing a 1500px panel. */\n --ccd-context-detail-max: 170px;\n /* The two value columns: the token column's right edge sits 48px in from the\n content edge (measured 618 of 715 device px), which is a 40px percentage\n column plus this gap. */\n --ccd-context-percent-width: 40px;\n --ccd-context-column-gap: 8px;\n /* The status bar's own glyph size: the command plus, the statistics readouts\n and the ring all draw 14px artwork in the 28px control row. The\n speech-to-text control draws 18px of its own; the composer sheet brings that\n one down to this size. The permission control draws no glyph at all \u2014 it is\n its text (composer.css). */\n --ccd-row-icon-size: 14px;\n --ccd-account-menu-width: 236px;\n --ccd-account-menu-padding: 5px;\n --ccd-account-row-height: 28px;\n --ccd-account-trigger-height: 30px;\n /* Conversation header action cluster. The CCD reference keeps every control\n on one 30px centre pitch with a 12px trailing inset (measured at @2x from\n docs/reference/ccd-conversation.png: icon centres 28.75/30/30px apart, the\n trailing glyph centre 25.75px from the window edge). That inset is what the\n cluster takes while the Composer is narrower than the column and centred in\n it; where the Composer fills the column, `conversation.css` ends the\n cluster on the input surface's own border instead, which is the line the\n reference puts the closing control on and a measurement rather than a\n second token. */\n --ccd-header-action-size: 28px;\n --ccd-header-action-compact: 24px;\n --ccd-header-icon-size: 16px;\n --ccd-header-action-gap: 2px;\n --ccd-header-trailing-inset: 12px;\n --ccd-header-menu-border: #d6d6d6;\n --ccd-header-menu-separator: #e2e2e2;\n --ccd-header-menu-danger: #b4262b;\n --ccd-menu-danger: #c04742;\n --ccd-menu-danger-ink: #ffffff;\n --ccd-header-trigger-hover: #f0f0ef;\n --ccd-header-project-fill: #e5e5e5;\n --ccd-header-project-active: #cfcfcf;\n /* Transcript edge fade. 24px is the band the host's own internal-request\n viewer uses for `fadeTop`\uFF0F`fadeBottom`, so the whole interface softens its\n scroll viewport edges by the same amount. */\n --ccd-edge-fade: 24px;\n /* Jump-to-bottom control. The reference's own affordance measures 40\xD744\n device px at @2x \u2014 a ~21px mark above the Composer \u2014 against the host's\n 34px floating circle, so the box shrinks to this one step while the glyph\n inside it keeps the host's 16px seat. */\n --ccd-to-bottom-size: 22px;\n /* Right panel (the Files, terminal and browser tabs). The reference draws it\n as a floating card: 16 device px in from the column's top, right and bottom\n edges; a 12px corner (measured off the fill: the curve is 20 device px at\n @2x from its first inset pixel to the straight edge, plus the 1px outline);\n a 32px header strip whose 24px tab mark sits 4px under the card's top; and\n an 8px pane gutter (16 device px), which is where the Files pane's own row\n line begins. */\n --ccd-right-panel-inset: 8px;\n --ccd-right-panel-radius: var(--ccd-radius-panel);\n --ccd-right-panel-strip-height: 32px;\n --ccd-right-panel-gutter: 8px;\n --ccd-right-panel-gap: 12px;\n /* The tab's own mark, measured off the reference: a 24px square (5px corner,\n carried by the chip radius) tinted #d3e2f9 behind the 16px glyph. */\n --ccd-right-panel-glyph-size: 24px;\n /* Files tree. The reference's rows run on a 24px pitch (48 device px at @2x)\n where the host's 13px/1.5 row draws 29.5px, and its pane header is the\n 26px rounded field over them. */\n --ccd-files-row-height: 24px;\n --ccd-files-field-height: 26px;\n --ccd-files-glyph-size: 16px;\n\n /* Claude Desktop 2.31226.1's active flat frame, confirmed by window capture:\n gray-10 canvas; sidebar mixes gray-20 and gray-10 equally in sRGB. */\n --ccd-canvas: #fcfcfb;\n --ccd-sidebar: #fbfbf9;\n --ccd-card: #ffffff;\n /* Segmented-control track. The reference measures #f6f6f4 against a white\n page; the same step down from this canvas keeps the same contrast. */\n --ccd-track: #f3f3f2;\n --ccd-raised: #f0f0ef;\n --ccd-hover: #f0f0ee;\n /* Sampled from the supplied view-options reference, separate from the\n warmer surfaces used by Composer and the host's other menus. */\n --ccd-view-menu-hover: #f5f5f5;\n --ccd-view-menu-text: #0b0b0b;\n --ccd-view-menu-muted: #9b9994;\n --ccd-view-menu-border: #d7d7d6;\n --ccd-view-menu-separator: #ebebeb;\n --ccd-view-menu-accent: #2a78d6;\n --ccd-view-menu-shadow: 0 1px 3px rgba(0, 0, 0, .08), 0 8px 20px rgba(0, 0, 0, .12), 0 16px 32px rgba(0, 0, 0, .06);\n --ccd-selected: #ecebe8;\n /* The fill a control takes while it sits on a row that is already filled:\n a Session row paints `--ccd-selected` under the pointer, so its \u22EE takes\n this one to stay a step below what it stands on. Sampled from the supplied\n reference at @2x, where that row measures #edece9 under the control's own\n #e1e0dd \u2014 the same 12/255 step, and the relationship `theme/palette.ts`\n derives for a configured canvas. */\n --ccd-hover-strong: #e1e0dd;\n /* The right panel's tab mark: the reference's own blue-tinted square,\n sampled at #d3e2f9 with the accent for its glyph. It is the one tinted seat\n in this plugin's surfaces, so it is stated rather than derived. */\n --ccd-right-panel-glyph-bg: #d3e2f9;\n /* The Files pane's own ink, sampled off the reference at @2x. Its tree names\n and its empty state's title measure #0b0b0b \u2014 a step below this palette's\n `--ccd-text`, the ink the rest of the interface draws \u2014 and its tab title\n measures #52514f, between `--ccd-text` and `--ccd-text-secondary`. The tab\n mark's glyph is the one blue that is not this palette's accent: the\n reference draws it #304e91 on the #d3e2f9 square. */\n --ccd-files-ink: #0b0b0b;\n --ccd-right-panel-tab-ink: #52514f;\n --ccd-files-chip-ink: #304e91;\n\n /* Lines */\n --ccd-border: #e3e3e1;\n --ccd-border-strong: #e0e0df;\n --ccd-border-soft: #ebebe9;\n /* The rule under a table head reads one step stronger than the card outline\n in the reference (#d9d9d9 against #e3e3e3). */\n --ccd-table-head-line: #d9d9d8;\n /* The right panel's card outline, sampled at #d7d7d6 \u2014 one step stronger than\n the row outline above and the same ink the menu cards' own border carries,\n which is what makes a floating panel and a menu read as one material. */\n --ccd-right-panel-border: #d7d7d6;\n --ccd-browser-canvas: #f7f7f7;\n --ccd-browser-dot: #d1d0ce;\n\n /* Scrollbar ink. The host paints the scrollbars themselves\n (`ui-theme/src/styles/scrollbar.css`: a 5px track and a pill thumb read\n from `--dsh-scrollbar-thumb`), and this interface keeps that geometry \u2014\n the transcript's stable gutter, the sidebar's\n `--dsh-session-list-scrollbar-width` padding and the dockkit panes are all\n measured against the host's own width \u2014 so these two tokens are the ink\n alone, bound in theme/scrollbars.css.\n The ink is near-black by decision rather than by measurement: the bar is\n 5px wide and carries no surface of its own, so none of this palette's\n surface steps \u2014 5% to 14% black \u2014 reads at that size, and the interface\n this one follows draws a dark scrollbar. Hover goes one step further down,\n the direction the host's own hover step takes. */\n --ccd-scrollbar-thumb: #333331;\n --ccd-scrollbar-thumb-hover: #171716;\n\n /* Text */\n --ccd-text: #1f1f1d;\n --ccd-text-secondary: #6f6f6a;\n --ccd-text-muted: #8f8f8a;\n --ccd-text-placeholder: #89877f;\n /* One step below full strength: a row that is not the current one. The\n reference paints its inactive navigation rows at #4a4a47 \u2014 between this\n palette's --ccd-text and --ccd-text-secondary \u2014 and keeps the current row\n at full black, so the stack reads as one current entry plus quieter\n neighbours instead of three equally loud labels. */\n --ccd-text-nav: #4a4a47;\n /* Archived Session row. The host fades that title with its own caption ink,\n but this plugin's row ink outranks the host pair, so the state needs a step\n of its own: one above --ccd-text-muted on the same warm ramp, which is the\n faded row the reference draws while still reading against the sidebar. A row\n that is current or under the pointer takes the second value, because the\n hover and selected fills sit a step below the sidebar the first one was\n measured on. */\n --ccd-text-archived: #a0a09b;\n --ccd-text-archived-hover: #8a8a85;\n\n /* New-session statistics card. The reference panel is a stacked translucent\n grey: the card is 5% black over the canvas and a stat tile (and an empty\n heat cell) is 10% black over the card, so these are the measured opaque\n equivalents. The four heat levels are the reference's own `hsl(217 70% L%)`\n with L = 72\uFF0F64\uFF0F56\uFF0F48, i.e. \"that day's value / the busiest day\" in four\n equal steps. */\n --ccd-stats-panel: #f0f0f0;\n --ccd-stats-tile: #dadada;\n /* The card header's active tab: the reference paints `fill-ghost-hover`, the\n same 5% black as the card itself, over the card \u2014 one step lighter than a\n stat tile. */\n --ccd-stats-tab: #e6e6e6;\n --ccd-stats-label: #898781;\n --ccd-stats-value: #0b0b0b;\n --ccd-stats-heat-1: hsl(217 70% 72%);\n --ccd-stats-heat-2: hsl(217 70% 64%);\n --ccd-stats-heat-3: hsl(217 70% 56%);\n --ccd-stats-heat-4: hsl(217 70% 48%);\n /* The `Models` view colours its bars and legend by rank:\n `hsl(217 70% min(88, 58 + 7n)%)`, which flattens into these six shades. */\n --ccd-stats-model-1: hsl(217 70% 58%);\n --ccd-stats-model-2: hsl(217 70% 65%);\n --ccd-stats-model-3: hsl(217 70% 72%);\n --ccd-stats-model-4: hsl(217 70% 79%);\n --ccd-stats-model-5: hsl(217 70% 86%);\n --ccd-stats-model-6: hsl(217 70% 88%);\n /* Tooltips are the reference's dark popup in both themes; on a dark panel it\n steps up to a mid grey so the box keeps its contrast. */\n --ccd-stats-tip-bg: #0c0c0c;\n --ccd-stats-tip-fg: #f7f7f5;\n\n /* Assistant Markdown palette matched to the CCD transcript reference. */\n --ccd-link: #2b61b5;\n --ccd-link-underline: #a7badd;\n --ccd-inline-code-text: #b63630;\n --ccd-inline-code-fill: #f1f1f0;\n --ccd-inline-code-border: #e2e2e0;\n\n /* Context meter. The host paints the ring's consumed arc with the same\n tertiary label grey as the percentage beside it, so the reading carries no\n weight. The accent blue is this plugin's one emphasis colour: taking it\n through `var()` lets the ring follow `--ccd-accent` the moment that token\n exists, and the fallback is the blue measured off the target arc\n (docs/issues/img/12-2.png), so the ring is never left grey meanwhile. The\n track underneath stays the host's `--dsw-alias-border-l3`, which\n theme/tokens.ts already overrides. */\n --ccd-context-ring-fill: var(--ccd-accent, #4b76ce);\n\n /* Context breakdown categories, sampled from the supplied reference's bar and\n swatches. Seven steps, in the order the panel and the bar draw them: the\n reference's own hues, which are deliberately outside this palette's blue\n ramp \u2014 a breakdown that reused one hue family would make five categories\n read as one. `--ccd-context-free` is both the free-space swatch and the\n bar's track, exactly as the reference draws them. */\n --ccd-context-mcp: #2a78d8;\n --ccd-context-tools: #e96a33;\n --ccd-context-system: #1ead7c;\n --ccd-context-skills: #eda105;\n --ccd-context-memory: #ea7ca4;\n /* The conversation's own row. The reference's crop happens to hold no\n messages at all \u2014 89k of its 9% reading is prompt, tools and skills \u2014 so\n this one is chosen rather than sampled: the same lightness and chroma as\n its neighbours, one hue family over, so it cannot be mistaken for the\n accent blue of MCP tools. */\n --ccd-context-messages: #8b6fd4;\n --ccd-context-buffer: #c2c0b8;\n --ccd-context-free: #eeeeee;\n\n /* The plugin's one emphasis blue: the selected check in every Menu surface,\n the context ring, and whatever else has to read as \"this one is chosen\".\n It is the blue measured off the reference check mark\n (docs/issues/img/01-3.png: the stroke's own pixels are #4b76d0/#507ad2, so\n the token takes the darker mode) and shares the stats heat ramp's hue\n family (hsl(217 \u2026)), which keeps every blue in the interface one voice. */\n --ccd-accent: #4b76ce;\n\n /* State colours that DSH already owns semantics for. */\n --ccd-diff-added: #508c48;\n --ccd-diff-removed: #b33156;\n\n /* Type. The two fallback tails are what a configured family is prepended to\n (see theme/tokens.ts); with nothing configured the consuming variables keep\n the built-in stacks. Geist leads the interface tail because it is the\n upstream design Anthropic Sans was cut from; it is resolved from the system\n font list, so the tail degrades to the platform stack when it is not\n installed (assets/fonts/ ships the file for a local install only). */\n --ccd-font-fallback: Geist, -apple-system, BlinkMacSystemFont, \"SF Pro Text\", \"Helvetica Neue\",\n \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif;\n --ccd-code-fallback: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace;\n --ccd-font-ui: var(--ccd-font-fallback);\n --ccd-font-code: var(--ccd-code-fallback);\n --ccd-font-size-body: 14px;\n --ccd-font-size-muted: 13px;\n /* Blank-session title. The reference's own type scale puts the greeting on\n `--cds-font-size-title` (1.25rem, ~20px) with a 25px leading at weight 400,\n which is a good deal quieter than the 26px this used to be. */\n --ccd-font-size-headline: 20px;\n /* Transcript headings. The reference's ladder sits one step under the host's\n (DSH draws h1/h2/h3 at 21/19/18px): its own crop measures a 19px h1 and a\n 16px h2 over the 14px body \u2014 27 and 23 device px of CJK ink against the\n 21-device-px body line at @2x \u2014 and the h2 is confirmed independently by\n the inline-code chip, whose 0.95em/1.2 rule this plugin already matches:\n it lands on the reference's 33 device px exactly at 16px. h3 has no crop of\n its own and takes the next step down. */\n --ccd-font-size-h1: 19px;\n --ccd-font-size-h2: 16px;\n --ccd-font-size-h3: 15px;\n /* Transcript leading. The host sets the assistant body at 14px/24px; the\n reference runs the same 14px on a 20px line. Its own window measures a\n 30.7-device-px pitch between two lines of a paragraph where this plugin's\n 24px draws 36.6, and both shots put their body's CJK ink at 20 device px\n with a 770px Composer at 1176 (1.53 device px per CSS px), so the two are\n read at one scale. The reference's paragraph-to-paragraph gap is 46 device\n px \u2014 this 20px line plus the 10px margin both sides already share. */\n --ccd-transcript-line-height: 20px;\n /* The one step up from the host's own 400: used where a control has to read\n as a chosen value rather than as chrome (model, reasoning effort). */\n --ccd-font-weight-strong: 600;\n\n /* Hand-drawn 16px marks matching the CCD interaction recording: return\n arrow and a small square in a ring. The host keeps its buttons, handlers\n and SVG state markers; these masks replace only their visible artwork. */\n --ccd-send-radius: 6px;\n --ccd-icon-send: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M12 4.5V8A2 2 0 0 1 10 10H3.5M6.5 7L3.5 10L6.5 13' stroke='black' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n --ccd-icon-stop: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='5.5' fill='none' stroke='black' stroke-width='1.25'/%3E%3Crect x='6' y='6' width='4' height='4' rx='.6' fill='black'/%3E%3C/svg%3E\");\n\n /* The header's three painted glyphs, taken from DSH 0.2.0-rc.2 shared\n artwork (MIT) so no host component is copied:\n - IconRightUpOutlineRegular (`ui-primitives/icons`) is the generic \"open\"\n glyph the native open-in-app control falls back to;\n - the terminal prompt is `ui-sidebar-terminal/TerminalIcon`'s own 16px\n geometry, the glyph that view's tab title draws;\n - the globe is `ui-primitives`' IconGlobeOutlineRegular, the glyph\n `ui-sidebar-browser` draws in its tab title.\n Masks let the host keep ownership of its buttons while the plugin supplies\n the artwork. */\n --ccd-icon-open: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M11.7256 2.77441C12.5538 2.77469 13.2256 3.44616 13.2256 4.27441V10.1416H12.2256V4.27441C12.2256 3.99844 12.0015 3.77469 11.7256 3.77441H5.7207V2.77441H11.7256Z' fill='black'/%3E%3Cpath d='M2.77441 13.2255L12.3756 3.62427' stroke='black'/%3E%3C/svg%3E\");\n --ccd-icon-terminal: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M3 4L7 8L3 12' stroke='black'/%3E%3Cpath d='M9 12H13' stroke='black'/%3E%3C/svg%3E\");\n --ccd-icon-browser: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M7.99986 14.0887C11.3626 14.0887 14.0886 11.3627 14.0886 7.99998C14.0886 4.63727 11.3626 1.91125 7.99986 1.91125C4.63715 1.91125 1.91113 4.63727 1.91113 7.99998C1.91113 11.3627 4.63715 14.0887 7.99986 14.0887Z' stroke='black'/%3E%3Cpath d='M2.34619 8H13.6538' stroke='black' stroke-linecap='square'/%3E%3Cpath d='M7.99976 14.0889C9.23509 14.0889 10.1743 11.3629 10.1743 8.00006C10.1743 4.63739 9.23509 1.91138 7.99976 1.91138' stroke='black'/%3E%3Cpath d='M7.99973 14.0889C6.76445 14.0889 5.8252 11.3629 5.8252 8.00006C5.8252 4.63739 6.76445 1.91138 7.99973 1.91138' stroke='black'/%3E%3C/svg%3E\");\n\n /* The session menu's own mark, stacked. The host draws\n `IconEllipsisOutlineRegular` (`ui-primitives`, MIT) as three 2px dots on one\n horizontal line \u2014 circles at (3, 8), (8, 8) and (13, 8) of a 16px box \u2014 and\n the reference stacks them, so this is that same geometry transposed to\n (8, 3), (8, 8) and (8, 13): one dot size, one 5-unit pitch, one 16px box,\n carried as a mask over the button's own `currentColor` so the host keeps its\n button and this interface supplies the mark. */\n --ccd-icon-more: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M8 4C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3C7 3.55228 7.44772 4 8 4Z' fill='black'/%3E%3Cpath d='M8 9C8.55228 9 9 8.55228 9 8C9 7.44772 8.55228 7 8 7C7.44772 7 7 7.44772 7 8C7 8.55228 7.44772 9 8 9Z' fill='black'/%3E%3Cpath d='M8 14C8.55228 14 9 13.55228 9 13C9 12.44772 8.55228 12 8 12C7.44772 12 7 12.44772 7 13C7 13.55228 7.44772 14 8 14Z' fill='black'/%3E%3C/svg%3E\");\n\n /* A bare plus, the one glyph the reference repeats on every actionable row.\n It is DSH's own `IconPlusOutlineArtwork` geometry (ui-primitives, MIT): two\n 1px strokes across a 16px box, so the plugin can put the same mark on the\n Workspace header's add button and on a project row's create button without\n authoring artwork of its own. */\n --ccd-icon-plus: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M8 2V14' stroke='black'/%3E%3Cpath d='M2 8H14' stroke='black'/%3E%3C/svg%3E\");\n\n /* The workspace picker chip's leading mark. DSH switches that glyph with the\n chip's own state \u2014 `IconFolderOpenRegular` once a workspace is chosen, a\n closed folder while the chip only carries a placeholder \u2014 and the open one\n draws a slanted front panel over a translucent back panel, where the\n reference's button leads with one closed folder in either state. The\n geometry below is DSH's own `FolderCloseArtwork` (`ui-primitives`, MIT) on\n its 16-unit grid and 1px stroke, with the artwork's second path \u2014 the rule\n line across the body \u2014 left out: the reference draws the body empty, and\n the tab, the step and the four rounded corners are the whole of the mark. */\n --ccd-icon-folder: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M1.50439 3.11059C1.50439 2.55831 1.95211 2.1106 2.50439 2.1106H5.43389C5.67773 2.1106 5.91318 2.19969 6.09593 2.36113L7.71649 3.79265C7.89924 3.95409 8.1347 4.04319 8.3785 4.04319H13.4958C14.0481 4.04319 14.4958 4.4909 14.4958 5.04319V12.8894C14.4958 13.4417 14.0481 13.8894 13.4958 13.8894H2.50439C1.95211 13.8894 1.50439 13.4417 1.50439 12.8894V4.04319V3.11059Z' stroke='black'/%3E%3C/svg%3E\");\n\n /* The reference's disclosure mark is a 1px line chevron where the host draws a\n filled triangle; this is DSH's own `IconChevronRightOutlineArtwork` geometry\n (ui-primitives, MIT). It is painted over the host's mark slot, so the host's\n own `arrowOpen` state still drives the quarter turn. */\n --ccd-icon-chevron-right: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M6 12L9.29289 8.70711C9.68342 8.31658 9.68342 7.68342 9.29289 7.29289L6 4' stroke='black'/%3E%3C/svg%3E\");\n\n /* The Files tree's two file marks, measured off the reference at @2x: a page\n with its bottom-right corner folded, and the angle-bracket pair, each drawn\n 8\u20139px wide inside the 16px seat the host's own type glyphs occupy (the\n reference's names then start on the same 33px the row's own gap states).\n DSH classifies a file by name and extension too, but its set is a\n different one \u2014 `.gitignore` is a git file to the host and a plain page to\n the reference, `LICENSE` a page to both \u2014 so `right-panel.css` carries the\n reference's own split as an extension list rather than reading the host's. */\n --ccd-icon-file: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M5.5 4.5H10.5C11.0523 4.5 11.5 4.94772 11.5 5.5V8.5L8.5 11.5H5.5C4.94772 11.5 4.5 11.0523 4.5 10.5V5.5C4.5 4.94772 4.94772 4.5 5.5 4.5Z' stroke='black'/%3E%3Cpath d='M8.5 8.5H11.5L8.5 11.5' stroke='black'/%3E%3C/svg%3E\");\n --ccd-icon-file-code: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M6.2 5.2L4.2 8.05L6.2 10.9' stroke='black' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M9.8 5.2L11.8 8.05L9.8 10.9' stroke='black' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M9.4 4.6L6.6 11.4' stroke='black' stroke-linecap='round'/%3E%3C/svg%3E\");\n\n /* The Files tab's mark: the reference draws a three-row list \u2014 a bullet and a\n rule per row \u2014 12px of ink on the tab's own blue square, so the artwork is\n stated on the square's 24-unit grid. The square itself is a seat the tab\n sheet paints; this is only the ink that sits in it. */\n --ccd-icon-files-list: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='black'%3E%3Crect x='6' y='6.5' width='2' height='2' rx='.5'/%3E%3Crect x='9.5' y='6.5' width='8' height='2' rx='.5'/%3E%3Crect x='6' y='11' width='2' height='2' rx='.5'/%3E%3Crect x='9.5' y='11' width='8' height='2' rx='.5'/%3E%3Crect x='6' y='15.5' width='2' height='2' rx='.5'/%3E%3Crect x='9.5' y='15.5' width='8' height='2' rx='.5'/%3E%3C/g%3E%3C/svg%3E\");\n\n /* The Files pane's magnifier, for the filter field's leading seat and for the\n one control the pane's header adds: a lens and a handle, 13px of ink in the\n 16px box the field's own row draws, one 1px stroke like the marks around it. */\n --ccd-icon-search: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Ccircle cx='6.6' cy='6.6' r='4.6' stroke='black'/%3E%3Cpath d='M9.9 9.9L13.9 13.9' stroke='black' stroke-linecap='round'/%3E%3C/svg%3E\");\n\n /* The archived Session row's leading mark. The host deliberately leaves that\n 16px cell empty, so the plugin paints the same geometry itself: DSH's own\n `IconArchiveOutlineRegular` artwork (ui-primitives, MIT) \u2014 a lid, a body and\n a handle drawn with 1px strokes \u2014 carried as a mask like the marks around\n it, so no third-party asset or copied component enters the stylesheet. */\n --ccd-icon-archive: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M13.5 2.5H2.5C1.94772 2.5 1.5 2.94772 1.5 3.5V4.5C1.5 5.05228 1.94772 5.5 2.5 5.5H13.5C14.0523 5.5 14.5 5.05228 14.5 4.5V3.5C14.5 2.94772 14.0523 2.5 13.5 2.5Z' stroke='black'/%3E%3Cpath d='M2.5 5.5V13.5C2.5 13.7652 2.60536 14.0196 2.79289 14.2071C2.98043 14.3946 3.23478 14.5 3.5 14.5H12.5C12.7652 14.5 13.0196 14.3946 13.2071 14.2071C13.3946 14.0196 13.5 13.7652 13.5 13.5V5.5' stroke='black'/%3E%3Cpath d='M6.5 9.5H9.5' stroke='black'/%3E%3C/svg%3E\");\n\n /* The idle Session row's leading ring. The host hands that cell to the\n plugin's `sidebar.session.row.leading` seat as soon as a row has no status\n of its own, and the running row's activity ring is `ui-primitives`'\n StateDot spinner: a 2-unit stroke on a 9.5-unit radius in a 24-unit box.\n The same circle is carried here as a mask, so the still mark and the\n spinning one are one geometry at the one 8px scale the stylesheet already\n gives the spinner \u2014 and the ring takes the cell's own `currentColor`\n (the host's `--dsw-alias-label-tertiary`, the spinner's ink) instead of an\n authored colour. */\n --ccd-icon-session-ring: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Ccircle cx='12' cy='12' r='9.5' stroke='black' stroke-width='2'/%3E%3C/svg%3E\");\n\n /* The context ring's track, for the seat an empty session has to fill. The\n host's own `ContextMeter` returns nothing at all until the token meter knows\n a numerator and the context window, so the plugin draws that ring's track\n itself \u2014 the host's exact geometry from `ContextMeter.module.css`\n (viewBox 0 0 14 14, cx=cy=7, r=5.5, 2px stroke) carried as a mask, so the\n colour stays the host track token above. The consumed arc is not drawn: at\n 0% the host's own arc has no length either. */\n --ccd-icon-context-ring: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none'%3E%3Ccircle cx='7' cy='7' r='5.5' stroke='black' stroke-width='2'/%3E%3C/svg%3E\");\n\n /* The Composer whale. DeepSeek's own mark is a blue whale with a pale belly,\n so the two inks are the brand pair rather than a derived palette step: the\n artwork only ever appears as this one mark. The dark side lifts the blue a\n step so it keeps its contrast on the dark canvas instead of sinking into\n it; the belly stays the light ink in both schemes, because it is what makes\n the silhouette read at 64px. */\n --ccd-pet-blue: #4d6bfe;\n --ccd-pet-light: #dfe6ff;\n\n /* Elevation */\n --ccd-shadow-card: 0 1px 2px rgb(0 0 0 / 4%);\n --ccd-shadow-segment: 0 1px 2px rgb(0 0 0 / 8%);\n /* The right panel's card, read off the reference's own edges: the canvas\n (252/255) sits at 243 half a pixel beside the card, 235 directly under it\n and back to 251 eight pixels out \u2014 a two-layer shadow, the near one for the\n edge and the far one for the falloff. */\n --ccd-right-panel-shadow: 0 1px 3px rgb(0 0 0 / 4%), 0 5px 14px rgb(0 0 0 / 8%);\n}\n\n/*\n * Host-token aliases belong on `body`, exactly where the host writes them.\n *\n * `--dsw-*` values are not in the document stylesheets: DSH's theme presenter\n * writes them, and this plugin's own overrides, as inline styles on `body`\n * (theme/tokens.ts). A custom property is resolved *where it is declared*, so an\n * alias of a host token declared on the root would reference a variable that is\n * not in scope there: it computes to the guaranteed-invalid value and inherits\n * as invalid into every subtree, and the rule consuming it falls back to\n * `transparent` rather than the host's colour. The empty-state context ring\n * (theme/composer.css, `.yhfFVG_dock::after`) vanished exactly that way.\n */\nhtml[data-dsh-ccd-style=\"true\"] body {\n /* Resolve on body so dark mode and configured palettes both participate. */\n --ccd-composer-focus-border: color-mix(in srgb, var(--ccd-card) 60%, var(--ccd-text-secondary));\n /* The empty state's ring draws the host's track alone. It stays the host's\n own track token (`ContextMeter.module.css` strokes `.y0jqnG_track` with\n `--dsw-alias-border-l3`, which theme/tokens.ts already retints), so an\n empty session shows the same hollow ring the host would draw at 0%. */\n --ccd-context-ring-track: var(--dsw-alias-border-l3);\n}\n\n/*\n * Dark palette.\n *\n * DSH's theme presenter writes `body[data-ds-dark-theme]` from the resolved\n * colour scheme (`@deepseek-ai/dsh-client-ui-theme` client styles, DSH\n * 0.2.0-rc.2), so the plugin follows the host's own switch instead of carrying a\n * second one. The block is a descendant of the root activation marker: the\n * variables land on `body`, cover every colour the light block declares, and\n * stay absent while the plugin is off.\n *\n * The warm-neutral family is kept rather than swapping in the host's bluish\n * greys: the same relationship holds in both schemes (canvas a touch lighter\n * than the sidebar, card the brightest surface), while the recessed steps\n * (track, raised, hover, selected) move *up* in lightness where the light\n * palette moves down, because on a dark canvas a surface reads as raised by\n * catching more light. Lines keep one visible step against the surfaces they\n * separate; text keeps the light palette's descending tone order.\n */\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n /* The same flat frame uses gray-850 for the dark page and mixes it with\n 20% black for the sidebar. The control track stays below its raised thumb\n while both sit above the darker page. */\n --ccd-canvas: #151515;\n --ccd-sidebar: #111111;\n --ccd-card: #30302e;\n --ccd-header-menu-border: var(--ccd-border);\n --ccd-header-menu-separator: var(--ccd-border-soft);\n --ccd-header-menu-danger: #f08080;\n --ccd-menu-danger: #c04742;\n --ccd-menu-danger-ink: #ffffff;\n --ccd-header-trigger-hover: var(--ccd-hover);\n --ccd-header-project-fill: var(--ccd-track);\n --ccd-header-project-active: var(--ccd-selected);\n --ccd-track: #1f1e1d;\n --ccd-raised: #2f2f2d;\n --ccd-hover: #313130;\n --ccd-view-menu-hover: var(--ccd-selected);\n --ccd-view-menu-text: var(--ccd-text);\n --ccd-view-menu-muted: var(--ccd-text-muted);\n --ccd-view-menu-border: var(--ccd-border);\n --ccd-view-menu-separator: var(--ccd-border-soft);\n --ccd-view-menu-accent: var(--ccd-accent);\n --ccd-view-menu-shadow: 0 1px 3px rgba(0, 0, 0, .4), 0 8px 20px rgba(0, 0, 0, .3), 0 16px 32px rgba(0, 0, 0, .2);\n --ccd-selected: #3a3a37;\n /* The same step as the light side, in the direction this canvas recesses:\n the fill goes one step up from `selected` here \u2014 which happens to land on\n the strong-outline step below, a coincidence of the two ramps rather than\n the reason for the value. */\n --ccd-hover-strong: #474743;\n /* The tab mark's tint, dark side: the accent's own hue over this card, which\n is the #d3e2f9 relationship the light side measures, not its value. */\n --ccd-right-panel-glyph-bg: #2b3a55;\n /* The Files pane's inks go back to the palette's own ramp here: the reference\n is a light-mode capture, and its three sampled values are only meaningful\n as relationships (a step below the body ink, a step above the muted one and\n the accent's own hue) that this side already carries. */\n --ccd-files-ink: var(--ccd-text);\n --ccd-right-panel-tab-ink: var(--ccd-text);\n --ccd-files-chip-ink: var(--ccd-accent);\n\n /* Lines */\n --ccd-border: #3e3e3b;\n --ccd-border-strong: #474743;\n --ccd-border-soft: #343431;\n /* The head rule stays the one line drawn stronger than the card outline. */\n --ccd-table-head-line: #4a4a46;\n /* The card outline's dark side: one step above the row outline, as in the\n light palette. */\n --ccd-right-panel-border: #474743;\n --ccd-browser-canvas: #242423;\n --ccd-browser-dot: #454542;\n\n /* Scrollbar ink, dark side: on this canvas the bar is the one piece of the\n chrome that has to read as raised, so it sits above every surface step\n here and lightens on hover \u2014 the mirror of the light palette, whose ink\n sits below every surface and darkens. */\n --ccd-scrollbar-thumb: #5c5b57;\n --ccd-scrollbar-thumb-hover: #75746f;\n\n /* Text */\n --ccd-text: #f0efec;\n --ccd-text-secondary: #b4b1ab;\n --ccd-text-muted: #918f89;\n /* Same step down from full strength as the light palette: the dark ink sits\n the same distance below --ccd-text as #4a4a47 sits below #1f1f1d. */\n --ccd-text-nav: #d3d0ca;\n --ccd-text-placeholder: #8b8983;\n /* Archived rows, dark side: the same two steps below the row ink, kept\n readable against this sidebar and the selected fill that sits above it. */\n --ccd-text-archived: #82807c;\n --ccd-text-archived-hover: #a6a39c;\n\n /* Composer whale, dark side: the same mark, with the blue raised so it reads\n against this canvas; the belly keeps the light ink. */\n --ccd-pet-blue: #7b93ff;\n --ccd-pet-light: #e8ecff;\n\n /* Statistics card, dark side: the same stacked greys over this canvas, and\n the heat ramp raised one step so the steps stay visible on a dark panel. */\n --ccd-stats-panel: #2c2c2a;\n --ccd-stats-tile: #383835;\n --ccd-stats-tab: #3a3a37;\n --ccd-stats-label: #918f89;\n --ccd-stats-value: #f0efec;\n --ccd-stats-heat-1: hsl(217 62% 78%);\n --ccd-stats-heat-2: hsl(217 64% 70%);\n --ccd-stats-heat-3: hsl(217 66% 62%);\n --ccd-stats-heat-4: hsl(217 70% 54%);\n /* Model ramp, raised for the dark panel; six distinct steps, as the light\n theme's clamped ramp produces. */\n --ccd-stats-model-1: hsl(217 62% 70%);\n --ccd-stats-model-2: hsl(217 64% 75%);\n --ccd-stats-model-3: hsl(217 66% 80%);\n --ccd-stats-model-4: hsl(217 68% 84%);\n --ccd-stats-model-5: hsl(217 70% 87%);\n --ccd-stats-model-6: hsl(217 70% 89%);\n --ccd-stats-tip-bg: #454542;\n --ccd-stats-tip-fg: #f7f7f5;\n\n /* Assistant Markdown palette, lightened for a dark transcript. */\n --ccd-link: #86b0e8;\n --ccd-link-underline: #4a5c76;\n --ccd-inline-code-text: #f0918a;\n --ccd-inline-code-fill: #35332f;\n --ccd-inline-code-border: #454239;\n\n /* Context meter ring, dark side: the same hue as the light accent, one step\n up in lightness (55% \u2192 68%) and saturation so the arc keeps its blue on\n this canvas instead of greying into it. Same `var()` order as the light\n block. */\n --ccd-context-ring-fill: var(--ccd-accent, #789be3);\n\n /* Context breakdown categories, dark side. The reference ships one light\n crop, so these are derived the way the rest of this palette is: the same\n hue, raised in lightness by the step the statistics ramp and the accent\n take on this canvas, so five categories stay five colours instead of\n sinking into the card. The two greys are the exception \u2014 they are surfaces\n rather than inks, so the buffer steps down to a mid warm grey and the free\n track steps up off the card, which is what keeps the reserved block and the\n empty room apart at a glance. */\n --ccd-context-mcp: #5b9ae8;\n --ccd-context-tools: #f0885a;\n --ccd-context-system: #43c79b;\n --ccd-context-skills: #f0b93c;\n --ccd-context-memory: #ef93b5;\n --ccd-context-messages: #a58fe6;\n --ccd-context-buffer: #5f5b53;\n --ccd-context-free: #3f3f3b;\n\n /* The accent, dark side: the same hue and the same 55% \u2192 68% lightness step\n the statistics heat ramp takes on this canvas, so the check keeps its blue\n against the menu's surface instead of sinking into it. The hue is the\n reference's measured blue (220) rather than the ramp's 217, but the two sit\n in one family. */\n --ccd-accent: #789be3;\n\n /* State colours that DSH already owns semantics for. */\n --ccd-diff-added: #7cbd72;\n --ccd-diff-removed: #e08fae;\n\n /* Elevation reads as a shadow under the surface, not as a grey wash. */\n --ccd-shadow-card: 0 1px 2px rgb(0 0 0 / 40%);\n --ccd-shadow-segment: 0 1px 2px rgb(0 0 0 / 50%);\n --ccd-right-panel-shadow: 0 1px 2px rgb(0 0 0 / 35%), 0 4px 10px rgb(0 0 0 / 35%);\n}\n\n/* zanwei effort reference palette, MIT; canvas reads these theme values. */\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-effort-color-1: #8c73c9;\n --ccd-effort-color-2: #a17ec2;\n --ccd-effort-color-3: #5f5b58;\n --ccd-effort-color-4: #3f3b38;\n --ccd-effort-color-5: #77736f;\n --ccd-effort-color-6: #edeae8;\n --ccd-effort-color-7: #e0dbd6;\n --ccd-effort-color-8: #ffffff;\n --ccd-effort-color-9: rgba(76, 70, 65, 0.12);\n --ccd-effort-color-10: #2788d6;\n --ccd-effort-color-11: rgba(62, 56, 50, 0.05);\n --ccd-effort-color-12: rgba(62, 56, 50, 0.04);\n --ccd-effort-color-13: rgba(62, 56, 50, 0.06);\n --ccd-effort-color-14: #74706d;\n --ccd-effort-color-15: rgba(82, 76, 70, 0.055);\n --ccd-effort-color-16: rgba(76, 70, 65, 0.1);\n --ccd-effort-color-17: #34312f;\n --ccd-effort-color-18: rgba(35, 31, 29, 0.12);\n --ccd-effort-color-19: #fff;\n --ccd-effort-color-20: rgba(70, 64, 59, 0.035);\n --ccd-effort-color-21: #eeebe9;\n --ccd-effort-color-22: #ece9e7;\n --ccd-effort-color-23: #e2dce3;\n --ccd-effort-color-24: #d9d0df;\n --ccd-effort-color-25: #d0c1da;\n --ccd-effort-color-26: #cdbcd9;\n --ccd-effort-color-27: #cbbad8;\n --ccd-effort-color-28: #d5cadc;\n --ccd-effort-color-29: #c8b5d4;\n --ccd-effort-color-30: #bda6cc;\n --ccd-effort-color-31: #b59bc6;\n --ccd-effort-color-32: #b6b2af;\n --ccd-effort-color-33: rgba(76, 70, 65, 0.13);\n --ccd-effort-color-34: rgba(62, 56, 50, 0.08);\n --ccd-effort-color-35: rgba(62, 56, 50, 0.055);\n --ccd-effort-pixel-leftColor: 210, 206, 214;\n --ccd-effort-pixel-deepViolet: 156, 120, 192;\n --ccd-effort-pixel-deepMid: 156, 132, 192;\n --ccd-effort-pixel-midPurple: 168, 144, 204;\n --ccd-effort-pixel-softMid: 168, 156, 204;\n --ccd-effort-pixel-softLilac: 180, 168, 204;\n --ccd-effort-pixel-paleCool: 192, 180, 204;\n --ccd-effort-pixel-highlightColor: 216, 204, 228;\n --ccd-effort-pixel-peakColor: 232, 224, 242;\n}\n\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-effort-shadow: 0 1px 2px rgba(62, 56, 50, .05), 0 4px 10px rgba(62, 56, 50, .04), 0 12px 28px rgba(62, 56, 50, .06);\n}\n\n/*\n * The same reference field on the dark canvas: the purple ramp keeps its\n * left-to-right direction (neutral \u2192 violet) inside the dark range, the\n * neutrals flip so the panel is a card above the transcript, and the knob stays\n * the brightest thing on the track \u2014 its fill is also the tooltip's text\n * colour, so the two keep following one value.\n */\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-effort-color-1: #a48ede;\n --ccd-effort-color-2: #b294d3;\n --ccd-effort-color-3: #e7e4de;\n --ccd-effort-color-4: #f6f4f0;\n --ccd-effort-color-5: #a09b94;\n --ccd-effort-color-6: #3a3936;\n --ccd-effort-color-7: #4b4944;\n --ccd-effort-color-8: #2b2a28;\n --ccd-effort-color-9: rgba(255, 255, 255, 0.1);\n --ccd-effort-color-10: #4d93f8;\n --ccd-effort-color-11: rgba(0, 0, 0, 0.45);\n --ccd-effort-color-12: rgba(0, 0, 0, 0.35);\n --ccd-effort-color-13: rgba(0, 0, 0, 0.45);\n --ccd-effort-color-14: #b7b2aa;\n --ccd-effort-color-15: rgba(255, 255, 255, 0.06);\n --ccd-effort-color-16: rgba(255, 255, 255, 0.14);\n --ccd-effort-color-17: #3a3936;\n --ccd-effort-color-18: rgba(0, 0, 0, 0.5);\n --ccd-effort-color-19: #ece9e4;\n --ccd-effort-color-20: rgba(255, 255, 255, 0.04);\n --ccd-effort-color-21: #34332f;\n --ccd-effort-color-22: #373430;\n --ccd-effort-color-23: #3e3943;\n --ccd-effort-color-24: #463e51;\n --ccd-effort-color-25: #4f4560;\n --ccd-effort-color-26: #57496a;\n --ccd-effort-color-27: #5c4d71;\n --ccd-effort-color-28: #524667;\n --ccd-effort-color-29: #63527c;\n --ccd-effort-color-30: #6e5989;\n --ccd-effort-color-31: #786096;\n --ccd-effort-color-32: #6f6c66;\n --ccd-effort-color-33: rgba(255, 255, 255, 0.16);\n --ccd-effort-color-34: rgba(0, 0, 0, 0.4);\n --ccd-effort-color-35: rgba(0, 0, 0, 0.35);\n --ccd-effort-pixel-leftColor: 92, 88, 98;\n --ccd-effort-pixel-deepViolet: 150, 116, 196;\n --ccd-effort-pixel-deepMid: 150, 128, 196;\n --ccd-effort-pixel-midPurple: 162, 140, 204;\n --ccd-effort-pixel-softMid: 162, 152, 204;\n --ccd-effort-pixel-softLilac: 174, 164, 206;\n --ccd-effort-pixel-paleCool: 184, 174, 206;\n --ccd-effort-pixel-highlightColor: 200, 188, 224;\n --ccd-effort-pixel-peakColor: 214, 204, 236;\n --ccd-effort-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 4px 10px rgba(0, 0, 0, .3), 0 12px 28px rgba(0, 0, 0, .35);\n}\n\n/*\n * Chosen-value ink. The Composer's model name \u2014 in the tool row and in the menu\n * it opens \u2014 is the value that row exists to show, so it takes full black\n * instead of the warm near-black every other primary label uses; the dark\n * scheme keeps the same relationship with its own strongest ink, white. Neither\n * side is derived from a configured surface, so the pair is declared here\n * rather than in the scheme blocks above.\n */\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-text-strong: #000000;\n}\n\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-text-strong: #ffffff;\n}\n\n/*\n * Header icon ink.\n *\n * The conversation header's trailing cluster is icon-only \u2014 the native session\n * menu, the two views this plugin adds, the scheduled-tasks entry while it has\n * records, the collapsed right panel's re-entry control \u2014 and the reference\n * draws those marks at full strength where the host uses its secondary label\n * grey. Like the chosen-value ink above, this pair answers to no configured\n * surface, so it is declared here rather than in the scheme blocks: the pure\n * black the reference measured on the light canvas, and its mirror white on the\n * dark one, because a black mark would vanish into that canvas.\n *\n * What each state puts behind the mark stays the host's: a near-black wash at\n * 6-14% in the light scheme, a white one at 8-14% in the dark, and the button's\n * own dimmed opacity while it is disabled \u2014 so the ink never meets a fill of its\n * own lightness (see `header-actions.css`).\n */\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-header-icon-color: #000000;\n}\n\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-header-icon-color: #ffffff;\n}\n\n/*\n * The selected check in every Menu surface.\n *\n * The host paints it with `--dsw-alias-label-primary` in the Menu primitive's\n * own `Menu.module.css` (`.check`), so the workspace picker, the permission\n * menu, the view-options menu and the session \u22EF menu all show the same\n * near-black mark \u2014 a selection reads no louder than the label beside it. One\n * rule recolours all of them, because they all come from that one primitive.\n * The model picker is not one of them: it is this plugin's own card, and the\n * block at the end of this file is the rule that reaches its mark.\n *\n * Only the colour changes: the mark keeps the host's 14px seat, its\n * `display: grid` centring, its row height and every hover fill. The class is\n * the one the shipped static web frontend gives that module (`_4ub78_`, whose\n * local names run `_check_4ub78_179`, `_item_4ub78_90`, \u2026), and that asset is\n * platform-independent \u2014 both installers carry the identical\n * `@deepseek-ai/dsh-web-frontend` dist \u2014 so it is the same name on Windows and\n * needs no second spelling in `host-builds.ts` (`host-dom.ts` records the same\n * prefix).\n *\n * The rule covers the seat and its artwork: the svg inherits through\n * `currentColor`, and naming it as well keeps the mark blue even if a future\n * build moves the colour onto the artwork instead of the seat.\n */\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] ._check_4ub78_179,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitem\"] ._check_4ub78_179,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] ._check_4ub78_179 svg,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitem\"] ._check_4ub78_179 svg {\n color: var(--ccd-accent);\n}\n\n/*\n * The selected mark in the model picker.\n *\n * The Composer's model seat is not the host's `ModelSelect`: this plugin's\n * `ModelControls` wins `conversation.input.model` (its registration carries\n * `priority: -10` while the host registers the same seat at the default 0, and\n * the slot chain takes the lowest priority that answers), and the card that\n * seat opens marks the chosen model with the text `\u2713` in the row's trailing\n * `span[aria-hidden=\"true\"]` (`features/model-controls/ModelControls.tsx`).\n * `features/model-controls/controls.css` paints that row `--ccd-text-strong`,\n * so the mark inherits full black \u2014 which is exactly what it did: it is\n * neither `._check_4ub78_179` nor an svg, so the Menu rule above cannot reach\n * it, and no `fill`/`stroke` override would either, because a text glyph is\n * painted by `color` alone.\n *\n * Only the ink changes: the row keeps its height, padding and hover, and the\n * artwork is named beside the seat so a later icon in the same seat stays\n * covered. The seat is reached two ways \u2014 the row's own selected state\n * (`aria-pressed`, which React writes as `\"true\"`/`\"false\"`) and the seat that\n * actually holds a glyph (`:not(:empty)`, because the unchosen rows render an\n * empty span) \u2014 so a later switch to `aria-checked` on a `menuitemradio` row\n * cannot silently return this mark to black.\n *\n * The host's own `ModelSelect` card is covered as well, for the path where\n * that seat is the one on screen: its `.check` seat holds an svg whose path\n * strokes `currentColor` (ui-primitives `IconCheckOutlineArtwork`), so the\n * same `color` reaches the artwork. `cl2Rlq_` is already in the prefix table\n * (`compat/host-dom.ts`), and the Windows build's `wq12jW_` spelling is what\n * `compat/dom.ts` substitutes when this sheet is mounted.\n */\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button[aria-pressed=\"true\"] > span[aria-hidden=\"true\"],\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button[aria-pressed=\"true\"] > span[aria-hidden=\"true\"] svg,\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button > span[aria-hidden=\"true\"]:not(:empty),\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button > span[aria-hidden=\"true\"]:not(:empty) svg,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] .cl2Rlq_check,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitemradio\"] .cl2Rlq_check,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] .cl2Rlq_check svg,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitemradio\"] .cl2Rlq_check svg {\n color: var(--ccd-accent);\n}\n";
4446
+ var tokens_default = "/* CCD geometry, type, artwork and light/dark colour variables.\n * Colours are centralized here; the dark palette follows the host's body marker.\n */\nhtml[data-dsh-ccd-style=\"true\"] {\n /* Geometry */\n /* Top of the blank-session greeting block. The reference puts the title a\n short step below the header instead of centring it, so the statistics card\n hanging under it still clears the Composer on a short window. */\n --ccd-hero-top: 16px;\n --ccd-sidebar-width: 264px;\n --ccd-sidebar-inline-padding: 10px;\n --ccd-sidebar-bottom-padding: 8px;\n --ccd-row-height: 28px;\n /* Workspace (group) row. The host's own 34px, pinned because the browsing\n region's merged header band is this same box: the section header parks on\n the row's line and the two have to agree to the pixel. */\n --ccd-workspace-row-height: 34px;\n /* Navigation stack. The reference's three rows measured 26px tall on a 26.5px\n pitch \u2014 contiguous, not separated \u2014 against the host's own 36px/7px row. */\n --ccd-nav-row-height: 26px;\n --ccd-nav-gap: 1px;\n --ccd-radius-row: 8px;\n --ccd-radius-panel: 12px;\n /* View-options reference: 20 device px corners at @2x. */\n --ccd-view-menu-radius: 10px;\n /* Assistant table card. The reference crop's corner curve fits a 12-device-px\n radius at @2x, so the card is rounder than the row radius it borrows its\n scale from. */\n --ccd-table-radius: 6px;\n /* Fenced code block card. The reference code block shows the same 12-device-px\n curve at @2x as the table card, so the transcript's two boxed surfaces stay\n one family. */\n --ccd-code-radius: 6px;\n --ccd-composer-width: 770px;\n --ccd-composer-min-height: 42px;\n --ccd-composer-radius: 10px;\n --ccd-composer-padding: 8px 14px;\n --ccd-composer-padding-block: 8px;\n --ccd-composer-padding-inline: 14px;\n --ccd-composer-row-gap: 4px;\n --ccd-composer-row-inset: 4px;\n --ccd-composer-bottom-gap: 5px;\n --ccd-control-row-height: 28px;\n /* Status-bar chip. The tool row's controls are all this one box: the row's\n 28px is the layout line, and every control inside it is a chip of this\n height rather than a box stretched to the line. The reference draws the\n model chip's fill as one label line \u2014 40 device px at @2x, so the row's\n 12px label sits 5.5px from the chip's top and bottom where the row itself\n would leave it 10px \u2014 and the same box now carries the command plus, the\n permission control, the voice control, the statistics readouts and the\n context ring, so a pointer crossing the row finds one fill height instead\n of three. The row keeps `--ccd-control-row-height`: the dock, the ring's\n seat and the trailing cluster are all measured from it. The corner follows\n the height \u2014 12 device px at @2x, the same curve the transcript's table and\n code cards carry, rather than the row's 8px radius, which is nearly half of\n a 20px chip and would round every fill towards a pill. */\n --ccd-chip-height: 20px;\n --ccd-chip-radius: 6px;\n /* The chip family's inline padding: the model/effort chips, the permission\n control and the two square glyph buttons (plus, voice), whose boxes are\n their 14px artwork plus one of these on each side. Six to seven px is the\n whole range in the reference; the readouts and the ring keep their own\n slightly tighter 6px, which is a 1px difference in ink and nothing in a\n fill's shape. */\n --ccd-chip-padding-inline: 7px;\n --ccd-send-size: 24px;\n --ccd-send-reserve: 30px;\n /* One gap for the whole status row: the row itself, the leading tools group,\n its modes cluster, the trailing cluster (the native readouts, the context\n ring, the model/effort pair) and the statistics dock all space their\n children with this. The host's own row ran 12px in the leading groups and\n the plugin's 6px in the trailing one, which read as two different rows in\n one bar. Each control carries its own 6-7px inner padding, so an even box\n gap also reads as an even visible rhythm. */\n --ccd-cluster-gap: 6px;\n /* Context ring. The host draws it as 14px artwork (`ContextMeter.module.css`:\n viewBox 0 0 14 14, cx=cy=7, r=5.5, 2px stroke, round cap) inside a 28px\n trigger with 6px of side padding, so the trigger's own box is 26px and the\n seat the status bar has to hold for it \u2014 that box plus one cluster gap \u2014 is\n 32px. The host's ring and this plugin's empty-state ring hang in that one\n seat, which is what keeps the ring's position and size the same before and\n after a session has usage. */\n --ccd-context-ring-size: 14px;\n --ccd-context-ring-trigger: 26px;\n --ccd-context-ring-seat: calc(var(--ccd-context-ring-trigger) + var(--ccd-cluster-gap));\n /* Context breakdown panel. Measured off the supplied reference at @2x\n (698\xD7178 for the collapsed state, 828\xD71006 for the expanded one): a 361px\n card with a 1px outline and a 12px corner, 12px inline and 8px top padding,\n a 13px/20px header, a 4px bar 5px under it, 19px value rows, 17px detail\n rows, and 10px swatches. The width is the one number the crop cut off, so\n it is the reference's own rounded value: the bar and the percentage column\n both end exactly at 360 \u2212 2 \u2212 24 = 334px, which is what the crop shows. */\n --ccd-context-panel-width: 360px;\n --ccd-context-panel-radius: 12px;\n --ccd-context-panel-padding-block: 8px;\n --ccd-context-panel-padding-inline: 12px;\n --ccd-context-panel-gap: 8px;\n --ccd-context-row-height: 19px;\n --ccd-context-detail-height: 17px;\n --ccd-context-swatch-size: 10px;\n --ccd-context-swatch-radius: 3px;\n --ccd-context-bar-height: 4px;\n --ccd-context-bar-radius: 2px;\n --ccd-context-bar-gap: 1px;\n /* 5px under the header line, and nothing below: the card's own bottom padding\n is what follows the bar in the collapsed state, and the rows state their\n own 4px above themselves in the expanded one. */\n --ccd-context-bar-margin-block: 5px 0;\n /* The buffer segment's own step away from the used group: the reference\n leaves 4px there where every used segment is 1px apart, because the grey\n block is a reservation rather than another category. */\n --ccd-context-bar-reserve-gap: 4px;\n /* Ten detail rows before a group scrolls \u2014 the reference's own visible run,\n and what keeps a session with 85 tools from drawing a 1500px panel. */\n --ccd-context-detail-max: 170px;\n /* The two value columns: the token column's right edge sits 48px in from the\n content edge (measured 618 of 715 device px), which is a 40px percentage\n column plus this gap. */\n --ccd-context-percent-width: 40px;\n --ccd-context-column-gap: 8px;\n /* The status bar's own glyph size: the command plus, the statistics readouts\n and the ring all draw 14px artwork in the 28px control row. The\n speech-to-text control draws 18px of its own; the composer sheet brings that\n one down to this size. The permission control draws no glyph at all \u2014 it is\n its text (composer.css). */\n --ccd-row-icon-size: 14px;\n --ccd-account-menu-width: 236px;\n --ccd-account-menu-padding: 5px;\n --ccd-account-row-height: 28px;\n --ccd-account-trigger-height: 30px;\n /* Conversation header action cluster. The CCD reference keeps every control\n on one 30px centre pitch with a 12px trailing inset (measured at @2x from\n docs/reference/ccd-conversation.png: icon centres 28.75/30/30px apart, the\n trailing glyph centre 25.75px from the window edge). That inset is what the\n cluster takes while the Composer is narrower than the column and centred in\n it; where the Composer fills the column, `conversation.css` ends the\n cluster on the input surface's own border instead, which is the line the\n reference puts the closing control on and a measurement rather than a\n second token. */\n --ccd-header-action-size: 28px;\n --ccd-header-action-compact: 24px;\n --ccd-header-icon-size: 16px;\n --ccd-header-action-gap: 2px;\n --ccd-header-trailing-inset: 12px;\n --ccd-header-menu-border: #d6d6d6;\n --ccd-header-menu-separator: #e2e2e2;\n --ccd-header-menu-danger: #b4262b;\n --ccd-menu-danger: #c04742;\n --ccd-menu-danger-ink: #ffffff;\n --ccd-header-trigger-hover: #f0f0ef;\n --ccd-header-project-fill: #e5e5e5;\n --ccd-header-project-active: #cfcfcf;\n /* Transcript edge fade. 24px is the band the host's own internal-request\n viewer uses for `fadeTop`\uFF0F`fadeBottom`, so the whole interface softens its\n scroll viewport edges by the same amount. */\n --ccd-edge-fade: 24px;\n /* Jump-to-bottom control. The reference's own affordance measures 40\xD744\n device px at @2x \u2014 a ~21px mark above the Composer \u2014 against the host's\n 34px floating circle, so the box shrinks to this one step while the glyph\n inside it keeps the host's 16px seat. */\n --ccd-to-bottom-size: 22px;\n /* Right panel (the Files, terminal and browser tabs). The reference draws it\n as a floating card: 16 device px in from the column's top, right and bottom\n edges; a 12px corner (measured off the fill: the curve is 20 device px at\n @2x from its first inset pixel to the straight edge, plus the 1px outline);\n a 32px header strip whose 24px tab mark sits 4px under the card's top; and\n an 8px pane gutter (16 device px), which is where the Files pane's own row\n line begins. */\n --ccd-right-panel-inset: 8px;\n --ccd-right-panel-radius: var(--ccd-radius-panel);\n --ccd-right-panel-strip-height: 32px;\n --ccd-right-panel-gutter: 8px;\n --ccd-right-panel-gap: 12px;\n /* The tab's own mark, measured off the reference: a 24px square (5px corner,\n carried by the chip radius) tinted #d3e2f9 behind the 16px glyph. */\n --ccd-right-panel-glyph-size: 24px;\n /* Files tree. The reference's rows run on a 24px pitch (48 device px at @2x)\n where the host's 13px/1.5 row draws 29.5px, and its pane header is the\n 26px rounded field over them. */\n --ccd-files-row-height: 24px;\n --ccd-files-field-height: 26px;\n --ccd-files-glyph-size: 16px;\n\n /* Claude Desktop 2.31226.1's active flat frame, confirmed by window capture:\n gray-10 canvas; sidebar mixes gray-20 and gray-10 equally in sRGB. */\n --ccd-canvas: #fcfcfb;\n --ccd-sidebar: #fbfbf9;\n --ccd-card: #ffffff;\n /* Segmented-control track. The reference measures #f6f6f4 against a white\n page; the same step down from this canvas keeps the same contrast. */\n --ccd-track: #f3f3f2;\n --ccd-raised: #f0f0ef;\n --ccd-hover: #f0f0ee;\n /* Sampled from the supplied view-options reference, separate from the\n warmer surfaces used by Composer and the host's other menus. */\n --ccd-view-menu-hover: #f5f5f5;\n --ccd-view-menu-text: #0b0b0b;\n --ccd-view-menu-muted: #9b9994;\n --ccd-view-menu-border: #d7d7d6;\n --ccd-view-menu-separator: #ebebeb;\n --ccd-view-menu-accent: #2a78d6;\n --ccd-view-menu-shadow: 0 1px 3px rgba(0, 0, 0, .08), 0 8px 20px rgba(0, 0, 0, .12), 0 16px 32px rgba(0, 0, 0, .06);\n --ccd-selected: #ecebe8;\n /* The fill a control takes while it sits on a row that is already filled:\n a Session row paints `--ccd-selected` under the pointer, so its \u22EE takes\n this one to stay a step below what it stands on. Sampled from the supplied\n reference at @2x, where that row measures #edece9 under the control's own\n #e1e0dd \u2014 the same 12/255 step, and the relationship `theme/palette.ts`\n derives for a configured canvas. */\n --ccd-hover-strong: #e1e0dd;\n /* The right panel's tab mark: the reference's own blue-tinted square,\n sampled at #d3e2f9 with the accent for its glyph. It is the one tinted seat\n in this plugin's surfaces, so it is stated rather than derived. */\n --ccd-right-panel-glyph-bg: #d3e2f9;\n /* The Files pane's own ink, sampled off the reference at @2x. Its tree names\n and its empty state's title measure #0b0b0b \u2014 a step below this palette's\n `--ccd-text`, the ink the rest of the interface draws \u2014 and its tab title\n measures #52514f, between `--ccd-text` and `--ccd-text-secondary`. The tab\n mark's glyph is the one blue that is not this palette's accent: the\n reference draws it #304e91 on the #d3e2f9 square. */\n --ccd-files-ink: #0b0b0b;\n --ccd-right-panel-tab-ink: #52514f;\n --ccd-files-chip-ink: #304e91;\n\n /* Lines */\n --ccd-border: #e3e3e1;\n --ccd-border-strong: #e0e0df;\n --ccd-border-soft: #ebebe9;\n /* The rule under a table head reads one step stronger than the card outline\n in the reference (#d9d9d9 against #e3e3e3). */\n --ccd-table-head-line: #d9d9d8;\n /* The right panel's card outline, sampled at #d7d7d6 \u2014 one step stronger than\n the row outline above and the same ink the menu cards' own border carries,\n which is what makes a floating panel and a menu read as one material. */\n --ccd-right-panel-border: #d7d7d6;\n --ccd-browser-canvas: #f7f7f7;\n --ccd-browser-dot: #d1d0ce;\n\n /* Scrollbar ink. The host paints the scrollbars themselves\n (`ui-theme/src/styles/scrollbar.css`: a 5px track and a pill thumb read\n from `--dsh-scrollbar-thumb`), and this interface keeps that geometry \u2014\n the transcript's stable gutter, the sidebar's\n `--dsh-session-list-scrollbar-width` padding and the dockkit panes are all\n measured against the host's own width \u2014 so these two tokens are the ink\n alone, bound in theme/scrollbars.css.\n The ink is near-black by decision rather than by measurement: the bar is\n 5px wide and carries no surface of its own, so none of this palette's\n surface steps \u2014 5% to 14% black \u2014 reads at that size, and the interface\n this one follows draws a dark scrollbar. Hover goes one step further down,\n the direction the host's own hover step takes. */\n --ccd-scrollbar-thumb: #333331;\n --ccd-scrollbar-thumb-hover: #171716;\n\n /* Text */\n --ccd-text: #1f1f1d;\n --ccd-text-secondary: #6f6f6a;\n --ccd-text-muted: #8f8f8a;\n --ccd-text-placeholder: #89877f;\n /* One step below full strength: a row that is not the current one. The\n reference paints its inactive navigation rows at #4a4a47 \u2014 between this\n palette's --ccd-text and --ccd-text-secondary \u2014 and keeps the current row\n at full black, so the stack reads as one current entry plus quieter\n neighbours instead of three equally loud labels. */\n --ccd-text-nav: #4a4a47;\n /* Archived Session row. The host fades that title with its own caption ink,\n but this plugin's row ink outranks the host pair, so the state needs a step\n of its own: one above --ccd-text-muted on the same warm ramp, which is the\n faded row the reference draws while still reading against the sidebar. A row\n that is current or under the pointer takes the second value, because the\n hover and selected fills sit a step below the sidebar the first one was\n measured on. */\n --ccd-text-archived: #a0a09b;\n --ccd-text-archived-hover: #8a8a85;\n\n /* New-session statistics card. The reference panel is a stacked translucent\n grey: the card is 5% black over the canvas and a stat tile (and an empty\n heat cell) is 10% black over the card, so these are the measured opaque\n equivalents. The four heat levels are the reference's own `hsl(217 70% L%)`\n with L = 72\uFF0F64\uFF0F56\uFF0F48, i.e. \"that day's value / the busiest day\" in four\n equal steps. */\n --ccd-stats-panel: #f0f0f0;\n --ccd-stats-tile: #dadada;\n /* The card header's active tab: the reference paints `fill-ghost-hover`, the\n same 5% black as the card itself, over the card \u2014 one step lighter than a\n stat tile. */\n --ccd-stats-tab: #e6e6e6;\n --ccd-stats-label: #898781;\n --ccd-stats-value: #0b0b0b;\n --ccd-stats-heat-1: hsl(217 70% 72%);\n --ccd-stats-heat-2: hsl(217 70% 64%);\n --ccd-stats-heat-3: hsl(217 70% 56%);\n --ccd-stats-heat-4: hsl(217 70% 48%);\n /* The `Models` view colours its bars and legend by rank:\n `hsl(217 70% min(88, 58 + 7n)%)`, which flattens into these six shades. */\n --ccd-stats-model-1: hsl(217 70% 58%);\n --ccd-stats-model-2: hsl(217 70% 65%);\n --ccd-stats-model-3: hsl(217 70% 72%);\n --ccd-stats-model-4: hsl(217 70% 79%);\n --ccd-stats-model-5: hsl(217 70% 86%);\n --ccd-stats-model-6: hsl(217 70% 88%);\n /* Tooltips are the reference's dark popup in both themes; on a dark panel it\n steps up to a mid grey so the box keeps its contrast. */\n --ccd-stats-tip-bg: #0c0c0c;\n --ccd-stats-tip-fg: #f7f7f5;\n\n /* Assistant Markdown palette matched to the CCD transcript reference. */\n --ccd-link: #2b61b5;\n --ccd-link-underline: #a7badd;\n --ccd-inline-code-text: #b63630;\n --ccd-inline-code-fill: #f1f1f0;\n --ccd-inline-code-border: #e2e2e0;\n\n /* Context meter. The host paints the ring's consumed arc with the same\n tertiary label grey as the percentage beside it, so the reading carries no\n weight. The accent blue is this plugin's one emphasis colour: taking it\n through `var()` lets the ring follow `--ccd-accent` the moment that token\n exists, and the fallback is the blue measured off the target arc\n (docs/issues/img/12-2.png), so the ring is never left grey meanwhile. The\n track underneath stays the host's `--dsw-alias-border-l3`, which\n theme/tokens.ts already overrides. */\n --ccd-context-ring-fill: var(--ccd-accent, #4b76ce);\n\n /* Context breakdown categories, sampled from the supplied reference's bar and\n swatches. Seven steps, in the order the panel and the bar draw them: the\n reference's own hues, which are deliberately outside this palette's blue\n ramp \u2014 a breakdown that reused one hue family would make five categories\n read as one. `--ccd-context-free` is both the free-space swatch and the\n bar's track, exactly as the reference draws them. */\n --ccd-context-mcp: #2a78d8;\n --ccd-context-tools: #e96a33;\n --ccd-context-system: #1ead7c;\n --ccd-context-skills: #eda105;\n --ccd-context-memory: #ea7ca4;\n /* The conversation's own row. The reference's crop happens to hold no\n messages at all \u2014 89k of its 9% reading is prompt, tools and skills \u2014 so\n this one is chosen rather than sampled: the same lightness and chroma as\n its neighbours, one hue family over, so it cannot be mistaken for the\n accent blue of MCP tools. */\n --ccd-context-messages: #8b6fd4;\n --ccd-context-buffer: #c2c0b8;\n --ccd-context-free: #eeeeee;\n\n /* The plugin's one emphasis blue: the selected check in every Menu surface,\n the context ring, and whatever else has to read as \"this one is chosen\".\n It is the blue measured off the reference check mark\n (docs/issues/img/01-3.png: the stroke's own pixels are #4b76d0/#507ad2, so\n the token takes the darker mode) and shares the stats heat ramp's hue\n family (hsl(217 \u2026)), which keeps every blue in the interface one voice. */\n --ccd-accent: #4b76ce;\n --ccd-hero-ripple-ink: #2477ac;\n\n /* State colours that DSH already owns semantics for. */\n --ccd-diff-added: #508c48;\n --ccd-diff-removed: #b33156;\n\n /* Type. The two fallback tails are what a configured family is prepended to\n (see theme/tokens.ts); with nothing configured the consuming variables keep\n the built-in stacks. Geist leads the interface tail because it is the\n upstream design Anthropic Sans was cut from; it is resolved from the system\n font list, so the tail degrades to the platform stack when it is not\n installed (assets/fonts/ ships the file for a local install only). */\n --ccd-font-fallback: Geist, -apple-system, BlinkMacSystemFont, \"SF Pro Text\", \"Helvetica Neue\",\n \"PingFang SC\", \"Hiragino Sans GB\", \"Microsoft YaHei\", sans-serif;\n --ccd-code-fallback: ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, monospace;\n --ccd-font-ui: var(--ccd-font-fallback);\n --ccd-font-code: var(--ccd-code-fallback);\n --ccd-font-size-body: 14px;\n --ccd-font-size-muted: 13px;\n /* Blank-session title. The reference's own type scale puts the greeting on\n `--cds-font-size-title` (1.25rem, ~20px) with a 25px leading at weight 400,\n which is a good deal quieter than the 26px this used to be. */\n --ccd-font-size-headline: 20px;\n /* Transcript headings. The reference's ladder sits one step under the host's\n (DSH draws h1/h2/h3 at 21/19/18px): its own crop measures a 19px h1 and a\n 16px h2 over the 14px body \u2014 27 and 23 device px of CJK ink against the\n 21-device-px body line at @2x \u2014 and the h2 is confirmed independently by\n the inline-code chip, whose 0.95em/1.2 rule this plugin already matches:\n it lands on the reference's 33 device px exactly at 16px. h3 has no crop of\n its own and takes the next step down. */\n --ccd-font-size-h1: 19px;\n --ccd-font-size-h2: 16px;\n --ccd-font-size-h3: 15px;\n /* Transcript leading. The host sets the assistant body at 14px/24px; the\n reference runs the same 14px on a 20px line. Its own window measures a\n 30.7-device-px pitch between two lines of a paragraph where this plugin's\n 24px draws 36.6, and both shots put their body's CJK ink at 20 device px\n with a 770px Composer at 1176 (1.53 device px per CSS px), so the two are\n read at one scale. The reference's paragraph-to-paragraph gap is 46 device\n px \u2014 this 20px line plus the 10px margin both sides already share. */\n --ccd-transcript-line-height: 20px;\n /* The one step up from the host's own 400: used where a control has to read\n as a chosen value rather than as chrome (model, reasoning effort). */\n --ccd-font-weight-strong: 600;\n\n /* Hand-drawn 16px marks matching the CCD interaction recording: return\n arrow and a small square in a ring. The host keeps its buttons, handlers\n and SVG state markers; these masks replace only their visible artwork. */\n --ccd-send-radius: 6px;\n --ccd-icon-send: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M12 4.5V8A2 2 0 0 1 10 10H3.5M6.5 7L3.5 10L6.5 13' stroke='black' stroke-width='1.25' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n --ccd-icon-stop: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='5.5' fill='none' stroke='black' stroke-width='1.25'/%3E%3Crect x='6' y='6' width='4' height='4' rx='.6' fill='black'/%3E%3C/svg%3E\");\n\n /* The header's three painted glyphs, taken from DSH 0.2.0-rc.2 shared\n artwork (MIT) so no host component is copied:\n - IconRightUpOutlineRegular (`ui-primitives/icons`) is the generic \"open\"\n glyph the native open-in-app control falls back to;\n - the terminal prompt is `ui-sidebar-terminal/TerminalIcon`'s own 16px\n geometry, the glyph that view's tab title draws;\n - the globe is `ui-primitives`' IconGlobeOutlineRegular, the glyph\n `ui-sidebar-browser` draws in its tab title.\n Masks let the host keep ownership of its buttons while the plugin supplies\n the artwork. */\n --ccd-icon-open: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M11.7256 2.77441C12.5538 2.77469 13.2256 3.44616 13.2256 4.27441V10.1416H12.2256V4.27441C12.2256 3.99844 12.0015 3.77469 11.7256 3.77441H5.7207V2.77441H11.7256Z' fill='black'/%3E%3Cpath d='M2.77441 13.2255L12.3756 3.62427' stroke='black'/%3E%3C/svg%3E\");\n --ccd-icon-terminal: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M3 4L7 8L3 12' stroke='black'/%3E%3Cpath d='M9 12H13' stroke='black'/%3E%3C/svg%3E\");\n --ccd-icon-browser: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M7.99986 14.0887C11.3626 14.0887 14.0886 11.3627 14.0886 7.99998C14.0886 4.63727 11.3626 1.91125 7.99986 1.91125C4.63715 1.91125 1.91113 4.63727 1.91113 7.99998C1.91113 11.3627 4.63715 14.0887 7.99986 14.0887Z' stroke='black'/%3E%3Cpath d='M2.34619 8H13.6538' stroke='black' stroke-linecap='square'/%3E%3Cpath d='M7.99976 14.0889C9.23509 14.0889 10.1743 11.3629 10.1743 8.00006C10.1743 4.63739 9.23509 1.91138 7.99976 1.91138' stroke='black'/%3E%3Cpath d='M7.99973 14.0889C6.76445 14.0889 5.8252 11.3629 5.8252 8.00006C5.8252 4.63739 6.76445 1.91138 7.99973 1.91138' stroke='black'/%3E%3C/svg%3E\");\n\n /* The session menu's own mark, stacked. The host draws\n `IconEllipsisOutlineRegular` (`ui-primitives`, MIT) as three 2px dots on one\n horizontal line \u2014 circles at (3, 8), (8, 8) and (13, 8) of a 16px box \u2014 and\n the reference stacks them, so this is that same geometry transposed to\n (8, 3), (8, 8) and (8, 13): one dot size, one 5-unit pitch, one 16px box,\n carried as a mask over the button's own `currentColor` so the host keeps its\n button and this interface supplies the mark. */\n --ccd-icon-more: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M8 4C8.55228 4 9 3.55228 9 3C9 2.44772 8.55228 2 8 2C7.44772 2 7 2.44772 7 3C7 3.55228 7.44772 4 8 4Z' fill='black'/%3E%3Cpath d='M8 9C8.55228 9 9 8.55228 9 8C9 7.44772 8.55228 7 8 7C7.44772 7 7 7.44772 7 8C7 8.55228 7.44772 9 8 9Z' fill='black'/%3E%3Cpath d='M8 14C8.55228 14 9 13.55228 9 13C9 12.44772 8.55228 12 8 12C7.44772 12 7 12.44772 7 13C7 13.55228 7.44772 14 8 14Z' fill='black'/%3E%3C/svg%3E\");\n\n /* A bare plus, the one glyph the reference repeats on every actionable row.\n It is DSH's own `IconPlusOutlineArtwork` geometry (ui-primitives, MIT): two\n 1px strokes across a 16px box, so the plugin can put the same mark on the\n Workspace header's add button and on a project row's create button without\n authoring artwork of its own. */\n --ccd-icon-plus: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M8 2V14' stroke='black'/%3E%3Cpath d='M2 8H14' stroke='black'/%3E%3C/svg%3E\");\n\n /* The workspace picker chip's leading mark. DSH switches that glyph with the\n chip's own state \u2014 `IconFolderOpenRegular` once a workspace is chosen, a\n closed folder while the chip only carries a placeholder \u2014 and the open one\n draws a slanted front panel over a translucent back panel, where the\n reference's button leads with one closed folder in either state. The\n geometry below is DSH's own `FolderCloseArtwork` (`ui-primitives`, MIT) on\n its 16-unit grid and 1px stroke, with the artwork's second path \u2014 the rule\n line across the body \u2014 left out: the reference draws the body empty, and\n the tab, the step and the four rounded corners are the whole of the mark. */\n --ccd-icon-folder: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M1.50439 3.11059C1.50439 2.55831 1.95211 2.1106 2.50439 2.1106H5.43389C5.67773 2.1106 5.91318 2.19969 6.09593 2.36113L7.71649 3.79265C7.89924 3.95409 8.1347 4.04319 8.3785 4.04319H13.4958C14.0481 4.04319 14.4958 4.4909 14.4958 5.04319V12.8894C14.4958 13.4417 14.0481 13.8894 13.4958 13.8894H2.50439C1.95211 13.8894 1.50439 13.4417 1.50439 12.8894V4.04319V3.11059Z' stroke='black'/%3E%3C/svg%3E\");\n\n /* The reference's disclosure mark is a 1px line chevron where the host draws a\n filled triangle; this is DSH's own `IconChevronRightOutlineArtwork` geometry\n (ui-primitives, MIT). It is painted over the host's mark slot, so the host's\n own `arrowOpen` state still drives the quarter turn. */\n --ccd-icon-chevron-right: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M6 12L9.29289 8.70711C9.68342 8.31658 9.68342 7.68342 9.29289 7.29289L6 4' stroke='black'/%3E%3C/svg%3E\");\n\n /* The Files tree's two file marks, measured off the reference at @2x: a page\n with its bottom-right corner folded, and the angle-bracket pair, each drawn\n 8\u20139px wide inside the 16px seat the host's own type glyphs occupy (the\n reference's names then start on the same 33px the row's own gap states).\n DSH classifies a file by name and extension too, but its set is a\n different one \u2014 `.gitignore` is a git file to the host and a plain page to\n the reference, `LICENSE` a page to both \u2014 so `right-panel.css` carries the\n reference's own split as an extension list rather than reading the host's. */\n --ccd-icon-file: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M5.5 4.5H10.5C11.0523 4.5 11.5 4.94772 11.5 5.5V8.5L8.5 11.5H5.5C4.94772 11.5 4.5 11.0523 4.5 10.5V5.5C4.5 4.94772 4.94772 4.5 5.5 4.5Z' stroke='black'/%3E%3Cpath d='M8.5 8.5H11.5L8.5 11.5' stroke='black'/%3E%3C/svg%3E\");\n --ccd-icon-file-code: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M6.2 5.2L4.2 8.05L6.2 10.9' stroke='black' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M9.8 5.2L11.8 8.05L9.8 10.9' stroke='black' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M9.4 4.6L6.6 11.4' stroke='black' stroke-linecap='round'/%3E%3C/svg%3E\");\n\n /* The Files tab's mark: the reference draws a three-row list \u2014 a bullet and a\n rule per row \u2014 12px of ink on the tab's own blue square, so the artwork is\n stated on the square's 24-unit grid. The square itself is a seat the tab\n sheet paints; this is only the ink that sits in it. */\n --ccd-icon-files-list: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='black'%3E%3Crect x='6' y='6.5' width='2' height='2' rx='.5'/%3E%3Crect x='9.5' y='6.5' width='8' height='2' rx='.5'/%3E%3Crect x='6' y='11' width='2' height='2' rx='.5'/%3E%3Crect x='9.5' y='11' width='8' height='2' rx='.5'/%3E%3Crect x='6' y='15.5' width='2' height='2' rx='.5'/%3E%3Crect x='9.5' y='15.5' width='8' height='2' rx='.5'/%3E%3C/g%3E%3C/svg%3E\");\n\n /* The Files pane's magnifier, for the filter field's leading seat and for the\n one control the pane's header adds: a lens and a handle, 13px of ink in the\n 16px box the field's own row draws, one 1px stroke like the marks around it. */\n --ccd-icon-search: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Ccircle cx='6.6' cy='6.6' r='4.6' stroke='black'/%3E%3Cpath d='M9.9 9.9L13.9 13.9' stroke='black' stroke-linecap='round'/%3E%3C/svg%3E\");\n\n /* The archived Session row's leading mark. The host deliberately leaves that\n 16px cell empty, so the plugin paints the same geometry itself: DSH's own\n `IconArchiveOutlineRegular` artwork (ui-primitives, MIT) \u2014 a lid, a body and\n a handle drawn with 1px strokes \u2014 carried as a mask like the marks around\n it, so no third-party asset or copied component enters the stylesheet. */\n --ccd-icon-archive: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none'%3E%3Cpath d='M13.5 2.5H2.5C1.94772 2.5 1.5 2.94772 1.5 3.5V4.5C1.5 5.05228 1.94772 5.5 2.5 5.5H13.5C14.0523 5.5 14.5 5.05228 14.5 4.5V3.5C14.5 2.94772 14.0523 2.5 13.5 2.5Z' stroke='black'/%3E%3Cpath d='M2.5 5.5V13.5C2.5 13.7652 2.60536 14.0196 2.79289 14.2071C2.98043 14.3946 3.23478 14.5 3.5 14.5H12.5C12.7652 14.5 13.0196 14.3946 13.2071 14.2071C13.3946 14.0196 13.5 13.7652 13.5 13.5V5.5' stroke='black'/%3E%3Cpath d='M6.5 9.5H9.5' stroke='black'/%3E%3C/svg%3E\");\n\n /* The idle Session row's leading ring. The host hands that cell to the\n plugin's `sidebar.session.row.leading` seat as soon as a row has no status\n of its own, and the running row's activity ring is `ui-primitives`'\n StateDot spinner: a 2-unit stroke on a 9.5-unit radius in a 24-unit box.\n The same circle is carried here as a mask, so the still mark and the\n spinning one are one geometry at the one 8px scale the stylesheet already\n gives the spinner \u2014 and the ring takes the cell's own `currentColor`\n (the host's `--dsw-alias-label-tertiary`, the spinner's ink) instead of an\n authored colour. */\n --ccd-icon-session-ring: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none'%3E%3Ccircle cx='12' cy='12' r='9.5' stroke='black' stroke-width='2'/%3E%3C/svg%3E\");\n\n /* The context ring's track, for the seat an empty session has to fill. The\n host's own `ContextMeter` returns nothing at all until the token meter knows\n a numerator and the context window, so the plugin draws that ring's track\n itself \u2014 the host's exact geometry from `ContextMeter.module.css`\n (viewBox 0 0 14 14, cx=cy=7, r=5.5, 2px stroke) carried as a mask, so the\n colour stays the host track token above. The consumed arc is not drawn: at\n 0% the host's own arc has no length either. */\n --ccd-icon-context-ring: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14' fill='none'%3E%3Ccircle cx='7' cy='7' r='5.5' stroke='black' stroke-width='2'/%3E%3C/svg%3E\");\n\n /* The Composer whale. DeepSeek's own mark is a blue whale with a pale belly,\n so the two inks are the brand pair rather than a derived palette step: the\n artwork only ever appears as this one mark. The dark side lifts the blue a\n step so it keeps its contrast on the dark canvas instead of sinking into\n it; the belly stays the light ink in both schemes, because it is what makes\n the silhouette read at 64px. */\n --ccd-pet-blue: #4d6bfe;\n --ccd-pet-light: #dfe6ff;\n\n /* Elevation */\n --ccd-shadow-card: 0 1px 2px rgb(0 0 0 / 4%);\n --ccd-shadow-segment: 0 1px 2px rgb(0 0 0 / 8%);\n /* The right panel's card, read off the reference's own edges: the canvas\n (252/255) sits at 243 half a pixel beside the card, 235 directly under it\n and back to 251 eight pixels out \u2014 a two-layer shadow, the near one for the\n edge and the far one for the falloff. */\n --ccd-right-panel-shadow: 0 1px 3px rgb(0 0 0 / 4%), 0 5px 14px rgb(0 0 0 / 8%);\n}\n\n/*\n * Host-token aliases belong on `body`, exactly where the host writes them.\n *\n * `--dsw-*` values are not in the document stylesheets: DSH's theme presenter\n * writes them, and this plugin's own overrides, as inline styles on `body`\n * (theme/tokens.ts). A custom property is resolved *where it is declared*, so an\n * alias of a host token declared on the root would reference a variable that is\n * not in scope there: it computes to the guaranteed-invalid value and inherits\n * as invalid into every subtree, and the rule consuming it falls back to\n * `transparent` rather than the host's colour. The empty-state context ring\n * (theme/composer.css, `.yhfFVG_dock::after`) vanished exactly that way.\n */\nhtml[data-dsh-ccd-style=\"true\"] body {\n /* Resolve on body so dark mode and configured palettes both participate. */\n --ccd-composer-focus-border: color-mix(in srgb, var(--ccd-card) 60%, var(--ccd-text-secondary));\n /* The empty state's ring draws the host's track alone. It stays the host's\n own track token (`ContextMeter.module.css` strokes `.y0jqnG_track` with\n `--dsw-alias-border-l3`, which theme/tokens.ts already retints), so an\n empty session shows the same hollow ring the host would draw at 0%. */\n --ccd-context-ring-track: var(--dsw-alias-border-l3);\n}\n\n/*\n * Dark palette.\n *\n * DSH's theme presenter writes `body[data-ds-dark-theme]` from the resolved\n * colour scheme (`@deepseek-ai/dsh-client-ui-theme` client styles, DSH\n * 0.2.0-rc.2), so the plugin follows the host's own switch instead of carrying a\n * second one. The block is a descendant of the root activation marker: the\n * variables land on `body`, cover every colour the light block declares, and\n * stay absent while the plugin is off.\n *\n * The warm-neutral family is kept rather than swapping in the host's bluish\n * greys: the same relationship holds in both schemes (canvas a touch lighter\n * than the sidebar, card the brightest surface), while the recessed steps\n * (track, raised, hover, selected) move *up* in lightness where the light\n * palette moves down, because on a dark canvas a surface reads as raised by\n * catching more light. Lines keep one visible step against the surfaces they\n * separate; text keeps the light palette's descending tone order.\n */\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-hero-ripple-ink: #4aabdb;\n /* The same flat frame uses gray-850 for the dark page and mixes it with\n 20% black for the sidebar. The control track stays below its raised thumb\n while both sit above the darker page. */\n --ccd-canvas: #151515;\n --ccd-sidebar: #111111;\n --ccd-card: #30302e;\n --ccd-header-menu-border: var(--ccd-border);\n --ccd-header-menu-separator: var(--ccd-border-soft);\n --ccd-header-menu-danger: #f08080;\n --ccd-menu-danger: #c04742;\n --ccd-menu-danger-ink: #ffffff;\n --ccd-header-trigger-hover: var(--ccd-hover);\n --ccd-header-project-fill: var(--ccd-track);\n --ccd-header-project-active: var(--ccd-selected);\n --ccd-track: #1f1e1d;\n --ccd-raised: #2f2f2d;\n --ccd-hover: #313130;\n --ccd-view-menu-hover: var(--ccd-selected);\n --ccd-view-menu-text: var(--ccd-text);\n --ccd-view-menu-muted: var(--ccd-text-muted);\n --ccd-view-menu-border: var(--ccd-border);\n --ccd-view-menu-separator: var(--ccd-border-soft);\n --ccd-view-menu-accent: var(--ccd-accent);\n --ccd-view-menu-shadow: 0 1px 3px rgba(0, 0, 0, .4), 0 8px 20px rgba(0, 0, 0, .3), 0 16px 32px rgba(0, 0, 0, .2);\n --ccd-selected: #3a3a37;\n /* The same step as the light side, in the direction this canvas recesses:\n the fill goes one step up from `selected` here \u2014 which happens to land on\n the strong-outline step below, a coincidence of the two ramps rather than\n the reason for the value. */\n --ccd-hover-strong: #474743;\n /* The tab mark's tint, dark side: the accent's own hue over this card, which\n is the #d3e2f9 relationship the light side measures, not its value. */\n --ccd-right-panel-glyph-bg: #2b3a55;\n /* The Files pane's inks go back to the palette's own ramp here: the reference\n is a light-mode capture, and its three sampled values are only meaningful\n as relationships (a step below the body ink, a step above the muted one and\n the accent's own hue) that this side already carries. */\n --ccd-files-ink: var(--ccd-text);\n --ccd-right-panel-tab-ink: var(--ccd-text);\n --ccd-files-chip-ink: var(--ccd-accent);\n\n /* Lines */\n --ccd-border: #3e3e3b;\n --ccd-border-strong: #474743;\n --ccd-border-soft: #343431;\n /* The head rule stays the one line drawn stronger than the card outline. */\n --ccd-table-head-line: #4a4a46;\n /* The card outline's dark side: one step above the row outline, as in the\n light palette. */\n --ccd-right-panel-border: #474743;\n --ccd-browser-canvas: #242423;\n --ccd-browser-dot: #454542;\n\n /* Scrollbar ink, dark side: on this canvas the bar is the one piece of the\n chrome that has to read as raised, so it sits above every surface step\n here and lightens on hover \u2014 the mirror of the light palette, whose ink\n sits below every surface and darkens. */\n --ccd-scrollbar-thumb: #5c5b57;\n --ccd-scrollbar-thumb-hover: #75746f;\n\n /* Text */\n --ccd-text: #f0efec;\n --ccd-text-secondary: #b4b1ab;\n --ccd-text-muted: #918f89;\n /* Same step down from full strength as the light palette: the dark ink sits\n the same distance below --ccd-text as #4a4a47 sits below #1f1f1d. */\n --ccd-text-nav: #d3d0ca;\n --ccd-text-placeholder: #8b8983;\n /* Archived rows, dark side: the same two steps below the row ink, kept\n readable against this sidebar and the selected fill that sits above it. */\n --ccd-text-archived: #82807c;\n --ccd-text-archived-hover: #a6a39c;\n\n /* Composer whale, dark side: the same mark, with the blue raised so it reads\n against this canvas; the belly keeps the light ink. */\n --ccd-pet-blue: #7b93ff;\n --ccd-pet-light: #e8ecff;\n\n /* Statistics card, dark side: the same stacked greys over this canvas, and\n the heat ramp raised one step so the steps stay visible on a dark panel. */\n --ccd-stats-panel: #2c2c2a;\n --ccd-stats-tile: #383835;\n --ccd-stats-tab: #3a3a37;\n --ccd-stats-label: #918f89;\n --ccd-stats-value: #f0efec;\n --ccd-stats-heat-1: hsl(217 62% 78%);\n --ccd-stats-heat-2: hsl(217 64% 70%);\n --ccd-stats-heat-3: hsl(217 66% 62%);\n --ccd-stats-heat-4: hsl(217 70% 54%);\n /* Model ramp, raised for the dark panel; six distinct steps, as the light\n theme's clamped ramp produces. */\n --ccd-stats-model-1: hsl(217 62% 70%);\n --ccd-stats-model-2: hsl(217 64% 75%);\n --ccd-stats-model-3: hsl(217 66% 80%);\n --ccd-stats-model-4: hsl(217 68% 84%);\n --ccd-stats-model-5: hsl(217 70% 87%);\n --ccd-stats-model-6: hsl(217 70% 89%);\n --ccd-stats-tip-bg: #454542;\n --ccd-stats-tip-fg: #f7f7f5;\n\n /* Assistant Markdown palette, lightened for a dark transcript. */\n --ccd-link: #86b0e8;\n --ccd-link-underline: #4a5c76;\n --ccd-inline-code-text: #f0918a;\n --ccd-inline-code-fill: #35332f;\n --ccd-inline-code-border: #454239;\n\n /* Context meter ring, dark side: the same hue as the light accent, one step\n up in lightness (55% \u2192 68%) and saturation so the arc keeps its blue on\n this canvas instead of greying into it. Same `var()` order as the light\n block. */\n --ccd-context-ring-fill: var(--ccd-accent, #789be3);\n\n /* Context breakdown categories, dark side. The reference ships one light\n crop, so these are derived the way the rest of this palette is: the same\n hue, raised in lightness by the step the statistics ramp and the accent\n take on this canvas, so five categories stay five colours instead of\n sinking into the card. The two greys are the exception \u2014 they are surfaces\n rather than inks, so the buffer steps down to a mid warm grey and the free\n track steps up off the card, which is what keeps the reserved block and the\n empty room apart at a glance. */\n --ccd-context-mcp: #5b9ae8;\n --ccd-context-tools: #f0885a;\n --ccd-context-system: #43c79b;\n --ccd-context-skills: #f0b93c;\n --ccd-context-memory: #ef93b5;\n --ccd-context-messages: #a58fe6;\n --ccd-context-buffer: #5f5b53;\n --ccd-context-free: #3f3f3b;\n\n /* The accent, dark side: the same hue and the same 55% \u2192 68% lightness step\n the statistics heat ramp takes on this canvas, so the check keeps its blue\n against the menu's surface instead of sinking into it. The hue is the\n reference's measured blue (220) rather than the ramp's 217, but the two sit\n in one family. */\n --ccd-accent: #789be3;\n\n /* State colours that DSH already owns semantics for. */\n --ccd-diff-added: #7cbd72;\n --ccd-diff-removed: #e08fae;\n\n /* Elevation reads as a shadow under the surface, not as a grey wash. */\n --ccd-shadow-card: 0 1px 2px rgb(0 0 0 / 40%);\n --ccd-shadow-segment: 0 1px 2px rgb(0 0 0 / 50%);\n --ccd-right-panel-shadow: 0 1px 2px rgb(0 0 0 / 35%), 0 4px 10px rgb(0 0 0 / 35%);\n}\n\n/* zanwei effort reference palette, MIT; canvas reads these theme values. */\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-effort-color-1: #8c73c9;\n --ccd-effort-color-2: #a17ec2;\n --ccd-effort-color-3: #5f5b58;\n --ccd-effort-color-4: #3f3b38;\n --ccd-effort-color-5: #77736f;\n --ccd-effort-color-6: #edeae8;\n --ccd-effort-color-7: #e0dbd6;\n --ccd-effort-color-8: #ffffff;\n --ccd-effort-color-9: rgba(76, 70, 65, 0.12);\n --ccd-effort-color-10: #2788d6;\n --ccd-effort-color-11: rgba(62, 56, 50, 0.05);\n --ccd-effort-color-12: rgba(62, 56, 50, 0.04);\n --ccd-effort-color-13: rgba(62, 56, 50, 0.06);\n --ccd-effort-color-14: #74706d;\n --ccd-effort-color-15: rgba(82, 76, 70, 0.055);\n --ccd-effort-color-16: rgba(76, 70, 65, 0.1);\n --ccd-effort-color-17: #34312f;\n --ccd-effort-color-18: rgba(35, 31, 29, 0.12);\n --ccd-effort-color-19: #fff;\n --ccd-effort-color-20: rgba(70, 64, 59, 0.035);\n --ccd-effort-color-21: #eeebe9;\n --ccd-effort-color-22: #ece9e7;\n --ccd-effort-color-23: #e2dce3;\n --ccd-effort-color-24: #d9d0df;\n --ccd-effort-color-25: #d0c1da;\n --ccd-effort-color-26: #cdbcd9;\n --ccd-effort-color-27: #cbbad8;\n --ccd-effort-color-28: #d5cadc;\n --ccd-effort-color-29: #c8b5d4;\n --ccd-effort-color-30: #bda6cc;\n --ccd-effort-color-31: #b59bc6;\n --ccd-effort-color-32: #b6b2af;\n --ccd-effort-color-33: rgba(76, 70, 65, 0.13);\n --ccd-effort-color-34: rgba(62, 56, 50, 0.08);\n --ccd-effort-color-35: rgba(62, 56, 50, 0.055);\n --ccd-effort-pixel-leftColor: 210, 206, 214;\n --ccd-effort-pixel-deepViolet: 156, 120, 192;\n --ccd-effort-pixel-deepMid: 156, 132, 192;\n --ccd-effort-pixel-midPurple: 168, 144, 204;\n --ccd-effort-pixel-softMid: 168, 156, 204;\n --ccd-effort-pixel-softLilac: 180, 168, 204;\n --ccd-effort-pixel-paleCool: 192, 180, 204;\n --ccd-effort-pixel-highlightColor: 216, 204, 228;\n --ccd-effort-pixel-peakColor: 232, 224, 242;\n}\n\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-effort-shadow: 0 1px 2px rgba(62, 56, 50, .05), 0 4px 10px rgba(62, 56, 50, .04), 0 12px 28px rgba(62, 56, 50, .06);\n}\n\n/*\n * The same reference field on the dark canvas: the purple ramp keeps its\n * left-to-right direction (neutral \u2192 violet) inside the dark range, the\n * neutrals flip so the panel is a card above the transcript, and the knob stays\n * the brightest thing on the track \u2014 its fill is also the tooltip's text\n * colour, so the two keep following one value.\n */\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-effort-color-1: #a48ede;\n --ccd-effort-color-2: #b294d3;\n --ccd-effort-color-3: #e7e4de;\n --ccd-effort-color-4: #f6f4f0;\n --ccd-effort-color-5: #a09b94;\n --ccd-effort-color-6: #3a3936;\n --ccd-effort-color-7: #4b4944;\n --ccd-effort-color-8: #2b2a28;\n --ccd-effort-color-9: rgba(255, 255, 255, 0.1);\n --ccd-effort-color-10: #4d93f8;\n --ccd-effort-color-11: rgba(0, 0, 0, 0.45);\n --ccd-effort-color-12: rgba(0, 0, 0, 0.35);\n --ccd-effort-color-13: rgba(0, 0, 0, 0.45);\n --ccd-effort-color-14: #b7b2aa;\n --ccd-effort-color-15: rgba(255, 255, 255, 0.06);\n --ccd-effort-color-16: rgba(255, 255, 255, 0.14);\n --ccd-effort-color-17: #3a3936;\n --ccd-effort-color-18: rgba(0, 0, 0, 0.5);\n --ccd-effort-color-19: #ece9e4;\n --ccd-effort-color-20: rgba(255, 255, 255, 0.04);\n --ccd-effort-color-21: #34332f;\n --ccd-effort-color-22: #373430;\n --ccd-effort-color-23: #3e3943;\n --ccd-effort-color-24: #463e51;\n --ccd-effort-color-25: #4f4560;\n --ccd-effort-color-26: #57496a;\n --ccd-effort-color-27: #5c4d71;\n --ccd-effort-color-28: #524667;\n --ccd-effort-color-29: #63527c;\n --ccd-effort-color-30: #6e5989;\n --ccd-effort-color-31: #786096;\n --ccd-effort-color-32: #6f6c66;\n --ccd-effort-color-33: rgba(255, 255, 255, 0.16);\n --ccd-effort-color-34: rgba(0, 0, 0, 0.4);\n --ccd-effort-color-35: rgba(0, 0, 0, 0.35);\n --ccd-effort-pixel-leftColor: 92, 88, 98;\n --ccd-effort-pixel-deepViolet: 150, 116, 196;\n --ccd-effort-pixel-deepMid: 150, 128, 196;\n --ccd-effort-pixel-midPurple: 162, 140, 204;\n --ccd-effort-pixel-softMid: 162, 152, 204;\n --ccd-effort-pixel-softLilac: 174, 164, 206;\n --ccd-effort-pixel-paleCool: 184, 174, 206;\n --ccd-effort-pixel-highlightColor: 200, 188, 224;\n --ccd-effort-pixel-peakColor: 214, 204, 236;\n --ccd-effort-shadow: 0 1px 2px rgba(0, 0, 0, .4), 0 4px 10px rgba(0, 0, 0, .3), 0 12px 28px rgba(0, 0, 0, .35);\n}\n\n/*\n * Chosen-value ink. The Composer's model name \u2014 in the tool row and in the menu\n * it opens \u2014 is the value that row exists to show, so it takes full black\n * instead of the warm near-black every other primary label uses; the dark\n * scheme keeps the same relationship with its own strongest ink, white. Neither\n * side is derived from a configured surface, so the pair is declared here\n * rather than in the scheme blocks above.\n */\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-text-strong: #000000;\n}\n\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-text-strong: #ffffff;\n}\n\n/*\n * Header icon ink.\n *\n * The conversation header's trailing cluster is icon-only \u2014 the native session\n * menu, the two views this plugin adds, the scheduled-tasks entry while it has\n * records, the collapsed right panel's re-entry control \u2014 and the reference\n * draws those marks at full strength where the host uses its secondary label\n * grey. Like the chosen-value ink above, this pair answers to no configured\n * surface, so it is declared here rather than in the scheme blocks: the pure\n * black the reference measured on the light canvas, and its mirror white on the\n * dark one, because a black mark would vanish into that canvas.\n *\n * What each state puts behind the mark stays the host's: a near-black wash at\n * 6-14% in the light scheme, a white one at 8-14% in the dark, and the button's\n * own dimmed opacity while it is disabled \u2014 so the ink never meets a fill of its\n * own lightness (see `header-actions.css`).\n */\nhtml[data-dsh-ccd-style=\"true\"] {\n --ccd-header-icon-color: #000000;\n}\n\nhtml[data-dsh-ccd-style=\"true\"] body[data-ds-dark-theme] {\n --ccd-header-icon-color: #ffffff;\n}\n\n/*\n * The selected check in every Menu surface.\n *\n * The host paints it with `--dsw-alias-label-primary` in the Menu primitive's\n * own `Menu.module.css` (`.check`), so the workspace picker, the permission\n * menu, the view-options menu and the session \u22EF menu all show the same\n * near-black mark \u2014 a selection reads no louder than the label beside it. One\n * rule recolours all of them, because they all come from that one primitive.\n * The model picker is not one of them: it is this plugin's own card, and the\n * block at the end of this file is the rule that reaches its mark.\n *\n * Only the colour changes: the mark keeps the host's 14px seat, its\n * `display: grid` centring, its row height and every hover fill. The class is\n * the one the shipped static web frontend gives that module (`_4ub78_`, whose\n * local names run `_check_4ub78_179`, `_item_4ub78_90`, \u2026), and that asset is\n * platform-independent \u2014 both installers carry the identical\n * `@deepseek-ai/dsh-web-frontend` dist \u2014 so it is the same name on Windows and\n * needs no second spelling in `host-builds.ts` (`host-dom.ts` records the same\n * prefix).\n *\n * The rule covers the seat and its artwork: the svg inherits through\n * `currentColor`, and naming it as well keeps the mark blue even if a future\n * build moves the colour onto the artwork instead of the seat.\n */\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] ._check_4ub78_179,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitem\"] ._check_4ub78_179,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] ._check_4ub78_179 svg,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitem\"] ._check_4ub78_179 svg {\n color: var(--ccd-accent);\n}\n\n/*\n * The selected mark in the model picker.\n *\n * The Composer's model seat is not the host's `ModelSelect`: this plugin's\n * `ModelControls` wins `conversation.input.model` (its registration carries\n * `priority: -10` while the host registers the same seat at the default 0, and\n * the slot chain takes the lowest priority that answers), and the card that\n * seat opens marks the chosen model with the text `\u2713` in the row's trailing\n * `span[aria-hidden=\"true\"]` (`features/model-controls/ModelControls.tsx`).\n * `features/model-controls/controls.css` paints that row `--ccd-text-strong`,\n * so the mark inherits full black \u2014 which is exactly what it did: it is\n * neither `._check_4ub78_179` nor an svg, so the Menu rule above cannot reach\n * it, and no `fill`/`stroke` override would either, because a text glyph is\n * painted by `color` alone.\n *\n * Only the ink changes: the row keeps its height, padding and hover, and the\n * artwork is named beside the seat so a later icon in the same seat stays\n * covered. The seat is reached two ways \u2014 the row's own selected state\n * (`aria-pressed`, which React writes as `\"true\"`/`\"false\"`) and the seat that\n * actually holds a glyph (`:not(:empty)`, because the unchosen rows render an\n * empty span) \u2014 so a later switch to `aria-checked` on a `menuitemradio` row\n * cannot silently return this mark to black.\n *\n * The host's own `ModelSelect` card is covered as well, for the path where\n * that seat is the one on screen: its `.check` seat holds an svg whose path\n * strokes `currentColor` (ui-primitives `IconCheckOutlineArtwork`), so the\n * same `color` reaches the artwork. `cl2Rlq_` is already in the prefix table\n * (`compat/host-dom.ts`), and the Windows build's `wq12jW_` spelling is what\n * `compat/dom.ts` substitutes when this sheet is mounted.\n */\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button[aria-pressed=\"true\"] > span[aria-hidden=\"true\"],\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button[aria-pressed=\"true\"] > span[aria-hidden=\"true\"] svg,\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button > span[aria-hidden=\"true\"]:not(:empty),\nhtml[data-dsh-ccd-style=\"true\"] .ccd-model-controls .ccd-model-options button > span[aria-hidden=\"true\"]:not(:empty) svg,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] .cl2Rlq_check,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitemradio\"] .cl2Rlq_check,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menu\"] .cl2Rlq_check svg,\nhtml[data-dsh-ccd-style=\"true\"] [role=\"menuitemradio\"] .cl2Rlq_check svg {\n color: var(--ccd-accent);\n}\n";
4442
4447
 
4443
4448
  // src/client/theme/mount.ts
4444
4449
  function mountTheme(environment, scope) {
@@ -5206,6 +5211,255 @@ function mountModelControls(ctx, environment, cleanup) {
5206
5211
  });
5207
5212
  }
5208
5213
 
5214
+ // src/client/compat/status-groups.ts
5215
+ function sessionGroup(status, running) {
5216
+ if (status?.pendingInteraction) return "input";
5217
+ return status?.running ?? running ? "working" : "ended";
5218
+ }
5219
+ var GROUPS = ["input", "working", "ended"];
5220
+ function mountStatusGroups(document2, ctx, showEmpty, report) {
5221
+ const status = ctx.uiSession?.sessionStatus;
5222
+ if (!status || !ctx.sessions?.list) return () => {
5223
+ };
5224
+ const host = hostSelectors(document2);
5225
+ const win = document2.defaultView;
5226
+ const motion = win.matchMedia("(prefers-reduced-motion: reduce)");
5227
+ const owned = /* @__PURE__ */ new Set();
5228
+ const saved = /* @__PURE__ */ new Map();
5229
+ const animations = /* @__PURE__ */ new Map();
5230
+ const orders = /* @__PURE__ */ new Map();
5231
+ let list = null;
5232
+ let queued = false;
5233
+ let disposed = false;
5234
+ const stopAnimations = () => {
5235
+ for (const animation of animations.values()) animation.cancel();
5236
+ animations.clear();
5237
+ };
5238
+ const restoreNode = (node, values) => {
5239
+ for (const [key, value] of values) {
5240
+ if (value === null) node.removeAttribute(key);
5241
+ else node.setAttribute(key, value);
5242
+ }
5243
+ const original = orders.get(node);
5244
+ if (original?.value) node.style.setProperty("--ccd-status-order", original.value, original.priority);
5245
+ else if (original) node.style.removeProperty("--ccd-status-order");
5246
+ orders.delete(node);
5247
+ };
5248
+ const remember = (node, key, value) => {
5249
+ let values = saved.get(node);
5250
+ if (!values) {
5251
+ values = /* @__PURE__ */ new Map();
5252
+ saved.set(node, values);
5253
+ }
5254
+ if (!values.has(key)) values.set(key, node.getAttribute(key));
5255
+ if (value === null) node.removeAttribute(key);
5256
+ else if (node.getAttribute(key) !== value) node.setAttribute(key, value);
5257
+ };
5258
+ const restore = () => {
5259
+ stopAnimations();
5260
+ for (const node of owned) node.remove();
5261
+ owned.clear();
5262
+ for (const [node, values] of saved) restoreNode(node, values);
5263
+ saved.clear();
5264
+ list = null;
5265
+ };
5266
+ const observer = new MutationObserver(() => schedule());
5267
+ const observe = () => observer.observe(document2.documentElement, {
5268
+ childList: true,
5269
+ subtree: true,
5270
+ attributes: true,
5271
+ attributeFilter: ["class", "lang", "data-row-key", "data-ccd-blank-session"]
5272
+ });
5273
+ const sync = () => {
5274
+ queued = false;
5275
+ if (disposed) return;
5276
+ observer.disconnect();
5277
+ try {
5278
+ const next = document2.querySelector(host.browserFlatList);
5279
+ if (next !== list) restore();
5280
+ if (!next) return;
5281
+ list = next;
5282
+ const catalog = ctx.sessions.list.getSnapshot();
5283
+ const statuses = status.getSnapshot();
5284
+ const childrenByParent = /* @__PURE__ */ new Map();
5285
+ for (const child of Object.values(catalog.byId)) {
5286
+ if (child.origin !== "subagent" || !child.parentId) continue;
5287
+ const children = childrenByParent.get(child.parentId) ?? [];
5288
+ children.push(child);
5289
+ childrenByParent.set(child.parentId, children);
5290
+ }
5291
+ const zh2 = document2.documentElement.lang.toLowerCase().startsWith("zh");
5292
+ const labels = zh2 ? ["\u9700\u8981\u8F93\u5165", "\u8FDB\u884C\u4E2D", "\u5DF2\u7ED3\u675F"] : ["Needs input", "Working", "Ended"];
5293
+ const rows = [...list.querySelectorAll('[data-row-key^="session:"]')].filter((row) => !row.hasAttribute("data-ccd-blank-session"));
5294
+ const before = new Map(rows.map((row) => [row, row.getBoundingClientRect()]));
5295
+ let layoutChanged = false;
5296
+ remember(list, "data-ccd-status-list", "");
5297
+ const counts = [0, 0, 0];
5298
+ const stride = (rows.length + 1) * 2;
5299
+ const ordered = [];
5300
+ for (const row of rows) {
5301
+ const id = row.dataset.rowKey.slice(8);
5302
+ const summary = catalog.byId[id];
5303
+ const children = childrenByParent.get(id) ?? [];
5304
+ const runningChild = children.some((child) => statuses.get(child.id)?.running ?? child.running);
5305
+ const ownStatus = statuses.get(id);
5306
+ const group = sessionGroup({
5307
+ ...ownStatus,
5308
+ running: (ownStatus?.running ?? summary?.running ?? false) || runningChild
5309
+ }, false);
5310
+ const index = GROUPS.indexOf(group);
5311
+ const order = index * stride + ++counts[index] * 2;
5312
+ if (row.dataset.ccdStatusOrder !== String(order)) layoutChanged = true;
5313
+ remember(row, "data-ccd-status-order", String(order));
5314
+ remember(row, "data-ccd-status-group", group);
5315
+ for (let parent = row.parentElement; parent && parent !== list; parent = parent.parentElement) {
5316
+ remember(parent, "data-ccd-status-wrapper", "");
5317
+ }
5318
+ if (!orders.has(row)) orders.set(row, {
5319
+ value: row.style.getPropertyValue("--ccd-status-order"),
5320
+ priority: row.style.getPropertyPriority("--ccd-status-order")
5321
+ });
5322
+ row.style.setProperty("--ccd-status-order", String(order));
5323
+ remember(row, "tabindex", "0");
5324
+ ordered.push(row);
5325
+ const childKey = `children:${id}`;
5326
+ let childBox = [...owned].find((node) => node.dataset.ccdStatusOwned === childKey);
5327
+ if (group === "working" && children.length) {
5328
+ if (!childBox) {
5329
+ layoutChanged = true;
5330
+ childBox = document2.createElement("div");
5331
+ childBox.className = "ccd-status-children";
5332
+ childBox.dataset.ccdStatusOwned = childKey;
5333
+ childBox.setAttribute("role", "group");
5334
+ owned.add(childBox);
5335
+ list.append(childBox);
5336
+ }
5337
+ childBox.style.order = String(order + 1);
5338
+ childBox.setAttribute("aria-label", zh2 ? "\u5B50\u4EFB\u52A1" : "Subagents");
5339
+ const signature = JSON.stringify(children.map((child) => [child.id, child.displayTitle, child.running]));
5340
+ if (childBox.dataset.signature !== signature) {
5341
+ layoutChanged = true;
5342
+ childBox.dataset.signature = signature;
5343
+ childBox.replaceChildren(...children.map((child) => {
5344
+ const button = document2.createElement("button");
5345
+ button.type = "button";
5346
+ button.textContent = child.displayTitle;
5347
+ button.title = child.displayTitle;
5348
+ button.addEventListener("click", () => ctx.uiWorkspace.openSession(child.id));
5349
+ return button;
5350
+ }));
5351
+ }
5352
+ } else if (childBox) {
5353
+ layoutChanged = true;
5354
+ owned.delete(childBox);
5355
+ childBox.remove();
5356
+ }
5357
+ }
5358
+ for (const [index, group] of GROUPS.entries()) {
5359
+ let heading = [...owned].find((node) => node.dataset.ccdStatusOwned === group);
5360
+ if (counts[index] || showEmpty) {
5361
+ if (!heading) {
5362
+ layoutChanged = true;
5363
+ heading = document2.createElement("div");
5364
+ heading.className = "ccd-status-heading";
5365
+ heading.dataset.ccdStatusOwned = group;
5366
+ heading.setAttribute("role", "presentation");
5367
+ owned.add(heading);
5368
+ list.append(heading);
5369
+ }
5370
+ heading.style.order = String(index * stride);
5371
+ if (heading.textContent !== labels[index]) heading.textContent = labels[index];
5372
+ } else if (heading) {
5373
+ layoutChanged = true;
5374
+ owned.delete(heading);
5375
+ heading.remove();
5376
+ }
5377
+ }
5378
+ const liveIds = new Set(rows.map((row) => `children:${row.dataset.rowKey.slice(8)}`));
5379
+ for (const node of owned) if (node.dataset.ccdStatusOwned?.startsWith("children:") && !liveIds.has(node.dataset.ccdStatusOwned)) {
5380
+ layoutChanged = true;
5381
+ node.remove();
5382
+ owned.delete(node);
5383
+ }
5384
+ if (layoutChanged) {
5385
+ stopAnimations();
5386
+ }
5387
+ if (layoutChanged && !motion.matches && !document2.hidden) for (const row of ordered) {
5388
+ const previous = before.get(row);
5389
+ const rect = row.getBoundingClientRect();
5390
+ const dy = previous.top - rect.top;
5391
+ if (!dy || !previous.height || typeof row.animate !== "function") continue;
5392
+ const animation = row.animate(
5393
+ [{ translate: `0 ${dy}px` }, { translate: "0 0" }],
5394
+ { duration: 260, easing: "cubic-bezier(.2,.8,.2,1)" }
5395
+ );
5396
+ animations.set(row, animation);
5397
+ animation.onfinish = () => {
5398
+ if (animations.get(row) === animation) animations.delete(row);
5399
+ };
5400
+ }
5401
+ for (const [node, values] of saved) if (!node.isConnected) {
5402
+ restoreNode(node, values);
5403
+ saved.delete(node);
5404
+ }
5405
+ } catch (error) {
5406
+ restore();
5407
+ report(error);
5408
+ } finally {
5409
+ if (!disposed) observe();
5410
+ }
5411
+ };
5412
+ function schedule() {
5413
+ if (queued || disposed) return;
5414
+ queued = true;
5415
+ queueMicrotask(sync);
5416
+ }
5417
+ const keydown = (event) => {
5418
+ const target = event.target;
5419
+ if (!list?.contains(target) || !target.matches("[data-ccd-status-order]")) return;
5420
+ const rows = [...list.querySelectorAll("[data-ccd-status-order]")].sort((a, b) => Number(a.dataset.ccdStatusOrder) - Number(b.dataset.ccdStatusOrder));
5421
+ const index = rows.indexOf(target);
5422
+ let next;
5423
+ if (event.key === "ArrowDown") next = rows[(index + 1) % rows.length];
5424
+ if (event.key === "ArrowUp") next = rows[(index - 1 + rows.length) % rows.length];
5425
+ if (event.key === "Home") next = rows[0];
5426
+ if (event.key === "End") next = rows.at(-1);
5427
+ if (next) {
5428
+ event.preventDefault();
5429
+ next.focus();
5430
+ }
5431
+ if (event.key === "Enter" || event.key === " ") {
5432
+ event.preventDefault();
5433
+ target.click();
5434
+ }
5435
+ };
5436
+ const drag = (event) => {
5437
+ if (list?.contains(event.target)) {
5438
+ event.preventDefault();
5439
+ event.stopPropagation();
5440
+ }
5441
+ };
5442
+ const offStatus = status.subscribe(schedule);
5443
+ const offList = ctx.sessions.list.subscribe(schedule);
5444
+ document2.addEventListener("keydown", keydown);
5445
+ document2.addEventListener("dragstart", drag, true);
5446
+ document2.addEventListener("visibilitychange", stopAnimations);
5447
+ motion.addEventListener?.("change", stopAnimations);
5448
+ observe();
5449
+ sync();
5450
+ return () => {
5451
+ disposed = true;
5452
+ observer.disconnect();
5453
+ offList();
5454
+ offStatus();
5455
+ document2.removeEventListener("keydown", keydown);
5456
+ document2.removeEventListener("dragstart", drag, true);
5457
+ document2.removeEventListener("visibilitychange", stopAnimations);
5458
+ motion.removeEventListener?.("change", stopAnimations);
5459
+ restore();
5460
+ };
5461
+ }
5462
+
5209
5463
  // src/client/compat/slots.ts
5210
5464
  var DSH_SLOTS = Object.freeze({
5211
5465
  sidebar: "sidebar",
@@ -5215,6 +5469,8 @@ var DSH_SLOTS = Object.freeze({
5215
5469
  conversation: "main.conversation",
5216
5470
  header: "conversation.header",
5217
5471
  sessionHeader: "conversation.session.header",
5472
+ /** Native subagent-catalog and agent-team entries occupy this list. */
5473
+ sessionHeaderActions: "conversation.session.header.actions",
5218
5474
  /** Trailing header seats: `utilities` is a list the native actions occupy too. */
5219
5475
  sessionHeaderUtilities: "conversation.session.header.utilities",
5220
5476
  sessionHeaderCorner: "conversation.session.header.corner",
@@ -5538,6 +5794,7 @@ var COPY = {
5538
5794
  zh: {
5539
5795
  viewOptions: "\u89C6\u56FE\u9009\u9879",
5540
5796
  status: "\u72B6\u6001",
5797
+ groupByStatus: "\u6309\u72B6\u6001",
5541
5798
  showEmptyGroups: "\u663E\u793A\u7A7A\u5206\u7EC4",
5542
5799
  clearFilters: "\u6E05\u9664\u7B5B\u9009",
5543
5800
  filters: ["\u6D3B\u8DC3", "\u5168\u90E8", "\u5DF2\u5F52\u6863"]
@@ -5545,6 +5802,7 @@ var COPY = {
5545
5802
  en: {
5546
5803
  viewOptions: "View options",
5547
5804
  status: "Status",
5805
+ groupByStatus: "By status",
5548
5806
  showEmptyGroups: "Show empty groups",
5549
5807
  clearFilters: "Clear filters",
5550
5808
  filters: ["Active", "All", "Archived"]
@@ -5604,7 +5862,9 @@ function Check() {
5604
5862
  function ViewOptionsCard({
5605
5863
  port,
5606
5864
  showEmptyGroups,
5607
- setShowEmptyGroups
5865
+ setShowEmptyGroups,
5866
+ groupByStatus = false,
5867
+ setGroupByStatus
5608
5868
  }) {
5609
5869
  const state = (0, import_react5.useSyncExternalStore)(port.subscribe, port.getSnapshot);
5610
5870
  const panel = (0, import_react5.useRef)(null);
@@ -5700,7 +5960,9 @@ function ViewOptionsCard({
5700
5960
  const choose = (group, host) => {
5701
5961
  setOpenRow(null);
5702
5962
  void port.choose(group, host).then((applied) => {
5703
- if (applied) port.close();
5963
+ if (!applied) return;
5964
+ if (group === 0 && groupByStatus) setGroupByStatus?.(false);
5965
+ port.close();
5704
5966
  });
5705
5967
  };
5706
5968
  const rows = () => {
@@ -5755,7 +6017,8 @@ function ViewOptionsCard({
5755
6017
  },
5756
6018
  children: [
5757
6019
  ROW_ORDER.map((index, position) => {
5758
- const group = groups[index];
6020
+ const nativeGroup = groups[index];
6021
+ const group = index === 0 && groupByStatus && nativeGroup ? { ...nativeGroup, selected: -1 } : nativeGroup;
5759
6022
  if (group === void 0) return null;
5760
6023
  const options = optionsOf(group, index, copy);
5761
6024
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react5.Fragment, { children: [
@@ -5795,12 +6058,12 @@ function ViewOptionsCard({
5795
6058
  },
5796
6059
  children: [
5797
6060
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "ccd-view-row-label", children: index === FILTER_GROUP ? copy.status : group.label }),
5798
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "ccd-view-row-value", children: valueOf(group, index, copy) }),
6061
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "ccd-view-row-value", children: index === 0 && groupByStatus ? copy.groupByStatus : valueOf(group, index, copy) }),
5799
6062
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chevron, {})
5800
6063
  ]
5801
6064
  }
5802
6065
  ),
5803
- openRow === index && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6066
+ openRow === index && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
5804
6067
  "div",
5805
6068
  {
5806
6069
  className: "ccd-view-submenu",
@@ -5812,31 +6075,61 @@ function ViewOptionsCard({
5812
6075
  onPointerLeave: () => {
5813
6076
  setOpenRow(null);
5814
6077
  },
5815
- children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
5816
- "button",
5817
- {
5818
- type: "button",
5819
- role: "menuitemradio",
5820
- "aria-checked": option.host === group.selected,
5821
- className: "ccd-view-row ccd-view-option",
5822
- "data-ccd-view-option": `${index}-${option.host}`,
5823
- onClick: () => {
5824
- choose(index, option.host);
5825
- },
5826
- onKeyDown: (event) => {
5827
- if (event.key === "ArrowLeft") {
5828
- event.preventDefault();
5829
- closeFlyout(index);
5830
- return;
5831
- }
6078
+ children: [
6079
+ index === 0 && setGroupByStatus && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
6080
+ "button",
6081
+ {
6082
+ type: "button",
6083
+ role: "menuitemradio",
6084
+ "aria-checked": groupByStatus,
6085
+ className: "ccd-view-row ccd-view-option",
6086
+ "data-ccd-view-option": "status",
6087
+ onClick: () => {
6088
+ void port.choose(0, 2).then((applied) => {
6089
+ if (applied) {
6090
+ setGroupByStatus(true);
6091
+ port.close();
6092
+ }
6093
+ });
6094
+ },
6095
+ onKeyDown: (event) => {
6096
+ if (event.key === "ArrowLeft") {
6097
+ event.preventDefault();
6098
+ closeFlyout(index);
6099
+ }
6100
+ },
6101
+ children: [
6102
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "ccd-view-row-label", children: copy.groupByStatus }),
6103
+ groupByStatus && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Check, {})
6104
+ ]
6105
+ }
6106
+ ),
6107
+ options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
6108
+ "button",
6109
+ {
6110
+ type: "button",
6111
+ role: "menuitemradio",
6112
+ "aria-checked": option.host === group.selected,
6113
+ className: "ccd-view-row ccd-view-option",
6114
+ "data-ccd-view-option": `${index}-${option.host}`,
6115
+ onClick: () => {
6116
+ choose(index, option.host);
6117
+ },
6118
+ onKeyDown: (event) => {
6119
+ if (event.key === "ArrowLeft") {
6120
+ event.preventDefault();
6121
+ closeFlyout(index);
6122
+ return;
6123
+ }
6124
+ },
6125
+ children: [
6126
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "ccd-view-row-label", children: option.label }),
6127
+ option.host === group.selected && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Check, {})
6128
+ ]
5832
6129
  },
5833
- children: [
5834
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "ccd-view-row-label", children: option.label }),
5835
- option.host === group.selected && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Check, {})
5836
- ]
5837
- },
5838
- option.host
5839
- ))
6130
+ option.host
6131
+ ))
6132
+ ]
5840
6133
  }
5841
6134
  )
5842
6135
  ] })
@@ -5921,6 +6214,15 @@ function mountViewOptions(ctx, environment, cleanup) {
5921
6214
  inject: () => ({
5922
6215
  port: driver.port,
5923
6216
  showEmptyGroups: environment.config.view.showEmptyGroups,
6217
+ groupByStatus: environment.config.view.groupByStatus,
6218
+ setGroupByStatus: (value) => {
6219
+ void form.mutate(
6220
+ [{ op: "set", path: ["view", "groupByStatus"], value }],
6221
+ form.getSnapshot().revision
6222
+ ).then((accepted) => {
6223
+ if (!accepted) environment.logger.error("view options: status grouping write was refused");
6224
+ }, (error) => environment.logger.error("view options: status grouping write failed", error));
6225
+ },
5924
6226
  setShowEmptyGroups: (value) => {
5925
6227
  void form.mutate(
5926
6228
  [{ op: "set", path: ["view", "showEmptyGroups"], value }],
@@ -5938,6 +6240,20 @@ function mountViewOptions(ctx, environment, cleanup) {
5938
6240
  cleanup.add(() => {
5939
6241
  void registration.dispose();
5940
6242
  });
6243
+ if (environment.config.view.groupByStatus) {
6244
+ let off = () => {
6245
+ };
6246
+ const ensureFlat = () => {
6247
+ const value = driver.settings.getSnapshot();
6248
+ if (!value) return;
6249
+ off();
6250
+ if (value.groups[0]?.selected !== 2) {
6251
+ void driver.port.choose(0, 2).catch((error) => environment.logger.error("view options: flat status body could not be selected", error));
6252
+ }
6253
+ };
6254
+ off = driver.settings.subscribe(ensureFlat);
6255
+ cleanup.add(() => off());
6256
+ }
5941
6257
  void driver.inspect().catch((error) => environment.logger.error("view options: preferences could not be read", error));
5942
6258
  return {
5943
6259
  settings: driver.settings,
@@ -7036,6 +7352,13 @@ html[data-dsh-ccd-style="true"] .ccd-pet-blank-seat {
7036
7352
  pointer-events: none;
7037
7353
  }
7038
7354
 
7355
+ /* The native hero creates a z-index: 1 stacking context, below shell.overlay
7356
+ * (20), where the pet lives. Lift the open menu's context above that layer;
7357
+ * raising the menu alone cannot escape its hero ancestor. */
7358
+ html[data-dsh-ccd-style="true"] .ST7X_W_composerHero:has([data-trigger-menu]) {
7359
+ z-index: 21;
7360
+ }
7361
+
7039
7362
  /* Hide when a row precedes Composer, except hero greeting and workspace chips.
7040
7363
  * The frame-wide seat uses a root :has() query to observe the Composer stack.
7041
7364
  * Selector sources: compat/host-dom.ts, composerStack/heroRoot/heroWorkspaceRow/composerRoot.
@@ -7588,6 +7911,10 @@ var zh = {
7588
7911
  "section.appearance": "\u5916\u89C2",
7589
7912
  "section.fonts": "\u5B57\u4F53",
7590
7913
  "section.view": "\u89C6\u56FE",
7914
+ "field.showHeaderSubagents": "\u663E\u793A\u9876\u680F\u5B50\u4EE3\u7406\u5165\u53E3",
7915
+ "hint.showHeaderSubagents": "\u663E\u793A\u4F1A\u8BDD\u9876\u680F\u7684\u5B50\u4EE3\u7406\u6570\u91CF\u4E0E\u5217\u8868\u5165\u53E3\uFF0C\u9ED8\u8BA4\u5173\u95ED\uFF1B\u5B50\u4EE3\u7406\u8FD0\u884C\u4E0E\u4FA7\u680F\u6811\u4E0D\u53D7\u5F71\u54CD",
7916
+ "field.showHeaderTeam": "\u663E\u793A\u9876\u680F\u56E2\u961F\u5165\u53E3",
7917
+ "hint.showHeaderTeam": "\u663E\u793A\u4F1A\u8BDD\u9876\u680F\u7684\u667A\u80FD\u4F53\u56E2\u961F\u5165\u53E3\uFF0C\u9ED8\u8BA4\u5173\u95ED\uFF1B\u56E2\u961F\u529F\u80FD\u4E0D\u53D7\u5F71\u54CD",
7591
7918
  "field.showEmptyGroups": "\u663E\u793A\u7A7A\u5206\u7EC4",
7592
7919
  "hint.showEmptyGroups": "\u5173\u6389\u65F6\u6CA1\u6709\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u533A\u4E0D\u518D\u663E\u793A\uFF1B\u89C6\u56FE\u9009\u9879\u83DC\u5355\u91CC\u7684\u540C\u4E00\u9879",
7593
7920
  "field.enabled": "\u542F\u7528 CCD \u98CE\u683C\u754C\u9762",
@@ -7638,6 +7965,10 @@ var en = {
7638
7965
  "section.appearance": "Appearance",
7639
7966
  "section.fonts": "Typefaces",
7640
7967
  "section.view": "View",
7968
+ "field.showHeaderSubagents": "Show header subagent entry",
7969
+ "hint.showHeaderSubagents": "Show the subagent count and list in the conversation header. Off by default; execution and the sidebar tree are unaffected.",
7970
+ "field.showHeaderTeam": "Show header team entry",
7971
+ "hint.showHeaderTeam": "Show Agent Teams in the conversation header. Off by default; team functionality is unaffected.",
7641
7972
  "field.showEmptyGroups": "Show empty groups",
7642
7973
  "hint.showEmptyGroups": "Off keeps a Workspace with no sessions out of the sidebar; the same switch the view-options menu carries",
7643
7974
  "field.enabled": "Enable the CCD interface",
@@ -7887,6 +8218,26 @@ function ConfigPage(props) {
7887
8218
  ] }),
7888
8219
  /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "ccd-settings-section", children: [
7889
8220
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h4", { className: "ccd-settings-title", children: translate("section.view") }),
8221
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
8222
+ SwitchRow,
8223
+ {
8224
+ id: "ccd-settings-show-header-subagents",
8225
+ label: translate("field.showHeaderSubagents"),
8226
+ hint: translate("hint.showHeaderSubagents"),
8227
+ checked: served.view.showHeaderSubagents,
8228
+ onChange: (value) => void write([setOperation(["view", "showHeaderSubagents"], value)])
8229
+ }
8230
+ ),
8231
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
8232
+ SwitchRow,
8233
+ {
8234
+ id: "ccd-settings-show-header-team",
8235
+ label: translate("field.showHeaderTeam"),
8236
+ hint: translate("hint.showHeaderTeam"),
8237
+ checked: served.view.showHeaderTeam,
8238
+ onChange: (value) => void write([setOperation(["view", "showHeaderTeam"], value)])
8239
+ }
8240
+ ),
7890
8241
  /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
7891
8242
  SwitchRow,
7892
8243
  {
@@ -10883,6 +11234,108 @@ html[data-dsh-ccd-style="true"] [data-menu-material] [data-ccd-sidebar-session-s
10883
11234
  font-size: 12px;
10884
11235
  line-height: 20px;
10885
11236
  }
11237
+
11238
+ /* Status view reuses the flat list's native rows and all their actions. */
11239
+ html[data-dsh-ccd-style="true"] [data-ccd-status-list] {
11240
+ display: flex;
11241
+ flex-direction: column;
11242
+ gap: 0;
11243
+ reading-flow: flex-visual;
11244
+ }
11245
+ /* The host's sibling margins follow DOM order, while these rows use visual
11246
+ order. Keep the row rhythm independent of where React mounted a wrapper. */
11247
+ html[data-dsh-ccd-style="true"] [data-ccd-status-list] > * {
11248
+ margin-block: 0;
11249
+ }
11250
+ html[data-dsh-ccd-style="true"] [data-ccd-status-wrapper] {
11251
+ display: contents;
11252
+ }
11253
+ html[data-dsh-ccd-style="true"] [data-ccd-status-order] {
11254
+ order: var(--ccd-status-order);
11255
+ flex-shrink: 0;
11256
+ box-sizing: border-box;
11257
+ min-width: 0;
11258
+ max-width: 100%;
11259
+ margin-block: 0;
11260
+ padding-inline-start: 8px;
11261
+ }
11262
+ html[data-dsh-ccd-style="true"] [data-ccd-status-order] .jJkEga_title {
11263
+ min-width: 0;
11264
+ font-size: var(--ccd-font-size-muted);
11265
+ line-height: 20px;
11266
+ overflow: hidden;
11267
+ text-overflow: ellipsis;
11268
+ white-space: nowrap;
11269
+ }
11270
+ /* Reserve the native overflow button's seat so hovering a long title does not
11271
+ change its measure. Focusing the row also exposes its real menu control. */
11272
+ html[data-dsh-ccd-style="true"] [data-ccd-status-order] .jJkEga_rowActions {
11273
+ display: inline-flex;
11274
+ visibility: hidden;
11275
+ }
11276
+ html[data-dsh-ccd-style="true"] [data-ccd-status-order]:is(:hover, :focus-within, .jJkEga_menuOpen) .jJkEga_rowActions {
11277
+ visibility: visible;
11278
+ }
11279
+ html[data-dsh-ccd-style="true"] .ccd-status-heading {
11280
+ flex: none;
11281
+ /* Native titles start after the 8px inset, 16px status seat and 4px gap. */
11282
+ padding: 18px 8px 6px 28px;
11283
+ color: var(--ccd-text);
11284
+ font-size: var(--ccd-font-size-muted);
11285
+ font-weight: 500;
11286
+ line-height: 20px;
11287
+ }
11288
+ html[data-dsh-ccd-style="true"] .ccd-status-children {
11289
+ flex: none;
11290
+ min-width: 0;
11291
+ /* Leave the stem inside the button's rounded clipping edge, at title x=28. */
11292
+ margin: 0 0 6px 22px;
11293
+ }
11294
+ html[data-dsh-ccd-style="true"] .ccd-status-children > button {
11295
+ position: relative;
11296
+ box-sizing: border-box;
11297
+ display: block;
11298
+ width: 100%;
11299
+ min-width: 0;
11300
+ height: 28px;
11301
+ border: 0;
11302
+ border-radius: 6px;
11303
+ padding: 4px 8px 4px 22px;
11304
+ background: transparent;
11305
+ color: var(--ccd-text-secondary);
11306
+ font: inherit;
11307
+ font-size: var(--ccd-font-size-muted);
11308
+ line-height: 20px;
11309
+ text-align: left;
11310
+ overflow: hidden;
11311
+ text-overflow: ellipsis;
11312
+ white-space: nowrap;
11313
+ cursor: pointer;
11314
+ }
11315
+ /* A continuous stem ends at the last label's row-centred elbow. Keeping
11316
+ each segment on its row also handles a single child without extra markers. */
11317
+ html[data-dsh-ccd-style="true"] .ccd-status-children > button::before {
11318
+ content: "";
11319
+ position: absolute;
11320
+ inset: 0 auto 0 6px;
11321
+ border-inline-start: 1px solid var(--ccd-border);
11322
+ pointer-events: none;
11323
+ }
11324
+ html[data-dsh-ccd-style="true"] .ccd-status-children > button:last-child::before {
11325
+ bottom: auto;
11326
+ width: 9px;
11327
+ height: 14px;
11328
+ border-bottom: 1px solid var(--ccd-border);
11329
+ border-end-start-radius: 3px;
11330
+ }
11331
+ html[data-dsh-ccd-style="true"] .ccd-status-children button:hover {
11332
+ background: var(--ccd-hover);
11333
+ color: var(--ccd-text);
11334
+ }
11335
+ html[data-dsh-ccd-style="true"] :is(.ccd-status-children button, [data-ccd-status-order]):focus-visible {
11336
+ outline: 1px solid var(--ccd-accent);
11337
+ outline-offset: -1px;
11338
+ }
10886
11339
  `;
10887
11340
 
10888
11341
  // src/client/features/sidebar/navigation.css
@@ -10931,10 +11384,263 @@ var sidebarFeature = {
10931
11384
  }
10932
11385
  };
10933
11386
 
11387
+ // src/client/contracts/hero-canvas.ts
11388
+ var HERO_RIPPLE_DURATION = 2800;
11389
+
11390
+ // src/client/compat/hero-canvas.ts
11391
+ function mountHeroCanvas(document2, draw, report) {
11392
+ const win = document2.defaultView;
11393
+ const host = hostSelectors(document2);
11394
+ const reduced = win.matchMedia("(prefers-reduced-motion: reduce)");
11395
+ let root = null;
11396
+ let canvas = null;
11397
+ let frame = 0;
11398
+ let last = 0;
11399
+ let elapsed = 0;
11400
+ let impulses = [];
11401
+ let disposed = false;
11402
+ const stop = () => {
11403
+ win.cancelAnimationFrame(frame);
11404
+ frame = 0;
11405
+ last = 0;
11406
+ };
11407
+ const resize = new ResizeObserver(() => {
11408
+ if (!canvas || !root) return;
11409
+ const ratio = Math.min(win.devicePixelRatio || 1, 2);
11410
+ const rect = root.getBoundingClientRect();
11411
+ canvas.width = Math.round(rect.width * ratio);
11412
+ canvas.height = Math.round(rect.height * ratio);
11413
+ sync();
11414
+ });
11415
+ const tick = (time) => {
11416
+ frame = 0;
11417
+ if (!canvas || disposed) return;
11418
+ if (!last || time - last >= 1e3 / 24) {
11419
+ if (last) elapsed += time - last;
11420
+ last = time;
11421
+ impulses = impulses.filter((impulse) => elapsed - impulse.startedAt < HERO_RIPPLE_DURATION);
11422
+ try {
11423
+ draw(canvas, elapsed, impulses);
11424
+ } catch (error) {
11425
+ stop();
11426
+ report(error);
11427
+ return;
11428
+ }
11429
+ }
11430
+ frame = win.requestAnimationFrame(tick);
11431
+ };
11432
+ function sync() {
11433
+ if (disposed) return;
11434
+ const next = document2.querySelector(`${host.conversationRoot}[data-phase="hero"]`);
11435
+ if (next !== root) {
11436
+ stop();
11437
+ resize.disconnect();
11438
+ canvas?.remove();
11439
+ root = next;
11440
+ canvas = null;
11441
+ elapsed = 0;
11442
+ impulses = [];
11443
+ if (root) {
11444
+ canvas = document2.createElement("canvas");
11445
+ canvas.className = "ccd-hero-ripples";
11446
+ canvas.setAttribute("aria-hidden", "true");
11447
+ root.prepend(canvas);
11448
+ resize.observe(root);
11449
+ }
11450
+ }
11451
+ if (!canvas || !root || !canvas.width || !canvas.height || document2.hidden || reduced.matches || !root.getClientRects().length) {
11452
+ stop();
11453
+ impulses = [];
11454
+ if (canvas) canvas.hidden = true;
11455
+ return;
11456
+ }
11457
+ canvas.hidden = false;
11458
+ if (!frame) {
11459
+ last = 0;
11460
+ frame = win.requestAnimationFrame(tick);
11461
+ }
11462
+ }
11463
+ const click = (event) => {
11464
+ if (disposed || !root || !canvas || canvas.hidden || reduced.matches || document2.hidden || event.defaultPrevented || event.button !== 0 || event.detail === 0) return;
11465
+ const target = event.target;
11466
+ if (!target || !root.contains(target) || typeof target.closest !== "function") return;
11467
+ if (target.closest(`a, button, input, textarea, select, summary, label,
11468
+ [contenteditable]:not([contenteditable="false"]), [role="button"], [role="tab"],
11469
+ [role="slider"], [role="menu"], [role="dialog"], [data-menu-material],
11470
+ ${host.composerCard}, ${host.conversationHeader}`)) return;
11471
+ const rect = canvas.getBoundingClientRect();
11472
+ if (!rect.width || !rect.height || event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) return;
11473
+ if (impulses.some((impulse) => elapsed - impulse.startedAt < HERO_RIPPLE_DURATION)) return;
11474
+ impulses = [{
11475
+ x: (event.clientX - rect.left) / rect.width,
11476
+ y: (event.clientY - rect.top) / rect.height,
11477
+ startedAt: elapsed
11478
+ }];
11479
+ };
11480
+ const observer = new MutationObserver(sync);
11481
+ observer.observe(document2.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["data-phase"] });
11482
+ document2.addEventListener("visibilitychange", sync);
11483
+ document2.addEventListener("click", click, { passive: true });
11484
+ reduced.addEventListener("change", sync);
11485
+ win.addEventListener("resize", sync);
11486
+ sync();
11487
+ return () => {
11488
+ disposed = true;
11489
+ stop();
11490
+ observer.disconnect();
11491
+ resize.disconnect();
11492
+ canvas?.remove();
11493
+ document2.removeEventListener("visibilitychange", sync);
11494
+ document2.removeEventListener("click", click);
11495
+ reduced.removeEventListener("change", sync);
11496
+ win.removeEventListener("resize", sync);
11497
+ root = null;
11498
+ canvas = null;
11499
+ impulses = [];
11500
+ };
11501
+ }
11502
+
11503
+ // src/client/features/new-session/ripples.ts
11504
+ var GLYPHS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
11505
+ var TAU = Math.PI * 2;
11506
+ var clamp3 = (value) => Math.max(0, Math.min(1, value));
11507
+ var smooth = (from, to, value) => {
11508
+ const t = clamp3((value - from) / (to - from));
11509
+ return t * t * (3 - 2 * t);
11510
+ };
11511
+ var mix2 = (a, b, t) => a + (b - a) * t;
11512
+ function hash(x, y) {
11513
+ let value = Math.imul(x, 374761393) ^ Math.imul(y, 668265263);
11514
+ value = Math.imul(value ^ value >>> 13, 1274126177);
11515
+ return ((value ^ value >>> 16) >>> 0) / 4294967296;
11516
+ }
11517
+ function noise(x, y) {
11518
+ const ix = Math.floor(x), iy = Math.floor(y);
11519
+ const fx = x - ix, fy = y - iy;
11520
+ const sx = fx * fx * fx * (fx * (fx * 6 - 15) + 10);
11521
+ const sy = fy * fy * fy * (fy * (fy * 6 - 15) + 10);
11522
+ return mix2(
11523
+ mix2(hash(ix, iy), hash(ix + 1, iy), sx),
11524
+ mix2(hash(ix, iy + 1), hash(ix + 1, iy + 1), sx),
11525
+ sy
11526
+ ) * 2 - 1;
11527
+ }
11528
+ function frameAt(elapsed, width, height) {
11529
+ const period = 12800;
11530
+ const cycle = Math.floor(elapsed / period);
11531
+ const age = elapsed % period / 1e3;
11532
+ return {
11533
+ time: age,
11534
+ scale: Math.max(320, Math.min(width, height, 900)),
11535
+ offsetX: hash(cycle, 17) * 13,
11536
+ offsetY: hash(cycle, 43) * 13,
11537
+ phase: hash(cycle, 71) * TAU,
11538
+ strength: smooth(1.8, 3.8, age) * (1 - smooth(6.4, 10.6, age))
11539
+ };
11540
+ }
11541
+ function fieldAt(x, y, frame) {
11542
+ const { time: t, scale, phase, offsetX, offsetY, strength } = frame;
11543
+ if (strength === 0) return 0;
11544
+ const nx = x / scale, ny = y / scale;
11545
+ const u = nx + 0.27 * noise(nx * 2 + offsetX + t * 0.08, ny * 2 - t * 0.11) + 0.065 * Math.sin(ny * 5.1 + t * 0.43 + phase);
11546
+ const v = ny + 0.24 * noise(nx * 2.3 + 23 - t * 0.09, ny * 2 + offsetY + t * 0.07) + 0.055 * Math.sin(nx * 4.7 - t * 0.37);
11547
+ const distanceA = Math.hypot((u - 0.17) * 0.84, v - 0.62);
11548
+ const distanceB = Math.hypot(u - 1.1, (v + 0.18) * 0.78);
11549
+ const frontA = Math.sin(distanceA * 12.2 - t * 2.05 + phase);
11550
+ const frontB = Math.sin(distanceB * 10.6 - t * 1.53 - phase * 0.7);
11551
+ const cross = Math.sin(u * 5.8 + v * 4.3 + t * 0.71 + phase);
11552
+ const crest = smooth(0.12, 0.94, frontA * 0.65 + frontB * 0.43 + cross * 0.2);
11553
+ const secondary = smooth(0.48, 1, frontB * 0.7 - frontA * 0.3);
11554
+ const patches = 0.3 + 0.7 * smooth(
11555
+ -0.5,
11556
+ 0.55,
11557
+ noise(u * 3.3 + offsetX - t * 0.12, v * 3.3 + offsetY + t * 0.08)
11558
+ );
11559
+ return strength * (crest * 0.46 + secondary * 0.14) * patches;
11560
+ }
11561
+ function clickFieldAt(x, y, elapsed, width, height, impulses) {
11562
+ let light = 0;
11563
+ const scale = Math.max(320, Math.min(width, height, 900));
11564
+ for (const impulse of impulses) {
11565
+ const age = (elapsed - impulse.startedAt) / HERO_RIPPLE_DURATION;
11566
+ if (age < 0 || age >= 1) continue;
11567
+ const dx = (x - impulse.x * width) / scale, dy = (y - impulse.y * height) / scale;
11568
+ const seed = impulse.x * 7 + impulse.y * 11 + impulse.startedAt / 1e4;
11569
+ const growth = smooth(0, 0.2, age);
11570
+ const u = dx + growth * (0.18 * noise(dx * 3.2 + seed + age * 0.5, dy * 3.2 - age * 0.4) + 0.065 * Math.sin(dy * 5 + seed));
11571
+ const v = dy + growth * (0.16 * noise(dx * 3.1 + 23 - age * 0.5, dy * 3.1 + seed) + 0.06 * Math.sin(dx * 4.3 - seed));
11572
+ const distance = Math.hypot(u * 0.9, v * 1.08);
11573
+ const front = (distance - age * 1.25) / (0.075 + age * 0.055);
11574
+ const spread = Math.exp(-front * front);
11575
+ const texture = fieldAt(x, y, {
11576
+ time: 3 + age * 3.5,
11577
+ scale,
11578
+ offsetX: seed,
11579
+ offsetY: seed + 13,
11580
+ phase: seed * 1.7,
11581
+ strength: 1
11582
+ });
11583
+ const fade = smooth(0, 0.055, age) * (1 - smooth(0.12, 1, age));
11584
+ const contact = Math.exp(-(u * u + v * v) / 0.018) * (1 - smooth(0.035, 0.16, age)) * 0.32;
11585
+ light += (texture * spread * 1.6 + contact) * fade;
11586
+ }
11587
+ return light;
11588
+ }
11589
+ function characterAt(x, y, illumination, textureFade = 1) {
11590
+ const grain = hash(Math.floor(x / 6), Math.floor(y / 11));
11591
+ return {
11592
+ // Lift the moving light while keeping the quiet character texture subdued.
11593
+ alpha: Math.min(0.62, (0.012 + grain * 0.013) * textureFade + illumination * 1.35 * (0.45 + 0.55 * grain)),
11594
+ glyph: GLYPHS[Math.floor(grain * GLYPHS.length)]
11595
+ };
11596
+ }
11597
+ function drawHeroRipples(canvas, elapsed, impulses = []) {
11598
+ const context = canvas.getContext("2d");
11599
+ if (!context) return;
11600
+ const ratio = Math.min(canvas.ownerDocument.defaultView.devicePixelRatio || 1, 2);
11601
+ const width = canvas.width / ratio, height = canvas.height / ratio;
11602
+ context.setTransform(ratio, 0, 0, ratio, 0, 0);
11603
+ context.clearRect(0, 0, width, height);
11604
+ if (!width || !height) return;
11605
+ context.fillStyle = getComputedStyle(canvas).getPropertyValue("--ccd-hero-ripple-ink").trim();
11606
+ context.font = "8px monospace";
11607
+ context.textBaseline = "top";
11608
+ const frame = frameAt(elapsed, width, height);
11609
+ const fadeIn = smooth(0, 1.4, elapsed / 1e3);
11610
+ const step = 18;
11611
+ const columns = Math.ceil(width / step) + 1, rows = Math.ceil(height / step) + 1;
11612
+ const light = new Float32Array(columns * rows);
11613
+ for (let row = 0; row < rows; row++) for (let col = 0; col < columns; col++) {
11614
+ light[row * columns + col] = fieldAt(col * step, row * step, frame) * fadeIn + clickFieldAt(col * step, row * step, elapsed, width, height, impulses);
11615
+ }
11616
+ for (let y = 0; y < height; y += 11) {
11617
+ const row = Math.floor(y / step), fy = y / step - row;
11618
+ for (let x = 0; x < width; x += 6) {
11619
+ const col = Math.floor(x / step), fx = x / step - col;
11620
+ const index = row * columns + col;
11621
+ const illumination = mix2(
11622
+ mix2(light[index], light[index + 1], fx),
11623
+ mix2(light[index + columns], light[index + columns + 1], fx),
11624
+ fy
11625
+ );
11626
+ const cell = characterAt(x, y, illumination, fadeIn);
11627
+ const edge = Math.min(
11628
+ smooth(0, 55, x),
11629
+ smooth(0, 55, width - x),
11630
+ smooth(0, 45, y),
11631
+ smooth(0, 100, height - y)
11632
+ );
11633
+ context.globalAlpha = cell.alpha * edge;
11634
+ if (context.globalAlpha > 6e-3) context.fillText(cell.glyph, x, y);
11635
+ }
11636
+ }
11637
+ context.globalAlpha = 1;
11638
+ }
11639
+
10934
11640
  // src/client/features/new-session/new-session.css
10935
11641
  var new_session_default = `/*
10936
11642
  * Blank-session page: the reference keeps the Composer at the bottom edge with
10937
- * the workspace row directly above it, and DSH renders the greeting, that row
11643
+ * the workspace row below it, and DSH renders the greeting, that row
10938
11644
  * and the input bar as one block inside the Composer seat. This module moves
10939
11645
  * the block to the bottom and lifts the greeting out of it into the middle of
10940
11646
  * the page \u2014 the Composer element, its editor and every control stay exactly
@@ -11001,6 +11707,21 @@ html[data-dsh-ccd-style="true"] .ST7X_W_root[data-phase="hero"] .bocITq_previewB
11001
11707
  html[data-dsh-ccd-style="true"] .ST7X_W_root[data-phase="hero"] .ST7X_W_composerSeat {
11002
11708
  padding-bottom: 0;
11003
11709
  }
11710
+
11711
+ html[data-dsh-ccd-style="true"] .ST7X_W_root[data-phase="hero"] {
11712
+ isolation: isolate;
11713
+ }
11714
+ html[data-dsh-ccd-style="true"] .ccd-hero-ripples {
11715
+ position: absolute;
11716
+ inset: 0;
11717
+ z-index: -1;
11718
+ width: 100%;
11719
+ height: 100%;
11720
+ pointer-events: none;
11721
+ }
11722
+ @media (prefers-reduced-motion: reduce) {
11723
+ html[data-dsh-ccd-style="true"] .ccd-hero-ripples { display: none; }
11724
+ }
11004
11725
  `;
11005
11726
 
11006
11727
  // src/client/features/new-session/index.ts
@@ -11012,6 +11733,11 @@ var newSessionFeature = {
11012
11733
  const probe = probeHost(document);
11013
11734
  if (!probe.conversation) environment.logger.debug("new-session: conversation not mounted yet");
11014
11735
  scope.add(environment.dom.mountStyles(new_session_default));
11736
+ scope.add(mountHeroCanvas(
11737
+ document,
11738
+ drawHeroRipples,
11739
+ (error) => environment.logger.error("new-session: ripple background failed", error)
11740
+ ));
11015
11741
  }
11016
11742
  };
11017
11743
 
@@ -11299,6 +12025,23 @@ var VIEW_SWITCH_ICONS = Object.freeze({
11299
12025
  trajectory: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">\n <path d="M5.3 5.8 3.05 8l2.25 2.2"/>\n <path d="M9.1 3.8 6.9 12.2"/>\n <path d="M10.7 5.8 12.95 8l-2.25 2.2"/>\n</svg>'
11300
12026
  });
11301
12027
 
12028
+ // src/client/features/conversation/header-actions/visibility.ts
12029
+ var ENTRIES = [
12030
+ { field: "showHeaderSubagents", id: "subagent-catalog", order: -30 },
12031
+ { field: "showHeaderTeam", id: "agent-team", order: -20 }
12032
+ ];
12033
+ function mountHeaderVisibility(slots, view, cleanup) {
12034
+ for (const entry of ENTRIES) {
12035
+ if (view[entry.field]) continue;
12036
+ cleanup.add(slots.inject(DSH_SLOTS.sessionHeaderActions, () => slots.register({
12037
+ name: DSH_SLOTS.sessionHeaderActions,
12038
+ id: entry.id,
12039
+ order: entry.order,
12040
+ priority: OVERRIDE_PRIORITY
12041
+ }, () => null)));
12042
+ }
12043
+ }
12044
+
11302
12045
  // src/client/features/conversation/index.ts
11303
12046
  var conversationFeature = {
11304
12047
  id: "conversation",
@@ -11308,6 +12051,7 @@ var conversationFeature = {
11308
12051
  const probe = probeHost(document);
11309
12052
  if (!probe.conversation) environment.logger.debug("conversation: body not mounted yet");
11310
12053
  scope.add(environment.dom.mountStyles(conversation_default));
12054
+ mountHeaderVisibility(environment.host.slots, environment.config.view, scope);
11311
12055
  scope.add(mountViewSwitch(
11312
12056
  document,
11313
12057
  VIEW_SWITCH_ICONS,
@@ -12510,7 +13254,7 @@ var FEATURES = [
12510
13254
  toolCallsFeature,
12511
13255
  statisticsFeature
12512
13256
  ];
12513
- var inject = ["slots", "theme", "uiWorkspace", "configForms", "sessions", "workspaces"];
13257
+ var inject = ["slots", "theme", "uiWorkspace", "configForms", "sessions", "workspaces", "uiSession"];
12514
13258
  function apply(ctx) {
12515
13259
  if (typeof document === "undefined") return;
12516
13260
  ctx.effect(() => {
@@ -12606,6 +13350,14 @@ function apply(ctx) {
12606
13350
  }
12607
13351
  if (next.features.sidebar) {
12608
13352
  const view = mountViewOptions(ctx, environment, scope);
13353
+ if (next.view.groupByStatus) {
13354
+ scope.add(mountStatusGroups(
13355
+ document,
13356
+ ctx,
13357
+ next.view.showEmptyGroups,
13358
+ (error) => logger.error("sidebar: status grouping failed", error)
13359
+ ));
13360
+ }
12609
13361
  scope.add(mountBrowserHeader(
12610
13362
  document,
12611
13363
  (error) => logger.error("sidebar: browsing header observer failed", error)