Command Center fixes
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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\)/);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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<string>([
|
||||
"--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<string>): 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<string, number[]> {
|
||||
// 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<string, number[]>();
|
||||
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<string>(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-<digits>) 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([]);
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user