export declare const LAYOUT_CSS = "/* ---------- mobile-only layout (narrow viewport AND touch-primary pointer) ---------- */\n\n@media (max-width: 1023px) and (pointer: coarse) {\n /* --- Phone chrome ---\n The system status bar stays visible (no fullscreen). Three adjustments\n make it behave:\n - touch-action: pan-y pinch-zoom kills double-tap-to-zoom (and the 300ms\n tap delay) while keeping vertical pan. Omitting pan-x (i.e. not using\n the manipulation alias) forbids HORIZONTAL pan on the root: a\n left-edge horizontal drag would otherwise be claimed by the browser as\n a pan (firing pointercancel) before the sidebar swipe layer can\n classify it. touch-action does not inherit and the behavior\n intersection stops at the first scroll container, so only touches\n landing directly on the root background are affected \u2014 inner\n horizontal scrolling of content containers is untouched. pinch-zoom is\n listed on purpose (#45): a bare pan-y also drops pinch, and then a\n zoom the browser applied by itself \u2014 iOS enlarges the viewport when a\n field under 16px takes focus \u2014 can no longer be undone by the user,\n so the app stays magnified until it is reopened or rotated. Two-finger\n zoom is also the WCAG 1.4.4 escape hatch and costs the gesture layer\n nothing: pinch is not a horizontal pan.\n - overscroll-behavior-x: none suppresses the browser's edge history\n navigation on the root scroller \u2014 Android Chrome claims a horizontal\n stroke that STARTS within its edge band (EDGE_WIDTH_DP=48dp,\n NavigationHandler.java) and navigates BACK, the exact gesture that\n opens the drawer (\"\u9875\u9762\u76F4\u63A5\u8FD4\u56DE\u4E0A\u4E00\u9875\", 2026-08-29 user report). Only\n html/body count for this (Chromium issue 41483088: inner containers\n are ignored by the navigation path). iOS Safari's edge back-swipe has\n no CSS opt-out (WebKit bug 240183) \u2014 there the widened gesture start\n zone (START_ZONE_RATIO 0.45 of the viewport width, ~176px at 390px,\n past every browser's edge-claim strip) is the mitigation.\n - With the client's viewport-fit=cover, env(safe-area-inset-top) is the\n status bar / notch height; the rules below push the app content below\n it so the status bar never covers anything. Off notched phones (or in\n a normal browser tab where the layout viewport already sits below the\n status bar) the inset is 0 and nothing shifts. */\n html,\n body {\n touch-action: pan-y pinch-zoom !important;\n overscroll-behavior-x: none !important;\n }\n\n /* AppFrame: the drawer takes the sidebar column out of grid flow, so the\n remaining in-flow items (center, details) land in tracks 1..2: give the\n center every pixel and keep the details track at zero. The top padding\n clears the status bar / notch for every in-flow surface (session header,\n messages, composer); the absolutely-positioned drawer is unaffected (its\n containing block is the frame's padding box, i.e. still the frame top).\n box-sizing MUST be border-box: the official frame is height:100% of a\n 100%-height body, and it is content-box by default, so the safe-area\n padding is ADDED on top of the full viewport height. The frame then grows\n to 100% + inset, the document itself becomes scrollable by exactly the\n inset, and the sticky composer seat (bottom:0 of the scroll body) lands\n below the visual viewport. Symptoms on a notched phone: the whole UI can\n be swiped up, the composer lifts off the bottom leaving a blank strip,\n and the newest message sits under the composer because the host's\n at-bottom follow scrolls its own scroll body, not the document. With\n border-box the padding is taken out of the 100% height instead, so the\n frame is exactly one viewport tall and the document never scrolls.\n\n The leading html element selector is load-bearing, not decoration: the\n third-party @linxin666/dsh-web-all sheet ships an equal-specificity\n !important grid-template-columns for this same element under\n (max-width: 768px), so without the extra element the winner is decided by\n which sheet happens to be injected later. Measured before and after with\n scripts/probes/cascade-conflict-probe.mjs: no computed value moves, the\n rule only stops depending on sheet order (audit D-5 option A). */\n html [data-mobile-nav=\"frame\"] {\n box-sizing: border-box !important;\n position: relative !important;\n grid-template-columns: minmax(0, 1fr) 0 0 !important;\n padding-top: env(safe-area-inset-top, 0px) !important;\n /* Bottom safe area, symmetric with the top inset above. It MUST stay in\n this rule: box-sizing: border-box is the pair that makes the padding eat\n into the one-viewport height instead of adding scrollable overflow\n (pitfalls \u00A7safe-area \u2014 padding without border-box pushes the composer\n seat below the fold).\n Why we have to own it: the third-party @linxin666 sheet (the same one\n the grid-template-columns note above is about) ships this padding only\n under (max-width: 768px), and the host ships none at all, so 769-1023px\n touch devices had no bottom inset from either side and their content sat\n in the system-bar band (issue #193). In the <=768px band that sheet's\n declaration and this one are the same property with the same value, so\n they do not stack. */\n padding-bottom: env(safe-area-inset-bottom, 0px) !important;\n }\n\n /* The sidebar column (first grid child) becomes a left drawer. The drawer\n hugs the sidebar content exactly (the wide sidebar carries an inline\n width, ~280px): a fixed 92vw box would leave a white strip where the\n container background shows beside the content.\n Closed state: translateX(-110%) \u2014 more than -100% of the max-content\n width \u2014 guarantees the whole drawer (and its shadow, had it one) leaves\n the viewport. A mere -100% leaves a sliver on screen; -105% (as used\n before) left 14px of the drawer plus a long 32px-blur shadow gradient\n visible along the left edge of the main UI. No box-shadow at all: the\n dimmed backdrop already separates drawer from content. */\n /* These legacy column rules stay armed on every host generation: the phone\n owner prefers this drawer over the official overlay one (2026-09-13). The\n host's own drawer ships NO full-screen backdrop, so the conversation beside\n it stays hit-testable - the rejection reason.\n Layering contract: this column is 1300 and the backdrop 1250 (base.css),\n both deliberately above the host's native sidebarCol at 1100. The earlier\n value of 40 sat BELOW that 1100: because this same rule also forces\n position/inset/width on the element, the column kept a correct-looking box\n while neither painting nor hit-testing, which is the \"all black, click\n anywhere closes\" root cause. The backdrop we append carries the dimming. */\n [data-mobile-nav=\"frame\"] > :first-child {\n position: absolute !important;\n inset: 0 auto 0 0 !important;\n /* !important is load-bearing: the host ships\n [data-dsh-frame] [data-pane=\"sidebar\"] { width: min(88vw, 320px) !important }\n under (max-width: 768px), which at 390px resolves to a flat 320px and\n BEATS a plain declaration here - measured: our max-content never applied\n and the column stayed 320px.\n 280 is the drawer's hard floor, measured by sweeping the column width from\n 304 down to 264: the inner surface is a FIXED 280px box and never\n reflows, so every pixel below 280 is simply clipped off its right edge\n (the list stays 270px at every width and its right edge sits at 278, so\n 270 and below cut into the list itself). At exactly 280 the panel is fully\n intact - only the 12px of its right-hand padding is given up - which is\n what the owner asked for over the previous 304. Going narrower is a\n one-line change, but it starts eating content. */\n width: min(88vw, 280px) !important;\n /* 1300 is a contract with base.css: the host pins its native sidebarCol at\n z-index:1100 and paints its mid layers up to that band, so the drawer must\n sit above the host stack AND above our own backdrop at 1250 (which dims\n the content area). At 40 the backdrop covered the drawer itself, so\n opening it showed a full-screen dim with no drawer (measured 2026-09-13\n at 390px: backdrop [0,0,390,844] z1250 over column [0,0,320,844] z40, and\n elementFromPoint(40,300) returned the backdrop). Keep in sync with the\n backdrop z in base.css. */\n z-index: 1300 !important;\n transform: translateX(-110%);\n transition: transform .28s var(--ds-ease-in-out, ease-in-out);\n /* Keep the drawer's own content below the status bar / notch: the drawer\n spans the full frame height (its absolute containing block is the\n frame's padding box, so the frame's own safe-area padding does NOT\n reach it). The drawer background paints the status-bar strip, which\n the client's theme-color meta matches, so the strip reads seamless. */\n padding-top: env(safe-area-inset-top, 0px) !important;\n /* Kill the official sidebarCol right border: with the backdrop the edge\n reads cleanly, and the settings dialog (width:100% of this box) stays\n pixel-flush with the drawer. */\n border-right: none !important;\n\n /* The drawer's inner surface is 280px wide while the column is 88vw/320px, so\n the remaining 40px showed our own column background as a vertical strip\n along the right edge (measured: content right edge 280, column 320; the\n owner reported a white bar). The inner surface owns that band instead, so\n the strip is filled by the drawer's real surface colour.\n That scenario cannot recur as the layout stands: the column is\n min(88vw, 280px), never wider than the 280px inner surface, so the\n inequality that produced the band (column > surface) no longer holds at any\n viewport width (measured 430/390/340/320 = flush at 280, 300 -> 264,\n 280 -> 246; a narrower column just crops the surface). The only change that\n would bring it back is raising the column's upper bound past 280px, or the\n host narrowing the inner surface below it. */\n /* The 40px band is a STACKING result, not a colour one: the drawer's inner\n surface is only 280px wide (host markup), while our column is 320px and\n carries z-index 1300 - so the column's own background paints OVER the\n surface's right 40px. Pixel-verified from a screenshot with the drawer open:\n x=10..270 rgb(249,250,251) (the surface) against x=285..315 rgb(255,255,255)\n (our white column). Repainting the column with the surface's own value makes\n the seam invisible.\n The value pinned here is the host's own drawer-fill token - the one\n .pI_x6G_sidebarCol paints with: --dsw-specific-sidebar-fill, i.e.\n --dsw-static-neutral-bluish-50 (#f9fafb) in light and\n --dsw-static-neutral-bluish-900 (#1b1b1c) in dark. Pinning it, rather than\n letting the host rule paint, keeps the band covered without depending on\n cascade order. The fallback is deliberately the token's LIGHT value: if the\n host ever renames this internal token the declaration degrades to today's\n light behaviour instead of going unset, so it cannot get worse. Do not\n \"simplify\" this back to --dsw-alias-bg-surface: that name is defined nowhere\n in the host, which froze this rule on its fallback and painted the drawer\n light in the dark theme (issue #192). */\n background: var(--dsw-specific-sidebar-fill, #f9fafb);\n /* Drawer swipe gestures (edge swipe-in / content swipe-out, see\n docs/specs/2026-08-27-sidebar-swipe-gestures.md).\n One rule is load-bearing for the gesture layer: dropping pan-x on the\n drawer lets horizontal pointermove events reach the gesture code \u2014\n WITHOUT it the browser treats a horizontal stroke as a pan, fires\n pointercancel and the gesture never classifies (vertical panning stays\n intact). Start-hit is decided purely by geometry on the document\n capture listener (START_ZONE_RATIO = 0.45 of the viewport width, ~176px\n at 390px); there is no hotspot element (removed per audit C2,\n 2026-08-27). pinch-zoom rides along with the\n root value so a browser-applied zoom stays undoable inside the drawer\n too (#45); touch-action intersects down the ancestor chain, so a bare\n pan-y here would cancel the root's pinch permission. */\n touch-action: pan-y pinch-zoom !important;\n }\n\n /* \u58C1\u7EB8\u517C\u5BB9\uFF08issue #228\uFF09\uFF1Adeepseek-harness-background 0.6.x \u5728\n body[data-dsh-bg] \u4E0A\u628A --dsw-specific-sidebar-fill \u7F6E\u4E3A transparent\uFF08body \u5185\u8054\uFF09\uFF0C\n \u800C\u62BD\u5C49\u5217\u4EE5\u8BE5\u4EE4\u724C\u4E3A\u552F\u4E00\u5E95\u8272\uFF1B\u4EE4\u724C\u5B58\u5728\u65F6 var() \u7684 fallback \u4E0D\u4F1A\u751F\u6548\uFF0C\u6574\u5217\n \u4E8E\u662F\u900F\u51FA\u58C1\u7EB8\u3002\u5BBF\u4E3B\u5185\u8868\u9762\uFF08sidebarCol\uFF09\u7528\u540C\u4E00\u4EE4\u724C\uFF0C\u4E5F\u900F\u660E\uFF0C\u6CA1\u6709\u7B2C\u4E8C\u5C42\n \u586B\u5145\u6E90\u3002\u58C1\u7EB8\u542F\u7528\u65F6\u6309\u8BE5\u4EE4\u724C\u81EA\u8EAB\u7684\u4E24\u6863\u9759\u6001\u503C\u8865\u56DE\u539F\u8272\uFF1A\u6D45\u8272\n --dsw-static-neutral-bluish-50\u3001\u6DF1\u8272 --dsw-static-neutral-bluish-900\u3002\n \u8FD9\u4E24\u4E2A\u9759\u6001\u4EE4\u724C\u5728\u660E\u6697\u4E24\u5957\u91CC\u53D6\u503C\u76F8\u540C\uFF0C\u6240\u4EE5\u6DF1\u8272\u5FC5\u987B\u5355\u72EC\u4E00\u6761\u3002\n \u89C4\u5219\u53EA\u5728 body[data-dsh-bg] \u4E0B\u547D\u4E2D\uFF0C\u65E0\u58C1\u7EB8\u65F6\u5B8C\u5168\u4E0D\u53C2\u4E0E\u3002 */\n /* @patch\n id: wallpaper-drawer-fill\n for: deepseek-harness-background 0.6.x \u7684 body[data-dsh-bg]\uFF08\u58C1\u7EB8\u542F\u7528\u65F6\u628A --dsw-specific-sidebar-fill \u7F6E\u4E3A transparent\uFF09\n why: \u62BD\u5C49\u5217\u7684\u552F\u4E00\u5E95\u8272\u5C31\u662F\u8BE5\u4EE4\u724C\uFF0C\u7B2C\u4E09\u65B9\u63D2\u4EF6\u628A\u5B83\u6E05\u7A7A\u540E\u6574\u5217\u900F\u51FA\u58C1\u7EB8\uFF1B\u5BBF\u4E3B\u5185\u8868\u9762\u540C\u6837\u900F\u660E\uFF0C\u6CA1\u6709\u5176\u5B83\u586B\u5145\u6E90\n until: \u4E0A\u6E38\u63D0\u4F9B\u4E0D\u900F\u660E\u7684\u9762\u677F\u586B\u5145\u63A5\u7F1D\uFF0C\u6216\u4E0D\u518D\u628A --dsw-specific-sidebar-fill \u7F6E\u7A7A\u2014\u2014\u5C4A\u65F6\u672C\u5757\u5220\u9664\n test: tests/wallpaper-surface-fill.test.ts\n */\n body[data-dsh-bg] [data-mobile-nav=\"frame\"] > :first-child {\n background: var(--dsw-static-neutral-bluish-50, #f9fafb);\n }\n body[data-ds-dark-theme][data-dsh-bg] [data-mobile-nav=\"frame\"] > :first-child {\n background: var(--dsw-static-neutral-bluish-900, #1b1b1c);\n }\n\n /* Closed slot, at the host's OWN specificity. 0.1.5 added a narrow-branch\n rule [data-dsh-frame][data-sidebar-collapsed] [data-pane=\"sidebar\"]\n { width:52px !important; transform:none; pointer-events:none;\n background:transparent !important } - specificity (0,3,0), one class above\n the rule above, so it won BOTH width and transform: the closed drawer\n stayed a 52px transparent shell at x=0 and the only state delta left was\n the width (52<->280), which \"transition: transform\" cannot animate.\n Measured 2026-09-17: closed pane transform:none / width:52 /\n rect [0,0,52,844], and every frame sampled across a toggle click stayed\n transform:none - the owner's \"no slide animation on click\" report.\n Matching that specificity (plus !important, since the host declaration is\n important) restores the design's own slot (spec 2026-08-27, drawer DOM):\n a min(88vw, 280px) column translated -110% of its own width, i.e. -308px\n at 390px. The gesture layer never depended on this rule - it writes an\n inline transform !important - so only the CSS-driven click paths regressed. */\n [data-mobile-nav=\"frame\"][data-sidebar-collapsed] > :first-child {\n width: min(88vw, 280px) !important;\n transform: translateX(-110%) !important;\n }\n\n /* Expanded state (frame without data-sidebar-collapsed) slides the drawer in.\n The open state must be transform:none \u2014 NOT translateX(0): an identity\n transform still makes the drawer the containing block for fixed-position\n descendants (the settings dialog's .VOzbGW_overlay is portaled into the\n sidebar DOM). With the identity transform the wide settings sheet\n (100vw-16) overflows the 280px drawer, the dialog's focus scrolls the\n overflow:hidden drawer to scrollLeft=102, and every static child (plus the\n fixed overlay) shifts 102px off-screen. With transform:none the overlay is\n viewport-anchored: it dims the full screen and the sheet sits at left:8. */\n [data-mobile-nav=\"frame\"]:not([data-sidebar-collapsed]) > :first-child {\n transform: none !important;\n }\n\n\n /* The host's own drawer handle. It renders the branded fish glyph (a 24x17\n path in a 23.16x17.04 viewBox) and the phone owner reads it as a stray\n \"whale\" sitting at the very top-left of the header: measured [10,14,44,44]\n against our own toggle at [8,12,28,28], i.e. the two overlap in the same\n corner. It also duplicates what our toggle already does, so on the mobile\n branch it is removed. The selector keys on the host's own label - the\n element carries no distinguishing class (hHd-Xa_iconButton is shared with\n every other icon button, and the label flips to \"Collapse sidebar\" when the\n drawer is open, which is why the attribute prefix matches both states and\n both get removed). Nothing in this plugin queries that element; the drawer\n still opens from our toggle, the edge swipe, and closes by tapping the\n backdrop or swiping it away. */\n /* Two selectors and both are needed. The competitor is NOT the host's own\n CSS: @linxin666/dsh-web-all injects, under (max-width: 768px),\n [data-dsh-frame][data-sidebar-collapsed] [data-pane=\"sidebar\"]\n [data-dsh-responsive-part=\"sidebar-toggle\"] { pointer-events: auto;\n display: inline-flex !important }. That is 4 attribute selectors AND\n !important - exactly what the first selector below is - so this is NOT an\n out-specify, it is a TIE decided by sheet order, and it holds only because\n our sheet is injected after theirs. Measured twice, not inferred:\n scripts/probes/cascade-conflict-probe.mjs reports both sides imp=true at\n (0,4,0) and lists this as a reviewed order-tie; if the injection order\n flips, the dismiss shadow returns as a visible inline-flex box with\n pointer-events restored. Done (audit D-5 option A, 2026-09-16): every\n selector below carries a leading html, which lifts the first one to\n (0,4,1) and ends the tie - the outcome no longer depends on which sheet is\n injected later. The hash class and the label stay as fallbacks for hosts\n without that hook. */\n html [data-mobile-nav=\"frame\"][data-sidebar-collapsed] [data-pane=\"sidebar\"] [data-dsh-responsive-part=\"sidebar-toggle\"],\n html [data-mobile-nav=\"frame\"] [data-dsh-responsive-part=\"sidebar-toggle\"],\n html [data-mobile-nav=\"frame\"] [class*=\"hHd-Xa_toggle\"]:is([aria-label*=\"sidebar\" i], [aria-label*=\"\u4FA7\u8FB9\u680F\"]),\n /* The label-only fallbacks MUST stay scoped to the seats the host's own\n drawer handle can live in. Unscoped they match by aria-label substring,\n and the session row's \u22EF carries \u4F1A\u8BDD\u201C
\u201D\u7684\u64CD\u4F5C \u2014 so any session\n whose title contains \u4FA7\u8FB9\u680F (or \"sidebar\") lost its \u22EF menu entirely\n (2026-09-22 phone repro: title \u4FA7\u8FB9\u680F\u4E0D\u89C1\u4E86 \u2192 rowActions button\n display:none, row height unchanged, time shifted right by the 16px the\n button would have taken). Anchor them to the frame's leading seat and to\n the header's leading cell instead. */\n html [data-mobile-nav=\"frame\"] [data-conversation-header-leading] button[aria-label*=\"sidebar\" i],\n html [data-mobile-nav=\"frame\"] [data-conversation-header-leading] button[aria-label*=\"\u4FA7\u8FB9\u680F\"],\n html [data-mobile-nav=\"frame\"] [data-shell-leading] button[aria-label*=\"sidebar\" i],\n html [data-mobile-nav=\"frame\"] [data-shell-leading] button[aria-label*=\"\u4FA7\u8FB9\u680F\"] {\n display: none !important;\n }\n\n /* The host's own right sidebar IS the Files panel on phones, and the host\n pins it as a fixed full-bleed sheet: [data-sidebar-right-panel=fullscreen]\n carries position:fixed; inset:0 and no inset of its own (the host CSS\n never mentions safe-area at all). Its top row - the tab strip holding the\n tab label, the + button and the Split / Exit-fullscreen pair at the right\n edge - therefore sat UNDER the status bar: measured at 390x844 with the\n panel open, the strip is [0,0,390,38] and the phone's status bar owns the\n top of the screen. The frame's own safe-area padding cannot reach it: a\n fixed element's containing block is the viewport, not the frame's padding\n box. Taking the inset as padding keeps the panel's own --dsw-alias-bg-base\n covering the whole viewport (no seam behind the status bar) and drops the\n entire row below it, with the right-hand buttons still on the right edge.\n ONLY the fullscreen form: the host's docked form (measured at 820x1180 -\n form=push, position:absolute, 365px right-anchored) has the frame's\n padding box as its containing block, so it already starts below the\n status bar; padding it too would add the inset a second time. A host\n generation that renames the form value should fail the probe loudly\n instead of silently double-padding. The rule lives in the mobile branch,\n so desktop keeps the host layout. */\n [data-sidebar-right-panel=\"fullscreen\"] {\n padding-top: env(safe-area-inset-top, 0px) !important;\n }\n\n /* Phone chrome keeps only the collapse control. Split visibility must not\n depend on data-dockkit-split-blocked: DockLayout measures after each commit,\n so conditional display can alternate blocked/allowed at the width threshold.\n Hide the wrapper too, since a blocked split wrapper is a tab stop. */\n @media (max-width: 767px) and (pointer: coarse) {\n [data-sidebar-right-panel] [data-dockkit-split-button],\n [data-sidebar-right-panel] span:has(> [data-dockkit-split-button]),\n [data-sidebar-right-panel] [data-sidebar-right-mode=\"push\"] {\n display: none !important;\n }\n }\n\n /* prefers-reduced-motion: the drawer's .28s slide is motion; drop it\n (audit S2 2026-08-27 \u2014 the old reduce block only covered the settings\n sheet and its mask). Same idiom as the animation:none blocks below. */\n @media (prefers-reduced-motion: reduce) {\n [data-mobile-nav=\"frame\"] > :first-child {\n transition: none !important;\n }\n }\n\n /* Drag handles are useless on touch and would float over the drawer. */\n [data-side=\"sidebar\"],\n [data-side=\"details\"] {\n display: none !important;\n }\n\n /* --- Conversation text on mobile ---\n The official message flow keeps desktop's 32px side gutters and 16px\n type. On a phone: shrink the type a notch and widen the lines by\n trimming the gutters (the sidebar drawer list keeps its size). The\n flow's scroll container holds the markdown
paragraphs; since\n DSH 0.1.2-rc.1 the composer is a Lexical contenteditable that also\n renders real
paragraphs inside its own _scroll container, so the\n composer must be excluded explicitly via\n :not(:has([data-composer-input])). */\n /* The official main scroll body reserves scrollbar-gutter for desktop\n scrollbars (8px), which shoves every column off-center on a phone.\n Classic desktop scrollbars (Edge/Chrome) also occupy ~8-17px in a\n phone-sized viewport, shifting the column further. Mobile scrolling\n is touch/wheel, so remove the scrollbar entirely on phones: the\n column is then exactly centered in every browser. */\n [data-phase] [class*=\"_scrollBody\"] {\n scrollbar-gutter: auto !important;\n scrollbar-width: none;\n }\n [data-phase] [class*=\"_scrollBody\"]::-webkit-scrollbar {\n display: none !important;\n width: 0;\n height: 0;\n }\n /* ---------- selection-drag autoscroll ramp (2026-10-07 live-host probe) ----------\n Report (Android): once the conversation chrome became unselectable, dragging\n the selection handle up stopped grabbing the title bar, but the conversation\n did not scroll WITH the finger - it teleported a few screens up instead.\n Mechanism measured on the live host (390x844, touch-emulated, selection anchor\n inside the message flow, pointer held 1.4s): Blink only starts autoscrolling a\n selection drag once the pointer is within ~3px of the scrollport's top edge,\n and the RATE grows with how far the pointer sits ABOVE that edge, saturating\n fast - y=140/100 -> 0 px/s, y=70 -> 1018, y=50 -> 2225, y=30 -> 3329,\n y=10 -> 3232 px/s. The conversation scrollport's top edge is the header's\n bottom edge (y=67), so every finger position on the header is 17-57px \"above\n the list\" and lands in the 2200-3300 px/s band: one 777px screen every ~0.23s,\n which reads as dropped frames / a jump to somewhere else. The ramp is\n geometric, not ours - from y>=100 nothing scrolls at all, so the speed is\n decided by where the list's box starts.\n Fix: extend the scrollport's box up under the header so a drag point over the\n header is only a few px above the list edge. Measured with the box moved to\n y=0: y=30 -> 0 px/s, y=10 -> 595 px/s. The visual position is unchanged by\n construction - the box grows upward by H while padding-top: H pushes the\n content back down, so an element at content offset X still paints at\n H + X - scrollTop (live-host check: header [0,0,390,67] and the composer seat\n [0,740,388,104] are identical before/after; only the box [0,67,388,777] ->\n [0,0,388,844] and scrollHeight +H move).\n H comes from --mobile-nav-header-h, written by the reconciler task\n \"header-metrics\" (phone-chrome.ts) as the header's bottom edge measured from\n the frame's top. It is 0px whenever the header is not measurable (hero / blank\n header), which makes both declarations below a no-op - the layout fails open if\n the host ever stops rendering a conversation header. Phone tier only: the\n desktop header is an ordinary in-flow bar and there is no touch selection drag\n to ramp. */\n [data-mobile-nav=\"frame\"] [data-phase] [class*=\"_scrollBody\"] {\n margin-top: calc(-1 * var(--mobile-nav-header-h, 0px)) !important;\n padding-top: var(--mobile-nav-header-h, 0px) !important;\n }\n /* ---------- selection handle drag: keep the extent local (2026-10-07) ----------\n The phone selection handle drag is a native (Android WebView\n TouchSelectionController) gesture: each move hit-tests the handle position to\n resolve the selection extent and then reveals that extent. With the bar\n unselectable but still hit-testable it won that hit test, Blink walked FORWARD\n in DOM order to the next selectable node - the flow's first item, the\n \"Load earlier\" gate, measured on the live host - and revealed it: the viewport\n teleported to the top of the conversation instead of extending by a line\n (reported as \"not scroll-selection, it jumps somewhere else\"). Dropping the bar\n out of the hit test for the duration of the selection lets the same point\n resolve into the message the lifted box above now puts underneath it, so the\n extent stays local and the scroll ramp stays gentle. \u300Cpointer-events\u300D only -\n no layout change, so nothing reflows while the finger is down. The marker is\n set by installSelectionChromeYield (phone-chrome.ts) and only for selections\n that live in the conversation (composer/drawer keep their chrome\n interactive); header buttons remain reachable the moment the selection\n collapses, which is also what a tap anywhere else does. */\n html[data-mobile-nav-selecting] [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header {\n pointer-events: none !important;\n }\n /* A transparent header was harmless while nothing could scroll underneath it;\n with the box lifted it would show the messages through the title row\n (headless screenshot 2026-10-07: message text bled across \"Standard mode\"\n and the tab strip), so the header rule below now carries an opaque\n background. */\n /* Message action rows (copy / run-time badges) can overflow the right\n edge on narrow screens \u2014 keep them inside the message width. */\n [data-phase] [class*=\"_actions\"] {\n overflow: hidden;\n }\n [data-phase] [class*=\"_actions\"] [class*=\"_timeEnd\"] {\n flex: 0 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n\n /* Message tooltip bubbles (copy / feedback labels, message-row hover\n bubbles) are redundant on touch: the icon already flips to a checkmark.\n Suppress only inside the actions row \u2014 the fork's original scope. On\n this host (0.1.1-rc.2) NO tooltip renders as a visible bubble: the copy\n label is a visuallyHidden span and no client-ui package emits\n role=\"tooltip\". The user message bubble (Sixlwa_bubble since the host moved\n it to dsh-client-ui-chat) and the goal\n bubble (oRe1gG_bubble) live in _userStack/_row, NOT in _actions \u2014 the\n previously unscoped selector hid every user message on touch devices\n (2026-09-06 live regression). role=\"tooltip\" stays globally suppressed:\n genuine ARIA tooltips are exactly what the sticky-residue fix targets,\n and nothing legitimate carries the role today. The actions-row arm\n re-activates by itself when a host version renders tooltip labels\n inline in the actions row (DSH 0.1.2 shape). */\n @media (hover: none), (pointer: coarse) {\n [data-phase] [role=\"tooltip\"],\n [data-phase] [class*=\"_actions\"] [class*=\"_bubble\"] {\n display: none !important;\n visibility: hidden !important;\n opacity: 0 !important;\n pointer-events: none !important;\n }\n }\n\n [data-phase]\n [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):not(:has([data-composer-input])):has(p) {\n padding-left: 20px;\n padding-right: 20px;\n /* Message text follows the host's own font-size axis (Settings -> \u5B57\u53F7\u5927\u5C0F)\n instead of a frozen phone constant. The host writes the user's choice to\n
as --dsh-content-font-size and derives the longhand token\n --dsw-font-markdown-base-font-size from it; the previous 15px !important\n cut that chain at the container, so settings 12-17 did nothing for message\n text while the host's own markdown blocks still moved \u2014 two sizes mixed in\n one column (#52). Read the longhand token only: the other token ending in\n -base is the font shorthand, an invalid font-size value that the parser\n drops and the cascade silently falls back on. The fallback chain ends at\n the host's own default axis value. */\n font-size: var(--dsw-font-markdown-base-font-size, var(--dsh-content-font-size, 14px)) !important;\n }\n /* Descendants only inherit: the host already resolves the same token on its\n own markdown blocks (and its styles pin 16px on paragraphs / list items),\n so a rule per p / li / user-message text would cut the axis a second time. */\n [data-phase]\n [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):not(:has([data-composer-input])):has(p) p,\n [data-phase]\n [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):not(:has([data-composer-input])):has(p) li,\n [data-phase]\n [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]):not(:has([data-composer-input])):has(p) [\n class*=\"_text_\"\n ] {\n font-size: inherit !important;\n }\n\n /* Markdown tables: the official table uses width:max-content, so on a phone\n it hugs the content and leaves dead space beside/inside the table. Force\n the table to fill the message column and let the table wrapper handle\n overflow if a cell is genuinely too wide. */\n [data-phase] table {\n width: 100%;\n max-width: 100%;\n }\n [data-phase] th,\n [data-phase] td {\n max-width: none;\n min-width: 0;\n }\n\n /* Markdown images: the official rule often forces width:100%, which\n upscales small square images to the full message column. Show small\n images at their intrinsic size; large / very wide images still scale\n down to fit the column (max-width:100% keeps horizontal panoramas\n adaptive without overflowing). */\n [data-phase] [class*=\"_scroll\"]:not([class*=\"_scrollBody\"]) img {\n width: auto !important;\n max-width: 100% !important;\n height: auto !important;\n /* Cap square / tall images so a big sticker does not dominate the\n narrow column; landscape images stay governed by max-width only.\n The plain px line is the fallback for engines without dvh. */\n max-height: 220px !important;\n max-height: min(40dvh, 220px) !important;\n }\n\n /* User bubbles: the official stack is capped at min(525px, 82%), which on a\n phone leaves a large blank strip on the left and pushes the bubble high.\n On mobile let the user message fill the same full width as assistant\n messages (the bubble background then spans the whole message column). */\n [data-phase] [class*=\"_userStack\"],\n [data-phase] [class*=\"_userStack\"] [class*=\"_bubble\"] {\n box-sizing: border-box;\n width: fit-content;\n max-width: 100%;\n }\n\n /* --- Composer bottom row on mobile ---\n The official row contains two lanes: tools (plus + permission/mode\n controls) and trailing (model + context + send). The previous rules made\n the modes lane flex:none, so its full intrinsic width collided with the\n model selector on narrow phones. Keep fixed hit targets fixed, but let\n text-bearing controls shrink and ellipsize before they paint over the\n trailing lane. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) {\n box-sizing: border-box;\n container-type: inline-size;\n container-name: dsh-mobile-composer;\n flex-wrap: nowrap;\n /* 2026-09-23 \u5E97\u4E3B\uFF1A\"\u6BCF\u4E2A\u529F\u80FD\u952E\u9694\u7684\u7A7A\u95F4\u592A\u591A\"\u3002\u771F\u673A\u5B9E\u6D4B\u95F4\u8DDD\u4E3B\u8981\u4E0D\u662F gap\uFF086px\uFF09\n \u800C\u662F\u5404\u63A7\u4EF6\u81EA\u5DF1\u7684\u5185\u8FB9\u8DDD\uFF1B\u8FD9\u91CC gap \u6536\u5230 3px\uFF0C\u914D\u5408\u4E0B\u9762\u6A21\u578B chip \u7684 padding\n \u6536\u7D27\uFF0C\u628A\u53F3\u7C07\u710A\u6210\u4E00\u56E2\u3002 */\n gap: 3px;\n padding-left: 6px;\n padding-right: 6px;\n /* The dropdown menu is absolutely positioned inside this row; any\n overflow: hidden here would clip it. Inner lanes keep their own\n overflow clipping, so the row itself can stay visible. */\n overflow: visible;\n }\n /* Dual-primary form (subagent view: stop + send). The four-control\n cluster [model][meter][stop][send] overflows the single-row lane the\n nowrap rule above enforces; the model pill is the only shrinkable\n item, so it collapses to zero and the fixed trio loses its auto\n margin (all hug the lane's left edge, send may even paint off-view).\n Restore the official wrap for this form only: the trailing lane\n drops to a second full-width row where the four controls always\n fit. Main-session three-control form keeps single-row layout. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]):has([class*=\"_primary\"] ~ [class*=\"_primary\"]) {\n flex-wrap: wrap;\n }\n /* Issue #140: in that same dual-primary form the stop key and the send key\n sit one 3px lane-gap apart \u2014 two same-shaped 34px pills where a mis-touch\n on the left one interrupts the running reply. The 2026-09-23 \u300C\u710A\u5728\u4E00\u8D77\u300D\n 3px decision keeps governing the main session's [model][send] cluster;\n only this form (the one with two adjacent destructive-adjacent primaries)\n gets +8px between the stop and the send key. Knob: margin-right. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]):has([class*=\"_primary\"] ~ [class*=\"_primary\"]) > [class*=\"_trailing\"] > [class*=\"_primary\"]:has(~ [class*=\"_primary\"]) {\n margin-right: 8px;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > :first-child {\n flex: 0 1 auto;\n min-width: 0;\n /* 2026-09-23 \u5E97\u4E3B\u7B2C\u4E09\u8F6E\uFF1A\"\u5DE6\u8FB9\u90A3\u4E09\u4E2A\u529F\u80FD\u533A\u6328\u5F97\u592A\u8FD1\u4E86\uFF0C\u9694\u5F00\u4E00\u70B9\u70B9\"\u3002\n \u6743\u9650\u63A7\u4EF6\u6536\u7A84 16px \u540E\uFF0C\uD83D\uDCCE \u8DDF\u7740\u6574\u4F53\u5DE6\u79FB\u3001\u8D34\u5230\u4E86 \u2304 \u4E0A\uFF08\u5B9E\u6D4B\u58A8\u8FF9\u95F4\u8DDD\u53EA\u5269 ~3px\uFF09\u3002\n \u5DE5\u5177\u9053 gap \u5355\u5217\u653E\u5BBD\u5230 8px\uFF08\u53F3\u7C07\u4ECD 3px\uFF0C\u4FDD\u6301\u710A\u5728\u4E00\u8D77\uFF09\u3002 */\n gap: 8px;\n /* The permission dropdown (Menu, side: top) pops upward from inside the\n tools lane; overflow hidden here would crop it, same as the row. Text\n ellipsis is handled by the trigger label itself. */\n overflow: visible;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] {\n flex: 1 1 auto;\n min-width: 0;\n gap: 3px;\n /* Must not clip the model dropdown; the model trigger clips its own label. */\n overflow: visible;\n }\n /* Permission / plan controls share the tools lane inside the a2-style\n 'div.modes' container (class survives as 'css.modes'; audit doc \u00A710.1 /\n E-1). The positional anchor '> :first-child > :nth-child(2)' was already\n off-target on rc.2 and dies entirely on a2, so the series re-anchors on\n the tools lane's modes container: '[class*=\"_tools\"] > [class*=\"_modes\"]'\n (live-verified on the rc.2 host: the modes div is a direct child of the\n tools lane, a grandchild of the row \u2014 a row-direct-child anchor matches\n nothing on either generation). The permission label uses the remaining\n tools width, while the lower-priority plan slot keeps an icon-sized\n target instead of stealing model width. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_tools\"] > [class*=\"_modes\"] {\n flex: 0 1 auto;\n min-width: 0;\n max-width: none;\n /* 2026-09-23 \u5E97\u4E3B\uFF1A\"\u5DE6\u8FB9\u90A3\u4E2A\u6743\u9650\u7684\u4E5F\u7F29\u4E00\u70B9\u70B9\"\uFF1A\u5BB9\u5668 gap 4\u21920\u3002 */\n gap: 0;\n /* The permission Menu list (side: top) pops upward out of this lane;\n overflow hidden crops it. The trigger label clips its own text. */\n overflow: visible;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_tools\"] > [class*=\"_modes\"] > [class*=\"_trigger\"] {\n flex: 1 1 auto;\n min-width: 28px;\n max-width: 100%;\n display: flex !important;\n overflow: hidden;\n /* \u6743\u9650 trigger \u81EA\u5E26\u5185\u8FB9\u8DDD + flex gap\uFF08\u56FE\u6807\u4E0E \u2304 \u4E4B\u95F4\uFF09\uFF0C\u56FE\u6807\u5316\u540E\u90FD\u662F\u6D6A\u8D39\uFF1A\n 2026-09-23 \u6309\u5E97\u4E3B\"\u7F29\u4E00\u70B9\u70B9\"\u5F52\u96F6\uFF08\u771F\u673A 44px \u76D2 \u2192 ~34px\uFF09\u3002 */\n padding: 0 !important;\n gap: 0 !important;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_tools\"] > [class*=\"_modes\"] > [class*=\"_trigger\"] > [class*=\"_triggerLabel\"] {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n /* Slot wrappers such as the live plan chip are not trigger elements. Do\n not force them into an icon-sized box: their child button would overflow\n that wrapper and paint over PermissionSelect. Keep the wrapper intrinsic;\n the model lane below is the one that sacrifices width. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_tools\"] > [class*=\"_modes\"] > :not([class*=\"_trigger\"]) {\n flex: 0 1 auto;\n min-width: 34px;\n max-width: max-content;\n overflow: visible;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_tools\"] > [class*=\"_modes\"] > [class*=\"_wrap\"] > [class*=\"_chip\"] {\n max-width: 100%;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n @container dsh-mobile-composer (max-width: 359px) {\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_tools\"] > [class*=\"_modes\"] > [class*=\"_trigger\"] > [class*=\"_triggerLabel\"] {\n display: none !important;\n }\n }\n /* \u6743\u9650\u89E6\u53D1\u5668\uFF08\u5BBF\u4E3B dsh-client-ui-permission-presets\uFF0C\u6837\u5F0F\u54C8\u5E0C iWlSmW_\uFF09\u81EA\u8EAB\u5E26\n padding:0 4px 0 8px + gap:4px \u2014\u2014 \u4E0E\u6A21\u578B chip \u540C\u6B3E\u6D6A\u8D39\uFF08\u5DE6 8px \u662F\u7ED9\u6587\u5B57\u7559\u7684\uFF09\u3002\n 2026-09-23 \u5E97\u4E3B\uFF1A\"\u5DE6\u8FB9\u90A3\u4E2A\u6743\u9650\u7684\u4E5F\u7F29\u4E00\u70B9\u70B9\"\u3002\u6CE8\u610F\uFF1A\u5B83\u5916\u9762\u5957\u4E86\u4E00\u5C42\n display:contents \u5305\u88C5\uFF08\u771F\u673A\u63A2\u9488\uFF1Amodes[55,44] > div[contents] > root[55,44]\uFF09\uFF0C\n \u6240\u4EE5\u300C_modes > _trigger\u300D\u8FD9\u7C7B\u76F4\u63A5\u5B50\u4EE3\u951A\u70B9\u547D\u4E0D\u4E2D\uFF08\u4E0A\u4E00\u7248\u6539\u4E86\u6CA1\u53CD\u5E94\uFF09\uFF0C\n \u5FC5\u987B\u7528\u54C8\u5E0C\u540E\u4EE3\u951A\u70B9\uFF1B\u54C8\u5E0C\u53D8\u4E86\u6574\u6761\u81EA\u52A8\u5931\u6548\uFF0C\u4E0D\u4F1A\u8BEF\u4F24\u522B\u5BB6\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] [class*=\"iWlSmW_trigger\"] {\n padding: 0 !important;\n gap: 0 !important;\n }\n /* 2026-09-23 \u5E97\u4E3B\uFF1A\"\u6743\u9650\u7684\u56FE\u6807\u6709\u70B9\u5C0F\uFF0C\u7A0D\u5FAE\u5927\u4E00\u70B9\u70B9\uFF0C\u4E0D\u7136\u5DE6\u8FB9\u8F7B\u53F3\u8FB9\u91CD\"\u3002\n \u5BBF\u4E3B\u628A\u56FE\u6807\u5305\u5728 _triggerIcon \u91CC\u3001\u81EA\u5DF1\u5199\u6B7B 14px\uFF08iWlSmW_triggerIcon svg\n \u7684 width/height \u90FD\u662F 14px\uFF09\uFF0C\u4E0E + / \uD83D\uDCCE \u7684 16px \u4E0D\u9F50\u3002\u53EA\u653E\u5927\u90A3\u4E2A\u5305\u88C5\u91CC\u7684\n svg\uFF1A\u2304 \u7BAD\u5934\u4E0D\u5728 _triggerIcon \u5185\uFF0C\u4E0D\u4F1A\u88AB\u4E00\u8D77\u653E\u5927\u3002\u76D2\u5B50 28\u00D728 \u4E0D\u53D8\uFF0816 \u4ECD\u6709\u4F59\u91CF\uFF09\u3002\n \u6CE8\u610F\uFF1A\u672C\u6587\u4EF6\u662F\u6A21\u677F\u5B57\u7B26\u4E32\uFF0C\u6CE8\u91CA\u91CC**\u4E0D\u80FD\u51FA\u73B0\u53CD\u5F15\u53F7**\uFF08\u4F1A\u5288\u5F00 CSS\uFF09\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] [class*=\"iWlSmW_triggerIcon\"] svg {\n width: 16px !important;\n height: 16px !important;\n }\n\n /* Model selector: flexible and shrinkable, but never clipped.\n The root must be overflow:visible so the dropdown menu can render.\n The trigger itself clips the label text. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"]) {\n flex: 0 1 auto;\n min-width: 0;\n overflow: visible;\n }\n @container dsh-mobile-composer (max-width: 359px) {\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"]) {\n flex-basis: auto;\n }\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"]) > [class*=\"_trigger\"] {\n display: flex !important;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n overflow: hidden;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"]) > [class*=\"_trigger\"] > [class*=\"_triggerLabel\"] {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_root\"]:has(> [class*=\"_trigger\"]):not(:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"])) {\n flex: 0 0 auto;\n }\n\n /* Model switcher menu: was centered here with left:50% + translateX(-50%), but the\n host now PORTALS the menu to (measured 2026-09-23: _7KE1Ra_menu, role=menu,\n position:fixed, parent=BODY, inline left/top), so this child-chain selector stopped\n matching and the rule had been dead. The re-anchor lives in JS instead \u2014\n effects/model-menu-anchor.ts centers the panel on the trigger and clamps it to the\n viewport. Do not re-add a CSS rule here without checking the portal parent. */\n\n /* Phone reasoning-effort list is compact; the model catalog and the tablet stay\n host-sized. Measured on the real host bundle (dsh-client-ui-model-selection\n 0.2.0-rc.2, 393x844, phone emulation): the effort pane renders 248px wide\n (its own min-width is 240px) while its four levels need far less.\n The two panes differ in the SHAPE of their radio list, and that difference is\n the only reliable discriminator (measured, same run):\n effort pane DIV._surface_ri079_1._7KE1Ra_menu[role=menu]\n > DIV._material_ri079_21\n > button._7KE1Ra_option[role=menuitemradio] <- DIRECT child\n model pane DIV._surface_ri079_1._7KE1Ra_menu[role=group]\n > DIV._material_ri079_21\n > DIV._7KE1Ra_groups.scrollable[role=menu]\n > SECTION._group_121p8_1[role=group] > button[role=menuitemradio]\n The host sets \u300Crole: pane === \"model\" ? \"group\" : \"menu\"\u300D, so the effort pane is\n the role=menu shell and its radios ARE direct children, while the catalog's sit\n two levels deeper. Requiring both halves \u2014 role=menu AND a direct-child radio \u2014\n therefore selects the effort list and leaves the catalog at its host size.\n Neither half is safe alone: dropping the role also matches the catalog's inner\n _groups container, and matching radios as descendants selects the catalog shell.\n (Measured with each variant: the group/descendant form hit the catalog only.)\n \u300Cmin-width: 0 !important\u300D is load-bearing: without it the host's own\n min-width 240px keeps the pane at 240 no matter what width is set. */\n @media (max-width: 767px) and (pointer: coarse) {\n [class*=\"_7KE1Ra_menu\"][role=\"menu\"]:has(> [role=\"menuitemradio\"]) {\n width: min(208px, calc(100vw - 32px)) !important;\n min-width: 0 !important;\n max-width: calc(100vw - 32px) !important;\n }\n }\n\n /* --- Fix composer row overflow at narrow widths (320px-360px) ---\n Force every direct child of the tools and trailing lanes to shrink,\n so they can fit within the available space without causing horizontal\n overflow. The fixed-size icon buttons are exempt: officially both are\n flex:none at a fixed size (plus 28x28, send 34x34) and must stay put,\n not participate in adaptation. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > :first-child > :not([class*=\"_add\"]) {\n flex-shrink: 1;\n min-width: 0;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > :not([class*=\"_primary\"]) {\n flex-shrink: 1;\n min-width: 0;\n }\n /* Pin the plus button at the left edge of the tools lane: official\n flex:none 28x28, never squeezed by narrower viewports. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > :first-child > [class*=\"_add\"] {\n flex: none;\n }\n /* The context meter in the trailing lane is another fixed-size icon\n control: its trigger is officially width:28px flex:none, but the root\n itself is shrinkable, so a squeezed root lets the trigger paint over\n the pinned send button. Keep the whole meter at its natural size; its\n trigger uses aria-haspopup=\"dialog\", so the model-selector menu rules\n (keyed on \"menu\") still do not apply.\n GENERATION NOTE (issue #140, 2026-09-29): 0.1.7-rc.2 moved the\n ContextMeter out of this lane into the dock row under the card (next to\n the TPS stats pills) \u2014 on rc.2 NONE of the trailing-lane meter rules in\n this section match any more, and the trigger is back to its official\n ~22px-tall box. They stay for the 0.1.5/0.1.6 generations where the\n meter really rendered in the lane (structural anchors, inert elsewhere);\n the rc.2+ hit-area repair lives in the dock-row section below. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > [class*=\"_root\"] {\n flex: none;\n min-width: 0;\n }\n /* --- \u53F3\u7C07\u8D34\u53F3\uFF1A2026-09-23 \u91CD\u65B0\u5BF9\u951A\uFF08\u6A21\u578B\u80F6\u56CA\u6539\"\u53EA\u7559\u56FE\u6807\"\u540E\u66B4\u9732\u7684\u65E7\u8D26\uFF09---\n \u5BBF\u4E3B\u628A\u53F3\u7C07\uFF08\u6A21\u578B\u5EA7\u4F4D standardControls / \u9EA6\u514B\u98CE activity / \u53D1\u9001 primary\uFF09\n \u653E\u8FDB\u53EF\u589E\u957F\u7684 trailing \u8F66\u9053\uFF0C\u9760\"\u67D0\u4E2A\u6210\u5458\u5E26 margin-left:auto\"\u628A\u6574\u7C07\u9876\u5230\u53F3\u7F18\u3002\n \u63D2\u4EF6\u539F\u6765\u628A\u5438\u6536\u5668\u6302\u5728\u6A21\u578B root \u4E0A\uFF1A\n > [class*=\"_trailing\"] [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"])\n \u4F46 0.1.7 \u7684\u7956\u5148\u94FE\u53D8\u6210\u4E86\n trailing > standardControls(flex item) > div[display:contents] > _root > _trigger\n \u4E8E\u662F root \u53EA\u662F standardControls **\u5185\u90E8**\u7684 flex item\uFF0Cauto \u5916\u8FB9\u8DDD\u843D\u5728\u4E00\u4E2A\n \u5185\u5BB9\u5BBD\u5EA6\u7684\u76D2\u5B50\u91CC \u21D2 \u7B49\u4E8E\u5931\u6548\u3002\u771F\u673A\u63A2\u9488\u5B9E\u6D4B\u4E09\u8005 ml \u5168 = 0px\uFF0C\u5C31\u662F\u94C1\u8BC1\u3002\n 2026-09-23 \u4E4B\u524D\u80F6\u56CA\u5F88\u5BBD\u3001\u628A\u8F66\u9053\u586B\u6EE1\uFF0C\u770B\u4E0D\u51FA\u6765\uFF1B\u80F6\u56CA\u4E00\u6536\u6210\u56FE\u6807\uFF0C\u53F3\u7C07\u7ACB\u523B\n \u584C\u5230\u5DE6\u8FB9\uFF08\u53D1\u9001 x\u2248316 \u2192 224\uFF0C\u53F3\u8FB9\u7A7A\u51FA ~76px\uFF0C\u5E97\u4E3B\u4E00\u773C\u770B\u51FA\"\u4F4D\u7F6E\u88AB\u79FB\u4E86\"\uFF09\u3002\n \u4FEE\u6CD5\uFF1A\u628A\u5438\u6536\u5668\u6539\u951A\u5230\u300C\u8F66\u9053\u7684\u7B2C\u4E00\u4E2A flex item\u300D\uFF0C\u5E76\u53EA\u5728\u6A21\u578B\u5EA7\u4F4D\u5728\u573A\u65F6\u751F\u6548\n \u2014\u2014 \u90A3\u65F6\u5BBF\u4E3B\u90A3\u6761\u628A primary \u7684 auto \u6E05\u96F6\u7684\u89C4\u5219\u4E5F\u5728\u751F\u6548\uFF0C\u907F\u514D\u4E24\u4E2A auto \u5E73\u5206\n \u7A7A\u9699\uFF1B\u6A21\u578B\u4E0D\u5728\u573A\uFF08\u5B50\u4EE3\u7406\u89C6\u56FE\uFF09\u7167\u65E7\u7531 primary \u81EA\u5DF1\u7684 auto \u6536\u5C3E\u3002\n justify-content: flex-end \u662F\u515C\u5E95\uFF1A\u4E07\u4E00\u9996\u4E2A child \u662F display:none\uFF0Cauto\n \u65E0\u5904\u53EF\u6302\u65F6\u4ECD\u80FD\u8D34\u53F3\uFF08\u6B64\u65F6\u65E0 auto \u5916\u8FB9\u8DDD\uFF0Cflex-end \u624D\u8D77\u4F5C\u7528\uFF09\u3002 */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"]:has([class*=\"_trigger\"][aria-haspopup=\"menu\"]) {\n justify-content: flex-end;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"]:has([class*=\"_trigger\"][aria-haspopup=\"menu\"]) > :first-child {\n margin-left: auto;\n }\n /* ContextMeter (JObwrW_ hash family) hugging the primary key. This single\n value is the whole spacing knob, and because the trigger box is centred on\n the ring ink it doubles as the ink offset:\n 6px + margin-right = the sliver before the primary key = the ink's\n leftward shift. 0px (current) therefore shifts the ink 6px -- exactly the\n official lane gap, with no negative-margin trick left in the chain --\n while -6px pins the ink perfectly still and +8px was vetoed on\n 2026-09-17 as \"too much\" (14px). The phone owner asked for a visible\n shift after 1px (-5px) proved imperceptible, and will re-tune this number\n by eye: change it and nothing else moves.\n Anchor on the unique aria-haspopup=\"dialog\" trigger (no other composer\n control uses it), not the hashed class, so an upstream hash bump cannot\n silently unhook us. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"dialog\"]) {\n margin-right: 0px;\n }\n /* The model pill joins the same right cluster: its margin-left:auto absorbs\n ALL trailing slack, so the adaptive void sits between the tools lane and\n the pill (visible on wide phones/tablets), while [pill][meter][send] stay\n welded together at the right edge on every width. Descendant combinator\n on purpose: the pill root sits behind a display:contents wrapper, so a\n direct-child combinator silently misses (probe-verified). Within the\n trailing lane aria-haspopup=\"menu\" belongs to the model trigger alone. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"menu\"]) {\n margin-left: auto;\n margin-right: -4px;\n }\n /* Grow only the invisible trigger BOX, never the ring ink: 24x24 -> 28x34.\n The WIDTH is capped at 28 by pure geometry, not by taste: the box is\n centred on the ink, and the primary key's hit box begins 14px right of the\n ink's centre, so 28 is the widest box that can reach that boundary without\n stealing a single pixel from the destructive key (the current 1px sliver\n is the spacing knob on the root rule above); the same arithmetic puts the\n left edge on the model pill's edge. The 34px HEIGHT is free: the primary\n key is already the tallest control in the lane, so the box cannot overlap\n anything vertically and the row height does not move. Hit area 576 -> 952\n square px (+65%) with the ink within 1px of its old spot (probe-asserted),\n and the ring's ink stays at its official 14px -- enlarging it is rejected\n as attention-grabbing. Knob: height can drop to 28 if the tap halo should\n be a circle rather than a stadium. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"dialog\"]) > [class*=\"_trigger\"] {\n width: 28px;\n height: 34px;\n padding: 0;\n }\n /* Slack-absorber priority in the trailing lane: model pill > meter > send.\n Exactly one element carries margin-left:auto so the adaptive void always\n sits BEFORE the welded right cluster, never inside it. The meter itself\n never had an auto before 2026-09-06: in subagent sessions the model seat\n is officially absent (the parent pins the model), and zeroing the send's\n auto on the meter's aria-haspopup=\"dialog\" then left NOTHING to absorb\n slack -- the whole right cluster hugged the lane's left edge (user\n screenshot). Fix: when no model pill renders, the meter root becomes the\n absorber, welding [meter][send] at the right edge like the main view's\n [pill][meter][send]; the send's auto only survives when neither renders. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"]:not(:has([class*=\"_trigger\"][aria-haspopup=\"menu\"])) > [class*=\"_root\"]:has(> [class*=\"_trigger\"][aria-haspopup=\"dialog\"]) {\n margin-left: auto;\n }\n\n /* --- rc.2+ \u7684\u7B2C\u4E8C\u4E2A\u5931\u6548\u9762\uFF1A\u5B50\u4EE3\u7406 composer \u91CC\u73AF\u951A\u70B9\u56DE\u4E0D\u5230\u53D1\u9001\u952E\u5DE6\u8FB9\uFF082026-10-12\uFF09---\n \u4E0A\u9762\u90A3\u6761\u300C\u65E0\u6A21\u578B\u80F6\u56CA\u65F6\u7531 ContextMeter \u5F53\u5438\u6536\u5668\u300D\u7684\u515C\u5E95\uFF0C\u5728 **0.1.7-rc.2+** \u4E0A\n \u518D\u4E5F\u5339\u914D\u4E0D\u5230\uFF1A\u5BBF\u4E3B\u5DF2\u7ECF\u628A ContextMeter \u4ECE trailing \u8F66\u9053\u642C\u8FDB\u5361\u7247\u4E0B\u65B9\u7684 dock \u884C\n \uFF08\u5B9E\u6D4B\u8DEF\u5F84 \u2026 > [class*=\"_card\"] > [class*=\"_root\"] > [class*=\"_dock\"] > span.JObwrW_root\uFF09\uFF0C\n \u5B83\u4E0D\u518D\u662F\u8F66\u9053\u7684\u5B50\u5143\u7D20\uFF0C\u300C:has(> [class*=\"_trigger\"][aria-haspopup=\"dialog\"])\u300D\u843D\u7A7A\u3002\n \u540E\u679C\uFF08headless 393\u00D7844 \u5B9E\u6D4B\uFF0C\u4E3B/\u5B50\u4E24\u89C6\u56FE\u540C\u673A\u5BF9\u6BD4\uFF09\uFF1A\u5B50\u4EE3\u7406\u4F1A\u8BDD\u91CC\u6A21\u578B\u80F6\u56CA\u6574\u4E2A\u4E0D\u6E32\u67D3\uFF0C\n \u300CstandardControls\u300D\u584C\u6210 0\u00D70 \u4E14 margin-left:0\uFF0C\u4E8E\u662F\u8F66\u9053\u91CC\u552F\u4E00\u5E26 auto \u7684\u662F\u53D1\u9001\u952E\u81EA\u5DF1\uFF0C\n \u63D2\u4EF6\u6CE8\u5165\u7684\u73AF\u951A\u70B9 span[data-mobile-nav=\"stats-ring-reserve\"]\uFF08\u666E\u901A\u6D41\u5185\u5143\u7D20\uFF09\u88AB\u7559\u5728\n \u8F66\u9053\u5DE6\u7F18 \u2014\u2014 \u73AF x=127\uFF0C\u800C\u4E3B\u4F1A\u8BDD\u540C\u4E00\u5143\u7D20 x=310\u3001\u53D1\u9001\u952E\u5728 333\uFF1A**188px \u7A7A\u6863**\uFF0C\n \u7528\u6237\u770B\u5230\u7684\u5C31\u662F\u300C\u4E0A\u4E0B\u6587\u8868\u8DD1\u5230\u5DE6\u8FB9\u53BB\u4E86\u300D\u3002\n \u4FEE\u6CD5\u4E0E #191 \u540C\u6E90\uFF08\u540C\u4E00\u6839\u56E0\u65CF\uFF1Arc.2 \u628A meter \u642C\u8D70\u540E\uFF0C\u8F66\u9053\u91CC\u7684 auto \u5F52\u5C5E\u6CA1\u4EBA\u63A5\u7BA1\uFF09\uFF1A\n \u6CA1\u6709\u6A21\u578B\u80F6\u56CA\u65F6\u8BA9**\u73AF\u951A\u70B9**\u9876\u66FF meter \u5F53\u5438\u6536\u5668\uFF0C\u5E76\u628A\u53D1\u9001\u952E\u7684 auto \u6E05\u96F6 \u2014\u2014\n \u4E0D\u6E05\u96F6\u7684\u8BDD\u4E24\u4E2A auto \u4F1A\u5E73\u5206\u7A7A\u9699\uFF0C\u73AF\u540C\u6837\u56DE\u4E0D\u5230\u952E\u8FB9\u3002\n \u95E8\u63A7\u4E0E\u4E0A\u9762\u90A3\u6761\u515C\u5E95\u5B8C\u5168\u4E00\u81F4\uFF08\u8F66\u9053\u91CC\u6CA1\u6709 aria-haspopup=\"menu\"\uFF09\uFF0C\u6240\u4EE5\u4E3B\u4F1A\u8BDD\n \uFF08\u6A21\u578B\u80F6\u56CA\u5728\u573A\uFF09\u96F6\u6539\u52A8\u3002 */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"]:not(:has([class*=\"_trigger\"][aria-haspopup=\"menu\"])) > [data-mobile-nav=\"stats-ring-reserve\"] {\n /* !important \u4E0D\u53EF\u7701\uFF1Acompat \u5C42\u6709\u4E00\u6761 [data-mobile-nav=\"stats-ring-reserve\"]\n { margin: 0 2px 0 0 !important }\u3002\u4E24\u6761\u90FD important \u65F6\u5148\u6BD4\u7279\u5F02\u6027 \u2014\u2014 \u672C\u9009\u62E9\u5668\n \u8FDC\u9AD8\u4E8E\u90A3\u6761\u88F8\u5C5E\u6027\u9009\u62E9\u5668\uFF0C\u52A0 !important \u5C31\u80FD\u8D62\uFF1B\u4E0D\u52A0\u5219\u88AB\u5B83\u538B\u6210 margin-left:0\u3002\n 2026-10-12 \u53D7\u63A7\u5B9E\u9A8C\u5B9E\u6D4B\uFF1A\u4E0D\u52A0 \u2192 \u73AF\u4ECD\u505C\u5728 x=127\u3001\u53D1\u9001\u952E\u53CD\u88AB\u62C9\u5230 150\uFF08188px \u7A7A\u6863\n \u53EA\u662F\u4ECE\u300C\u73AF\u4E0E\u952E\u4E4B\u95F4\u300D\u642C\u5230\u300C\u952E\u7684\u53F3\u4FA7\u300D\uFF09\uFF1B\u52A0 \u2192 \u73AF 310 / \u952E 333\uFF0C\u6B63\u662F\u671F\u671B\u503C\u3002 */\n margin-left: auto !important;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"]:not(:has([class*=\"_trigger\"][aria-haspopup=\"menu\"])) > [class*=\"_primary\"] {\n margin-left: 0;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > [class*=\"_primary\"] {\n flex: none;\n margin-left: auto;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"]:has([class*=\"_trigger\"][aria-haspopup=\"menu\"], > [class*=\"_root\"] > [class*=\"_trigger\"][aria-haspopup=\"dialog\"]) > [class*=\"_primary\"] {\n margin-left: 0;\n }\n /* Issue #191 \u2014 the subagent running form (stop + send, both _primary) has\n NEITHER of the zeroing rule's two gates: ModelSelect renders nothing in an\n addressed subagent session (no aria-haspopup=\"menu\" in the lane) and the\n meter lives in the card's dock row since rc.2 (no _root > dialog trigger\n in the lane either). Both primaries therefore keep the auto margin from the\n rule above, and flex SPLITS the free space between the two auto margins \u2014\n the stop key lands mid-lane with a void on both sides of it.\n Same recipe as the model-present case (:707-712): zero every auto so no\n element competes for the slack, and let justify-content pin the whole\n cluster right. Zeroing alone would hug the LEFT edge instead, so both\n halves are required. Scoped to the dual-primary form, so the main\n session's single-primary path keeps its auto untouched. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]):has([class*=\"_primary\"] ~ [class*=\"_primary\"]) > [class*=\"_trailing\"] {\n justify-content: flex-end;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]):has([class*=\"_primary\"] ~ [class*=\"_primary\"]) > [class*=\"_trailing\"] > [class*=\"_primary\"] {\n margin-left: 0;\n }\n /* 2026-10-20\uFF08\u5E97\u4E3B\uFF09\uFF1A\u300C\u6682\u505C\u952E\u548C\u53D1\u9001\u952E\u2026\u2026\u5927\u5C0F\u7F29\u5C0F\uFF0C\u548C\u5176\u4ED6\u529F\u80FD\u952E\u4FDD\u6301\u4E00\u6837\u7684\u5927\u5C0F\u300D\u3002\n \u540C\u884C\u4E09\u4E2A\u529F\u80FD\u952E\uFF08+ / \u6743\u9650 / \uD83D\uDCCE\uFF09\u7684\u5B98\u65B9\u6807\u79F0\u662F 28\u00D728\uFF0C\u4E3B\u952E\uFF08\u53D1\u9001\u3001\u505C\u6B62\u751F\u6210\uFF09\u5B98\u65B9\n \u662F 34\u00D734 \u2014\u2014 \u624B\u673A\u6863\u628A\u4E3B\u952E\u538B\u5230\u540C\u4E00\u6863\uFF1A\u76D2 28\u00D728\u3001\u5185\u8FB9\u8DDD\u6E05\u96F6\u3001\u5706\u89D2\u4FDD\u6301\u6B63\u5706\uFF0C\n \u56FE\u6807\u4ECD\u662F 16px\uFF0C\u56E0\u6B64\u5706\u5FC3\u4E0E\u540C\u884C\u6309\u94AE\u843D\u5728\u540C\u4E00\u6761\u7EBF\u4E0A\u3002\u53CC\u4E3B\u952E\u5F62\u6001\uFF08\u505C\u6B62 + \u53D1\u9001\uFF09\n \u540C\u6837\u547D\u4E2D\uFF0C\u4E24\u8005\u90FD\u6536\u5C0F\uFF0C8px \u7684\u9632\u8BEF\u89E6\u95F4\u8DDD\u89C4\u5219\u4E0D\u53D7\u5F71\u54CD\u3002\n 2026-10-20 \u4E8C\u8F6E\uFF1AApp \u4F1A\u5F80\u9875\u9762\u6CE8\u5165\u4E00\u5F20\u8BFB\u4E0D\u5230 cssRules \u7684\u6837\u5F0F\u8868\uFF08\u89C1\u4E0A\u65B9\u9875\u7B7E\u6761\n \u6CE8\u91CA\uFF09\uFF0C\u7B2C\u4E00\u7248\u6CA1\u52A0 !important\uFF0C\u771F\u673A\u4E0A\u5C3A\u5BF8\u6CA1\u53D8\u3002\u8FD9\u91CC\u6309\u300C\u6297\u8986\u76D6\u300D\u5199\uFF1A\u4E09\u9879\u5C3A\u5BF8\n \u5168\u90E8 important\uFF0C\u5E76\u8865\u4E00\u6761\u4E0D\u4F9D\u8D56 [data-phase] / _card / _row \u7956\u5148\u94FE\u7684\u515C\u5E95\u9009\u62E9\u5668\n \uFF08\u8F66\u9053\u76F4\u7CFB\u5B50\u5143\u7D20\u5373\u4E3B\u952E\uFF09\uFF0C\u7956\u5148\u94FE\u4EFB\u4E00\u65B0\u4EE3\u65AD\u5C42\u90FD\u4E0D\u81F3\u4E8E\u6574\u6761\u89C4\u5219\u6B7B\u6389\u3002\n \u540E\u7EED\uFF1A2026-10-20 \u56DB/\u4E94\u8F6E\u628A**\u624B\u673A\u6863**\u518D\u6539\u5230 30px + 18px \u56FE\u6807\u5E76\u7EDF\u4E00\u989C\u8272\uFF0C\n \u8986\u76D6\u5728\u6587\u4EF6\u672B\u5C3E\u300C\u8F93\u5165\u533A\u529F\u80FD\u952E\u5C3A\u5BF8\u300D\u6BB5\uFF1B\u672C\u6BB5\u4ECD\u662F 768\u20131023 \u5E73\u677F\u6863\u7684\u503C\uFF0C\u522B\u5220\u3002 */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > [class*=\"_primary\"] {\n box-sizing: border-box !important;\n width: 28px !important;\n min-width: 28px !important;\n height: 28px !important;\n min-height: 28px !important;\n padding: 0 !important;\n border-radius: 50% !important;\n }\n [class*=\"_trailing\"] > [class*=\"_primary\"] {\n box-sizing: border-box !important;\n width: 28px !important;\n min-width: 28px !important;\n height: 28px !important;\n min-height: 28px !important;\n padding: 0 !important;\n border-radius: 50% !important;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] > [class*=\"_primary\"] svg {\n width: 16px !important;\n height: 16px !important;\n }\n [class*=\"_trailing\"] > [class*=\"_primary\"] svg {\n width: 16px !important;\n height: 16px !important;\n }\n\n /* --- ContextMeter hit area on 0.1.7-rc.2+ (issue #140) ---\n The stats-line overlay parks the ring in the composer card's trailing\n lane (right cluster next to the send key \u2014 a deliberate 2026-09-23\n placement, kept per the reporter's confirmation at acceptance). The\n official trigger is 16x20px, far under the touch minimum. Regrow the\n hit area IN PLACE with a transparent ::after (the \uD83D\uDCCE recipe).\n 2026-09-29 acceptance, final geometry (headless-measured): the ring\n svg and its reserve are set to 18px (compat.css.ts \u2014 16px was too\n small to aim, 24px/20px too big, the reporter settled on 18px), the\n width growth is absorbed by the lane's left slack so the key gaps\n stay 6px/5px, and the hit box is a SYMMETRIC 26x26 square\n (inset -4px) keeping the generous touch area around the smaller\n ring \u2014 2px/1px clearance to the model and send keys. The track is\n deepened to 25% black (compat.css.ts) so the donut reads as a\n meter, not a spinner.\n Knobs: the svg/reserve size (compat.css.ts) and this inset; the box\n must stay a square hugging the ring, its edges clamped by the two\n neighbouring keys. The dock container owns only this one dialog\n trigger (the TPS stats pills render plain text), so a scoped\n aria-haspopup=\"dialog\" anchor cannot cross-match anything; the DOM\n ancestry (ring inside the dock container) is unchanged by the\n overlay's absolute positioning. */\n [data-phase] [class*=\"_dock\"] [class*=\"_trigger\"][aria-haspopup=\"dialog\"] {\n position: relative;\n }\n [data-phase] [class*=\"_dock\"] [class*=\"_trigger\"][aria-haspopup=\"dialog\"]::after {\n content: '';\n position: absolute;\n inset: -4px;\n }\n\n /* --- Third-party model seats (issue #60: @hytime/dsh-thinking-effort) ---\n A seat registered on conversation.input.model replaces the official pill,\n so the trailing lane no longer contains an aria-haspopup=\"menu\" trigger:\n the pill absorber rule above never matches, and the meter fallback below\n would split the slack with the seat (two auto margins share it), leaving\n the seat stranded mid-lane. Worse, in the seat's open state the root's\n only child is the absolutely positioned panel, so the root collapses to\n zero width and the panel's right:0 anchor (width min(336px, 100vw - 32px))\n sweeps 336px leftward from wherever the stranded root sits \u2014 230px off\n screen at 393px (reporter-measured: root x=106, panel left=-230; with our\n stylesheet disabled the root sat at x=339 and the panel at +3, which pins\n the blame on our injection). Both repairs anchor on the plugin's own\n stable data-seat-* markers (identical across v0.2.3-v0.3.7) and leave the\n official pill untouched:\n 1. the seat root stretches across the trailing lane with its content\n pushed to the right edge, so the closed chip welds onto the\n [meter][send] cluster AND the grown root consumes all free space,\n which zeroes the meter fallback's margin-left:auto (flexible lengths\n resolve before auto margins \u2014 no double void). The root is also made\n position:static so the panel below anchors to the composer card\n instead \u2014 the root is 0-width while the panel is open, so any\n root-relative offset is meaningless;\n 2. while the panel is open its anchor is laid over the composer card\n (left:0/right:0 against the card's padding box + an auto-margin\n centre), so the panel is centred on the card, never rides the\n collapsed root and never leaves the viewport.\n\n \u2500\u2500 2026-10-04, thinking-effort 0.3.7: the old centring recipe had to go \u2500\u2500\n Repair 2 used to be 'left:50%; right:auto; transform:translateX(-50%)'.\n That recipe only worked while the plugin positioned nothing itself: a\n mobile viewport left the panel hanging off whichever edge the collapsed\n root sat near. 0.3.7 added its own narrow-screen clamp, which writes an\n INLINE 'left' (390px phone, new chat: root x=122, inline left=-106px \u2014\n i.e. 16px, exactly the right place). Inline 'left' wins over the\n stylesheet, so the recipe's 'left' became dead weight while its\n 'transform' kept firing, shifting the panel half its width further left:\n x = 122 + (-106) + (-168) = -152px, off screen by 152px \u2014 the reproduced\n bug. Two layers each half-applied. The fix keeps repair 1 (the stretch\n is still what welds the closed chip onto the [meter][send] cluster) and\n replaces repair 2 with the card-anchored recipe above; 'transform:none'\n is what neutralises the stray translateX, and 'left:0' is '!important'\n because it must beat that inline value. Panel width stays the plugin's\n own (336px, capped at 100%) so the Off/High/Max ticks keep their\n designed spacing.\n\n The panel opens bottom:calc(100% + 8px) above the card, but the card is\n only 70-108px tall on a phone while the panel is 208px, so it always\n overflows upward \u2014 that is the plugin's own desktop behaviour and is\n kept. What is NOT acceptable is overflowing the VIEWPORT, so three\n guards follow (the inner listbox, the keyboard-short phone, landscape).\n Every guard stays inside this mobile media query: desktop untouched. */\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] [data-seat-root] {\n flex: 1 1 auto;\n justify-content: flex-end;\n /* Keep parked here rather than in a second rule: the panel below anchors\n to the card, not to this root. */\n position: static !important;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] [data-seat-root] > [data-seat-panel] {\n left: 0 !important;\n right: 0 !important;\n max-width: min(100%, 420px) !important;\n transform: none !important;\n margin-left: auto !important;\n margin-right: auto !important;\n }\n\n /* Guard 1 \u2014 the panel's inner model listbox opens upward (bottom:58px\n inside the panel) with max-height:min(220px, 100vh - 96px). On a short\n screen that ceiling is taller than the room above the panel, so the\n listbox pokes past the viewport top (320x568: menu y=-41). Clamp it to\n half the viewport minus the panel's own 58px offset + padding. */\n @media (max-height: 700px) {\n [data-seat-model-menu] {\n max-height: min(220px, calc(50vh - 110px)) !important;\n }\n }\n\n /* Guard 2 \u2014 with the on-screen keyboard up (portrait, \u2264505px tall) there\n is not even 208px of room above the card. Let the whole panel scroll\n inside itself instead of escaping the top; children keep their natural\n height so the slider and its ticks are never squashed. */\n @media (orientation: portrait) and (max-height: 505px) {\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] [data-seat-root] > [data-seat-panel] {\n max-height: calc(50dvh - 45px) !important;\n overflow-y: auto !important;\n overscroll-behavior: contain !important;\n }\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] [data-seat-root] > [data-seat-panel] > * {\n flex: 0 0 auto !important;\n }\n }\n\n /* Guard 3 \u2014 landscape: above the card there are only ~156px (the card\n sits low, the panel is 208px), so an upward opening can never fit.\n Detach the panel into a bottom-docked sheet instead; it floats clear\n of the card and the viewport top. */\n @media (orientation: landscape) {\n [data-phase] [class*=\"_card\"]:has(textarea, [data-composer-input]) [class*=\"_row\"]:has([class*=\"_trailing\"]) > [class*=\"_trailing\"] [data-seat-root] > [data-seat-panel] {\n position: fixed !important;\n left: 16px !important;\n right: 16px !important;\n bottom: 12px !important;\n top: auto !important;\n transform: none !important;\n margin: 0 auto !important;\n max-width: min(100%, 420px) !important;\n }\n }\n\n /* --- Composer file entry (0.1.6 host) ---\n The 0.1.6-alpha.2 host deleted the composer's paperclip attach button, so\n the only file entry left is the \u6587\u4EF6 row inside the \"+\" listbox. The\n control is contributed to the host-declared conversation.input.left list\n slot (\"Compact controls at the left of the composer tool row\"), inside the\n tools lane beside the plus button, so only its own box is needed here:\n 28x28 like the plus button and fixed \u2014 one of the row's hit targets, never\n part of the adaptive shrink. Its click handler triggers the host's own\n hidden input[type=file], so intake validation and upload stay host-owned. */\n [data-composer-card] [data-mobile-nav=\"file-upload\"] {\n flex: 0 0 auto !important;\n /* 2026-09-23 \u5E97\u4E3B\uFF1A\"\u89E6\u53D1\u70B9\u6709\u70B9\u5C0F\uFF0C\u6CA1\u90A3\u4E48\u5BB9\u6613\u70B9\" \u21D2 \u76D2\u5B50 28\u00D728 \u2192 34\u00D734\n \uFF08\u9762\u79EF +47%\uFF09\uFF0C\u518D\u7531\u4E0B\u9762\u7684 ::after \u5411\u5916\u6269 4px\uFF08\u6700\u7EC8\u547D\u4E2D\u533A\u7EA6 42\u00D742\uFF09\u3002\n **\u56FE\u6807\u4F4D\u7F6E\u4E0D\u53D8**\uFF1A\u76D2\u5BBD +6 \u540E margin-left \u4ECE -10 \u6536\u5230 -13\uFF0C\u56FE\u6807\u4E2D\u5FC3\u539F\u5730\u4E0D\u52A8\uFF1B\n \u9AD8\u5EA6\u5BF9\u9F50\u53D1\u9001\u952E\u7684 34px\uFF0C\u884C\u9AD8\u4E0D\u53D7\u5F71\u54CD\u3002 */\n /* 2026-10-07 \u5E97\u4E3B\uFF1A\u300C\u70B9\u4E00\u4E0B\u6709\u4E00\u5C42\u6DF1\u4E00\u70B9\u7684\u7070\u8272\uFF0C\u4E5F\u6709\u4E00\u5C42\u6D45\u4E00\u70B9\u7684\u7070\u8272\uFF0C\u53BB\u6389\u4E00\u5C42\u300D\u3002\n \u6839\u56E0\u662F**\u5D4C\u5957\u4E24\u5C42**\uFF1A\u5BBF\u4E3B\u7684\u6309\u94AE\u76D2\u5E95\u8272\uFF0834x34\u3001\u5706\u89D2 8\uFF09\u4E0E\u6211\u4EEC\u7684 ::before \u80F6\u56CA\n \uFF0828x28 \u5706\uFF09\u534A\u900F\u660E\u53E0\u534A\u900F\u660E \u2014\u2014 \u91CD\u53E0\u533A\u6DF1\u3001\u5916\u5708\u6D45\u3002\u538B\u5C42\u53E0\uFF08!important\uFF09\u5728\u771F\u673A\u4E0A\n \u538B\u4E0D\u4F4F\u90A3\u4E00\u5C42\uFF08\u5B9E\u6D4B\u6309\u4E0B\u4ECD\u662F 233 \u5916\u5708 + 222 \u5185\u5C42\uFF09\uFF0C\u6240\u4EE5\u6539\u6210**\u7ED3\u6784\u4E0A\u53EA\u6709\u4E00\u5C42**\uFF1A\n \u53EF\u89C1\u80F6\u56CA = \u6309\u94AE\u76D2\u672C\u8EAB\u3002\u76D2\u5B50 28x28 + \u5168\u5706\u89D2\uFF0C\u4E0E\u52A0\u53F7\u540C\u5C3A\u5BF8\uFF1B\u56FE\u6807\u4E2D\u5FC3\u4E0D\u53D8\n \uFF08\u76D2\u5BBD 34\u219228 \u21D2 margin-left \u7531 -11 \u6536\u5230 -8\uFF09\uFF1B\u547D\u4E2D\u533A\u4ECD\u7531 ::after \u5916\u6269\u3002 */\n width: 28px !important;\n min-width: 28px !important;\n max-width: 28px !important;\n height: 28px !important;\n min-height: 28px !important;\n padding: 0 !important;\n position: relative !important;\n /* \u5DE6\u79FB 10px + \u56FE\u6807 14\u219216px\uFF082026-09-23\uFF0C\u5E97\u4E3B\uFF1A\"\u592A\u5F80\u53F3\u4E86\u3001\u6709\u70B9\u5C0F\"\uFF09\uFF1A\n \u5DE5\u5177\u9053\u73B0\u5728\u662F [+][\u26A0\u2304][\uD83D\uDCCE]\uFF0C\u5BBF\u4E3B\u7ED9 modes \u63A7\u4EF6\u7559\u4E86\u8F83\u5BBD\u7684\u5C3E\u90E8\u7559\u767D\uFF0C\uD83D\uDCCE \u770B\u7740\n \u79BB\u5DE6\u8FB9\u4E00\u622A\u3002\u4E0E\u53C2\u8003\u56FE\u9010\u50CF\u7D20\u5BF9\u9F50\uFF08\u4EE5 + \u4E3A\u951A\u70B9\uFF09\uFF1A\u53C2\u8003 \uD83D\uDCCE \u58A8\u8FF9 107..117 CSS\uFF0C\n \u6211\u4EEC\u539F\u5148\u662F 114..123\uFF1B\u800C\u58A8\u8FF9\u9AD8\u5EA6 48 vs \u53C2\u8003 54 \u7269\u7406 px \u21D2 \u56FE\u6807 14 \u504F\u5C0F\uFF0C\n \u6362\u6210\u5BBF\u4E3B\u901A\u7528\u7684 16\uFF08+ / \u26A0 \u90FD\u662F 16\uFF09\u300228px \u76D2 + 16px \u56FE\u6807\u5C45\u4E2D \u21D2 \u58A8\u8FF9\u5DE6\u7F18\n = \u76D2\u5DE6\u7F18 + 8.85\uFF0C\u6545\u76D2\u5DE6\u7F18\u53D6 98 \u21D2 margin-left: -10px\uFF08\u5403\u6389 6px gap \u540E\u518D\n \u538B\u8FDB modes \u5C3E\u90E8\u7559\u767D 4px\uFF0C\u4E0D\u78B0\u5B83\u7684\u58A8\u8FF9\uFF1Achevron \u58A8\u8FF9\u6B62\u4E8E ~91\uFF09\u3002\n \u8FD9\u4E00\u4E2A\u6570\u503C\u5C31\u662F\"\u5F80\u5DE6\u591A\u5C11\"\u7684\u65CB\u94AE\uFF0C\u53EF\u6309\u773C\u775B\u8C03\uFF0C\u522B\u52A8\u522B\u7684\u3002 */\n margin: 0 0 0 -8px !important;\n display: grid !important;\n place-items: center;\n border: 0 !important;\n border-radius: 999px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n /* \u6309\u4E0B/\u60AC\u505C\u53CD\u9988\uFF1A\u5BBF\u4E3B\u5176\u5B83\u6309\u94AE\uFF08\u52A0\u53F7\u5E38\u9A7B\u3001\u6A21\u578B\u4E0E\u6743\u9650\u89E6\u53D1\u5668\u6309\u4E0B\uFF09\u90FD\u6709\u7070\u80F6\u56CA\uFF0C\n \u53EA\u6709\u6211\u4EEC\u8FD9\u4E2A\u662F\u7EAF\u900F\u660E\u3001\u4E5F\u6CA1\u6709 :active \u2014\u2014 \u5E97\u4E3B 2026-09-23\uFF1A\"\u6587\u4EF6\u4E0A\u4F20\u90A3\u4E2A\u56FE\u6807\n \u600E\u4E48\u6CA1\u6709\u80F6\u56CA\uFF1F\"\uFF08\u70B9\u4E86\u6CA1\u53CD\u5E94\uFF09\u3002\u7528\u5BBF\u4E3B\u81EA\u5DF1\u7684 hover token\uFF0C\u89C6\u89C9\u4E0E\u5B98\u65B9\u4E00\u81F4\u3002 */\n /* \u53EF\u89C1\u80F6\u56CA\u53EA\u5728 ::before \u4E0A\u753B 28\u00D728 \u7684\u5706\uFF08\u4E0E\u52A0\u53F7\u540C\u5C3A\u5BF8\uFF0C\u5E97\u4E3B\uFF1A\"\u80F6\u56CA\u6709\u70B9\u592A\u5927\"\uFF09\uFF0C\n \u6309\u94AE\u76D2\u5B50\u4ECD\u662F 34\u00D734 + ::after \u5916\u6269 \u2014\u2014 \u547D\u4E2D\u533A\u5927\u3001\u770B\u8D77\u6765\u5C0F\uFF0C\u4E24\u8005\u89E3\u8026\u3002 */\n [data-composer-card] [data-mobile-nav=\"file-upload\"]::before {\n content: '';\n position: absolute;\n inset: 3px;\n border-radius: 999px;\n background: transparent;\n transition: background .12s ease;\n }\n [data-composer-card] [data-mobile-nav=\"file-upload\"]::before {\n /* \u80F6\u56CA\u5DF2\u7531\u76D2\u5B50\u672C\u4F53\u627F\u62C5\uFF0C\u8FD9\u4E00\u5C42\u6C38\u4E45\u900F\u660E\uFF08\u4FDD\u7559\u8282\u70B9\u662F\u4E3A\u4E86\u4E0D\u60CA\u52A8\u65E2\u6709\u951A\u70B9\uFF09\u3002 */\n background: transparent !important;\n }\n /* 2026-10-07 \u5E97\u4E3B\uFF1A\"\u70B9\u4E00\u4E0B\u6709\u4E00\u5C42\u6DF1\u4E00\u70B9\u7684\u7070\u8272\uFF0C\u4E5F\u6709\u4E00\u5C42\u6D45\u4E00\u70B9\u7684\u7070\u8272\uFF0C\u53BB\u6389\u4E00\u5C42\"\u3002\n \u771F\u56E0\u662F**\u534A\u900F\u660E\u53E0\u534A\u900F\u660E**\uFF0C\u4E0D\u662F\u6211\u4EEC\u753B\u4E86\u4E24\u5C42\u80F6\u56CA\uFF1A\u5BBF\u4E3B\u5168\u5C40 CSS \u91CC\u6709\n \u300Cbutton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}\u300D\n \uFF08\u7279\u5F02\u6027 0,2,1 > \u4E0A\u9762\u90A3\u6761\u57FA\u7840\u89C4\u5219\u7684 0,2,0\uFF0C\u6240\u4EE5\u5B83\u8D62\u4E86\uFF09\u4E0E\n \u300Cbutton:active{background-color:#0000001f}\u300D\uFF0C\u4E24\u8005\u90FD\u753B\u5728\u8FD9\u4E2A\u6309\u94AE\u7684**\u76D2\u5B50**\u4E0A\uFF1B\n \u800C ::before \u7684\u53EF\u89C1\u80F6\u56CA\u53C8\u753B\u4E00\u5C42 \u21D2 \u91CD\u53E0\u533A\u6DF1\u3001\u5916\u5708\u6D45\uFF0C\u770B\u7740\u5C31\u662F\u4E24\u5C42\u7070\u3002\n \u53EF\u89C1\u80F6\u56CA\u53EA\u7559 ::before \u4E00\u5C42\uFF1A\u76D2\u5B50\u5728\u6240\u6709\u72B6\u6001\u4E0B\u5F3A\u5236\u900F\u660E\uFF08::after \u53EA\u6709\u547D\u4E2D\u533A\u3001\u65E0\u5E95\u8272\uFF09\u3002 */\n [data-composer-card] [data-mobile-nav=\"file-upload\"]:hover,\n [data-composer-card] [data-mobile-nav=\"file-upload\"]:active,\n [data-composer-card] [data-mobile-nav=\"file-upload\"]:focus-visible {\n background: var(--dsw-alias-interactive-bg-hover, rgba(0, 0, 0, .06));\n box-shadow: none !important;\n outline: none !important;\n border-color: transparent !important;\n }\n /* \u538B\u6389\u6D4F\u89C8\u5668\u9ED8\u8BA4\u7684\u6DE1\u84DD tap \u9AD8\u4EAE\uFF08\u5E97\u4E3B 2026-09-23\uFF1A\"\u5355\u7EAF\u70B9\u51FB\u56FE\u6807\uFF0C\u51FA\u73B0\u4E00\u4E2A\u6DE1\u84DD\u8272\n \u7684\u539F\u59CB\u7684\u70B9\u51FB\u753B\u9762\"\uFF09\u3002\u8BFB\u6E90\u7801\u53D6\u8BC1\uFF1A\u5BBF\u4E3B\u5934\u90E8\u90A3\u51E0\u4E2A\u5305\uFF08dsh-client-ui-subagent /\n agent-preset / dsh-experimental-client-ui-agent-team / jobs\uFF09**\u90FD\u6CA1\u6709 :active\u3001\n \u4E5F\u6CA1\u6709\u4EFB\u4F55 tap-highlight \u5904\u7406**\uFF0C\u89E6\u6478\u8BBE\u5907\u4E0A\u70B9\"\u6807\u51C6\u6A21\u5F0F / Agent Team / 1 \u4E2A\u5B50\u4EE3\u7406 /\n \u5BF9\u8BDD\u00B7\u8F68\u8FF9\"\u5C31\u4F1A\u53E0\u4E00\u5C42\u539F\u59CB\u9AD8\u4EAE\uFF1B\u6211\u4EEC\u8F93\u5165\u533A\u7684\u63A7\u4EF6\u65E9\u5DF2\u5904\u7406\uFF08\u89C1\u4E0A\u9762 file-upload \u90A3\u7EC4\uFF09\u3002\n \u505A\u6CD5\u4E0E\u8F93\u5165\u533A\u540C\u6E90\uFF1A\u9AD8\u4EAE\u900F\u660E\uFF0C\u6309\u4E0B\u53CD\u9988\u4EA4\u7ED9\u5BBF\u4E3B\u81EA\u5DF1\u7684 :hover/:active token\n \uFF08\u90A3\u51E0\u4E2A\u5305\u5404\u6709 2~9 \u6761 :hover \u89C4\u5219\uFF0C\u89E6\u6478\u65F6 Chromium \u4F1A\u5957\u7528\uFF09\u3002 */\n /* \u8986\u76D6\u8303\u56F4\u653E\u5BBD\uFF1A\u5BBF\u4E3B\u6709\u4E9B\u63A7\u4EF6\u4E0D\u662F button\uFF08\u5B9E\u6D4B\u8F93\u5165\u533A\u91CC\u5C31\u6709 [role=button]\u3001\u5E26\n tabindex \u7684 div \u5F62\u6001\uFF09\uFF0C\u6240\u4EE5\u4E09\u7C7B\u4E00\u8D77\u6536\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header button,\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tab\"],\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"menuitem\"],\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"button\"],\n [data-mobile-nav=\"frame\"] [data-phase] header [tabindex],\n [data-composer-card] button,\n [data-composer-card] [role=\"button\"],\n [data-composer-card] [tabindex] {\n -webkit-tap-highlight-color: transparent;\n }\n\n /* \u6DF1\u8272\u4E0B\u9876\u680F\u4E0E\u9875\u9762\u5E95\u8272\u7684\u65AD\u5C42\uFF08issue #176\u300C\u51CF\u8F7B\u9876\u90E8\u7EAF\u9ED1\u533A\u57DF\u4E0E\u7F51\u9875\u5934\u90E8\u7684\u7A81\u5140\u8272\u5DEE\u300D/\n 2026-10-11 \u771F\u673A\u53CD\u9988\uFF1A\u624B\u673A\u4E0A\u5934\u90E8\u5448\u7070\u9ED1\u4E00\u5757\uFF0C\u8DDF\u4E0A\u9762\u90A3\u884C\u7CFB\u7EDF\u65F6\u95F4\u680F\u5206\u5F97\u592A\u5F00\uFF09\u3002\n \u5B9E\u6D4B\uFF08393\u00D7844\uFF0C\u771F\u5B9E\u4F1A\u8BDD\uFF0C\u6DF1\u8272\uFF09\uFF1Apage/body \u4E0E frame \u90FD\u662F #151517\uFF08--dsw-alias-bg-base\uFF09\uFF0C\n \u800C\u5BBF\u4E3B\u4F1A\u8BDD\u5934\u90E8\u81EA\u5E26\u5C42\u8272 #232324\uFF0C\u5934\u90E8\u4E0A\u65B9\u8FD8\u5939\u7740\u4E00\u6761\u8DDF\u968F\u9875\u9762\u5E95\u8272\u7684\u5B89\u5168\u533A\u5E26\n \u21D2 \u300C\u6DF1\u8272\u5E26 \u2192 \u8F83\u4EAE\u5934\u90E8 \u2192 \u6DF1\u8272\u5185\u5BB9\u300D\u4E09\u6BB5\u65AD\u5C42\u3002\n \u5904\u7406\uFF1A\u624B\u673A\u6863\uFF08\u672C\u5757\u5728\u79FB\u52A8\u5A92\u4F53\u67E5\u8BE2\u5185\uFF09\u628A\u5934\u90E8\u5E95\u8272\u5E76\u5230\u9875\u9762\u5E95\u8272\uFF0C\u5C42\u6B21\u6539\u7531\u5206\u9694\u7EBF\u4E0E\u5185\u5BB9\u627F\u62C5\uFF1B\n \u6D45\u8272\u6863\u5BBF\u4E3B\u4E24\u5934\u540C\u4E3A\u767D\u3001\u672C\u6765\u5C31\u6CA1\u6709\u65AD\u5C42\uFF0C\u4E0D\u53C2\u4E0E\uFF1B\u684C\u9762\u6863\u4E0D\u78B0\u3002\n \u5BBF\u4E3B\u6DF1\u8272\u6807\u8BB0\u6302\u5728 body \u4E0A\uFF08\u5B9E\u6D4B\u8BBE body[data-ds-dark-theme] \u5373\u5207\u5230 #151517\uFF09\uFF0C\n html \u4E0A\u82E5\u4E5F\u6302\u540C\u4E00\u4E2A\u6807\u8BB0\u4E00\u5E76\u8986\u76D6\u3002 */\n body[data-ds-dark-theme] [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header,\n html[data-ds-dark-theme] [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header {\n background-color: var(--dsw-alias-bg-base, #151517) !important;\n }\n /* \u58C1\u7EB8\u517C\u5BB9\uFF08issue #228\uFF09\uFF1A\u540C\u4E00\u4E2A\u63D2\u4EF6\u628A --dsw-alias-bg-base \u4E5F\u7F6E\u4E3A transparent\n \uFF08\u89C1\u4E0A\u65B9\u6DF1\u8272\u9876\u680F\u89C4\u5219\uFF09\u3002\u6DF1\u8272\u4E0B\u9876\u680F\u7528\u8BE5\u4EE4\u724C\u4E0E\u9875\u9762\u540C\u8272\uFF0C\u4EE4\u724C\u88AB\u6E05\u7A7A\u540E\u9876\u680F\n \u5931\u53BB\u5E95\u8272\uFF0C\u6D88\u606F\u6EDA\u52A8\u533A\u4ECE\u6807\u9898\u884C\u4E0B\u65B9\u7A7F\u8FC7\u3002\u58C1\u7EB8\u542F\u7528\u65F6\u7528\u8BE5\u4EE4\u724C\u81EA\u8EAB\u7684\u6DF1\u8272\u9759\u6001\n \u5B9A\u4E49\u8865\u56DE\u539F\u8272\uFF1B\u6D45\u8272\u6863\u901A\u7528\u89C4\u5219\u5DF2\u7ECF\u7528\u672A\u88AB\u8986\u76D6\u7684 --dsw-alias-bg-layer-1\uFF0C\n \u4E0D\u9700\u8981\u65B0\u89C4\u5219\u3002\u95E8\u63A7\u542B data-ds-dark-theme\uFF0C\u7279\u5F02\u6027 (0,4,2) \u9AD8\u4E8E\u4E0A\u65B9\u6DF1\u8272\n \u89C4\u5219\u7684 (0,3,2)\uFF0C\u4E0D\u4F9D\u8D56\u6E90\u7801\u987A\u5E8F\u3002 */\n /* @patch\n id: wallpaper-header-fill\n for: deepseek-harness-background 0.6.x \u7684 body[data-dsh-bg]\uFF08\u58C1\u7EB8\u542F\u7528\u65F6\u628A --dsw-alias-bg-base \u7F6E\u4E3A transparent\uFF09\n why: \u6DF1\u8272\u9876\u680F\u4EE5\u8BE5\u4EE4\u724C\u4E0E\u9875\u9762\u540C\u8272\uFF0C\u7B2C\u4E09\u65B9\u63D2\u4EF6\u628A\u5B83\u6E05\u7A7A\u540E\u9876\u680F\u5931\u53BB\u5E95\u8272\uFF0C\u6EDA\u52A8\u5185\u5BB9\u4ECE\u6807\u9898\u884C\u7A7F\u8FC7\n until: \u4E0A\u6E38\u63D0\u4F9B\u4E0D\u900F\u660E\u7684\u9762\u677F\u586B\u5145\u63A5\u7F1D\uFF0C\u6216\u4E0D\u518D\u628A --dsw-alias-bg-base \u7F6E\u7A7A\u2014\u2014\u5C4A\u65F6\u672C\u5757\u5220\u9664\n test: tests/wallpaper-surface-fill.test.ts\n */\n body[data-ds-dark-theme][data-dsh-bg] [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header {\n background-color: var(--dsw-static-neutral-bluish-950, #151517) !important;\n }\n /* \u5934\u90E8 UI \u7684\u6309\u4E0B\u53CD\u9988\uFF08\u5E97\u4E3B 2026-09-23\uFF1A\"\u662F\u5934\u90E8 UI\uFF0C\u6CA1\u6709\u89E6\u53D1\u53CD\u9988\"\uFF09\u3002\n \u53D6\u8BC1\uFF1A\u5934\u90E8\u56DB\u4E2A\u5BBF\u4E3B\u5305 :active \u5168\u4E3A 0\uFF0C\u53CD\u9988\u53EA\u6302 :hover\u3002\n \u26A0 \u7B2C\u4E00\u7248\u6211\u7ED9\u6574\u9897 button \u4E0A background-color\uFF0C\u5E97\u4E3B\u5B9E\u6D4B\"\u80F6\u56CA\u8FC7\u5BBD\u3001\u8DD1\u5230\u5B50\u4EE3\u7406\u4E0B\u9762\"\n \u2014\u2014 \u56E0\u4E3A button \u76D2\u6BD4\u53EF\u89C1\u80F6\u56CA\u5927\uFF08\u82AF\u7247\u6587\u5B57\u53EA\u5360\u76D2\u7684\u4E00\u90E8\u5206\uFF09\u3002\u6240\u4EE5\u6539\u6210**\u4E0D\u6539\u51E0\u4F55**\u7684\n \u6309\u4E0B\u6548\u679C\uFF1A\u6574\u4F53\u538B\u6697\uFF08.92 \u2248 \u5BBF\u4E3B token \u7684\u89C2\u611F\u5F3A\u5EA6\uFF1B\u592A\u6DE1\u5E97\u4E3B\u4F1A\u89C9\u5F97\"\u6CA1\u53D8\"\uFF09\u3002\u80F6\u56CA\u7C7B\u7684\u89C6\u89C9\u4ECD\u7531\u5BBF\u4E3B\u81EA\u5DF1\u7684 chip \u80CC\u666F\u8D1F\u8D23\u3002\n \u4E0D\u7528 position/\u4F2A\u5143\u7D20\uFF1A\u5934\u90E8\u82AF\u7247\u91CC\u6302\u7740\u5BBF\u4E3B\u7684\u5F39\u5C42\uFF0C\u6539 position \u4F1A\u632A\u52A8\u5305\u542B\u5757\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header button:active,\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tab\"]:active {\n filter: brightness(.92);\n }\n /* \u5934\u90E8\u90A3\u4E9B v \u7684\u7FFB\u8F6C\uFF1A**\u6807\u51C6\u6A21\u5F0F\u90A3\u4E2A\u73B0\u5728\u4F1A\u7FFB** \u2014\u2014 \u89C4\u5219\u5728\u672C\u6587\u4EF6\u300CDSHA \u96C6\u6210\u5C42\uFF1A\u9884\u8BBE chip\u300D\n \u90A3\u4E00\u5757\uFF08\u641C data-dsha-agent-preset=\"header\" \u7684 svg:last-of-type \u4E24\u6761\uFF09\u3002\u8FD9\u91CC\u7559\u4E00\u6BB5\u7EA0\u6B63\u8BB0\u5F55\uFF0C\n \u514D\u5F97\u540E\u4EBA\u88AB\u5DF2\u7ECF\u4F5C\u5E9F\u7684\u65E7\u7ED3\u8BBA\u8BEF\u5BFC\uFF1A\n\n \u00B7 \u65E7\u7ED3\u8BBA\uFF08\u540C\u65E5\u65E9\u5148\u5199\u7684\uFF09\u79F0\"\u672C WebView \u91CC\u8BE5 svg \u7684 CSS transform \u5B8C\u5168\u5931\u6548\"\u2014\u2014**\u9519\u7684**\u3002\n \u771F\u56E0\u662F\u9884\u8BBE chip \u7684 > svg \u4E0A\u6709\u4E00\u6761\u6211\u4EEC\u81EA\u5DF1\u5199\u7684\n [data-dsha-agent-preset=\"header\"] > svg { transform: none !important }\uFF08DSHA \u96C6\u6210\u5C42\u62FF\u5B83\u628A\n \u56FE\u6807\u62C9\u56DE\u9759\u6001\u6D41\uFF09\u3002**\u5185\u8054 transform: rotate(45deg) \u6CA1\u5E26 !important\uFF0C\u88AB\u90A3\u6761\u538B\u6389**\uFF0C\n \u4E8E\u662F\u91CF\u51FA\"\u76D2\u5B50\u4E0D\u53D8\u3001computed \u4ECD\u662F none\"\uFF0C\u88AB\u6211\u8BEF\u5224\u6210 WebView \u4E0D\u5403 CSS transform\u3002\n \u00B7 \u5B50\u4EE3\u7406 chip \u7684 v \u4E00\u76F4\u662F\u5BBF\u4E3B\u81EA\u5E26\uFF1Adsh-client-ui-subagent \u7684\n .ZKlsPq_trigger svg{transition:transform .12s} + \u7C7B .ZKlsPq_triggerOpen{transform:rotate(180deg)}\u3002\n \u00B7 \u7981\u6B62\u5BF9\u5934\u90E8 svg \u5199\u901A\u914D\u89C4\u5219\uFF08header svg{...} / [class*=chevron]{...}\uFF09\uFF1A\u90A3\u4F1A\u8986\u76D6\u5B50\u4EE3\u7406 chip\n \u81EA\u5DF1\u7684 triggerOpen \u72B6\u6001\uFF0C\u51FA\u73B0\"\u4FEE\u4E00\u4E2A\u538B\u6389\u53E6\u4E00\u4E2A\"\uFF08\u8FD9\u6B63\u662F\u5F53\u65F6\u53CD\u590D\u7FFB\u8F66\u7684\u539F\u56E0\uFF09\u3002 */\n /* \u8F93\u5165\u533A**\u5BBF\u4E3B\u6E32\u67D3**\u7684\u529F\u80FD\u952E**\u4E0D\u518D\u81EA\u52A0\u80F6\u56CA**\uFF08\u5E97\u4E3B 2026-09-23\uFF1A\"\u70B9\u51FB\u529F\u80FD\u952E\u600E\u4E48\u6709\u4E24\u4E2A\n \u7070\u8272\u7684\u53E0\u52A0\uFF1F\"\uFF09\u3002\n \u539F\u56E0\uFF1A\u5BBF\u4E3B\u672C\u6765\u5C31\u6709\u81EA\u5DF1\u7684 hover \u5E95\u8272\uFF08conversation \u5305 13 \u6761 :hover\u3001model-selection 3 \u6761\u3001\n permission-presets 2 \u6761\u3001input-trigger 3 \u6761\uFF09\uFF0C\u6211\u4EEC\u518D\u52A0\u4E00\u5C42 ::before \u5C31\u662F**\u4E24\u5C42\u7070\u53E0\u5728\u4E00\u8D77**\u3002\n \u6559\u8BAD\uFF1A\u4E0A\u4E00\u8F6E\u5E97\u4E3B\u8BF4\"\u8FD9\u51E0\u4E2A\u529F\u80FD\u6CA1\u6709\u89E6\u51FB\u53CD\u9988\"\uFF0C\u6211\u636E\u6B64\u52A0\u4E86\u80F6\u56CA \u2014\u2014 \u5B9E\u9645\u662F\u90A3\u6B21\u521A\u628A\u6D4F\u89C8\u5668\u9ED8\u8BA4\n \u6DE1\u84DD tap \u9AD8\u4EAE\u538B\u6389\u3001\u89C2\u611F\u53CD\u5DEE\u7684\u9519\u89C9\uFF1B**\u5BBF\u4E3B\u5DF2\u6709\u7684\u53CD\u9988\u4E0D\u8981\u518D\u53E0\u4E00\u5C42**\u3002\n \u6211\u4EEC\u81EA\u5DF1\u6CE8\u5165\u7684 \uD83D\uDCCE\uFF08[data-mobile-nav=\"file-upload\"]\uFF09\u4F8B\u5916\uFF1A\u5BBF\u4E3B\u6CA1\u6709\u5BF9\u5E94\u63A7\u4EF6\u3001\u4E5F\u5C31\u6CA1\u6709\u5E95\u8272\uFF0C\n \u5B83\u7684\u80F6\u56CA\u7559\u5728\u4E0A\u9762\u90A3\u7EC4\u89C4\u5219\u91CC\u3002 */\n /* \u547D\u4E2D\u533A\u5916\u6269\uFF1A::after \u5C5E\u4E8E\u6309\u94AE\u672C\u8EAB\uFF0C\u4E00\u8D77\u53C2\u4E0E\u547D\u4E2D\u6D4B\u8BD5\uFF0C\u89C6\u89C9\u5B8C\u5168\u4E0D\u53D8\u3002 */\n [data-composer-card] [data-mobile-nav=\"file-upload\"]::after {\n content: '';\n position: absolute;\n inset: -7px;\n border-radius: 999px;\n }\n /* A busy submit phase or a subagent session refuses attachments. The host\n gates intake on canAcceptDrop (package-private), so this reads the closest\n observable facts \u2014 input phase and subagent \u2014 and keeps the control from\n opening a dialog the host would then reject. */\n [data-composer-card] [data-mobile-nav=\"file-upload\"]:disabled {\n opacity: 0.38;\n cursor: default;\n }\n /* The hidden input[type=file] this control triggers only exists on\n 0.1.6-alpha.2+ hosts (the rc generation's intake is paste/drop only),\n while the host renders the input.left seat on both generations. Hide the\n control wherever the host has no file input for it to trigger \u2014 its click\n would otherwise be a permanent silent no-op there (review 2026-09-19). */\n [data-composer-card]:not(:has(input[type=file])) [data-mobile-nav=\"file-upload\"] {\n display: none !important;\n }\n\n /* --- Composer vertical slack on mobile (0.1.6 host) ---\n The host's own .card padding-top:8px + gap:12px and .row padding leave 29px of pure\n blank space in a 98px single-line card (measured). Only the vertical slack is trimmed;\n horizontal padding and both hit targets stay untouched. Scoped to the active phase on\n purpose: the hero composer's input carries the host's own min-height floor, and trimming\n it there re-creates the clip/scrollbar defect recorded under Pitfalls\u300Chero \u8F93\u5165\u6846\u4E0B\u9650\u300D. */\n /* DSHA\uFF1A\u8F93\u5165\u5361\u7247\u81EA\u8EAB\u7559\u767D\u504F\u5927\u3002\u5BBF\u4E3B\u90A3\u4E24\u58F0\u660E\u5168\u51FA\u81EA\u5B83\u81EA\u5DF1\u7684\n dsh-client-ui-conversation\uFF08.uV2eYG_card \u662F padding-top:8px + gap:12px\uFF0C\n .uV2eYG_row \u518D\u5403 padding:2px 8px 6px\uFF09\uFF0C\u5355\u884C\u8F93\u5165\u65F6\u5361\u7247 98px \u91CC\u6709 29px\n \u662F\u7EAF\u7A7A\u767D\u3002\u624B\u673A\u4E0A\u53EA\u538B\u7EB5\u5411\u7559\u767D\uFF08\u771F\u673A\u5B9E\u6D4B moderate \u6863\uFF09\uFF1A\n \u5361\u7247 98 -> 78\u3001\u7F16\u8F91\u5668 36 -> 32\u3001\u6309\u94AE\u884C 42 -> 36\u3001\u6587\u5B57\u5E95\u5230\u6309\u94AE\u9876 29 -> 19px\u3002\n \u6A2A\u5411 padding\uFF088px\uFF09\u4E0E\u4E24\u4E2A\u6309\u94AE\u5C3A\u5BF8\uFF0828/34px\uFF09\u4E00\u5F8B\u4E0D\u52A8\uFF0C\u89E6\u63A7\u76EE\u6807\u4E0D\u53D8\uFF1B\n \u7F16\u8F91\u5668\u4ECD\u662F\u53EF\u589E\u957F\u7684\u591A\u884C\u6846\uFF08max-height 336px\uFF09\uFF0C\u53EA\u662F\u5355\u884C\u65F6\u4E0D\u518D\u57AB\u9AD8\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase=\"active\"] [data-composer-card] {\n padding-top: 2px !important;\n gap: 4px !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase=\"active\"] [data-composer-card] [class*=\"_row\"] {\n padding: 0 8px !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase=\"active\"] [data-composer-card] [data-composer-input],\n [data-mobile-nav=\"frame\"] [data-phase=\"active\"] [data-composer-card] [class*=\"_scroll\"] {\n min-height: 28px !important;\n padding-top: 2px !important;\n }\n /* --- Session header on mobile ---\n Keep the host-owned metadata in one responsive row. The conversation\n title, the mode text and the running/subagent status all keep their\n words; the one tenant that yields width when a phone runs out of it is\n the background-job trigger's verbose label (\"1 background job running\"),\n while Files keeps its hit area. */\n /* Both !important flags are load-bearing. The host's session-controller sheet\n ships [data-dsh-frame] [data-dsh-responsive-part=\"conversation-header\"] with\n padding-left: 60px !important under (max-width: 768px), so a plain\n declaration here loses however specific it is: measured 2026-09-13 at\n 390px, the computed padding-left stayed 60px and the title still began at\n x=100 with our rule present, matching and later in source order. The value\n is 0 because our own toggle already occupies that left seat (painted at\n x=8-36), so the host reservation is pure dead space on a phone. */\n [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header {\n padding-left: 0 !important;\n padding-right: 8px !important;\n position: relative !important;\n /* Opaque AND above the flow, both required: the host bar has no background,\n and the message flow is a later sibling, so it painted OVER the bar (three\n headless screenshots 2026-10-07: transparent -> content read through the\n title row; opaque but unraised -> byte-identical to transparent, i.e. the\n background was painted underneath; opaque + raised -> pixel-identical to\n the untouched band). The scroll box runs underneath because of the\n \"selection-drag autoscroll ramp\" rule above (it lifts it by\n --mobile-nav-header-h). Same surface token the panel ghost uses, so themes\n carry over; the host keeps its --dsw-alias-border-l3 bottom border.\n z-index 30 clears the flow's own raised layers (host banners measured at\n z 6-7 and the marks slot / composer seat at 7 on the live host) while\n staying under this plugin's overlay tier (55+ backdrops/panels, FAB 21 is\n hero-only where the header is hidden, drawer/menus 1000+) so a dialog or\n the drawer still covers the bar. */\n background: var(--dsw-alias-bg-layer-1, #fff) !important;\n z-index: 30 !important;\n }\n /* The hero phase's empty header must stay hidden on phones. The host hides\n it via the headerHidden class at (0,1,0), but its own session-controller\n sheet re-shows the conversation header as a grid at <=768px \u2014\n [data-dsh-frame] [data-dsh-responsive-part=\"conversation-header\"] with\n display grid at (0,2,0) \u2014 and that beats the hide on the very element\n carrying both classes. Result measured 2026-09-19 at 390px: an empty 85px\n header paints only its 1px border-bottom (--dsw-alias-border-l3) as a stray\n gray hairline under the status bar (pixel-scanned at y=84-85,\n rgb(224,224,224)); desktop keeps display none and no line. Our (0,3,1)\n re-hide needs no !important: the grid rule's display is a normal\n declaration and our style tag loads last. The header carries no children in\n hero (drawer entry is the FAB), so hiding it frees the dead 85px too. */\n [data-mobile-nav=\"frame\"] [data-phase] header[class*=\"_headerHidden\"] {\n display: none;\n }\n /* 0.1.6-alpha.2 renamed the hero-empty marker: headerHidden -> headerBlank\n (audit \u00A71 row 3), so the rule above is a dead needle on alpha.2 and this\n one is dead on rc hosts \u2014 together they cover both generations. Same\n (0,3,1) shape, same no-!important reasoning as above. */\n [data-mobile-nav=\"frame\"] [data-phase] header[class*=\"headerBlank\"] {\n display: none;\n }\n /* Header popovers resolve against the header, not against their 28px flow\n box. 0.1.5's background-job chip anchors its menu with\n position:absolute; top:calc(100% + 5px) inside .QsffPG_root\n {position:relative} \u2014 a 28px-tall chip \u2014 so the menu was laid out at\n x=-16 (our right:8px resolved against that 156px chip root) and then\n clipped twice: by our own overflow:hidden on the chip root and by the\n host's [data-dsh-responsive-part=\"session-title-cluster\"]\n {overflow:hidden}. The chip still reported aria-expanded=true with\n nothing painted and nothing hit-testable: measured 2026-09-14 at 390px,\n menu rect [-16,49,336,40], elementFromPoint at its centre returned the\n view tabs row. A positioned header plus a static chip root puts the same\n menu at [46,77,336,73] \u2014 inside the viewport, its rows hit-testable, and\n an outside tap still dismisses it (menus 1 -> 0). On 0.1.6-alpha.2 the\n chip leaves the flow entirely (absolute, in the gated block below), and\n this rule's higher specificity ((0,6,2) vs the new (0,4,1)) would pin it\n static there too \u2014 so it is excluded on alpha.2 hosts via :not(:has(...))\n and keeps governing rc hosts (review 2026-09-19).\n BOTH halves are load-bearing: forcing the chip root static without\n positioning the header moves the containing block out to the frame, and\n the menu lands at x=8 y=849 \u2014 past the 844px viewport (A/B 2026-09-13).\n Scoped to the header actions slot, so the subagent lineage root inside\n the crumbs keeps its own anchored, fixed-position menu. */\n [data-mobile-nav=\"frame\"] [data-phase] header:not(:has([class*=\"_headerLeading\"])) [class*=\"_headerActions\"] [class*=\"_root\"]:not([class*=\"_switcherRoot\"]):has(> button[class*=\"_trigger\"]) {\n position: static !important;\n }\n /* The tab strip is a separate grid item from the title row and does not\n inherit the title row's inset, so after the header padding above went to 0\n it sat flush against the bezel (measured: tablist x=0, first tab 0..30\n while the title starts at 40). Give it the same left inset as the toggle so\n the two rows read as one column. */\n /* ---------- \u624B\u673A\u6863\u4E13\u5C5E\uFF1A\u5934\u90E8\u7559\u767D\u6536\u7D27\uFF08\u2264767px + coarse\uFF09----------\n \u6570\u503C\u662F\u7167 360\u00D7754 \u771F\u673A\u91CF\u7684\uFF08\u9875\u7B7E\u6761 margin-top -4 / \u9875\u7B7E\u4E0B\u5212\u7EBF 5px /\n \u9875\u7B7E\u6309\u94AE\u53BB\u4E0A\u5185\u8FB9\u8DDD\u3001\u9760\u5E95\u5BF9\u9F50 / \u6807\u9898\u884C\u56DE\u5230\u5185\u5BB9\u9AD8\u5EA6\uFF09\u3002**\u53EA\u5BF9\u771F\u00B7\u624B\u673A\u6863\u751F\u6548**\uFF1A\n 768\u20131023 \u7684\u5E73\u677F\u6863\u4FDD\u6301\u4E0A\u6E38\u624B\u673A UI \u7684\u6392\u5E03\uFF0C\u4E0D\u5957\u8FD9\u53F0\u624B\u673A\u7684\u9B54\u6570\n \uFF08\u4ED3\u5E93\u65E2\u6709\u60EF\u4F8B\uFF0C\u89C1\u6587\u4EF6\u672B\u5C3E\u7684 DSHA \u9884\u8BBE\u5757\uFF09\u3002\n \u771F\u673A\u8BFB\u6570\uFF08\u4FEE\u524D \u2192 \u4FEE\u540E\uFF09\uFF1A\u5934\u90E8 77 \u2192 67px\u3001\u6807\u9898\u2194\u9875\u7B7E\u6587\u5B57\u95F4\u8DDD 22 \u2192 15px\u3002 */\n @media (max-width: 767px) and (pointer: coarse) {\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"wSkVaW_tabs\"] {\n padding-left: 8px !important;\n /* 2026-09-23 \u5E97\u4E3B\uFF1A\"\u6807\u9898\u548C\u4E0B\u9762\u300E\u5BF9\u8BDD\u300F\u4E2D\u95F4\u7684\u7A7A\u767D\u6709\u70B9\u591A\"\u3002\n \u5BBF\u4E3B\u7ED9\u8FD9\u6761\u9875\u7B7E\u6761 margin-top:10px\uFF0C\u9875\u7B7E\u6309\u94AE\u81EA\u5DF1\u8FD8\u5E26 padding-bottom:9px\n \uFF08\u7ED9\u9009\u4E2D\u4E0B\u5212\u7EBF\u7559\u4F4D\uFF09\uFF0C\u4E24\u884C\u6587\u5B57\u4E4B\u95F4\u5C31\u7A7A\u51FA\u4E00\u6761\u3002\u6536\u7D27\uFF1A\n margin \u5F52\u96F6\uFF08\u771F\u673A 4 \u2192 0\uFF09+ \u4E0B\u5212\u7EBF\u8D34\u5230 5px\uFF08\u9875\u7B7E\u6761 36 \u2192 31px\uFF09\u3002\n \u26A0 \u9009\u62E9\u5668\u5FC5\u987B\u7528**\u540E\u4EE3**\uFF1A\u9875\u7B7E\u6761\u5916\u9762\u5957\u4E86\u4E00\u5C42 display:contents \u7684 div\n \uFF08\u771F\u673A\u94FE\uFF1Adiv.wSkVaW_tabs < div[0..0] < header.wSkVaW_header\uFF09\uFF0C\n \u6240\u4EE5\u539F\u6765\u7684\u300Cheader > [class*=\"wSkVaW_tabs\"]\u300D\u662F\u6761\u6B7B\u89C4\u5219 \u2014\u2014 padding-left\n \u4ECE\u6765\u6CA1\u751F\u6548\u8FC7\uFF08\u73B0\u6309\u540E\u4EE3\u5199\uFF0C\u503C\u4ECD\u662F\u5B9E\u6D4B\u7684 8px\uFF0C\u89C6\u89C9\u4E0D\u53D8\uFF09\u3002 */\n margin-top: 0 !important;\n margin-bottom: 0 !important;\n }\n /* 2026-10-20 \u4E94\u8F6E\uFF08\u771F\u673A\u622A\u56FE\u5B9E\u6D4B\uFF09\uFF1A\u4E0A\u9762\u90A3\u6761 5px \u4E00\u76F4\u6CA1\u751F\u6548 \u2014\u2014 \u5BBF\u4E3B\u6309\u94AE\u81EA\u5E26\n padding: 0 0 9px\uFF0CApp \u6CE8\u5165\u8868\u53C8\u628A\u5B83\u9489\u56DE 9px\uFF0C\u6240\u4EE5\u6587\u5B57\u79BB\u4E0B\u5212\u7EBF 10px\u3001\u79BB\u6807\u9898\u53EA\u6709\n 7px\uFF08\u5E97\u4E3B\uFF1A\u300C\u592A\u6324\u4E86\uFF0C\u628A\u5BF9\u8BDD\u90A3\u4E00\u884C\u79FB\u52A8\u8D34\u8FD1\u4E0B\u9762\u90A3\u6761\u7EBF\u300D\uFF09\u3002\u6539\u7528\u5BBF\u4E3B\u7A33\u5B9A\u7684\n data-conversation-tabs \u6807\u8BB0 + html body \u524D\u7F00\u628A\u7279\u5F02\u6027\u62C9\u6EE1\uFF0C\u628A\u4E0B\u5185\u8FB9\u8DDD\u538B\u5230 3px\uFF1A\n \u6587\u5B57\u968F\u4E4B\u4E0B\u6C89 6px \u2014\u2014 \u8D34\u8FD1\u5206\u9694\u7EBF\uFF0C\u540C\u65F6\u6807\u9898\u4FA7\u7684\u7559\u767D\u56DE\u6765\u3002 */\n html body [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header [data-conversation-tabs][role=\"tablist\"] > button[role=\"tab\"],\n html body [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header [data-conversation-tabs] > button[class*=\"wSkVaW_tab\"] {\n /* 2026-10-20\uFF1A\u5E97\u4E3B\u300C\u5148\u628A\u521A\u521A\u7684\u6539\u52A8\u8FD8\u539F\u300D\u2014\u2014\u56DE\u5230\u4E0A\u4E00\u7248\u5B9A\u7A3F\u7684 6 / 3\n \uFF08\u603B\u9AD8\u4ECD\u662F 16 + 9 = 25px\uFF0C\u6587\u5B57\u4E0B\u6C89\u3001\u4E0B\u5212\u7EBF\u4E0D\u52A8\uFF09\u3002\u540E\u7EED\u518D\u6309\u5E97\u4E3B\u7ED9\u7684\u76EE\u6807\u95F4\u8DDD\u8C03\u3002 */\n padding: 6px 0 3px !important;\n }\n /* 2026-10-20 \u4FEE\u6B63\uFF1A\u9875\u7B7E\u6761\u7684 margin-top **\u662F\u6709\u6548\u7684**\uFF08\u65E9\u524D\u5224\u5B9A\"\u65E0\u6548\"\u662F\u8BEF\u5224 \u2014\u2014 \u5F53\u65F6\n \u4E0E\u884C\u9AD8\u6539\u52A8\u53E0\u5728\u4E00\u8D77\uFF0C\u6D4B\u5230\u7684\u4F4D\u79FB\u88AB\u884C\u9AD8\u53D8\u5316\u63A9\u76D6\uFF09\u3002\u7ECF\u9A8C\u516C\u5F0F\uFF08\u8BBE\u5907\u50CF\u7D20\uFF09\uFF1A\n \u95F4\u8DDD \u2248 67.5 + 3.81 \u00D7 (row-gap + margin-top)\uFF1B\u57FA\u7EBF margin-top \u7531\u672C\u6587\u4EF6\u4E0B\u65B9\n \u300Cheader:has(_headerLeading) [role=\"tablist\"] { margin-top: 4px }\u300D \u7ED9\u51FA\u3002\n \u7EC8\u6001 = row-gap 3.5 + margin-top \u22128 \u21D2 \u51C0 \u22124.5 \u21D2 \u5B9E\u6D4B 50\uFF08\u5E97\u4E3B\u5B9A\u7A3F\uFF09\u3002 */\n html body [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header [data-conversation-tabs][role=\"tablist\"],\n html body [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [data-conversation-tabs][role=\"tablist\"] {\n /* \u5FC5\u987B\u538B\u8FC7\u672C\u6587\u4EF6\u4E0B\u65B9 header:has(_headerLeading) [role=\"tablist\"] \u7684 4px\uFF08(0,4,1)\uFF09\uFF0C\n \u6240\u4EE5\u8FD9\u91CC\u6302\u6EE1 data \u6807\u8BB0\uFF08(0,5,3)\uFF09\uFF1B\u53EA\u5199 [role=\"tablist\"] \u4F1A\u8F93\u3002 */\n margin-top: -8px !important;\n }\n /* 2026-10-20\uFF08\u7EC8\u6001\uFF09\uFF1A\u300C\u6807\u9898\u2194\u5BF9\u8BDD\u300D\u95F4\u8DDD\u7684\u552F\u4E00\u6709\u6548\u65CB\u94AE\u662F header \u7684 row-gap\u3002\n \u4E24\u884C\u7F51\u683C\u5148\u56DE\u5230\u5185\u5BB9\u9AD8\uFF08App \u6CE8\u5165\u8868\u539F\u672C\u9489\u6B7B 40px + 36px\uFF09\uFF0C\u518D\u7531 row-gap \u6491\u7F1D\uFF1A\n \u9875\u7B7E\u884C\u6574\u4F53\u4E0B\u79FB\u3001header \u8DDF\u7740\u957F\u9AD8 \u21D2 \u6807\u9898\u4FA7\u7559\u767D\u53D8\u5927\u3001\u5BF9\u8BDD\u5230\u4E0B\u65B9\u9ED1\u7EBF\u7684\u8DDD\u79BB\u4E0D\u53D8\u3002\n \u5B9E\u6D4B\uFF08\u8BBE\u5907\u50CF\u7D20\uFF09\uFF1Aauto/0 \u2192 37\uFF1B+6px \u2192 60\uFF1B+3.5px \u2192 50\uFF08\u5E97\u4E3B\u5B9A\u7A3F\u503C\uFF09\u3002\n \u9875\u7B7E\u6761\u81EA\u8EAB\u7684 margin-top \u88AB App \u8868\u9489\u6B7B\uFF0C-4/-8/0/6px \u56DB\u4E2A\u503C\u90FD\u65E0\u6548\uFF0C\u5DF2\u653E\u5F03\u3002 */\n html body [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header {\n grid-template-rows: auto auto !important;\n row-gap: 3.5px !important;\n }\n /* \u9875\u7B7E\u884C\u9489\u5230\u5185\u5BB9\u9AD8\uFF0816px \u884C\u9AD8 + 5px \u4E0B\u5212\u7EBF\u4F4D = 21px\uFF09\uFF1A\u6587\u5B57\u4E0E\u4E0B\u5212\u7EBF\u8D34\u4F4F\u884C\u5E95\uFF0C\n \u4E0D\u518D\u5728 36px \u7684\u8001\u884C\u9AD8\u91CC\u5C45\u4E2D\uFF0C\u591A\u51FA\u6765\u7684\u7A7A\u767D\u7531\u4E0A\u9762\u7684 row-gap \u7EDF\u4E00\u7BA1\u7406\u3002 */\n html body [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tablist\"] {\n min-height: 0 !important;\n height: 21px !important;\n align-items: flex-end !important;\n }\n\n /* \u771F\u673A\u8BFB\u6570\uFF1A\u5934\u90E8\u7684 grid-template-rows \u88AB\u9489\u6210\u56FA\u5B9A\u7684 40px 36px\uFF08\u5BBF\u4E3B\u81EA\u5DF1\u6CA1\u5199\u884C\u9AD8\uFF0C\n \u662F DSHA \u90A3\u5F20\u8868\u7ED9\u7684\uFF09\uFF0C\u4E8E\u662F\u6807\u9898\u884C\u3001\u9875\u7B7E\u884C\u90FD\u5404\u7559\u4E00\u622A\u6B7B\u7A7A\u95F4\u3002\u6539\u6210 auto\uFF1A\u4E24\u884C\u5404\u81EA\n \u8D34\u4F4F\u5185\u5BB9\uFF0C\u6807\u9898\u884C\u6309 36px \u7684\u9884\u8BBE chip \u8D70\u3001\u9875\u7B7E\u884C\u7531\u9875\u7B7E\u6309\u94AE\u6491\u5F00\u3002 */\n /* \u6807\u9898\u884C\u5B9E\u6D4B 40px \u9AD8\uFF0C\u800C\u91CC\u9762\u6700\u9AD8\u7684\u4E1C\u897F\u662F 36px \u7684\u9884\u8BBE chip\uFF08\"\u6807\u51C6\u6A21\u5F0F\"\uFF09\u2014\u2014\n \u591A\u51FA\u6765\u7684 4px \u662F\u6B7B\u7A7A\u95F4\u3002\u8BA9\u884C\u9AD8\u56DE\u5230\u5185\u5BB9\u9AD8\u5EA6\uFF08\u7528 auto + min-height:0\uFF0C\n \u4E0D\u5199\u6B7B 36\uFF1A\u5C06\u6765\u6807\u9898\u7C07\u91CC\u51FA\u73B0\u66F4\u9AD8\u7684\u4E1C\u897F\uFF08\u5B50\u4EE3\u7406\u8C31\u7CFB\u7B49\uFF09\u4E5F\u4E0D\u4F1A\u88AB\u88C1\uFF09\u3002 */\n html [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header [class*=\"wSkVaW_titleRow\"] {\n height: auto !important;\n min-height: 0 !important;\n }\n /* \u9875\u7B7E\u6309\u94AE\u6587\u5B57\u4E0A\u65B9\u8FD8\u6709 6px \u7A7A\u767D\uFF08\u6309\u94AE\u88AB\u5BB9\u5668\u6491\u5230 32px \u9AD8\u3001\u6587\u5B57\u5C45\u4E2D\uFF09\uFF1A\u53BB\u6389\u4E0A\u5185\u8FB9\u8DDD\uFF0C\n \u4E0B\u5185\u8FB9\u8DDD 5px \u5DF2\u5728\u4E0A\u9762\u9489\u4F4F\uFF08\u4E0B\u5212\u7EBF\u4F4D\u7F6E\u4E0D\u53D8\uFF09\u3002 */\n html [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header [class*=\"wSkVaW_tab\"] {\n padding-top: 0 !important;\n align-self: flex-end !important;\n }\n }\n /* NOTHING extra here on purpose. The header's own padding is already forced\n to 0 above, and the title row carries padding-left:40px of its own, so the\n title lands at x=40 - the toggle's right edge (36) plus 4px. A negative\n margin added on top of that over-corrected and pulled the title off the\n left edge (measured 2026-09-13: crumb x=20, and the string's first glyph\n painted partially outside the viewport), so the reclaim lives in exactly\n one place: the header padding. */\n\n [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header > :first-child {\n display: flex !important;\n align-items: center;\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n gap: 2px;\n /* Just enough for the toggle (28px at left:8 -> right edge 36) plus 4px of\n breathing room; the host's 60px rail reservation is neutralised above. */\n padding-left: 40px;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header > :first-child > :first-child {\n display: flex !important;\n align-items: center;\n flex: 1 1 auto;\n min-width: 0;\n gap: 2px;\n }\n /* The directory toggle stays at the far left of the header. */\n [data-mobile-nav=\"toggle\"] {\n position: absolute !important;\n left: 8px !important;\n top: 12px !important;\n z-index: 2 !important;\n }\n /* The files opener is pinned to the header's right corner, mirroring the\n directory toggle on the left (same 8px edge, same 12px seat). In flow it\n can never reach that corner: the host reserves the last 44px of the title\n cluster for a utilities seat that is EMPTY on mobile - measured at 390px,\n headerUtilities sits at x=374 with width 0 while the title cluster carries\n padding-right: 44px - so the button stopped at x=300..328 and left 62px of\n bare header to its right (2026-09-14 phone-side report: the opener is not\n pinned to the top-right corner). Absolute positioning also returns its\n 28px of flow width to the title lane, and the containing block is the same\n one the toggle resolves against, so both controls shift together with the\n frame's safe-area padding. The 44px reservation itself is trimmed to the\n 28px band this button actually paints in the compact-rows block below, so\n the title lane keeps the difference. */\n [data-mobile-nav=\"files\"] {\n position: absolute !important;\n right: 8px !important;\n left: auto !important;\n top: 12px !important;\n z-index: 2 !important;\n }\n /* \u624B\u673A\u6863\uFF08\u2264767 + coarse\uFF09\uFF1A\u6587\u4EF6\u5939\u6309\u94AE\u53F3\u79FB 4px\uFF08\u539F 8px\uFF09\uFF0C\u4E3A\u6807\u9898\u884C\u53F3\u7C07\u518D\u817E\u51FA\u7A7A\u95F4\u3002\n \u4E0E\u5DE6\u4FA7 \u2630 \u7684 8px \u4E0D\u518D\u5BF9\u79F0\uFF0C\u662F\u7528\u6237\u660E\u786E\u63A5\u53D7\u7684\u53D6\u820D\uFF082026-10-12 \u7528\u6237\u89C4\u683C\uFF09\u3002\n \u5E73\u677F\u6863\u8FD9\u4E00\u6863\u6CA1\u88AB\u8981\u6C42\u52A8\uFF0C\u6240\u4EE5\u7559\u5728\u8FD9\u6761\u624B\u673A\u6863\u4F5C\u7528\u57DF\u91CC\uFF1B\u5171\u7528\u6863\u4FDD\u6301\u672C\u6279\u4E4B\u524D\u7684\u503C\u3002 */\n @media (max-width: 767px) and (pointer: coarse) {\n [data-mobile-nav=\"files\"] {\n right: 4px !important;\n }\n }\n [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header [class*=\"_headerActions\"] {\n display: flex !important;\n align-items: center;\n box-sizing: border-box;\n flex: 0 1 auto;\n min-width: 0;\n max-width: calc(100% - 32px);\n margin-left: auto;\n justify-content: flex-end;\n gap: 2px;\n }\n /* The title takes the remaining width and never paints outside it; the\n metadata lane's mode text is what shrinks first. */\n /* min-width is a readable floor (2026-09-13 phone report: the title showed a\n single glyph then an ellipsis). This lane has flex basis 0, so it is the\n first thing every crowding neighbour eats: measured at 320px with a lineage\n chip in the row, the crumb client width collapsed to 16px and NOTHING of\n the title was painted. 30% of the row keeps 2-4 CJK glyphs plus the host's\n own ellipsis whatever else is pinned next to it. */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_crumbs\"] {\n flex: 1 1 0;\n min-width: 30%;\n max-width: none;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n /* Mode label: keep the icon AND the words. On a phone this chip is the only\n mode switcher there is, so its text is not the surplus it was once\n treated as: the longest preset name measured needs 121px including the\n 18px icon seat, while the old cap min(22vw, 220px) allowed just 85.8px at\n 390px \u2014 the text was clipped at every phone width even before the\n crowding rules below pinned it to the icon alone (2026-09-14 phone\n report: the mode label showed only its glyph). 38vw keeps the label whole\n from 320px up and still lets it ellipsize before the title on wider\n screens. */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_label\"]:has(> svg) {\n order: 1;\n flex: 0 1 auto;\n min-width: 0;\n max-width: min(38vw, 220px);\n display: block;\n position: relative;\n box-sizing: border-box;\n padding-left: 18px;\n padding-right: 2px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_label\"]:has(> svg) > svg {\n position: absolute !important;\n left: 0 !important;\n top: 50% !important;\n transform: translateY(-50%) !important;\n }\n /* Running/subagent controls keep their full status text and hit area; they\n do not give up width to the mode label. NOTE: the real subagent lineage\n root has class=\"ZKlsPq_root \" \u2014 a TRAILING SPACE from the plugin's\n template-literal className \u2014 so [class$=\"_root\"] never matches it. Use\n [class*=\"_root\"] and exclude the switcher root ([class*=\"_switcherRoot\"])\n so only the count/job roots get pinned (the switcher must stay shrinkable\n so its own title can ellipsize). */\n /* Pinned (flex 0 0 auto) with a max-width cap. A shrinkable chip is squeezed\n below its content and the count reads as clipped or overwritten (the\n 2026-08-22 report), while a bare max-content pin eats the session title,\n whose flex basis is 0: measured 2026-09-13 at 320px, the crumb went 68px\n -> 16px and the painted title was EMPTY while the chip kept its full text.\n Pinned + capped + the crumbs min-width floor above is what holds both \u2014\n the title ellipsizes, the count keeps its words, and the hit area stays\n one inline-flex button.\n NOTE: the popover containment lives with the header rules above, which\n force this root position:static. That only works together with the\n positioned header: static on its own moved the containing block out to\n the frame and the menu landed at x=8 y=849, past the 844px viewport\n (A/B 2026-09-13). */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_root\"]:not([class*=\"_switcherRoot\"]):has(> button[class*=\"_trigger\"]) {\n order: 2;\n flex: 0 0 auto;\n min-width: 0;\n max-width: min(40vw, 180px);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_root\"]:not([class*=\"_switcherRoot\"]):has(> button[class*=\"_trigger\"]) > button {\n min-width: 0;\n max-width: 100%;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_root\"]:not([class*=\"_switcherRoot\"]):has(> button[class*=\"_trigger\"]) > button > * {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_root\"]:not([class*=\"_switcherRoot\"]):has(> button[class*=\"_trigger\"]) > button,\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_root\"]:not([class*=\"_switcherRoot\"]):has(> button[class*=\"_trigger\"]) > button * {\n white-space: nowrap !important;\n }\n /* The lineage count's leading \"/\" (ZKlsPq_separator \u2014 official desktop\n chrome rendered only for a root session inside the crumbs) looks like a\n stray extra breadcrumb level on small screens; hide it. The crumbSep \"/\"\n between ancestry segments (subagent sessions) is a real separator and\n stays. */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_crumbs\"] [class*=\"_separator\"] {\n display: none !important;\n }\n /* The header's right-hand slot clips its own dropdown away (0.1.5 host bug).\n wSkVaW_headerUtilities is a 44x44 grid cell with overflow:auto, and the host\n mounts its \"More actions\" menu INSIDE it: the menu is 218x52, so the cell\n clipped it to 44x44 and the menu was never painted and never hit-testable\n (measured: menu rect 156,56 218x52, computed flex/visible/opacity 1, yet\n elementsFromPoint at the item centre returned the view tabs row and nothing\n from the menu). Raising the menu z-index cannot help - the cell's own\n stacking context traps it. Releasing the overflow paints the menu where the\n host positioned it, and the item then works (verified: a real tap opening\n the session-log export dialog, menus 1 -> 0 dialogs 1). Scoped to the mobile\n branch and to this one cell, so desktop keeps the host layout. The section\n is hidden on mobile anyway - the drawer footer carries the same action - but\n the release stays for any plugin that registers a header dropdown here. */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"wSkVaW_headerUtilities\"] {\n overflow: visible !important;\n /* The seat is empty on a phone (its only button is hidden just below) yet\n still 44px tall, which floors the whole title row \u2014 see the compact-rows\n block after the tab strip. */\n height: 30px !important;\n min-height: 0 !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"wSkVaW_headerUtilities\"] [class*=\"nL4_yW_moreButton\"] {\n display: none !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [data-mobile-nav=\"files\"] {\n width: 28px;\n }\n /* Session log download: gone from the header row on mobile (the utilities\n seat holds only the session-log-export capsule).\n \u26A0 \u4F5C\u7528\u57DF\u5FC5\u987B\u662F\u4F1A\u8BDD\u9876\u680F\u672C\u8EAB\uFF08header.wSkVaW_header\uFF09\uFF0C\u4E0D\u80FD\u5199\u6210\u88F8 header\uFF1A\n \u63D0\u95EE\u5361\uFF08dsh-client-ui-user-questions\uFF09\u7684 Mbwy4a_frame \u5C31\u6E32\u67D3\u5728 composerSeat \u91CC\u3001\n \u4E5F\u5728 [data-phase] \u4E4B\u4E0B\uFF0C\u5B83\u7684 Mbwy4a_header > headingBlock > :last-child \u6B63\u662F\u95EE\u9898\u6B63\u6587\n
\u3002\u88F8 header \u7248\u672C\u628A\u95EE\u9898\u6B63\u6587\u6574\u884C display:none \u2014\u2014 \u5E97\u4E3B\u300C\u4F60\u63D0\u7684\u95EE\u9898\u88AB\u541E\u6389\u4E86\u300D\u5373\u6B64\n \uFF082026-10-20 \u771F\u673A DOM \u53D6\u8BC1\uFF1Ah2 computed display:none\uFF0C\u9010\u6761\u7981\u7528\u672C\u6837\u5F0F\u8868\u5185\u7684\u89C4\u5219\u5B9A\u4F4D\u5230\n \u8FD9\u6761\uFF09\u3002\u9876\u680F\u7684\u7B7E\u540D\u7C7B\u7531\u5BBF\u4E3B ConversationRoot.module.css \u7684 .header \u63D0\u4F9B\uFF08wSkVaW_header\uFF09\uFF0C\n \u672C\u6587\u4EF6\u5176\u5B83\u9876\u680F\u89C4\u5219\u540C\u6837\u4EE5\u5B83/\u5176\u5B50\u7C7B\u4F5C\u4EE3\u9645\u951A\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header.wSkVaW_header > :first-child > :last-child {\n display: none !important;\n }\n /* View tabs strip (official [role=\"tablist\"] under the crumbs row).\n Desktop ships a single flex row (gap: 36) sized for the two stock tabs\n (\u5BF9\u8BDD/\u8F68\u8FF9). Plugins register further views (memory / skill / todo\n panels, per-plugin settings pages), and once the count passes two the\n shrinkable buttons collapse to their min-content: CJK labels stack one\n glyph per line (staircase), latin labels break word-per-line \u2014 the\n strip eats a screenful of vertical space (#41, 8 tabs, HarmonyOS\n browser). Scroll the strip horizontally instead \u2014 the standard mobile\n tab-bar pattern \u2014 with every label kept whole (flex-shrink: 0 +\n nowrap). Affordance is the peek: the naturally cut-off tab at the right\n edge says \"more this way\" (unlike the settings navList, whose buttons\n nearly fit and would show no cut edge), which is why this strip scrolls\n while that one wraps. touch-action: pan-x opts the strip into\n horizontal panning \u2014 the root's pan-y intersection stops at this first\n scroll container (same mechanism as the drawer's pan-y), so the page\n never scrolls sideways. overscroll-behavior-x: contain stops a flick\n from chaining past the ends; snap keeps tabs edge-aligned after a\n fling; the scrollbar stays hidden like every native tab bar. */\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tablist\"] {\n flex-wrap: nowrap;\n gap: 0 16px;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n scroll-snap-type: x proximity;\n touch-action: pan-x;\n scrollbar-width: none;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tablist\"]::-webkit-scrollbar {\n display: none;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tablist\"] > button {\n flex-shrink: 0;\n white-space: nowrap;\n scroll-snap-align: start;\n }\n /* Compact session header rows (2026-09-14 phone report: the top is very\n empty). The host's own mobile sheet lays the header out as\n grid-template-rows: minmax(32px, auto) minmax(44px, auto) with\n [role=\"tab\"] { min-height: 44px }, and both rows then grow to 44: the\n title row is floored by the empty utilities seat above, the tab row by the\n buttons' own floor. Measured at 390px: header 97px = 8 padding + 44 + 44 +\n 1 border, for 36px of painted content. Capping the rows at 36/32 and the\n tabs at their own content height gives 77px, with nothing else degraded \u2014\n title, mode text, status chips, chevrons and both pinned corner buttons\n keep their measured geometry, and the tab strip keeps its #41 contract\n (horizontal scroll, 16px gap, whole labels, pan-x).\n The host's 8px padding-top is deliberately kept: the title row's 28px\n content then centres at y=26, exactly the centre of the pinned corner\n controls (toggle and Files opener both sit at top:12, 28px tall). Trimming\n that padding to 4 shaved 4 more px but left the text row visibly riding\n above both buttons (2026-09-14 phone report: the text row sits too high\n against the drawer and Files controls), so the row height is what pays for\n the compaction, not the alignment.\n :has(> *) guards the hero header: it is an EMPTY, host-hidden grid that\n still occupies 85px while the composer is laid out under it. In the hero\n the header has 0 element children, so the guard leaves it at its official\n height \u2014 measured, the hero composer rect [0,349,388,231] is identical\n with and without this block. */\n [data-mobile-nav=\"frame\"] [data-phase] header:has(> *) {\n min-height: 0 !important;\n /* 2026-09-23 \u4E8C\u8F6E\uFF1A\u9875\u7B7E\u884C\u5730\u677F 32 \u2192 26\uFF08\u5E97\u4E3B\uFF1A\"\u6807\u9898\u548C\u4E0B\u9762\u300E\u5BF9\u8BDD\u300F\u4E2D\u95F4\u7A7A\u767D\u6709\u70B9\u591A\"\uFF09\u3002\n \u6807\u9898\u884C\u5730\u677F\u4FDD\u6301 36 \u2014\u2014 \u5B83\u4E0B\u9762\u7684\u6587\u5B57\u8981\u8DDF top:6 \u7684\u5706\u5F62\u6309\u94AE\u5BF9\u9F50\uFF08\u5B9E\u6D4B\u6587\u5B57\u4E2D\u5FC3\n y=20 = \u5706\u5F62\u6309\u94AE\u4E2D\u5FC3\uFF09\uFF0C\u538B\u6807\u9898\u884C\u4F1A\u628A\u6587\u5B57\u9876\u5F97\u6BD4\u6309\u94AE\u9AD8\uFF082026-09-14 \u5DF2\u8E29\u8FC7\uFF09\u3002\n \u9875\u7B7E\u6309\u94AE\u7684 32px \u5730\u677F\u540C\u7406\u4E0B\u5230 26px\uFF08\u6587\u5B57 16px + \u4E0B\u5212\u7EBF\u7559 5px\uFF09\uFF0C\n \u9875\u7B7E\u6761\u7684\u4E0B\u6CBF\u968F\u4E4B\u4ECE 76 \u6536\u5230 66\u3002 */\n grid-template-rows: minmax(36px, auto) minmax(32px, auto) !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tab\"] {\n min-height: 32px !important;\n }\n /* \u624B\u673A\u6863\u4E13\u5C5E\uFF08\u2264767px + coarse\uFF09\uFF1A\u9875\u7B7E\u884C\u5730\u677F 32 \u2192 26\uFF08\u4E0B\u5212\u7EBF\u6536\u5230 5px \u540E\u4ECD\u591F\u70B9\uFF09\u3002\n \u5E73\u677F\u6863\u4FDD\u7559 32px \u7684\u65E2\u6709\u503C\uFF0C\u4E0D\u8DDF\u624B\u673A\u4E00\u8D77\u538B\u3002 */\n @media (max-width: 767px) and (pointer: coarse) {\n [data-mobile-nav=\"frame\"] [data-phase] header:has(> *) {\n grid-template-rows: minmax(36px, auto) minmax(26px, auto) !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header [role=\"tab\"] {\n min-height: 26px !important;\n }\n }\n /* The title cluster reserves its last 44px for that empty utilities seat.\n The lane's right edge must stay clear of the Files opener's HIT BOX,\n otherwise the opener eats the trailing chips' taps. The pre-2026-09-22\n value (26px, a width optimisation) only cleared at the 390px test width:\n measured at 360x754 (dpr 4) the Agent Team chip ran to x=334 while the\n opener's 36px box started at x=316 \u2014 an 18px overlap, so tapping the\n chip's tail opened the Files panel. The reference phone UI shows the lane\n ending at ~314 with the opener box at 316..352, i.e. the full 44px seat\n plus 2px of breathing room, so restore that instead of narrowing the\n opener: 46px clears the 36px box at right:8 by 2px at every width. */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"wSkVaW_titleCluster\"] {\n /* \u672C\u6279\u4E4B\u524D\u7684\u503C\u30022026-10-12/13 \u90A3\u4E32\u300C46 \u2192 40 \u2192 36 \u2192 32 \u2192 26 \u2192 34\u300D\u7684\u5B9E\u9A8C\n **\u53EA\u9488\u5BF9\u624B\u673A\u6863**\uFF08\u540E\u53F0\u4EFB\u52A1\u5706\u70B9\u642C\u8FDB\u6807\u9898\u884C\u540E\u4E0E\u9884\u8BBE chip \u7684\u95F4\u8DDD\uFF09\uFF0C\u5DF2\u6574\u4E32\n \u642C\u8FDB\u4E0B\u9762\u90A3\u6761\u624B\u673A\u6863\u4F5C\u7528\u57DF\uFF1B\u5171\u7528\u6863\uFF08= \u5E73\u677F\u6863\uFF09\u4FDD\u6301\u672C\u6279\u4E4B\u524D\u7684 46px \u4E0D\u52A8\u3002\n \u9884\u7559\u4ECE padding \u6539\u8BB0 margin\uFF082026-10-17\uFF09\uFF1A\u6807\u9898\u7C07\u662F overflow:auto \u7684\u6EDA\u52A8\n \u5BB9\u5668\uFF0C\u5185\u5BB9\u6EA2\u51FA\u65F6\u7684\u88C1\u526A\u7EBF\u662F **padding box** \u2014\u2014 \u5199\u5728 padding \u4E0A\u4F1A\u7559\u4E0B 46px\n \u7684\u300C\u53EF\u7ED8\u5236\u6EA2\u51FA\u533A\u300D\uFF0C\u6324\u7206\u7684\u90A3\u4E00\u622A chip \u6B63\u597D\u753B\u8FDB\u9884\u7559\u5E26\u3001\u88AB\u7EDD\u5BF9\u5B9A\u4F4D\u7684\u6587\u4EF6\n \u6309\u94AE\u538B\u4F4F\uFF08\u771F\u673A\u75C7\u72B6\uFF1A\u9884\u8BBE chip \u672B\u5B57\u88AB\u6587\u4EF6\u5939\u56FE\u6807\u76D6\u4F4F\uFF09\u3002\u6539\u8BB0 margin \u540E\u7C07\u7684\n border box \u6536\u5728\u9884\u7559\u5E26\u5DE6\u4FA7\uFF0C\u6EA2\u51FA\u518D\u5927\u4E5F\u6B62\u6B65\u4E8E\u6309\u94AE\u4E4B\u524D\uFF0C\u5185\u5BB9\u5BBD\u5EA6\u4E0D\u53D8\n \uFF08345 \u2212 46 \u21C4 299 \u2212 0\uFF09\u3002 */\n padding-right: 0 !important;\n margin-right: 46px !important;\n }\n /* Header crowding on narrow phones.\n Three tenants want the same row: the session title, the mode chip and the\n status chips. The mode chip is the only mode switcher a phone has and the\n title is the only session identity, so both keep their words and the title\n ellipsizes instead (measured 2026-09-14 at 390px with a lineage chip\n present: after this the mode label keeps 101px of text and the crumb\n 135px).\n The lineage root (dsh-client-ui-subagent) sits in the crumbs for BOTH\n running and idle descendants, so the guards below key on that root rather\n than the transient running-state dot \u2014 otherwise the row would reflow the\n moment agents go idle. Match roots with [class*=\"_root\"] (the real class\n carries a trailing space; [class$=\"_root\"] matches nothing).\n The background-job label used to yield here through two width-gated rules\n (<=440px, and <=559px when the lineage chip was present). Both were keyed\n on the chip's classed wrapper, which host 0.2.1 no longer renders, so they\n are deleted: the label is now hidden unconditionally by the job-chip rule\n in the phone-scope section (see header-job-chip-collapse). */\n /* With the subagent lineage (any state) AND a background job present\n together, 390px cannot hold the title, the mode words and the lineage\n count at once; the crumb gives 8px back to the action lane. */\n @media (max-width: 559px) {\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_crumbs\"] {\n padding-right: 8px;\n }\n }\n /* Last resort on 320px-class screens: the title and both status chips cannot\n share the row with the mode words, so the mode chip keeps only its icon. */\n @media (max-width: 359px) {\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_crumbs\"] [class*=\"_root\"]):has([class*=\"_headerActions\"] [class*=\"_root\"]) [class*=\"_label\"]:has(> svg) {\n display: none !important;\n }\n }\n\n /* --- \u9876\u680F\u72B6\u6001 chip \u5EA7\u4F4D\u5951\u7EA6\uFF1A**\u6682\u7F13**\uFF082026-10-12 \u53D7\u63A7\u5B9E\u9A8C\u540E\u6574\u5757\u64A4\u56DE\uFF09---\n \u7528\u6237\u89C4\u683C\uFF1A\u300C\u5B50\u667A\u80FD\u4F53 chip \u56FA\u5B9A\u4E0D\u53D8\uFF0C\u540E\u53F0\u4EFB\u52A1 chip \u51FA\u73B0\u5728\u5B83\u5DE6\u4FA7\u3001\u95F4\u9694 2px\u300D\u3002\n \u9996\u7248\u7528 flex \u5BB9\u5668 + order + gap \u5B9E\u73B0\uFF0C**\u53D7\u63A7\u5B9E\u9A8C\u8BC1\u660E\u8BE5\u673A\u5236\u4E0D\u6210\u7ACB**\uFF1A\n \u5B50\u667A\u80FD\u4F53 chip\uFF08ZKlsPq_root\uFF09\u5728 alpha.2 \u4EE3\u5BBF\u4E3B\u4E0A\u88AB\u63D2\u4EF6\u81EA\u5DF1\u9489\u6210 position:absolute\uFF0C\n \u7EDD\u5BF9\u5B9A\u4F4D\u5143\u7D20\u8131\u79BB\u6587\u6863\u6D41\uFF0Cflex \u7684 order \u4E0E\u5BB9\u5668 gap \u90FD\u51B3\u5B9A\u4E0D\u4E86\u5B83\u7684\u843D\u70B9 \u2014\u2014\n \u6CE8\u5165\u4E00\u9897\u5408\u6210 jobs chip \u540E\u8BE5 chip \u5B9E\u6D4B\u4ECE x=292 \u8DF3\u5230 x=174\uFF08\u89C6\u89C9\u95F4\u8DDD \u2212211px\uFF09\uFF0C\n \u4E09\u4E2A\u76EE\u6807\u70B9\u65E0\u4E00\u8FBE\u6210\uFF1B\u5BB9\u5668 computed gap \u4E5F\u4ECD\u662F\u5BBF\u4E3B\u81EA\u5DF1\u7684 4px\u3002\n \u771F\u5B9E jobs chip \u65E0\u6CD5\u5728\u53D7\u63A7\u73AF\u5883\u6784\u9020\uFF08\u5BBF\u4E3B\u5728\u540E\u53F0\u4EFB\u52A1\u6570\u4E3A 0 \u65F6\u6574\u9897\u4E0D\u6E32\u67D3\uFF09\uFF0C\n \u6545\u672C\u6761**\u5DF2\u6574\u5757\u64A4\u56DE**\uFF0C\u7B49\u62FF\u5230\u300C\u771F\u673A\u5E26\u540E\u53F0\u4EFB\u52A1\u7684\u622A\u56FE + \u89C6\u89C9\u7A3F\u300D\u540E\u6309\u7EDD\u5BF9\u5B9A\u4F4D\u53E3\u5F84\u91CD\u505A\u3002\n \u64A4\u56DE\u662F\u5B89\u5168\u7684\uFF1A\u672C\u7EC4\u53EA\u5728\u4E24\u9897 chip \u540C\u65F6\u5728\u573A\u65F6\u5339\u914D\uFF0C\u64A4\u6389\u540E\u5355 chip \u5F62\u6001\u56DE\u5230\u65E2\u6709\u90A3\u6279\n \u89C4\u5219\u7684\u7BA1\u8F96\uFF08\u53D7\u63A7\u5B9E\u9A8C\uFF1A\u5355 chip \u7684 rect \u4E0E\u64A4\u524D\u9010\u50CF\u7D20\u4E00\u81F4\uFF0C\u89C4\u5219\u5339\u914D\u6570=0\uFF09\u3002 */\n\n /* --- Header popovers on mobile (dsh-client-ui-jobs / dsh-client-ui-subagent) --- */\n /* Both entries sit in the session header and both anchor their panel to the\n trigger's left edge (left:0 inside their own root), so clamp them to the\n viewport. The background-job menu resolves against the header (see the\n containment rules at the top of this section) and the subagent lineage\n menu is position:fixed, so right:8px pins either panel 8px from the\n phone's right edge: measured [46,77,336,73] for the job menu and\n [38,41,336,58] for the lineage menu at 390px, both fully inside the\n viewport. Do NOT clamp with left:8px: measured, that put the panel at\n x=350..686 (off-screen) against a right-anchored x=30..366. */\n [data-mobile-nav=\"frame\"] [data-phase] header [class*=\"_menu\"] {\n left: auto !important;\n right: 8px !important;\n width: min(336px, calc(100vw - 16px));\n max-width: none;\n max-height: min(420px, calc(100dvh - 120px));\n }\n\n /* --- 0.1.6-alpha.2 session-header adaptation (audited on a real device) ---\n The 16-item reconciliation in docs/upstream/2026-09-19-mobile-header-0.1.6-adaptation.md,\n landing the 14 items whose anchors exist in 0.1.6-alpha.2 host builds. Two preset items\n (#6/#7) are deliberately omitted: they anchor on .dsha-preset-header-anchor, a marker\n that exists only in the DSHA build, so they would be dead rules here.\n GENERATION GATING: only _headerLeading/_crumbCurrent/_crumbSeg/_headerCorner are\n alpha.2-only classes \u2014 every other anchor below (_titleCluster/_crumbs/_headerActions/\n _headerUtilities/tablist/QsffPG_/ZKlsPq_ and the :first-child chains) also exists on\n 0.1.5-rc hosts, where these rules would silently re-tune geometry the older rules\n measured (review 2026-09-19). Every selector therefore carries\n header:has([class*=\"_headerLeading\"]): the whole block is dead on pre-alpha.2 hosts and\n the rc-generation rules keep governing there unchanged. */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) {\n /* \u9876\u90E8\u7559\u767D\u6536\u7A84\uFF1A\u5BBF\u4E3B header \u81EA\u5E26 padding-top: 10px\u3001\u6807\u9898\u884C\u518D\u57AB 2px\uFF0C\n \u53E0\u5728\u5218\u6D77/\u72B6\u6001\u680F\u907F\u8BA9\u4E4B\u4E0A\u5C31\u663E\u7A7A\u3002\u8FD9\u4E24\u5904\u4E00\u8D77\u6E05\u96F6\u3002 */\n padding-left: 8px !important;\n padding-right: 8px !important;\n padding-top: 0 !important;\n /* \u5BBF\u4E3B header \u6709 min-height: 76px\uFF0C\u800C\u5185\u5BB9\u53EA\u6709 ~69px\uFF0C\u5E95\u90E8\u4F1A\u57AB\u51FA 7.6px \u7A7A\u767D\n \uFF08\u5B9E\u6D4B\uFF1A\u6807\u7B7E\u884C\u5E95\u8FB9 106\uFF0Cheader \u5E95\u8FB9 113.6\uFF09\u3002\u8D34\u5E95\u5B9A\u4F4D\u7684\u72B6\u6001 chip \u4F1A\u88AB\u8FD9\n \u6BB5\u7A7A\u767D\u9876\u4E0B\u53BB\u3001\u548C\u6807\u7B7E\u884C\u9519\u5F00\u3002\u624B\u673A\u4E0A\u8BA9 header \u8D34\u4F4F\u5185\u5BB9\u9AD8\u5EA6\u3002 */\n min-height: 0 !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) > :first-child {\n flex-wrap: nowrap !important;\n align-items: center !important;\n gap: 0 !important;\n padding-left: 32px !important;\n padding-right: 0 !important;\n padding-top: 0 !important;\n }\n /* \u76EE\u5F55\u5F00\u5173\u8DDF\u7740\u4E00\u8D77\u4E0A\u79FB\uFF0C\u4FDD\u6301\u4E0E\u6807\u9898/\u6309\u94AE\u540C\u4E00\u884C\u5C45\u4E2D\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [data-mobile-nav=\"toggle\"] {\n top: 6px !important;\n }\n /* \u7A7A\u5EA7\u4F4D\u4E0D\u5224\u7A7A\u3001\u53EA\u584C\u5BBD\uFF1Aa2 \u69FD\u4F4D\u6E32\u67D3\u5668\u6C38\u8FDC\u5728 headerLeading \u91CC\u6302\u4E00\u4E2A\n [data-slot] \u5305\u88C5\u5143\u7D20\uFF08display:contents\u30010\u00D70\uFF09\uFF0C:empty \u4E0E :not(:has(*))\n \u4E24\u79CD\u300C\u7A7A\u300D\u5224\u5B9A\u90FD\u6052\u4E0D\u547D\u4E2D\uFF08\u5BBF\u4E3B\u81EA\u5DF1\u7684 :empty \u89C4\u5219\u540C\u6837\u5931\u6548\uFF09\uFF0C\u800C\n display:none \u53C8\u4F1A\u5728\u67D0\u4EE3\u771F\u7684\u6E32\u67D3\u63A7\u4EF6\u65F6\u8BEF\u85CF\u771F\u63A7\u4EF6\u3002\u8FD9\u91CC\u4E0D\u5224\u5B9A\u7A7A\u4E0D\u7A7A\uFF0C\n \u53EA\u628A\u7B2C\u4E09\u65B9\u8BEF\u6807\u8FDB\u6765\u7684\u9884\u7559 padding \u584C\u6389\u2014\u2014web-all \u517C\u5BB9\u5C42\u6309 0.1.5 \u7ED3\u6784\n \u628A\u672C\u5EA7\u4F4D\u8BEF\u6807\u6210 session-title-cluster\uFF0C\u6CE8\u5165 padding-inline-end:44px\uFF0C\n \u5EA7\u4F4D\u4E8E\u662F 0 \u5185\u5BB9 + 44 padding = 44px \u6B7B\u5360\uFF08\u5B9E\u6D4B 390px\uFF1A\u5EA7\u4F4D\n [40,22,44,0]\u3001titleCluster \u88AB\u9876\u5230 x=84\uFF09\u3002padding \u5F52\u96F6\u540E\u7A7A\u5EA7\u4F4D = 0\u00D70\uFF0C\n \u771F\u6709\u5185\u5BB9\u7684\u5BBF\u4E3B\u4E5F\u4E0D\u53D7\u5F71\u54CD\uFF08\u5185\u5BB9\u76D2\u7167\u5E38\u6E32\u67D3\uFF09\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [class*=\"_headerLeading\"] {\n /* \u4E0D\u80FD\u584C\u6389\u5DE6\u4FA7\u5EA7\u4F4D\u672C\u8EAB\uFF1A\u4E0A\u9762\u90A3\u6761\uFF08> :first-child\uFF09\u7ED9\u672C\u5EA7\u4F4D\u7559\u4E86\n padding-left:32px \u4F5C\u9762\u677F\u5F00\u5173\u7684\u5EA7\u4F4D\uFF0C\u800C padding: 0 !important \u662F\n \u7B80\u5199\uFF0C\u4F1A\u628A\u5B83\u4E00\u5E76\u6E05\u96F6\u3002\u4E24\u6761\u89C4\u5219\u7279\u5F02\u6027\u540C\u4E3A (0,4,1)\uFF0C\u6309\u6E90\u5E8F\u672C\u5757\u5728\u540E\n \u21D2 \u7B80\u5199\u80DC\u51FA\uFF0C\u5EA7\u4F4D\u584C\u6210 0\u00D70\u3001\u7F51\u683C\u7B2C\u4E00\u5217 0px\u3001\u6807\u9898\u76F4\u63A5\u538B\u5230 left:8 \u7684\n \u9762\u677F\u6309\u94AE\u4E0A\uFF08\u771F\u673A\u5B9E\u6D4B 2026-09-22\uFF0C360x754@4\uFF1Acrumbs x=8\u3001\n toggle 8,6 28x28\uFF1B\u771F\u673A DOM \u89C4\u5219\u679A\u4E3E\u786E\u8BA4\u80DC\u51FA\u8005\u5C31\u662F\u672C\u5757\uFF09\u3002\n NOTE: \u672C\u6587\u4EF6\u6574\u4F53\u662F JS \u6A21\u677F\u5B57\u7B26\u4E32\uFF0C\u6CE8\u91CA\u91CC\u7EDD\u4E0D\u80FD\u51FA\u73B0\u53CD\u5F15\u53F7\u3002 */\n padding: 0 !important;\n padding-left: 32px !important;\n }\n /* --- 0.2.0-rc.x\uFF1Aheader \u53D8 grid\uFF0C\u5EA7\u4F4D\u4ECE titleRow \u5185\u90E8\u642C\u5230\u4E86 header \u81EA\u5DF1\u7684\u7B2C\u4E00\u5217 ---\n \u4E0A\u9762\u4E24\u6761\u628A\u300C\u9762\u677F\u5F00\u5173\u7684 32px \u5EA7\u4F4D\u300D\u8BB0\u5728\u5EA7\u4F4D\u81EA\u5DF1\u8EAB\u4E0A\uFF08padding-left\uFF09\u3002\u5728\n 0.1.6-alpha.2 \u91CC headerLeading \u662F titleRow \u7684\u7B2C\u4E00\u4E2A\u5B69\u5B50\uFF0C\u8FD9\u4E2A padding \u5C31\u662F\n titleRow \u5185\u5BB9\u76D2\u7684\u8D77\u70B9\uFF0C\u6807\u9898\u7684 40px \u843D\u70B9\u662F\u5B83\u76F4\u63A5\u7B97\u51FA\u6765\u7684\u30020.2.0-rc.x \u628A header\n \u6539\u6210 grid-template-columns: auto minmax(0,1fr)\uFF1A\u5EA7\u4F4D\u6210\u4E86 header \u7684\u76F4\u63A5\u5B69\u5B50\n \uFF08grid-area: 1/1\uFF09\uFF0CtitleRow \u72EC\u5360\u7B2C\u4E8C\u5217\uFF08grid-column: 2\uFF09\uFF0C\u4E8E\u662F\u6807\u9898\u7684 40px \u843D\u70B9\n \u53D8\u6210\u300C\u7F51\u683C\u7B2C\u4E00\u5217\u6070\u597D 32px\u300D\u7684\u526F\u4F5C\u7528\u2014\u2014\u5EA7\u4F4D\u4E00\u65E6\u88AB\u8C01\u584C\u6389\uFF08padding \u88AB\u8986\u76D6\u3001\u5BBD\u5EA6\u88AB\n \u7B2C\u4E09\u65B9\u5F52\u96F6\u3001display \u88AB\u85CF\uFF09\uFF0C\u7B2C\u4E00\u5217\u5C31\u56DE\u5230 0px\uFF0C\u6807\u9898\u7ACB\u523B\u538B\u5230 left:8 \u7684\u5706\u5F62\u5F00\u5173\u4E0A\u3002\n 2026-09-22 \u5728 0.1.6 \u4E0A\u5B9E\u6D4B\u8FC7\u540C\u4E00\u4E2A\u5931\u8D25\u9762\uFF08\u5EA7\u4F4D\u88AB padding \u7B80\u5199\u6E05\u96F6 \u2192 \u7B2C\u4E00\u5217 0px\n \u2192 crumbs x=8\u3001toggle 8,6 28x28\uFF09\uFF0C\u5F53\u65F6\u9760\u628A padding-left \u8865\u56DE\u6765\u6B62\u4F4F\uFF1B\u8FD9\u4E00\u4EE3\u6539\u6210\n \u628A\u5EA7\u4F4D\u8BB0\u5728\u6807\u9898\u884C\u81EA\u5DF1\u8EAB\u4E0A\uFF1Apadding-left \u52A0\u5728 titleRow \u4E0A\uFF08border-box\uFF0C\u4E0D\u6491\u7834\u7B2C\u4E8C\n \u5217\uFF09\uFF0C\u5EA7\u4F4D\u683C\u5F52\u96F6\uFF0C\u6807\u9898\u843D\u70B9\u4E0D\u518D\u4F9D\u8D56\u5EA7\u4F4D\u683C\u5B58\u5728\u3001\u4E5F\u4E0D\u4F9D\u8D56\u5B83\u7684\u5BBD\u5EA6\u7B97\u5F97\u5BF9\u4E0D\u5BF9\u3002\n \u5224\u522B\u5F0F\u662F\u300C\u5EA7\u4F4D\u662F\u4E0D\u662F header \u7684\u76F4\u63A5\u5B69\u5B50\u300D\u2014\u20140.1.6 \u53CA\u66F4\u65E9\u5EA7\u4F4D\u5728 titleRow \u5185\u90E8\uFF0C\n \u6574\u5757\u4E0D\u547D\u4E2D\uFF0C\u8001\u89C4\u5219\u539F\u6837\u7BA1\u8001\u5BBF\u4E3B\u3002\n \u9644\u5E26\u4FEE\u6389\u4E00\u6761\u9759\u9ED8\u6F02\u79FB\uFF1A\u8001\u89C4\u5219\u300Cheader > :first-child > :last-child { display:none }\u300D\n \u5728 0.1.5 \u85CF\u7684\u662F\u4F1A\u8BDD\u65E5\u5FD7\u80F6\u56CA\uFF1B0.2.0 \u91CC header \u7684\u7B2C\u4E00\u683C\u662F\u5EA7\u4F4D\uFF0C\u5B83\u6700\u540E\u4E00\u4E2A\u5B69\u5B50\u662F\n conversation.header.leading \u69FD\u7684\u5305\u88C5\u5143\u7D20\uFF0C\u6574\u6761\u89C4\u5219\u4E8E\u662F\u53D8\u6210\u300C\u85CF\u6389\u6574\u4E2A leading \u69FD\u300D\n \uFF08\u5B9E\u6D4B\uFF1A\u5F80\u69FD\u91CC\u6CE8\u5165 28x28 \u6309\u94AE\uFF0C\u8BA1\u7B97\u76D2 0x0\uFF09\u3002\u624B\u673A\u6863\u8FD9\u4E00\u683C\u662F\u63D2\u4EF6\u81EA\u5DF1\u7684\u62BD\u5C49\u5F00\u5173\n \uFF08\u7EDD\u5BF9\u5B9A\u4F4D left:8\uFF09\uFF0C\u69FD\u91CC\u7684\u63A7\u4EF6\u5FC5\u7136\u548C\u5B83\u53E0\u5728\u4E00\u8D77\uFF0C\u6240\u4EE5\u300C\u85CF\u300D\u7684\u7ED3\u679C\u662F\u5BF9\u7684\u3001\u7406\u7531\n \u4E00\u76F4\u6CA1\u5199\u4E0B\u6765\uFF1B\u8FD9\u91CC\u6309\u69FD\u540D\u663E\u5F0F\u85CF\uFF0C\u522B\u518D\u9760 :last-child \u8BEF\u4F24\u3002\n NOTE: \u672C\u6587\u4EF6\u6574\u4F53\u662F JS \u6A21\u677F\u5B57\u7B26\u4E32\uFF0C\u6CE8\u91CA\u91CC\u7EDD\u4E0D\u80FD\u51FA\u73B0\u53CD\u5F15\u53F7\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]):has(> [data-conversation-header-leading]) > [data-conversation-header-leading] {\n width: auto !important;\n min-width: 0 !important;\n padding: 0 !important;\n gap: 0 !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]):has(> [data-conversation-header-leading]) [data-slot=\"conversation.header.leading\"] {\n display: none !important;\n }\n /* \u8FD9\u91CC\u7528 [class*=\"_titleRow\"] \u540E\u7F00\u5F62\u800C\u4E0D\u662F\u90BB\u8FD1\u4E24\u6761\u7684 [class*=\"wSkVaW_titleRow\"]\uFF1A\n \u5168\u5305\u53EA\u6709 wSkVaW_titleRow \u542B\u8FD9\u4E2A\u7247\u6BB5\uFF08\u65E0\u524D\u7F00\u91CD\u53E0\uFF0C\u4E14\u5DF2\u88AB header:has \u95E8\u63A7\uFF09\uFF0C\n \u540E\u7F00\u5F62\u5BF9\u54C8\u5E0C\u524D\u7F00\u6539\u540D\u514D\u75AB\u2014\u2014\u5EA7\u4F4D\u8BB0\u9519\u5730\u65B9\u7684\u4EE3\u4EF7\u662F\u6807\u9898\u9759\u9ED8\u538B\u56DE\u5F00\u5173\u4E0A\uFF0C\u4E0D\u503C\u5F97\n \u4E3A\u98CE\u683C\u7EDF\u4E00\u5192\u8FD9\u4E2A\u9669\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]):has(> [data-conversation-header-leading]) [class*=\"_titleRow\"] {\n box-sizing: border-box !important;\n padding-left: 32px !important;\n }\n /* 0.1.6 \u7684\u65B0\u5934\u90E8\u91CC\uFF0CtitleRow \u7684\u7B2C\u4E00\u4E2A\u5B69\u5B50\u662F\u65B0\u589E\u7684\u7A7A\u5EA7\u4F4D\n headerLeading\uFF08macOS \u684C\u9762\u63A7\u4EF6\uFF0C\u5B89\u5353\u4E0A\u6E32\u67D3 null\uFF09\u3002\u63D2\u4EF6\u6309 0.1.5 \u8001\u7ED3\u6784\n \u5199\u7684\u300Cheader > :first-child > :first-child { flex: 1 1 auto }\u300D\u73B0\u5728\u5957\u5728\n \u8FD9\u4E2A\u7A7A\u5EA7\u4F4D\u4E0A\uFF0C\u4E8E\u662F\u5B83\u5403\u6389\u5168\u90E8\u5269\u4F59\u5BBD\u5EA6\u3001\u628A\u6807\u9898\u9876\u5230\u53F3\u4FA7\uFF08\u5B9E\u6D4B 411px \u5BBD\n \u5C4F\u5E55\u4E0A\u6807\u9898\u88AB\u63A8\u5230 131px \u5904\uFF09\u3002\u8BA9\u5B83\u4E0D\u53C2\u4E0E\u4F38\u7F29\u5373\u53EF\u2014\u2014\u6709\u5185\u5BB9\u65F6\u4E5F\u4E0D\u4F1A\u584C\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) > :first-child > :first-child {\n flex: 0 0 auto !important;\n width: auto !important;\n min-width: 0 !important;\n gap: 0 !important;\n }\n /* \u7B2C\u4E09\u65B9\u517C\u5BB9\u5C42\uFF08@linxin666/dsh-web-all \u7684 web-ui-compat \u884C\uFF09\u6309 0.1.5 \u7ED3\u6784\n \u628A\u672C\u4EE3 titleCluster \u8BEF\u6807\u6210 session-utilities\uFF0C\u7ED9\u91CC\u9762\u6240\u6709\u6309\u94AE\u6CE8\u5165\n min-width/min-height:44px + flex:none\uFF1Atoggle/files\u3001\u6A21\u5F0F/\u56E2\u961F/\u9762\u5305\u5C51\n \u6309\u94AE\u5168\u88AB\u9876\u6210 44 \u2014\u2014 toggle (8,6,44,44) \u4E2D\u5FC3 28\u3001files (338,2,44,44)\n \u4E2D\u5FC3 24\u3001\u6807\u9898\u5E26\u4E2D\u5FC3 22 \u4E09\u5FC3\u4E0D\u9F50\uFF1Bfiles \u52A0\u5BBD\u540E\u8D8A\u8FC7 headerActions \u6D41\u53F3\u7F18\n 6px\uFF08338 < 344\uFF09\u3002\u5BBF\u4E3B 0.1.6-alpha.2 \u81EA\u8EAB\u6CA1\u6709\u4EFB\u4F55 44px \u4E0B\u9650\uFF08\u5168\u5305\n grep \u96F6\u547D\u4E2D\uFF09\uFF0C\u8FD9\u91CC\u628A\u5916\u6765\u4E0B\u9650\u5F52\u96F6\uFF1A\u63A7\u4EF6\u56DE\u5230\u5404\u81EA\u8BBE\u8BA1\u5C3A\u5BF8\uFF08toggle 28\n \u6765\u81EA base.css\u3001files 36 \u6765\u81EA\u4E0B\u9762\u7684 a2 \u4E13\u6761\u3001chips/\u9762\u5305\u5C51\u56DE\u5BBF\u4E3B\u81EA\u7136\n \u9AD8\u5EA6\uFF09\uFF0C\u4E09\u5FC3\u56DE\u5230 20\uFF0CtitleCluster \u7684 min-height:40 !important \u91CD\u65B0\n \u4E3B\u5BFC\u884C\u9AD8\u3002QsffPG/ZKlsPq \u4E24\u4E2A\u72B6\u6001 chip \u7528 :not \u660E\u786E\u8C41\u514D\uFF1A\u5B83\u4EEC\u7684\n 25px \u4E0B\u9650\u7531\u540E\u9762 min-height:25px !important \u4E13\u6761\u4F9B\u7ED9\uFF0C\u7279\u5F02\u6027 (0,4,1)\n \u4F4E\u4E8E\u672C\u6761 (0,7,1)\uFF0C\u4E0D\u8C41\u514D\u4F1A\u88AB\u987A\u624B\u538B\u6389\uFF0C\u4E0D\u9760\u4E66\u5199\u987A\u5E8F\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [class*=\"_titleCluster\"] :is(button, [role=\"button\"]):not([class*=\"QsffPG_root\"] button):not([class*=\"ZKlsPq_root\"] button) {\n min-width: 0 !important;\n min-height: 0 !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [class*=\"_titleCluster\"] {\n display: flex !important;\n flex-wrap: nowrap !important;\n flex: 1 1 auto !important;\n width: auto !important;\n max-width: none !important;\n min-width: 0 !important;\n min-height: 40px !important;\n /* \u4E09\u7EA7\u95F4\u9699 6 \u2192 4\uFF082026-09-23 \u7528\u6237\u62CD\u677F\uFF09\uFF1A\u56E2\u961F chip \u5728\u624B\u673A\u6863\u88AB\u5BBF\u4E3B\n @container(width<=480px) \u85CF\u6389\u6807\u7B7E\u3001\u53EA\u5269 14px \u56FE\u6807\uFF08\u5BF9\u8D26\u89C1 \u00A76\uFF09\uFF0C\n \u8FD9\u4E00\u884C\u4E0D\u518D\u9700\u8981 6px \u7684\u547C\u5438\u91CF\uFF1B\u6536\u6210 4px \u8BA9\u300C\u6A21\u5F0F / \u56E2\u961F / \u6587\u4EF6\u5939\u300D\n \u770B\u8D77\u6765\u662F\u4E00\u7EC4\u3002 */\n /* \u672C\u6279\u4E4B\u524D\u7684\u503C\u30022026-10-12 \u7684\u300C\u6807\u9898\u8FD9\u4E00\u884C\u4E09\u4E2A\u4E4B\u95F4\u653E\u5BBD\u5230 6px\u300D\u53EA\u9488\u5BF9\u624B\u673A\u6863\n \uFF08\u540E\u53F0\u4EFB\u52A1\u5706\u70B9\u642C\u8FDB\u6807\u9898\u884C\u540E\u4E0E\u9884\u8BBE chip \u7684\u95F4\u8DDD\uFF09\uFF0C\u5DF2\u642C\u8FDB\u624B\u673A\u6863\u4F5C\u7528\u57DF\u3002 */\n gap: 0 4px !important;\n justify-content: flex-start !important;\n align-items: center !important;\n /* \u7C07\u6EA2\u51FA\u5B88\u536B\uFF0C\u968F\u65AD\u70B9 A \u65E0\u6761\u4EF6\u5316\u5E76\u5165\u672C\u663E\u793A\u89C4\u5219\uFF08\u539F\u4E3A\u72EC\u7ACB\u6761\uFF09\uFF1A\u6781\u7AEF\n \u5B57\u4F53\u4E0B crumbs \u89E6\u5730\u677F\u540E\u7684\u6B8B\u4F59\u6EA2\u51FA\u4FDD\u6301\u53EF\u6A2A\u6ED1\uFF0C\u4E0D\u4F9D\u8D56 web-all \u57AB\u7247\n \uFF08\u7F3A\u5E2D\u65F6\u7C07\u6EA2\u51FA\u9ED8\u8BA4 visible\uFF0C\u4F1A\u538B\u753B\u5230 corner \u6309\u94AE\u4E0A\uFF09\uFF1B\u5185\u5BB9\u653E\u5F97\u4E0B\u65F6\n \u672C\u58F0\u660E\u5B8C\u5168\u60F0\u6027\u3002x:auto \u628A y \u4E5F\u7B97\u6210 auto\uFF0C\u7C07\u5185\u5BB9\u9AD8 \u226440px \u6052\u4E0D\u7EB5\u6EA2\n \u65E0\u5B9E\u5BB3\uFF1BfindHorizontalScroller \u5BF9 overflow-x \u5BB9\u5668\u8BA9\u4F4D\u3002 */\n overflow-x: auto !important;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [class*=\"_titleCluster\"] > [class*=\"_crumbs\"] {\n /* \u6807\u9898\u6539\u6210\u81EA\u9002\u5E94\uFF1A\u9762\u5305\u5C51\u6761\u5403\u6389\u52A8\u4F5C\u533A\u4E4B\u5916\u7684\u5269\u4F59\u5BBD\u5EA6\uFF0C\u6807\u9898\u591A\u957F\u5C31\u663E\u793A\u591A\u5C11\uFF0C\n \u88C5\u4E0D\u4E0B\u65F6\u7531\u6BCF\u4E00\u6BB5\u81EA\u5DF1\u7684\u6ED1\u52A8\u7A97\u53E3\uFF08\u89C1\u4E0B\uFF09\u6A2A\u5411\u6ED1\u3002min-width \u4FDD\u5E95 4 \u5B57\uFF0C\n \u9632\u6B62\u9884\u8BBE\u540D\u5B57\u5F88\u957F\u65F6\u628A\u6807\u9898\u6324\u6CA1\u3002 */\n flex: 1 1 auto !important;\n width: auto !important;\n min-width: 72px !important;\n max-width: none !important;\n margin-left: 0 !important;\n margin-right: 0 !important;\n min-height: 0 !important;\n padding-right: 0 !important;\n overflow: visible !important;\n white-space: nowrap !important;\n }\n /* \u6807\u9898\u672C\u4F53\uFF1A\u81EA\u9002\u5E94\u5BBD\u5EA6 + \u6A2A\u5411\u6ED1\u52A8\u3002\u5BBD\u5EA6\u7531\u4E0A\u9762\u9762\u5305\u5C51\u6761\u7684\u5269\u4F59\u7A7A\u95F4\u51B3\u5B9A\uFF0C\n \u88C5\u4E0D\u4E0B\u65F6\u5728\u672C\u6BB5\u5185\u5DE6\u53F3\u6ED1\uFF08touch-action: pan-x \u8BA9\u6D4F\u89C8\u5668\u5148\u8BA4\u9886\u6A2A\u6ED1\uFF0C\n \u5DE6\u7F18\u62BD\u5C49\u624B\u52BF\u4E0D\u4F1A\u62A2\u8D70\u8FD9\u4E00\u7B14\uFF09\u3002 */\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [class*=\"_crumbs\"] [class*=\"_crumbCurrent\"] {\n flex: 0 1 auto !important;\n width: auto !important;\n min-width: 0 !important;\n /* 6 \u4E2A\u6C49\u5B57\u4E0A\u9650\uFF1A6\u00D714px + \u5DE6\u53F3 padding 16px = 100px\u3002\u518D\u957F\u5C31\u5728\u672C\u6BB5\u5185\u6A2A\u6ED1\uFF0C\n \u8FD9\u6837\u6807\u9898\u6C38\u8FDC\u4E0D\u4F1A\u9876\u5230\u53F3\u4FA7\u7684\u9884\u8BBE\u3002 */\n /* \u672C\u6279\u4E4B\u524D\u7684\u503C\uFF08100px \u6A2A\u6ED1\u7A97 + \u786C\u5207\uFF09\u30022026-10-12 \u7684\u300C\u7F29\u5230 80px \u518D\u6539\u7701\u7565\u53F7\u3001\n \u6700\u540E\u53D6\u6D88\u786C\u9876\u6539 max-width: 100%\u300D\u53EA\u9488\u5BF9\u624B\u673A\u6863\uFF08\u5B50\u667A\u80FD\u4F53 chip \u8FDB\u6807\u9898\u884C\u540E\n \u8981\u8BA9\u51FA\u7EA6 100px\uFF09\uFF0C\u5DF2\u6574\u4E32\u642C\u8FDB\u624B\u673A\u6863\u4F5C\u7528\u57DF\uFF1B\u5171\u7528\u6863\uFF08= \u5E73\u677F\u6863\uFF09\u4FDD\u6301\u4E0D\u52A8\u3002 */\n max-width: 100px !important;\n overflow-x: auto !important;\n overflow-y: hidden !important;\n text-overflow: clip !important;\n white-space: nowrap !important;\n text-align: left !important;\n justify-content: flex-start !important;\n touch-action: pan-x !important;\n overscroll-behavior-x: contain !important;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n }\n [data-mobile-nav=\"frame\"] [data-phase] header:has([class*=\"_headerLeading\"]) [class*=\"_crumbs\"] [class*=\"_crumbCurrent\"]::-webkit-scrollbar {\n display: none;\n }\n /* \u9762\u5305\u5C51\u7684\u7236\u4F1A\u8BDD\u6BB5\u540C\u6837\u662F