Context
The ui: 'inline' design pass for dock tab headers (#17950 variants, #17963 header actions, #18043 title weight and trim, #18048) left one value untouched: the header's band. theme-neo-dark/tab/Container.scss:10-14 and its neo-light twin value --tab-header-inline-background-image as a 180° gradient from --sem-color-surface-neutral-highlighted to --sem-color-surface-neutral-default — in neo-dark that resolves to gray-800 #292D28 → gray-900 #0E0F0D, an olive-tinted ramp; in neo-light to white → #fafafa. src/tab/Container.scss:1-7 paints it (&.neo-tab-container-inline > .neo-tab-header-toolbar { background-image: var(--tab-header-inline-background-image, none) }), and the header owns nothing else: src/tab/header/Toolbar.scss:2 is background-color: transparent, no border, no color token.
The operator (2026-09-02) saw the ramp on a consumer's dock panes and named it as not fitting the app; he had assumed the inline pass flattened it. It did — for one app. resources/scss/src/apps/workstation/Viewport.scss:74-84 re-values the hook with the Workstation's own two panel colors and explains why: "The neo themes value this hook with a neutral olive ramp; painted over this instrument's blue-slate panel it read as a foreign surface" — then sets the header's background-color longhand and a border-bottom line separately (:196-204), noting the shorthand fights the engine rule. The flagship app rejects the default; every other host inherits it.
Sibling, same family (defaults lag the apps' overrides): #18080 — the engine's default reveal chrome vanishes on a dark ground while the Workstation and the cockpit override it.
The Problem
The default should be the good default. A consumer that adopts enableDock*Action and ui: 'inline' gets the engine's density and action chrome for free, then still has to discover one token to stop the band reading as a gradient over its surfaces — and has NO token at all for the header's own color or its separating line, because the inline header carries neither. The Workstation's answer (its own palette + longhand background + border) is the shape the theme should offer as its baseline: a flat header surface and a hairline, valued from semantic tokens, with the gradient hook kept for consumers who want one.
The Architectural Reality
resources/scss/theme-neo-dark/tab/Container.scss:1-14 and resources/scss/theme-neo-light/tab/Container.scss:10-14 — the inline band token; the same sheets already carry the inline density tier (--tab-button-height: var(--sem-height-large) etc.).
resources/scss/src/tab/Container.scss:1-7 — the variant selector that paints the band; the comment there names it "the public inline-header hook".
resources/scss/src/tab/header/Toolbar.scss:2 — the toolbar's own paint is transparent; actions (:12-49) keep their tokens.
resources/scss/theme-neo-dark/design-tokens/Semantic.scss:18,31,32 — --sem-color-border-default: var(--gray-700), --sem-color-surface-neutral-default: var(--gray-900), --sem-color-surface-neutral-highlighted: var(--gray-800); neo-light :18,31,32 — gray-200, gray-50, white.
resources/scss/src/apps/workstation/Viewport.scss:70-84, 196-204 — the Workstation's override (its own palette; stays).
buildScripts/util/check-theme-coverage.mjs — values must land in BOTH neo themes.
- Screenshots that contain an inline header:
test/playwright/e2e/dashboard/DockPinCollapseNL.spec.mjs:281-315 (eight darwin reveal-pin-<theme>-{enabled,disabled}.png, re-recorded by PR #18090 for #18089 today); test/playwright/visual/PreviewLanguageVisual.spec.mjs:115,131 (to be checked at implementation).
The Fix
- Both neo themes (
tab/Container.scss, same block that owns the inline tokens): --tab-header-inline-background-image: none (the hook stays a public token — consumers who want a gradient keep valuing it); add --tab-header-inline-background-color: var(--sem-color-surface-neutral-highlighted) and --tab-header-inline-box-shadow: inset 0 -1px 0 var(--sem-color-border-default).
src/tab/Container.scss inline rule paints the header from those tokens with transparent fallbacks, so the legacy themes and every other host stay byte-identical: background-color: var(--tab-header-inline-background-color, transparent), the existing background-image hook, and the hairline as box-shadow: var(--tab-header-inline-box-shadow, none) — one whole-value token (a colour-inside-a-fixed-shadow fallback still computes to a transparent shadow STRING on the legacy themes, not none), an inset shadow, NOT border-bottom, so the header's box does not grow by a pixel under the zero-gap geometry (#18015) and no height-asserting spec moves.
- Workstation: its override keeps winning on its own palette; the comment that calls the theme value an olive ramp is corrected to name the new baseline.
- Witness: a component paint spec in the DockRailTabPaint idiom (computed styles on a rendered inline header, both neo themes, with a control): the inline header's
background-image is none, its background-color equals the resolved --sem-color-surface-neutral-highlighted, the inset line is present — and a standalone (ui: null) header keeps its established paint. Red-first on dev: the computed background-image is the gradient.
- Baselines: the eight
DockPinCollapseNL reveal-pin PNGs show the inline header and change with the band. They are re-recorded in this PR after #18090 merges (sequencing: #18090 first, then this), or, if this lands first, #18090's images are re-recorded once more — either way one recording against the final band.
Acceptance Criteria
Out of Scope
- Brand or overlay themes (a token-only theme riding another theme's sheets) — the primitive a consumer brand theme needs; ideation-sandbox material, not this leaf.
- #18080 (default reveal chrome on a dark ground) — sibling, separate.
- The legacy
theme-dark / theme-light — they carry no inline tokens and keep their paint.
- Promoting the Workstation palette itself into a theme.
Avoided Traps
border-bottom for the hairline — grows the header box by 1 px under the zero-gap geometry and moves every height-asserting spec; the inset box-shadow paints the same line at zero layout cost.
background shorthand — its implicit background-image: none fights the higher-specificity engine rule (the Workstation learned this at Viewport.scss:196-204); longhands only.
- Removing the gradient hook — consumers (the Workstation included) value it; the default becomes
none, the token stays public.
- Re-recording baselines before #18090 lands — two PRs racing on the same eight PNGs; sequence, record once.
Related
Live latest-open sweep: checked the latest 20 open issues at 2026-09-02T14:00Z; no equivalent found. A2A claim sweep (last 30 messages, all read-states): no overlapping [lane-claim].
Origin Session ID: 87c91db1-7fcd-4987-9932-2bf78d3dda25
Retrieval Hint: "inline tab header band gradient neo theme flat surface hairline token"
Context
The
ui: 'inline'design pass for dock tab headers (#17950 variants, #17963 header actions, #18043 title weight and trim, #18048) left one value untouched: the header's band.theme-neo-dark/tab/Container.scss:10-14and its neo-light twin value--tab-header-inline-background-imageas a 180° gradient from--sem-color-surface-neutral-highlightedto--sem-color-surface-neutral-default— in neo-dark that resolves to gray-800#292D28→ gray-900#0E0F0D, an olive-tinted ramp; in neo-light to white →#fafafa.src/tab/Container.scss:1-7paints it (&.neo-tab-container-inline > .neo-tab-header-toolbar { background-image: var(--tab-header-inline-background-image, none) }), and the header owns nothing else:src/tab/header/Toolbar.scss:2isbackground-color: transparent, no border, no color token.The operator (2026-09-02) saw the ramp on a consumer's dock panes and named it as not fitting the app; he had assumed the inline pass flattened it. It did — for one app.
resources/scss/src/apps/workstation/Viewport.scss:74-84re-values the hook with the Workstation's own two panel colors and explains why: "The neo themes value this hook with a neutral olive ramp; painted over this instrument's blue-slate panel it read as a foreign surface" — then sets the header'sbackground-colorlonghand and aborder-bottomline separately (:196-204), noting the shorthand fights the engine rule. The flagship app rejects the default; every other host inherits it.Sibling, same family (defaults lag the apps' overrides): #18080 — the engine's default reveal chrome vanishes on a dark ground while the Workstation and the cockpit override it.
The Problem
The default should be the good default. A consumer that adopts
enableDock*Actionandui: 'inline'gets the engine's density and action chrome for free, then still has to discover one token to stop the band reading as a gradient over its surfaces — and has NO token at all for the header's own color or its separating line, because the inline header carries neither. The Workstation's answer (its own palette + longhand background + border) is the shape the theme should offer as its baseline: a flat header surface and a hairline, valued from semantic tokens, with the gradient hook kept for consumers who want one.The Architectural Reality
resources/scss/theme-neo-dark/tab/Container.scss:1-14andresources/scss/theme-neo-light/tab/Container.scss:10-14— the inline band token; the same sheets already carry the inline density tier (--tab-button-height: var(--sem-height-large)etc.).resources/scss/src/tab/Container.scss:1-7— the variant selector that paints the band; the comment there names it "the public inline-header hook".resources/scss/src/tab/header/Toolbar.scss:2— the toolbar's own paint is transparent; actions (:12-49) keep their tokens.resources/scss/theme-neo-dark/design-tokens/Semantic.scss:18,31,32—--sem-color-border-default: var(--gray-700),--sem-color-surface-neutral-default: var(--gray-900),--sem-color-surface-neutral-highlighted: var(--gray-800); neo-light:18,31,32— gray-200, gray-50, white.resources/scss/src/apps/workstation/Viewport.scss:70-84, 196-204— the Workstation's override (its own palette; stays).buildScripts/util/check-theme-coverage.mjs— values must land in BOTH neo themes.test/playwright/e2e/dashboard/DockPinCollapseNL.spec.mjs:281-315(eight darwinreveal-pin-<theme>-{enabled,disabled}.png, re-recorded by PR #18090 for #18089 today);test/playwright/visual/PreviewLanguageVisual.spec.mjs:115,131(to be checked at implementation).The Fix
tab/Container.scss, same block that owns the inline tokens):--tab-header-inline-background-image: none(the hook stays a public token — consumers who want a gradient keep valuing it); add--tab-header-inline-background-color: var(--sem-color-surface-neutral-highlighted)and--tab-header-inline-box-shadow: inset 0 -1px 0 var(--sem-color-border-default).src/tab/Container.scssinline rule paints the header from those tokens with transparent fallbacks, so the legacy themes and every other host stay byte-identical:background-color: var(--tab-header-inline-background-color, transparent), the existingbackground-imagehook, and the hairline asbox-shadow: var(--tab-header-inline-box-shadow, none)— one whole-value token (a colour-inside-a-fixed-shadow fallback still computes to a transparent shadow STRING on the legacy themes, notnone), an inset shadow, NOTborder-bottom, so the header's box does not grow by a pixel under the zero-gap geometry (#18015) and no height-asserting spec moves.background-imageisnone, itsbackground-colorequals the resolved--sem-color-surface-neutral-highlighted, the inset line is present — and a standalone (ui: null) header keeps its established paint. Red-first on dev: the computedbackground-imageis the gradient.DockPinCollapseNLreveal-pin PNGs show the inline header and change with the band. They are re-recorded in this PR after #18090 merges (sequencing: #18090 first, then this), or, if this lands first, #18090's images are re-recorded once more — either way one recording against the final band.Acceptance Criteria
theme-neo-darkandtheme-neo-lighttab/Container.scssvalue--tab-header-inline-background-image: none,--tab-header-inline-background-colorand--tab-header-inline-box-shadowfrom semantic tokens;check-theme-coveragestays green.src/tab/Container.scsspaints the inline header's color and inset hairline from the tokens with transparent fallbacks;theme-dark,theme-light,theme-cyberpunkcompile to unchanged inline-header paint (no tokens → transparent/none).background-imagenone,background-color= resolved--sem-color-surface-neutral-highlighted, hairline present as the inset shadow; standalone header control unchanged; red-first on dev.DockPinCollapseNLreveal-pin baselines recorded against the flat band in the order stated in Fix 5;PreviewLanguageVisualchecked and re-recorded only if an inline header is in frame.components+unit/dashboardsuites green at head.Out of Scope
theme-dark/theme-light— they carry no inline tokens and keep their paint.Avoided Traps
border-bottomfor the hairline — grows the header box by 1 px under the zero-gap geometry and moves every height-asserting spec; the insetbox-shadowpaints the same line at zero layout cost.backgroundshorthand — its implicitbackground-image: nonefights the higher-specificity engine rule (the Workstation learned this atViewport.scss:196-204); longhands only.none, the token stays public.Related
Live latest-open sweep: checked the latest 20 open issues at 2026-09-02T14:00Z; no equivalent found. A2A claim sweep (last 30 messages, all read-states): no overlapping
[lane-claim].Origin Session ID: 87c91db1-7fcd-4987-9932-2bf78d3dda25
Retrieval Hint: "inline tab header band gradient neo theme flat surface hairline token"