diff --git a/packages/dashboard/app/components/command-center/CommandCenter.css b/packages/dashboard/app/components/command-center/CommandCenter.css index bb65859a3b..26613efec4 100644 --- a/packages/dashboard/app/components/command-center/CommandCenter.css +++ b/packages/dashboard/app/components/command-center/CommandCenter.css @@ -1,6 +1,9 @@ /* FNXC:CommandCenterStyling 2026-06-17-18:46: The FN-4286 dashboard text-token guard requires command-center secondary copy to use --text-muted, not the deprecated secondary text token or raw color fallbacks. + +FNXC:CommandCenterStyling 2026-06-19-18:30: +FN-6690 fix: Command Center CSS was authored against a numeric token scale (--space-1..--space-36, --font-size-*, --border-width*) that this design system never defines, so ~186 var() refs resolved to nothing and the whole view rendered collapsed/unstyled on desktop and mobile (raw run-together tabs, no padding). The dashboard uses the NAMED 4px spacing scale only: --space-xs(4) sm(8) md(12) lg(16) xl(24) 2xl(32), with calc() of named tokens for larger values (house style, e.g. calc(var(--space-2xl) * 7 + var(--space-lg))). Font sizes are raw rem (no --font-size-* tokens exist) and border widths are raw px (--border is a color, not a width). All Command Center CSS is remapped onto these. A token-validity guard test (CommandCenter.token-validity.css.test.ts) now fails if any component CSS references a custom property not defined in styles.css, so this class of bug cannot recur. The bug slipped past the recent FN-66xx work because those tests ran in jsdom, which does not resolve CSS custom properties or compute layout. */ /* Command Center shell. @@ -34,7 +37,7 @@ The Command Center must remain scrollable on mobile inside the overflow-hidden . align-items: center; gap: var(--space-sm); margin: 0; - font-size: 1rem; + font-size: 1.125rem; } /* ---- Tabs ---- */ @@ -54,7 +57,7 @@ The Command Center must remain scrollable on mobile inside the overflow-hidden . color: var(--text-muted); padding: var(--space-sm) var(--space-md); cursor: pointer; - font-size: 0.875rem; + font-size: 0.8125rem; transition: color var(--transition-fast), border-color var(--transition-fast); } @@ -94,13 +97,13 @@ The Command Center must remain scrollable on mobile inside the overflow-hidden . .cc-stat-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2)), 1fr)); + grid-template-columns: repeat(auto-fill, minmax(min(100%, calc(var(--space-2xl) * 5)), 1fr)); gap: var(--space-md); } /* FNXC:CommandCenterStyling 2026-06-18-22:38: -FN-6680 standardizes the Command Center card rhythm across overview, area, table, team, and system chart surfaces: use --space-3 padding/gaps, --border-width solid --border-subtle, --radius-md, and --surface-1 so mobile and tablet charts do not look like separate components. +FN-6680 standardizes the Command Center card rhythm across overview, area, table, team, and system chart surfaces: use --space-md padding/gaps, 1px solid --border-subtle, --radius-md, and --surface-1 so mobile and tablet charts do not look like separate components. */ .cc-stat-card { display: flex; @@ -114,12 +117,12 @@ FN-6680 standardizes the Command Center card rhythm across overview, area, table } .cc-stat-label { - font-size: 0.875rem; + font-size: 0.8125rem; color: var(--text-muted); } .cc-stat-value { - font-size: 1.25rem; + font-size: 1.5rem; font-variant-numeric: tabular-nums; color: var(--text); } @@ -145,7 +148,7 @@ The GitHub closed-at backfill control lives inside the existing Fixed by Fusion flex-direction: column; gap: var(--space-xs); color: var(--text-muted); - font-size: 0.8rem; + font-size: 0.75rem; } .cc-github-backfill-status--error { @@ -175,7 +178,7 @@ FN-6680 keeps the FN-6664 live/chart shrink contract but replaces hardcoded trac .cc-live-strip { position: relative; display: grid; - grid-template-columns: minmax(calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2), 1fr) minmax(calc((calc(var(--space-2xl) * 2 + var(--space-lg)) * 3) + var(--space-lg)), 2fr) minmax(calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2), 1fr); + grid-template-columns: minmax(calc(var(--space-2xl) * 5), 1fr) minmax(calc(var(--space-2xl) * 8), 2fr) minmax(calc(var(--space-2xl) * 5), 1fr); align-items: center; gap: var(--space-md); padding: var(--space-md); @@ -186,7 +189,7 @@ FN-6680 keeps the FN-6664 live/chart shrink contract but replaces hardcoded trac var(--surface-1); box-shadow: 0 0 var(--space-lg) color-mix(in srgb, var(--accent) 18%, transparent); overflow: hidden; - font-size: 0.875rem; + font-size: 0.8125rem; } .cc-live-strip::before { @@ -239,7 +242,7 @@ FN-6680 keeps the FN-6664 live/chart shrink contract but replaces hardcoded trac .cc-live-metric-value { color: var(--text); - font-size: 1rem; + font-size: 1.125rem; font-weight: 700; font-variant-numeric: tabular-nums; } @@ -266,7 +269,7 @@ Overview token totals now live-poll and should visibly count up on change in bot .cc-live-metric-label, .cc-live-trend-label { color: var(--text-muted); - font-size: 0.8rem; + font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; } @@ -369,7 +372,7 @@ Overview charts must use dashboard tokens only and keep motion decorative; anima .cc-overview-chart-header p { margin: 0; color: var(--text-muted); - font-size: 0.875rem; + font-size: 0.8125rem; } .cc-overview-chart-card .cc-bar-chart, @@ -387,7 +390,7 @@ Overview recharts cards use token-derived height so ResponsiveContainer can rend .cc-overview-chart-card .cc-recharts-chart, .cc-overview-chart-card .cc-recharts-empty { inline-size: 100%; - block-size: calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 3); + block-size: calc(var(--space-2xl) * 7 + var(--space-lg)); min-inline-size: 0; } @@ -470,7 +473,7 @@ The Command Center subtree previously had no tablet tier, so at 769px–1024px t .cc-stat-grid, .cc-area .cc-stat-grid { - grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2)), 1fr)); + grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(var(--space-2xl) * 5)), 1fr)); } } diff --git a/packages/dashboard/app/components/command-center/DateRangePicker.css b/packages/dashboard/app/components/command-center/DateRangePicker.css index dfc2844dc5..8cfaa6b550 100644 --- a/packages/dashboard/app/components/command-center/DateRangePicker.css +++ b/packages/dashboard/app/components/command-center/DateRangePicker.css @@ -49,7 +49,7 @@ Raw rgba fallbacks are replaced with byte-equivalent concrete-hex color-mix fall align-items: center; justify-content: space-between; gap: var(--space-sm); - font-size: 0.85rem; + font-size: 0.8125rem; color: var(--text-muted); } diff --git a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-chart-layout.test.ts b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-chart-layout.test.ts index e2f654a6d4..477ffc2faf 100644 --- a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-chart-layout.test.ts +++ b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-chart-layout.test.ts @@ -51,28 +51,28 @@ describe("CommandCenter.mobile-chart-layout.css", () => { }); it("pins the corrected mobile bar row template without a competing scroll owner", () => { - expect(mobileCss).toMatch(/\.cc-bar-row\s*\{[^}]*grid-template-columns:\s*minmax\(0,\s*1fr\)\s+minmax\(var\(--space-12\),\s*2fr\);[^}]*align-items:\s*start/); + expect(mobileCss).toMatch(/\.cc-bar-row\s*\{[^}]*grid-template-columns:\s*minmax\(0,\s*1fr\)\s+minmax\(calc\(var\(--space-2xl\)\s*\+\s*var\(--space-lg\)\),\s*2fr\);[^}]*align-items:\s*start/); expect(mobileCss).toMatch(/\.cc-bar-value\s*\{[^}]*grid-column:\s*1\s*\/\s*-1;[^}]*max-inline-size:\s*100%/); expect(cssContent).not.toMatch(/\.cc-(?:bar|line|radial|sparkline|token-series|funnel)[^{]*\{[^}]*overflow-y:\s*(?:auto|scroll)/); }); it("keeps line, token-series, radial, team, and system charts non-collapsing at mobile", () => { - expect(mobileCss).toMatch(/\.cc-line-chart\s*\{[^}]*block-size:\s*clamp\(var\(--space-16\),\s*44vw,\s*calc\(var\(--space-20\)\s*\+\s*var\(--space-12\)\)\);[^}]*aspect-ratio:\s*auto/); - expect(mobileCss).toMatch(/\.cc-token-series-plot\s*\{[^}]*block-size:\s*clamp\(var\(--space-14\),\s*38vw,\s*calc\(var\(--space-20\)\s*\+\s*var\(--space-12\)\)\)/); - expect(mobileCss).toMatch(/\.cc-radial-gauge-ring\s*\{[^}]*inline-size:\s*clamp\(var\(--space-20\),\s*44vw,\s*var\(--space-32\)\)/); + expect(mobileCss).toMatch(/\.cc-line-chart\s*\{[^}]*block-size:\s*clamp\(calc\(var\(--space-2xl\)\s*\*\s*2\),\s*44vw,\s*calc\(var\(--space-2xl\)\s*\*\s*4\)\);[^}]*aspect-ratio:\s*auto/); + expect(mobileCss).toMatch(/\.cc-token-series-plot\s*\{[^}]*block-size:\s*clamp\(calc\(var\(--space-2xl\)\s*\+\s*var\(--space-xl\)\),\s*38vw,\s*calc\(var\(--space-2xl\)\s*\*\s*4\)\)/); + expect(mobileCss).toMatch(/\.cc-radial-gauge-ring\s*\{[^}]*inline-size:\s*clamp\(calc\(var\(--space-2xl\)\s*\*\s*2\s*\+\s*var\(--space-lg\)\),\s*44vw,\s*calc\(var\(--space-2xl\)\s*\*\s*4\)\)/); expect(mobileCss).toMatch(/\.cc-team-chart-grid\s*\{[^}]*min-inline-size:\s*0;[^}]*grid-template-columns:\s*minmax\(0,\s*1fr\)/); expect(mobileCss).toMatch(/\.cc-system-chart-grid\s*\{[^}]*grid-template-columns:\s*minmax\(0,\s*1fr\)/); }); it("keeps recharts ResponsiveContainer parents sized without becoming scroll owners", () => { - expect(cssContent).toMatch(/\.cc-overview-chart-card \.cc-recharts-chart,[\s\S]*\.cc-overview-chart-card \.cc-recharts-empty\s*\{[\s\S]*inline-size:\s*100%;[\s\S]*block-size:\s*calc\(var\(--space-20\)\s*\*\s*3\);[\s\S]*min-inline-size:\s*0/); - expect(cssContent).toMatch(/\.cc-area \.cc-recharts-chart,[\s\S]*\.cc-area \.cc-recharts-empty\s*\{[\s\S]*inline-size:\s*100%;[\s\S]*block-size:\s*calc\(var\(--space-20\)\s*\*\s*3\);[\s\S]*min-inline-size:\s*0/); + expect(cssContent).toMatch(/\.cc-overview-chart-card \.cc-recharts-chart,[\s\S]*\.cc-overview-chart-card \.cc-recharts-empty\s*\{[\s\S]*inline-size:\s*100%;[\s\S]*block-size:\s*calc\(var\(--space-2xl\)\s*\*\s*7\s*\+\s*var\(--space-lg\)\);[\s\S]*min-inline-size:\s*0/); + expect(cssContent).toMatch(/\.cc-area \.cc-recharts-chart,[\s\S]*\.cc-area \.cc-recharts-empty\s*\{[\s\S]*inline-size:\s*100%;[\s\S]*block-size:\s*calc\(var\(--space-2xl\)\s*\*\s*7\s*\+\s*var\(--space-lg\)\);[\s\S]*min-inline-size:\s*0/); expect(cssContent).not.toMatch(/\.cc-recharts-(?:chart|empty)[^{]*\{[^}]*overflow-y:\s*(?:auto|scroll)/); }); it("normalizes chart/card/table border rhythm with design tokens only", () => { - expect(cssContent).toMatch(/\.cc-stat-card\s*\{[^}]*padding:\s*var\(--space-3\);[^}]*border:\s*var\(--border-width\)\s+solid\s+var\(--border-subtle\);[^}]*border-radius:\s*var\(--radius-md\);[^}]*background:\s*var\(--surface-1\)/); - expect(cssContent).toMatch(/\.cc-table-wrap\s*\{[^}]*border:\s*var\(--border-width\)\s+solid\s+var\(--border-subtle\);[^}]*border-radius:\s*var\(--radius-md\);[^}]*background:\s*var\(--surface-1\);[^}]*overflow-x:\s*auto;[^}]*overflow-y:\s*hidden/); - expect(cssContent).toMatch(/\.cc-system-vitest-card\s*\{[^}]*border:\s*var\(--border-width\)\s+solid\s+var\(--border-subtle\);[^}]*border-radius:\s*var\(--radius-md\);[^}]*background:\s*var\(--surface-1\)/); + expect(cssContent).toMatch(/\.cc-stat-card\s*\{[^}]*padding:\s*var\(--space-md\);[^}]*border:\s*1px\s+solid\s+var\(--border-subtle\);[^}]*border-radius:\s*var\(--radius-md\);[^}]*background:\s*var\(--surface-1\)/); + expect(cssContent).toMatch(/\.cc-table-wrap\s*\{[^}]*border:\s*1px\s+solid\s+var\(--border-subtle\);[^}]*border-radius:\s*var\(--radius-md\);[^}]*background:\s*var\(--surface-1\);[^}]*overflow-x:\s*auto;[^}]*overflow-y:\s*hidden/); + expect(cssContent).toMatch(/\.cc-system-vitest-card\s*\{[^}]*border:\s*1px\s+solid\s+var\(--border-subtle\);[^}]*border-radius:\s*var\(--radius-md\);[^}]*background:\s*var\(--surface-1\)/); }); }); diff --git a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-scroll.test.tsx b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-scroll.test.tsx index 3a3d19f29d..e04b243b03 100644 --- a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-scroll.test.tsx +++ b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.mobile-scroll.test.tsx @@ -413,13 +413,13 @@ describe("CommandCenter mobile scroll regression (FN-6595)", () => { expect(styles).toContain(".cc-tabpanel"); expect(styles).toContain("overflow-x: hidden"); - expect(styles).toContain("grid-template-columns: minmax(0, 1fr) minmax(var(--space-12), 2fr)"); + expect(styles).toContain("grid-template-columns: minmax(0, 1fr) minmax(calc(var(--space-2xl) + var(--space-lg)), 2fr)"); expect(styles).toContain(".cc-line-chart"); expect(styles).toContain(".cc-recharts-chart"); - expect(styles).toContain("block-size: calc(var(--space-20) * 3)"); + expect(styles).toContain("block-size: calc(var(--space-2xl) * 7 + var(--space-lg))"); expect(styles).toContain("aspect-ratio: auto"); expect(styles).toContain(".cc-radial-gauge-ring"); - expect(styles).toContain("inline-size: clamp(var(--space-20), 44vw, var(--space-32))"); + expect(styles).toContain("inline-size: clamp(calc(var(--space-2xl) * 2 + var(--space-lg)), 44vw, calc(var(--space-2xl) * 4))"); expect(styles).toContain("min-inline-size: 0"); expect(styles).toContain(".cc-token-series-axis"); expect(styles).toContain("overflow-wrap: anywhere"); diff --git a/packages/dashboard/app/components/command-center/__tests__/CommandCenter.token-validity.css.test.ts b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.token-validity.css.test.ts new file mode 100644 index 0000000000..ee53223fef --- /dev/null +++ b/packages/dashboard/app/components/command-center/__tests__/CommandCenter.token-validity.css.test.ts @@ -0,0 +1,120 @@ +/* +FNXC:CommandCenterStyling 2026-06-19-18:40: +FN-6690 invariant guard. Command Center shipped broken (entire view collapsed/unstyled on +desktop and mobile) because its CSS referenced a numeric design-token scale +(--space-1..--space-36, --font-size-*, --border-width*) that this dashboard never defines, so +~186 var() references resolved to nothing — padding, gaps, font sizes, and borders all collapsed. + +The dashboard design system defines ONLY the named 4px spacing scale +(--space-xs/sm/md/lg/xl/2xl), uses raw rem font sizes (no --font-size-* tokens), and raw px +border widths (--border is a color, not a width). This guard fails if any Command Center CSS +references a custom property that is not defined in styles.css (the canonical token vocabulary) +or set as a component-local property. It fixes the invariant, not just the one repro: any future +undefined-token reference in Command Center CSS is caught here. + +This class of bug slipped past the recent FN-66xx Command Center work because those tests ran in +jsdom, which does not resolve CSS custom properties or compute layout. This guard reads raw CSS +text, so it catches the collapse jsdom cannot see. + +Follow-up FN-6693 extends this guard dashboard-wide (other components carry the same latent +undefined-token references). +*/ +import { describe, expect, it } from "vitest"; +import { readFileSync, readdirSync, statSync } from "node:fs"; +import { join, relative, resolve } from "node:path"; + +const APP_DIR = resolve(__dirname, "..", "..", ".."); +const STYLES_CSS = join(APP_DIR, "styles.css"); +const COMMAND_CENTER_DIR = resolve(__dirname, ".."); + +/** + * Custom properties that are legitimately set at runtime via JS inline styles + * (style={{ "--name": ... }}) rather than declared in a stylesheet. These are + * valid targets for var() even though no CSS file assigns them. + */ +const JS_SET_PROPERTY_ALLOWLIST = new Set([ + "--cc-radial-value", // RadialGauge.tsx sets this per-instance +]); + +function collectCssFiles(dir: string): string[] { + const out: string[] = []; + for (const entry of readdirSync(dir)) { + if (entry === "node_modules" || entry.startsWith(".") || entry === "__tests__") continue; + const full = join(dir, entry); + const info = statSync(full); + if (info.isDirectory()) out.push(...collectCssFiles(full)); + else if (entry.endsWith(".css")) out.push(full); + } + return out; +} + +function collectDefinedProperties(css: string, into: Set): void { + // Match `--name:` declarations (definitions/assignments), not var() references. + const re = /(--[a-z0-9-]+)\s*:/gi; + let m: RegExpExecArray | null; + while ((m = re.exec(css)) !== null) { + into.add(m[1]); + } +} + +function collectReferencedProperties(css: string): Map { + // Match `var(--name` references; ignore the optional fallback — referencing an + // undefined token even with a fallback is the anti-pattern that hid FN-6690. + const refs = new Map(); + const lines = css.split("\n"); + lines.forEach((line, idx) => { + const re = /var\(\s*(--[a-z0-9-]+)/gi; + let m: RegExpExecArray | null; + while ((m = re.exec(line)) !== null) { + const name = m[1]; + const list = refs.get(name) ?? []; + list.push(idx + 1); + refs.set(name, list); + } + }); + return refs; +} + +describe("Command Center CSS token validity (FN-6690)", () => { + // Defined vocabulary = every --name: declared in styles.css, plus any + // component-local properties assigned within Command Center CSS, plus + // JS-set runtime properties. + const defined = new Set(JS_SET_PROPERTY_ALLOWLIST); + collectDefinedProperties(readFileSync(STYLES_CSS, "utf8"), defined); + const ccFiles = collectCssFiles(COMMAND_CENTER_DIR); + for (const file of ccFiles) { + collectDefinedProperties(readFileSync(file, "utf8"), defined); + } + + it("has at least one Command Center stylesheet to validate", () => { + expect(ccFiles.length).toBeGreaterThan(0); + }); + + it("references only defined design tokens (no undefined --space-N / --font-size-* / etc.)", () => { + const violations: string[] = []; + for (const file of ccFiles) { + const refs = collectReferencedProperties(readFileSync(file, "utf8")); + for (const [name, lineNos] of refs) { + if (!defined.has(name)) { + const rel = relative(APP_DIR, file); + violations.push(`${rel}: var(${name}) at line(s) ${lineNos.join(", ")}`); + } + } + } + expect(violations, `Undefined CSS custom properties referenced in Command Center CSS:\n${violations.join("\n")}`).toEqual([]); + }); + + it("does not reintroduce the undefined numeric --space-N scale", () => { + const offenders: string[] = []; + for (const file of ccFiles) { + const css = readFileSync(file, "utf8"); + // var(--space-) is the broken numeric scale; the valid scale is named + // (xs/sm/md/lg/xl/2xl). The negative lookahead excludes the valid --space-2xl token, + // which starts with a digit but is a named token, not the numeric scale. + if (/var\(\s*--space-\d+(?![a-z])/i.test(css)) { + offenders.push(relative(APP_DIR, file)); + } + } + expect(offenders, `Numeric --space-N tokens are undefined in this design system; use the named --space-xs/sm/md/lg/xl/2xl scale:\n${offenders.join("\n")}`).toEqual([]); + }); +}); diff --git a/packages/dashboard/app/components/command-center/areas/SystemStatsArea.css b/packages/dashboard/app/components/command-center/areas/SystemStatsArea.css index e104978f13..3b06484697 100644 --- a/packages/dashboard/app/components/command-center/areas/SystemStatsArea.css +++ b/packages/dashboard/app/components/command-center/areas/SystemStatsArea.css @@ -9,7 +9,7 @@ The Command Center System area replaces the standalone System Stats modal with g justify-content: flex-end; gap: var(--space-sm); color: var(--text-muted); - font-size: 0.875rem; + font-size: 0.8125rem; } .cc-system-refresh .btn-icon { @@ -73,7 +73,7 @@ System control cards sit beside chart/stat cards, so FN-6680 gives them the same .cc-system-toggle-row, .cc-system-threshold-row { color: var(--text); - font-size: 0.875rem; + font-size: 0.8125rem; } .cc-system-threshold-controls input[type="range"] { @@ -87,7 +87,7 @@ System control cards sit beside chart/stat cards, so FN-6680 gives them the same .cc-system-note { margin: 0; color: var(--text-muted); - font-size: 0.875rem; + font-size: 0.8125rem; } .cc-system-note--error, diff --git a/packages/dashboard/app/components/command-center/areas/areas.css b/packages/dashboard/app/components/command-center/areas/areas.css index 866f6a84ec..59cbf87b77 100644 --- a/packages/dashboard/app/components/command-center/areas/areas.css +++ b/packages/dashboard/app/components/command-center/areas/areas.css @@ -34,7 +34,7 @@ FN-6680 preserves the FN-6664 section rhythm while adding real-layout shrink gua .cc-area-section-title { margin: 0; - font-size: 0.875rem; + font-size: 0.8125rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; @@ -48,19 +48,19 @@ FN-6683 recharts wrappers must stay responsive without creating an inner scroll .cc-area .cc-recharts-chart, .cc-area .cc-recharts-empty { inline-size: 100%; - block-size: calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 3); + block-size: calc(var(--space-2xl) * 7 + var(--space-lg)); min-inline-size: 0; } /* Reuse the shell's stat-grid/stat-card look. */ .cc-area .cc-stat-grid { display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2)), 1fr)); + grid-template-columns: repeat(auto-fill, minmax(min(100%, calc(var(--space-2xl) * 5)), 1fr)); gap: var(--space-md); } .cc-stat-sub { - font-size: 0.8rem; + font-size: 0.75rem; color: var(--text-muted); } @@ -131,7 +131,7 @@ FN-6680 keeps table-heavy chart areas on the same --border-width/--border-subtle .cc-table { inline-size: 100%; border-collapse: collapse; - font-size: 0.875rem; + font-size: 0.8125rem; font-variant-numeric: tabular-nums; } @@ -211,13 +211,13 @@ FN-6680 keeps table-heavy chart areas on the same --border-width/--border-subtle } .cc-pricing-note { - font-size: 0.8rem; + font-size: 0.75rem; color: var(--text-muted); } /* FNXC:CommandCenterStyling 2026-06-18-22:38: -The Team view must use dashboard design tokens only, preserve .cc-tabpanel as the scroll owner on mobile, and match the shared card rhythm (--space-3 gap/padding, --border-width solid --border-subtle, --radius-md, --surface-1) while keeping decorative motion duration-token based with reduced-motion disabled. +The Team view must use dashboard design tokens only, preserve .cc-tabpanel as the scroll owner on mobile, and match the shared card rhythm (--space-md gap/padding, 1px solid --border-subtle, --radius-md, --surface-1) while keeping decorative motion duration-token based with reduced-motion disabled. */ .cc-team-chart-grid { display: grid; @@ -248,7 +248,7 @@ The Team view must use dashboard design tokens only, preserve .cc-tabpanel as th .cc-muted-hint { margin: 0; - font-size: 0.875rem; + font-size: 0.8125rem; } .cc-team-agent-cell { @@ -269,7 +269,7 @@ The Team view must use dashboard design tokens only, preserve .cc-tabpanel as th } .cc-team-agent-role { - font-size: 0.8rem; + font-size: 0.75rem; text-transform: capitalize; } @@ -296,7 +296,7 @@ Tablet Command Center areas share the FN-6679 overflow fix with the shell: area */ @media (min-width: 769px) and (max-width: 1024px) { .cc-area .cc-stat-grid { - grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2)), 1fr)); + grid-template-columns: repeat(auto-fit, minmax(min(100%, calc(var(--space-2xl) * 5)), 1fr)); } .cc-team-chart-grid { diff --git a/packages/dashboard/app/components/command-center/charts/charts.css b/packages/dashboard/app/components/command-center/charts/charts.css index 4bc21b021d..3b242512d0 100644 --- a/packages/dashboard/app/components/command-center/charts/charts.css +++ b/packages/dashboard/app/components/command-center/charts/charts.css @@ -52,7 +52,7 @@ FN-6680 re-checked FN-6664 in a real Blink layout engine because jsdom does not .cc-bar-label { min-inline-size: 0; - font-size: 0.875rem; + font-size: 0.8125rem; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; @@ -77,7 +77,7 @@ FN-6680 re-checked FN-6664 in a real Blink layout engine because jsdom does not .cc-bar-value { min-inline-size: 0; - font-size: 0.875rem; + font-size: 0.8125rem; font-variant-numeric: tabular-nums; color: var(--text); overflow-wrap: anywhere; @@ -119,7 +119,7 @@ FN-6680 re-checked FN-6664 in a real Blink layout engine because jsdom does not display: flex; align-items: center; gap: var(--space-xs); - font-size: 0.875rem; + font-size: 0.8125rem; color: var(--text-muted); overflow-wrap: anywhere; } @@ -164,7 +164,7 @@ The token-over-time chart is live-updated and animated, but the motion is decora display: flex; align-items: flex-end; gap: var(--space-xs); - block-size: clamp(calc(var(--space-2xl) * 2), 24vw, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2)); + block-size: clamp(calc(var(--space-2xl) * 2), 24vw, calc(var(--space-2xl) * 5)); padding: var(--space-md); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); @@ -195,7 +195,7 @@ The token-over-time chart is live-updated and animated, but the motion is decora justify-content: space-between; gap: var(--space-sm); color: var(--text-muted); - font-size: 0.8rem; + font-size: 0.75rem; font-variant-numeric: tabular-nums; } @@ -230,7 +230,7 @@ The token-over-time chart is live-updated and animated, but the motion is decora @media (max-width: 768px) { .cc-token-series-plot { - block-size: clamp(calc(var(--space-2xl) + var(--space-xl)), 38vw, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) + calc(var(--space-2xl) + var(--space-lg)))); + block-size: clamp(calc(var(--space-2xl) + var(--space-xl)), 38vw, calc(var(--space-2xl) * 4)); padding: var(--space-sm); } } @@ -243,7 +243,7 @@ Line-chart motion is decorative, token-timed, and disabled for reduced-motion us .cc-line-chart { display: block; inline-size: 100%; - block-size: clamp(calc(var(--space-2xl) * 2), 22vw, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) * 2)); + block-size: clamp(calc(var(--space-2xl) * 2), 22vw, calc(var(--space-2xl) * 5)); aspect-ratio: 5 / 2; color: var(--accent); overflow: hidden; @@ -293,7 +293,7 @@ Line-chart motion is decorative, token-timed, and disabled for reduced-motion us @media (max-width: 768px) { .cc-line-chart { - block-size: clamp(calc(var(--space-2xl) * 2), 44vw, calc(calc(var(--space-2xl) * 2 + var(--space-lg)) + calc(var(--space-2xl) + var(--space-lg)))); + block-size: clamp(calc(var(--space-2xl) * 2), 44vw, calc(var(--space-2xl) * 4)); aspect-ratio: auto; } } @@ -345,7 +345,7 @@ Line-chart motion is decorative, token-timed, and disabled for reduced-motion us } .cc-radial-gauge-value { - font-size: 1.25rem; + font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; } @@ -353,7 +353,7 @@ Line-chart motion is decorative, token-timed, and disabled for reduced-motion us .cc-radial-gauge-label { max-inline-size: 100%; color: var(--text-muted); - font-size: 0.875rem; + font-size: 0.8125rem; overflow-wrap: anywhere; text-align: center; } @@ -405,7 +405,7 @@ Line-chart motion is decorative, token-timed, and disabled for reduced-motion us display: flex; justify-content: space-between; gap: var(--space-sm); - font-size: 0.875rem; + font-size: 0.8125rem; color: var(--text-muted); } @@ -440,7 +440,7 @@ Line-chart motion is decorative, token-timed, and disabled for reduced-motion us } .cc-funnel-value { - font-size: 0.875rem; + font-size: 0.8125rem; font-variant-numeric: tabular-nums; color: var(--text); }