| Wrapper | .bar-chart | Composition root. Owns the SVG aspect-ratio (default 800 / 380) and provides plot-inset slots used by the optional alternative .chart-avatar-row sibling. |
| SVG plot area | .bars · .bars--mixed | Categorical bar chart — one color per bar. The --mixed modifier signals "per-bar color, not per-series." Composes .bars--with-labels to enable .bar-value-label rendering. |
| Bar group | <g class="series-N"> | Wraps a <rect class="bar-rect"> + <text class="bar-value-label">. The .series-N class (N = 1..12) binds the categorical color declaratively — never use inline style="fill:…". |
| Bar rectangle | .bar-rect | Single SVG rect. Inherits fill: currentColor from the .series-N wrapper. rx/ry rounded corners; 4 px is the standard radius (use 2 for very short bars). |
| Value label | .bar-value-label | SVG text rendered above each bar. Sans body 600 + tabular-nums (NOT mono — values are content, not measurements). text-anchor="middle" at the bar's center x. |
| X-axis identity unit | <g class="chart-x-identity"> | Default identity pattern. A rotated SVG <g> at the bar's center x, containing a <foreignObject> with an HTML flex container. The whole unit rotates -45° around the pivot at (bar_cx, baseline_y + 16). Flex layout right-aligns content so all labels END at the pivot regardless of length. |
| foreignObject wrapper | <foreignObject x="-240" y="-12" width="240" height="24"> | Embeds HTML inside SVG. Width 240 px (in viewBox units) is the layout area for the unit; height 24 px matches .avatar--xs. The container's RIGHT EDGE is at local x=0 (the rotation pivot). |
| Flex content | .chart-x-identity__content | display: flex; align-items: center; justify-content: flex-end; gap: var(--space-12). The justify-end pushes [avatar | gap | label] to the right of the foreignObject so the label ends at the pivot. |
| Avatar (single) | img.avatar.avatar--xs.avatar--circle | Uses the canonical .avatar primitive — 24 px circular by default. Drop in any size (--xs 24 / --sm 32 / default 40 / --lg 48) and shape (--circle / --rounded / --square) modifier from the avatar family. Source order is FIRST in the flex row (leading the unit). |
| Avatar (tandem) | .avatar-tandem (inside __content) | For token + chain badge identities, swap the single <img class="avatar"> for an .avatar-tandem wrapper containing the token <img class="avatar avatar--circle"> + chain <img class="avatar-badge avatar-badge--br">. Flex still right-aligns the unit. |
| Label | .chart-x-identity__label | Mono caption text — var(--font-mono), var(--text-caption), weight medium, color: var(--text-faint), letter-spacing: var(--tracking-wide), white-space: nowrap. Source order SECOND in the flex row (after the avatar). |
| Y-axis title | .chart-axis-title | Mono caption uppercase semibold (one tier above .chart-tick). For rotated Y-axis titles ("Volume", "Open Interest"). Pair with transform="rotate(-90 cx cy)". |
| Y-axis ticks · grid · baseline | .chart-tick · .chart-grid-line · .chart-axis-line | Shared chart scaffolding — mono faint tick labels + dotted gridlines + solid baseline. Used by every chart family. |
| Categorical palette | .series-1 ... .series-12 | 1–8 map to --series-N (the curated 8-color subset of the spectral palette); 9–12 extend to the remaining spectral hues (lime, teal, sky, rose) for >8-category charts. |
| Alternative — separate avatar row | .chart-avatar-row | Optional fallback pattern. HTML flex row BELOW the SVG. Use when labels are short enough to read horizontally (no rotation needed) OR when avatars must be richer HTML primitives (links, buttons, complex hover states). Padding-inline coordinated via --bar-chart-plot-inset-start/-end. |
| Customization — plot inset start | --bar-chart-plot-inset-start | Left gutter of the plot area (where the Y-axis labels sit). Default 6% — matches the 48/800 viewBox y-gutter used by the chartFrame binder. Used by the optional .chart-avatar-row sibling. |
| Customization — plot inset end | --bar-chart-plot-inset-end | Right gutter. Default 1.5% — matches the 12/800 viewBox right margin. |
| Customization — gap | --bar-chart-gap | Vertical gap between the SVG and the optional avatar row. Default var(--space-12). |
| Customization — aspect | --bar-chart-aspect | Aspect ratio for the SVG container. Default 800 / 380 (accommodates the rotated identity units below the baseline). Override for taller/shorter chart shapes. |
| Customization — bar radius | --bar-radius | System-wide rx/ry for every .bar-rect in the chart. Default 4. Set to 0 for square corners. CSS overrides per-rect rx attributes via SVG2 geometry-as-CSS — for per-bar radius variation (rare — only the smallest bars in long leaderboards typically want rx=2), keep the attribute and DON'T set the slot. |
| Customization — mono tone | --bar-chart-mono-tone | Single hue used by .bar-chart--mono. Defaults to var(--accent-primary); override per-instance for success/danger/neutral-toned charts (e.g., style="--bar-chart-mono-tone: var(--success);"). |
| Variant — palette mode | .bar-chart--mono · --sequential · --diverging | Color routing. --mono: all bars one hue (categories are about identity, not rank). --sequential: --seq-9..1 ramp where saturation IS the rank signal. --diverging: --div-* Pink↔Slate↔Green for benchmark deltas (consumer orders bars by signed magnitude). Default behavior (no modifier): per-bar categorical fill via .series-N. |
| Variant — identity mode | .bar-chart--no-labels · --no-avatars · --avatars-only | --no-labels hides every .chart-x-identity (axis is just bars + ticks). --no-avatars keeps the tilted labels but suppresses the leading .avatar child. --avatars-only shows avatars HORIZONTAL (un-rotated) directly under each bar center; pairs with the per-bar .chart-x-identity--horizontal marker (markup shape changes — see Rules). For permanently labelless or avatar-less charts, prefer omitting the markup entirely — modifiers are for toggleable demos and runtime state. |
| Variant — identity order | .bar-chart--label-first | Flips the identity unit's visual order from [avatar][gap][label] (default) to [label][gap][avatar] via CSS order: -1 on the .chart-x-identity__label element. flex-direction stays row and justify-content: flex-end still packs the cluster at the rotation pivot — after right-pack + -45° rotation, the AVATAR anchors at the bar's center x and the LABEL trails down-left. A second rule centers the avatar's geometric middle on the bar's center x via transform: translateX(50%) on the .avatar / .avatar-tandem (without it, justify-end would put the avatar's RIGHT EDGE at the pivot, leaving the avatar's center half-a-width to the left of the bar). Markup is unchanged — the source order stays <img> first, <span> second; only the flex visual order flips. Pick by which element should sit nearest the bar: default for label-as-name; --label-first when the avatar is the recognizable mark and the label is supporting text. |
| Per-bar — horizontal identity | .chart-x-identity--horizontal | Per-bar marker for the avatars-only variant. Consumer authors the identity <g> without rotate(-45) in its transform, with a tight foreignObject anchored to x="-12" (half of .avatar--xs width) so the foreignObject centers on the bar's center x. The CSS flips the inner flex from justify-content: flex-end to center so the avatar sits in the middle of the (now tight) box. Sized for .avatar--xs (24 px) by default — consumers using .avatar--sm scale the foreignObject x/width to -16/32. |
| Variant — density tier | .bar-chart--compact · default · --hero | Three chart-density tiers. --compact: aspect 800 / 280, gap --space-8, label --text-micro — for sidebar slots and dashboard tiles. Default: aspect 800 / 380, gap --space-12, label --text-caption. --hero: aspect 800 / 480, gap --space-16, label --text-sm — for marketing decks. Avatar size on the per-bar markup is the consumer's call (.avatar--xs for default/compact, .avatar--sm for hero). |
| Highlight state | .bars--active + .is-active on g.series-N and matching g.chart-x-identity | One bar emphasised, siblings dimmed. The .bars--active wrapper on .bars activates the recipe; the matching .is-active class on a single <g class="series-N"> (and the matching <g class="chart-x-identity"> below it) keeps that bar and its identity at full opacity while siblings fade to 0.45. The active identity's label ink lifts from --text-faint to --text-primary so the active row reads as one unit. |
| Reference line (composable atom) | .chart-threshold + .chart-threshold-label | Not a leaderboard modifier — a reusable sibling atom. Composes inside any .bars SVG (or area chart). Markup: <line class="chart-threshold" x1=70 y1=N x2=780 y2=N/> + optional <text class="chart-threshold-label" x=780 y=N>…</text>. Dashed 4-4 stroke at 30 % --text-primary mix; reads as quieter than .chart-axis-line and louder than .chart-grid-line so the line registers as a deliberate reference without competing with the data. |