diff --git a/src/client/components/contextView.tsx b/src/client/components/contextView.tsx
index 91990cb..bc6118b 100644
--- a/src/client/components/contextView.tsx
+++ b/src/client/components/contextView.tsx
@@ -458,31 +458,28 @@ export function makeContextView(
{t('trend.title')}
- {/* The DNA toggle rides the title text's right, left of the adaptive switch (the browser
- card's DNA toggle idiom): each bar becomes that request's per-item context fingerprint;
- combined with Delta, each band shows that item's change against the previous bar. */}
-
+ {/* The three display modifiers ride the title text's right as ONE multi-toggle segmented group
+ (the browser card's DNA toggle idiom), each segment lighting independently: DNA draws every
+ bar as that request's per-item context fingerprint (with Delta, per-item changes against the
+ previous bar); Adaptive rescales the axis to the visible bars, following the scroll; Duration
+ overlays each bar's step active time as a curve read off the right-hand quartile axis. */}
+
-
- {/* The adaptive switch rides the title's right (the browser card's DNA toggle idiom): bars rescale
- to the bars currently on screen instead of the whole retained log. */}
-
-
- {/* The duration overlay switch rides with the other title-adjacent toggles: each bar's step
- active time as a curve over the bars, read off the right-hand quartile axis. */}
-
diff --git a/src/client/styles/base.css b/src/client/styles/base.css
index 0fd08b6..96e73a8 100644
--- a/src/client/styles/base.css
+++ b/src/client/styles/base.css
@@ -74,14 +74,14 @@
.lc-trend-ctl .lc-gran, .lc-heat-ctl .lc-gran { margin-left: 0; }
/* The heat title's hint text loses its own auto margin inside the wrapper. */
.lc-heat-ctl .lc-card-sub { margin-left: 0; }
-/* The trend title's DNA toggle and adaptive switch ride the title text's right as an adjacent pair —
- each single-button group's auto margin is neutralized so they stay together (the browser card's DNA
+/* The trend title's modifier group (DNA / adaptive / duration as one multi-toggle segmented group)
+ rides the title text's right — its auto margin is neutralized so the group hugs the title and the
+ control cluster's own auto margin remains the row's single right push (the browser card's DNA
toggle idiom). */
-.lc-trend-dna, .lc-trend-adaptive { margin-left: 0; flex: none; }
+.lc-trend-mods { margin-left: 0; flex: none; }
.lc-gran-btn { border: 0; background: transparent; color: var(--dsw-alias-label-secondary); font-size: 11px; line-height: 1; padding: 3px 8px; border-radius: 5px; cursor: pointer; font-family: inherit; transition: color var(--ds-transition-duration, 0.2s) var(--ds-ease-in-out, ease-in-out); }
.lc-gran-btn:hover { color: var(--dsw-alias-label-primary); }
-/* Disabled chips (the Total/Delta pair while the trend card's DNA mode is on): inert and visually
- receded, keeping the group's layout so the row does not reflow when DNA toggles. */
+/* Disabled chips: inert and visually receded, keeping the group's layout so the row does not reflow. */
.lc-gran-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.lc-gran-btn:disabled:hover { color: var(--dsw-alias-label-secondary); }
.lc-gran-on, .lc-gran-on:hover { background: var(--dsw-alias-button-primary-fill); color: var(--dsw-alias-label-primary-foreground); }
diff --git a/tests/client/components/contextView.spec.ts b/tests/client/components/contextView.spec.ts
index 82ac3fb..9715d84 100644
--- a/tests/client/components/contextView.spec.ts
+++ b/tests/client/components/contextView.spec.ts
@@ -470,14 +470,15 @@ describe('ContextView — interactions', () => {
const titleText = query(card, '.lc-card-title-text')
assert.equal(text(titleText), DICT_EN['trend.title'])
- // The switch is the DNA toggle's NEXT sibling — the pair rides the title text's right, left of the
+ // The three display modifiers ride the title text's right as ONE segmented group, left of the
// card's right-hand control cluster.
const toggleOf = () => buttonByText(m.container, DICT_EN['trend.adaptive'])
- const dnaGroupOf = () => buttonByText(m.container, DICT_EN['trend.dna']).parentElement as HTMLElement
- assert.ok(dnaGroupOf().className.includes('lc-trend-dna'))
- assert.equal(dnaGroupOf().previousElementSibling, titleText)
- assert.equal(toggleOf().parentElement?.previousElementSibling, dnaGroupOf())
- assert.equal(toggleOf().parentElement?.getAttribute('title'), DICT_EN['trend.adaptiveHint'])
+ const modsGroupOf = () => buttonByText(m.container, DICT_EN['trend.dna']).parentElement as HTMLElement
+ assert.ok(modsGroupOf().className.includes('lc-trend-mods'))
+ assert.equal(modsGroupOf().previousElementSibling, titleText)
+ assert.equal(toggleOf().parentElement, modsGroupOf())
+ assert.equal(toggleOf().previousElementSibling, buttonByText(m.container, DICT_EN['trend.dna']), 'Adaptive rides right of DNA inside the group')
+ assert.equal(toggleOf().getAttribute('title'), DICT_EN['trend.adaptiveHint'])
assert.ok(!toggleOf().className.includes('lc-gran-on'), 'off at mount')
// Toggling is mount-local: the chart keeps rendering (jsdom has no layout, so the zero-width viewport falls
@@ -503,13 +504,12 @@ describe('ContextView — interactions', () => {
})),
}))
- // The switch rides the title's right, next after the adaptive one.
+ // The switch rides inside the title-adjacent modifier group, after the adaptive one.
const msBtn = () => buttonByText(m.container, DICT_EN['trend.duration'])
const group = msBtn().parentElement as HTMLElement
- assert.ok(group.className.includes('lc-trend-duration'))
- assert.equal(group.getAttribute('title'), DICT_EN['trend.durationTip'])
- const adaptiveGroup = buttonByText(m.container, DICT_EN['trend.adaptive']).parentElement as HTMLElement
- assert.equal(group.previousElementSibling, adaptiveGroup, 'Duration rides right of the adaptive switch')
+ assert.ok(group.className.includes('lc-trend-mods'))
+ assert.equal(msBtn().getAttribute('title'), DICT_EN['trend.durationTip'])
+ assert.equal(msBtn().previousElementSibling, buttonByText(m.container, DICT_EN['trend.adaptive']), 'Duration rides right of the adaptive switch')
// The settings default (show) mounts the overlay ON: the curve spans the two stamped bars and the
// right axis reads the 2s peak (jsdom's zero-width viewport keeps the whole-log scale, adaptive off anyway).
assert.ok(msBtn().className.includes('lc-gran-on'), 'on at mount (the settings default)')
@@ -534,9 +534,9 @@ describe('ContextView — interactions', () => {
const dnaBtn = () => buttonByText(m.container, DICT_EN['trend.dna'])
assert.ok(!dnaBtn().className.includes('lc-gran-on'), 'off at mount')
const dnaGroup = dnaBtn().parentElement as HTMLElement
- assert.ok(dnaGroup.className.includes('lc-trend-dna'))
- assert.equal(dnaGroup.getAttribute('title'), DICT_EN['trend.dnaTip'])
- assert.ok((dnaGroup.nextElementSibling as HTMLElement | null)?.className.includes('lc-trend-adaptive'), 'DNA rides left of the adaptive switch')
+ assert.ok(dnaGroup.className.includes('lc-trend-mods'))
+ assert.equal(dnaBtn().getAttribute('title'), DICT_EN['trend.dnaTip'])
+ assert.equal(dnaBtn().nextElementSibling, buttonByText(m.container, DICT_EN['trend.adaptive']), 'DNA rides left of the adaptive switch')
// DNA on: the bars become per-item fingerprints and the axis reads totals.
await click(dnaBtn())
@@ -568,7 +568,7 @@ describe('ContextView — interactions', () => {
test('the trend and browser DNA toggles move as one', async () => {
const m = await mountRich('sv-dna-link')
- const trendDna = () => query(m.container, '.lc-trend-dna .lc-gran-btn')
+ const trendDna = () => buttonByText(m.container, DICT_EN['trend.dna'])
const browserDna = () => query(m.container, '.lc-br-dna-ctl .lc-gran-btn')
assert.ok(!trendDna().className.includes('lc-gran-on') && !browserDna().className.includes('lc-gran-on'), 'both off at mount')