
A10 Brand
- 3 installs
- 28 repo stars
- Updated June 29, 2026
- nickcrew/claude-ctx-plugin
Helps with ai & agent building tasks.
About
a10-brand is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- a10-brand
- AI & Agent Building
- AI-coding skill
A10 Brand by the numbers
- 3 all-time installs (skills.sh)
- Ranked #13,655 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/nickcrew/claude-ctx-plugin --skill a10-brandAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 28 |
| Last updated | June 29, 2026 |
| Repository | nickcrew/claude-ctx-plugin ↗ |
What it does
Helps with ai & agent building tasks.
Files
A10 Networks Brand Skill
This skill ensures every visual output for A10 Networks looks like it belongs to the same family — whether it's a React dashboard, an HTML landing page, a PDF report, or a data visualization.
The goal is not robotic compliance with a checklist. The goal is to internalize the brand's personality — confident, bold, clean, engineered — and express it naturally across every medium.
Brand Spirit
A10's visual identity communicates: "We are serious engineers who build elegant solutions."
The feeling: Precision without coldness. Confidence without arrogance. Technical depth presented with clarity. Think: the cockpit of a fighter jet — every element has purpose, nothing is decorative for its own sake, but the overall effect is striking.
Design principles:
- Bold, not busy — Strong visual hierarchy. One focal point per section. Generous whitespace.
- Diagonal energy — A10's signature is the diagonal split (white/navy). Use clip-paths and
angled dividers to create dynamism without chaos.
- Sharp edges — Square corners on EVERYTHING. Buttons, cards, inputs, images, badges. This is
the single most recognizable A10 brand element. border-radius: 0 is law.
- Engineered typography — Rubik Light (300) for headlines creates an elegant, modern feel.
Headlines should feel lightweight and spacious, not heavy and shouty.
- Purposeful color — Blues dominate. Magenta punctuates. Accents inform. Every color choice
should have a reason.
---
Critical Rules (Non-Negotiable)
These are the rules that, if violated, make something instantly "not A10":
1. Square corners everywhere — border-radius: 0 on buttons, cards, inputs, badges, images, modals, tooltips, everything. No exceptions. No "just a little rounding." Zero.
2. Rubik font family — Load from Google Fonts. Fallback to Calibri for Office contexts.
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&display=swap" rel="stylesheet">3. Headline weight is Light (300) — This is counterintuitive and the #1 mistake. H1-H4 use Rubik Light 300, NOT bold. Bold headlines are off-brand. Medium (500) for H5-H6 and buttons.
4. On-brand colors only — Use the brand palette. Off-brand colors are not forbidden but should be rare and justified. When in doubt, use A10 Blue #0057B7.
5. Logo in approved colors only — A10 Blue, Navy, White, or Black. Never magenta, never on accent backgrounds, never with effects.
6. WCAG 2.1 AA contrast — 4.5:1 minimum for text. No light-on-light or dark-on-dark.
---
Color System
Proportions (This Is the Key)
Think of color usage like a pyramid. The visual weight should roughly follow:
PRIMARY (dominant ~80% of all color)
├── Navy Blue #001E62 — 35% — Dark backgrounds, headers, primary text on light
├── A10 Blue #0057B7 — 25% — CTAs, links, primary brand moments
└── White #FFFFFF — 20% — Light backgrounds, text on dark
SECONDARY (supporting ~15%)
├── Sky Blue #529EEC — Dark-theme links, secondary accents, lighter chart elements
├── Magenta #D62598 — THE dramatic accent. Badges, highlight CTAs, key moments. Sparingly.
└── Black #000000 — Dark backgrounds, body text alternative
ACCENT (data & status only ~5%)
├── Purple #440099 — Charts, illustrations
├── Cloud Blue #5E8AB4 — Charts, alternative to gray
├── Orange #E35205 — Warnings, emphasis, data viz
├── Green #00B140 — Success states, positive KPIs
└── Red #EF3340 — Error states, negative KPIs, dangerAccent color rules: Purple, Cloud Blue, Orange, Green, and Red are reserved for functional use — data visualization series, status badges, KPI values, table cell highlights, alert states. They should NOT be used for backgrounds, large UI areas, or decorative elements.
Magenta rules: Magenta is the "spice." Use it for one or two high-impact moments per page — a primary CTA button, a featured badge, a key metric highlight. Never as a background color. Never dominant. If you squint at the page and magenta is the first thing you see everywhere, you've used too much.
Full Palette Reference
For the complete palette with tints, shades, UI neutrals, hover states, and CSS custom properties, read references/color-system.md.
---
Typography
| Element | Size | Weight | Notes |
|---|---|---|---|
| Eyebrow | 16px | Bold 700 | ALL-CAPS, letter-spacing: 0.1em. Only place for caps. |
| H1 | 48px / 3rem | Light 300 | |
| H2 | 32px / 2rem | Light 300 | |
| H3 | 28px / 1.75rem | Light 300 | |
| H4 | 24px / 1.5rem | Light 300 | |
| H5 | 20px / 1.25rem | Medium 500 | |
| H6 | 16px / 1rem | Medium 500 | |
| Body | 16px / 1rem | Regular 400 | Line-height: 24px |
| Small | 14px | Regular 400 | |
| Buttons | per size | Medium 500 | Title Case labels |
| Links | 16px | SemiBold 600 |
Rules: Ragged-right alignment (never justified). No hyphenation. No ALL-CAPS except eyebrows and small labels. Keep "A10 Networks" on the same line (use white-space: nowrap on brand names).
---
Themes
When to Use Which
- Light theme — Corporate marketing, external-facing content, documentation, landing pages,
white papers, blog posts
- Dark theme — Product UI, dashboards, security tools, demos, internal platform interfaces,
anything for Signal Horizon / Synapse / ThreatX Labs / The Crows
If context doesn't make it obvious, default to light for documents/marketing, dark for product/technical UI.
Light Theme
| Layer | Color | Usage |
|---|---|---|
| Base background | #FFFFFF | Page background |
| Section background | #F0F4F8 | Alternating sections |
| Card background | #DFE8F0 | Cards, subtle containers |
| Primary text | #001E62 (Navy) | Headlines, body |
| Secondary text | #404040 | Supporting text |
| Links | #0057B7 → hover #003EC8 | |
| Primary button | #0057B7 → hover #004189 | White text |
| Magenta button | #D62598 → hover #A01B72 | White text (use sparingly) |
| Outline button | 2px #001E62 border → hover fill #DFE8F0 | Navy text |
Dark Theme
Signal Horizon uses a charcoal/zinc-based dark mode for better data contrast in dense dashboard views. This is the approved product dark theme — not a brand violation.
| Layer | Color | Usage |
|---|---|---|
| Hero/Header bg | #001E62 (Navy) | Brand headers retain navy |
| Content bg | #09090b (Zinc 950) or #000000 | Charcoal base for data contrast |
| Card bg | #121212 (Deep Charcoal) or #0A1A3A (Navy variant) | |
| Surface subtle | #18181b (Zinc 900) | |
| Primary text | #f4f4f5 (Zinc 100) | |
| Secondary text | #a1a1aa (Zinc 400) | |
| Links | #529EEC → hover #7CBAFF | |
| Primary button | #529EEC → hover #7CBAFF | White text |
| Outline button | 2px #F0F4F8 border → hover fill #003EC8 | White text |
Note: For marketing/corporate dark contexts, a navy-based palette (#00174A, #0A1A3A) is also acceptable. The charcoal approach is preferred for product UIs with dense data.
---
Buttons
Shape: Rectangular. border-radius: 0. Always. No exceptions. No slanted/angled edges. Labels: Title Case ("Learn More" not "LEARN MORE" or "learn more").
| Size | Height | Font | Padding |
|---|---|---|---|
| Large (Primary) | 56px | Rubik Medium 500, 16px | 0 32px |
| Medium (Outlined) | 48px | Rubik Medium 500, 14px | 0 24px |
| Small (Secondary) | 40px | Rubik SemiBold 600, 12px | 0 20px |
---
Charts & Data Visualization
Charts are a critical brand surface. Read references/chart-standards.md for the complete chart component reference with gradient formulas, but here are the essentials:
Series color priority (use in this order): 1. A10 Blue #0057B7 (primary series) 2. Sky Blue #529EEC (secondary series) 3. Green #00B140 (success/positive) 4. Orange #E35205 (warning/caution) 5. Red #EF3340 (danger/error) 6. Magenta #D62598 (accent, if needed) 7. Cloud Blue #5E8AB4 (additional series) 8. Purple #440099 (additional series)
Chart rules:
- Value labels on every bar/data point
- Dashed grid lines at opacity 0.3
- Rubik font throughout (Light 300 for chart titles, Regular 400 for labels)
- Subtitle with context below every chart title
- Hover states for interactivity
- Subtle gradients on bars (not flat fills) — vertical: lighten+30 top → darken-20 bottom
- No rounded corners on bars
- Dark theme default: cards on
#0A1A3Abackground - Left/top highlight edge on bars:
rgba(255,255,255,0.12) - Base opacity 0.9, hover opacity 1.0
The assets/chart-reference.jsx file contains production-ready React components for vertical bar, horizontal bar, stacked horizontal, and grouped vertical charts. Use these as templates when building chart components.
---
Logos
Logo SVG assets are available in assets/ for both light and dark themes:
| Product | Files | Usage |
|---|---|---|
| Apparatus (app icon) | apparatus-dark.svg, apparatus-light.svg | Favicon, app icon, small mark |
| Signal Horizon | signal-logo-{theme}.svg | Logo mark only |
signal-stacked-2line-{theme}.svg | Stacked with product name | |
signal-horizontal-2line-tagline-{theme}.svg | Horizontal with tagline | |
| Synapse | synapse-logo-{theme}.svg | Logo mark only |
synapse-lockup-stacked-{theme}.svg | Stacked with product name | |
synapse-lockup-horizontal-tagline-{theme}.svg | Horizontal with tagline |
Logo rules:
- Use
-darkvariants on dark/navy backgrounds,-lighton white/light backgrounds - Preferred placement: top-left. Acceptable: top-right, bottom-left. Avoid bottom-right.
- Clear space around logo = height of the white triangle inside the "A" in A10's mark
- Minimum size: 50px on screen
- Never distort, add shadows, rotate, recolor, or place on busy backgrounds
- When embedding SVGs inline, preserve viewBox and aspect ratio
---
Layout Patterns
Section alternation: Cycle backgrounds — White → Light Gray #F0F4F8 → Navy #001E62 → A10 Blue #0057B7 — to create rhythm without borders.
Diagonal split (signature A10 treatment):
.hero-diagonal::after {
content: '';
position: absolute;
top: 0; right: 0;
width: 50%; height: 100%;
background: #FFFFFF;
clip-path: polygon(20% 0, 100% 0, 100% 100%, 0 100%);
}Cards: No borders, no rounded corners. Use subtle box-shadow:
- Light:
box-shadow: 0 2px 8px rgba(0, 30, 98, 0.1) - Dark:
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3)
Spacing scale: 4 / 8 / 16 / 24 / 32 / 48 / 64px
---
Review Mode
When asked to review or audit existing work against A10 brand guidelines, perform a structured pass through these categories. Report findings grouped by severity.
Critical (Must Fix — instantly off-brand)
- [ ] Rounded corners anywhere (buttons, cards, inputs, images, badges)
- [ ] Wrong font (not Rubik, or Rubik not loaded)
- [ ] Bold headlines instead of Light 300
- [ ] Off-brand colors used prominently (not from palette, or accents used as primary)
- [ ] Logo in wrong colors or on wrong background
- [ ] Magenta used as background or dominant color
- [ ] Poor contrast (failing WCAG AA)
Major (Should Fix — noticeably off)
- [ ] Wrong button heights or padding
- [ ] Missing or wrong hover states
- [ ] Incorrect font weights for element types
- [ ] Color proportions wrong (too much accent, not enough navy/blue)
- [ ] Charts without value labels or using flat fills
- [ ] Typography: justified text, ALL-CAPS body text, bold where light expected
- [ ] Missing Rubik font import (falling back to system fonts)
- [ ] Accent colors used for non-functional purposes (backgrounds, decorative)
Minor (Polish — good to great)
- [ ] Inconsistent spacing (not using the 4/8/16/24/32/48/64 scale)
- [ ] Section backgrounds not alternating
- [ ] Icon sizing inconsistent
- [ ] Missing diagonal split opportunity on hero sections
- [ ] Links missing SemiBold weight or hover color change
- [ ] Charts missing subtitle context line
- [ ] Eyebrow text not using letter-spacing 0.1em
Spirit Check (brand personality)
- [ ] Does it feel confident and clean, or cluttered and uncertain?
- [ ] Is there a clear visual hierarchy with one focal point per section?
- [ ] Is whitespace generous or cramped?
- [ ] Would this look at home next to a10networks.com?
- [ ] Is magenta used as a deliberate accent or scattered randomly?
- [ ] Do the blues dominate the color landscape as they should?
When reporting, lead with the most impactful issues. Provide specific fixes with exact hex codes, font weights, and CSS properties. Don't just say "wrong color" — say "Header background is #2563EB (Tailwind blue-600), should be #0057B7 (A10 Blue)."
---
Reference Files
For detailed specifications beyond what's in this file:
| File | When to Read |
|---|---|
references/color-system.md | Need full tint/shade values, CSS custom properties, gradient specs |
references/typography.md | Need complete type scale, kerning details, or Office/print specs |
references/chart-standards.md | Building any chart or data visualization |
references/components.md | Need button CSS, card patterns, alert styles, layout CSS |
references/review-checklist.md | Performing a detailed brand audit with expanded criteria |
---
CSS Quick-Start
For any new A10 artifact, start with this foundation:
@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&display=swap');
* { box-sizing: border-box; }
button, input, select, textarea, .card, .btn { border-radius: 0; }
:root {
--a10-blue: #0057B7;
--a10-navy: #001E62;
--a10-white: #FFFFFF;
--a10-sky: #529EEC;
--a10-magenta: #D62598;
--a10-black: #000000;
--font: 'Rubik', 'Calibri', sans-serif;
}
body {
font-family: var(--font);
font-weight: 400;
font-size: 16px;
line-height: 1.5;
color: var(--a10-navy);
}
h1, h2, h3, h4 { font-weight: 300; }
h5, h6 { font-weight: 500; }React Quick-Start
For JSX/React artifacts, apply the same principles. Use inline styles or a style object:
const a10 = {
blue: '#0057B7', navy: '#001E62', white: '#FFFFFF',
sky: '#529EEC', magenta: '#D62598', black: '#000000',
green: '#00B140', orange: '#E35205', red: '#EF3340',
purple: '#440099', cloudBlue: '#5E8AB4',
grayLight: '#F0F4F8', grayMedium: '#DFE8F0',
grayDark: '#404040', grayMid: '#7F7F7F',
cardDark: '#0A1A3A', navyDark: '#00174A',
blueDark: '#004189', blueLight: '#7CBAFF',
skyLight: '#BEDDFF', magentaDark: '#A01B72',
};
// Always include Rubik font link
// Always set border-radius: 0 on all interactive/container elements
// Always use fontWeight: 300 for h1-h4, 500 for h5-h6import { useState } from "react";
// A10 Brand Color System
const colors = {
// Primary
blue: "#0057B7",
navy: "#001E62",
white: "#FFFFFF",
// Secondary
sky: "#529EEC",
magenta: "#D62598",
// Accents
green: "#00B140",
orange: "#E35205",
red: "#EF3340",
purple: "#440099",
cloudBlue: "#5E8AB4",
// UI
cardDark: "#0A1A3A",
grayLight: "#F0F4F8",
grayMedium: "#DFE8F0",
grayDark: "#404040",
grayMid: "#7F7F7F",
// Tints
blueDark: "#004189",
blueLight: "#7CBAFF",
skyLight: "#BEDDFF",
navyDark: "#00174A",
};
// Chart data series color assignments (ordered by usage priority)
const seriesColors = {
primary: colors.blue,
secondary: colors.sky,
success: colors.green,
warning: colors.orange,
danger: colors.red,
accent: colors.magenta,
info: colors.cloudBlue,
highlight: colors.purple,
};
// SVG gradient definitions for depth
const GradientDefs = ({ id, baseColor, darkMode = true }) => {
const lighten = (hex, amt) => {
const num = parseInt(hex.replace("#", ""), 16);
const r = Math.min(255, ((num >> 16) & 0xff) + amt);
const g = Math.min(255, ((num >> 8) & 0xff) + amt);
const b = Math.min(255, (num & 0xff) + amt);
return `rgb(${r},${g},${b})`;
};
const darken = (hex, amt) => lighten(hex, -amt);
return (
<>
<linearGradient id={`${id}-v`} x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={lighten(baseColor, 30)} />
<stop offset="100%" stopColor={darken(baseColor, 20)} />
</linearGradient>
<linearGradient id={`${id}-h`} x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor={darken(baseColor, 20)} />
<stop offset="100%" stopColor={lighten(baseColor, 30)} />
</linearGradient>
</>
);
};
// ─── VERTICAL BAR CHART ────────────────────────────
const VerticalBarChart = ({ data, title, subtitle, height = 300, showValues = true }) => {
const [hovered, setHovered] = useState(null);
const maxVal = Math.max(...data.map((d) => d.value));
const yTicks = 5;
const padding = { top: 20, right: 20, bottom: 60, left: 60 };
const chartW = 560;
const chartH = height;
const innerW = chartW - padding.left - padding.right;
const innerH = chartH - padding.top - padding.bottom;
const barGap = 0.3;
const barW = (innerW / data.length) * (1 - barGap);
const barSpacing = innerW / data.length;
const niceMax = Math.ceil(maxVal / Math.pow(10, Math.floor(Math.log10(maxVal)))) * Math.pow(10, Math.floor(Math.log10(maxVal)));
return (
<div style={{ background: colors.cardDark, padding: "24px", marginBottom: 24 }}>
<div style={{ marginBottom: 16 }}>
<h3 style={{ color: colors.grayLight, fontSize: 20, fontWeight: 300, margin: 0, fontFamily: "'Rubik', sans-serif" }}>{title}</h3>
{subtitle && <p style={{ color: colors.grayMid, fontSize: 14, margin: "4px 0 0", fontFamily: "'Rubik', sans-serif", fontWeight: 400 }}>{subtitle}</p>}
</div>
<svg width={chartW} height={chartH} style={{ overflow: "visible" }}>
<defs>
{data.map((d, i) => (
<GradientDefs key={i} id={`vbar-${i}`} baseColor={d.color || colors.blue} />
))}
</defs>
{/* Grid lines */}
{Array.from({ length: yTicks + 1 }).map((_, i) => {
const y = padding.top + innerH - (i / yTicks) * innerH;
const val = Math.round((i / yTicks) * niceMax);
return (
<g key={i}>
<line x1={padding.left} y1={y} x2={padding.left + innerW} y2={y} stroke={colors.navy} strokeWidth={1} strokeDasharray={i === 0 ? "none" : "4,4"} opacity={i === 0 ? 0.8 : 0.3} />
<text x={padding.left - 10} y={y + 4} textAnchor="end" fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{val >= 1000 ? `${(val / 1000).toFixed(val >= 10000 ? 0 : 1)}k` : val}
</text>
</g>
);
})}
{/* Bars */}
{data.map((d, i) => {
const barH = (d.value / niceMax) * innerH;
const x = padding.left + i * barSpacing + (barSpacing - barW) / 2;
const y = padding.top + innerH - barH;
const isHovered = hovered === i;
return (
<g key={i} onMouseEnter={() => setHovered(i)} onMouseLeave={() => setHovered(null)} style={{ cursor: "default" }}>
{/* Bar */}
<rect x={x} y={y} width={barW} height={barH} fill={`url(#vbar-${i}-v)`} opacity={isHovered ? 1 : 0.9} style={{ transition: "opacity 0.15s ease" }} />
{/* Highlight edge (left) */}
<rect x={x} y={y} width={2} height={barH} fill="rgba(255,255,255,0.15)" />
{/* Value label */}
{showValues && (
<text x={x + barW / 2} y={y - 8} textAnchor="middle" fill={isHovered ? colors.white : colors.grayLight} fontSize={13} fontFamily="'Rubik', sans-serif" fontWeight={500} opacity={isHovered ? 1 : 0.85}>
{d.value >= 1000 ? `${(d.value / 1000).toFixed(1)}k` : d.value}
</text>
)}
{/* X-axis label */}
<text x={x + barW / 2} y={padding.top + innerH + 20} textAnchor="middle" fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{d.label}
</text>
</g>
);
})}
</svg>
</div>
);
};
// ─── HORIZONTAL BAR CHART ──────────────────────────
const HorizontalBarChart = ({ data, title, subtitle, barHeight = 28, showValues = true }) => {
const [hovered, setHovered] = useState(null);
const maxVal = Math.max(...data.map((d) => d.value));
const padding = { top: 10, right: 70, bottom: 10, left: 100 };
const chartW = 560;
const rowH = barHeight + 16;
const chartH = padding.top + data.length * rowH + padding.bottom;
const innerW = chartW - padding.left - padding.right;
const niceMax = Math.ceil(maxVal / Math.pow(10, Math.floor(Math.log10(maxVal)))) * Math.pow(10, Math.floor(Math.log10(maxVal)));
return (
<div style={{ background: colors.cardDark, padding: "24px", marginBottom: 24 }}>
<div style={{ marginBottom: 16 }}>
<h3 style={{ color: colors.grayLight, fontSize: 20, fontWeight: 300, margin: 0, fontFamily: "'Rubik', sans-serif" }}>{title}</h3>
{subtitle && <p style={{ color: colors.grayMid, fontSize: 14, margin: "4px 0 0", fontFamily: "'Rubik', sans-serif", fontWeight: 400 }}>{subtitle}</p>}
</div>
<svg width={chartW} height={chartH} style={{ overflow: "visible" }}>
<defs>
{data.map((d, i) => (
<GradientDefs key={i} id={`hbar-${i}`} baseColor={d.color || colors.blue} />
))}
</defs>
{/* Vertical grid lines */}
{Array.from({ length: 5 }).map((_, i) => {
const x = padding.left + ((i + 1) / 5) * innerW;
return <line key={i} x1={x} y1={padding.top} x2={x} y2={chartH - padding.bottom} stroke={colors.navy} strokeWidth={1} strokeDasharray="4,4" opacity={0.3} />;
})}
{/* Bars */}
{data.map((d, i) => {
const barW = (d.value / niceMax) * innerW;
const y = padding.top + i * rowH + (rowH - barHeight) / 2;
const isHovered = hovered === i;
return (
<g key={i} onMouseEnter={() => setHovered(i)} onMouseLeave={() => setHovered(null)} style={{ cursor: "default" }}>
{/* Label */}
<text x={padding.left - 12} y={y + barHeight / 2 + 4} textAnchor="end" fill={colors.grayLight} fontSize={13} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{d.label}
</text>
{/* Bar */}
<rect x={padding.left} y={y} width={barW} height={barHeight} fill={`url(#hbar-${i}-h)`} opacity={isHovered ? 1 : 0.9} style={{ transition: "opacity 0.15s ease" }} />
{/* Top highlight edge */}
<rect x={padding.left} y={y} width={barW} height={2} fill="rgba(255,255,255,0.12)" />
{/* Value */}
{showValues && (
<text x={padding.left + barW + 10} y={y + barHeight / 2 + 5} textAnchor="start" fill={isHovered ? colors.white : colors.grayLight} fontSize={13} fontFamily="'Rubik', sans-serif" fontWeight={500}>
{d.value >= 1000 ? `${(d.value / 1000).toFixed(1)}k` : d.value}
</text>
)}
</g>
);
})}
{/* Baseline */}
<line x1={padding.left} y1={padding.top} x2={padding.left} y2={chartH - padding.bottom} stroke={colors.navy} strokeWidth={1} opacity={0.6} />
</svg>
</div>
);
};
// ─── STACKED HORIZONTAL BAR ────────────────────────
const StackedHorizontalBar = ({ data, title, subtitle, series, barHeight = 28 }) => {
const [hovered, setHovered] = useState(null);
const maxTotal = Math.max(...data.map((d) => series.reduce((sum, s) => sum + (d[s.key] || 0), 0)));
const padding = { top: 10, right: 20, bottom: 40, left: 100 };
const chartW = 560;
const rowH = barHeight + 16;
const chartH = padding.top + data.length * rowH + padding.bottom;
const innerW = chartW - padding.left - padding.right;
return (
<div style={{ background: colors.cardDark, padding: "24px", marginBottom: 24 }}>
<div style={{ marginBottom: 16 }}>
<h3 style={{ color: colors.grayLight, fontSize: 20, fontWeight: 300, margin: 0, fontFamily: "'Rubik', sans-serif" }}>{title}</h3>
{subtitle && <p style={{ color: colors.grayMid, fontSize: 14, margin: "4px 0 0", fontFamily: "'Rubik', sans-serif", fontWeight: 400 }}>{subtitle}</p>}
</div>
<svg width={chartW} height={chartH} style={{ overflow: "visible" }}>
<defs>
{series.map((s, si) => (
<GradientDefs key={si} id={`sbar-${si}`} baseColor={s.color} />
))}
</defs>
{data.map((d, i) => {
const y = padding.top + i * rowH + (rowH - barHeight) / 2;
const total = series.reduce((sum, s) => sum + (d[s.key] || 0), 0);
let xOffset = padding.left;
const isHovered = hovered === i;
return (
<g key={i} onMouseEnter={() => setHovered(i)} onMouseLeave={() => setHovered(null)}>
<text x={padding.left - 12} y={y + barHeight / 2 + 4} textAnchor="end" fill={colors.grayLight} fontSize={13} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{d.label}
</text>
{series.map((s, si) => {
const val = d[s.key] || 0;
const segW = (val / maxTotal) * innerW;
const segX = xOffset;
xOffset += segW;
return (
<g key={si}>
<rect x={segX} y={y} width={Math.max(segW, 0)} height={barHeight} fill={`url(#sbar-${si}-h)`} opacity={isHovered ? 1 : 0.9} style={{ transition: "opacity 0.15s ease" }} />
{segW > 40 && (
<text x={segX + segW / 2} y={y + barHeight / 2 + 4} textAnchor="middle" fill="rgba(255,255,255,0.9)" fontSize={11} fontFamily="'Rubik', sans-serif" fontWeight={500}>
{val >= 1000 ? `${(val / 1000).toFixed(1)}k` : val}
</text>
)}
{/* Top highlight */}
<rect x={segX} y={y} width={Math.max(segW, 0)} height={1.5} fill="rgba(255,255,255,0.1)" />
</g>
);
})}
{/* Total label */}
<text x={xOffset + 10} y={y + barHeight / 2 + 4} textAnchor="start" fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{total >= 1000 ? `${(total / 1000).toFixed(1)}k` : total}
</text>
</g>
);
})}
{/* Baseline */}
<line x1={padding.left} y1={padding.top} x2={padding.left} y2={chartH - padding.bottom} stroke={colors.navy} strokeWidth={1} opacity={0.6} />
{/* Legend */}
{series.map((s, i) => {
const legendX = padding.left + i * 140;
const legendY = chartH - 10;
return (
<g key={i}>
<rect x={legendX} y={legendY - 8} width={12} height={12} fill={s.color} />
<text x={legendX + 18} y={legendY + 3} fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{s.label}
</text>
</g>
);
})}
</svg>
</div>
);
};
// ─── GROUPED VERTICAL BAR ──────────────────────────
const GroupedVerticalBar = ({ data, title, subtitle, series, height = 300 }) => {
const [hovered, setHovered] = useState(null);
const allVals = data.flatMap((d) => series.map((s) => d[s.key] || 0));
const maxVal = Math.max(...allVals);
const yTicks = 5;
const padding = { top: 20, right: 20, bottom: 70, left: 60 };
const chartW = 560;
const chartH = height;
const innerW = chartW - padding.left - padding.right;
const innerH = chartH - padding.top - padding.bottom;
const groupW = innerW / data.length;
const groupPad = 0.25;
const subBarW = (groupW * (1 - groupPad)) / series.length;
const niceMax = Math.ceil(maxVal / Math.pow(10, Math.floor(Math.log10(maxVal)))) * Math.pow(10, Math.floor(Math.log10(maxVal)));
return (
<div style={{ background: colors.cardDark, padding: "24px", marginBottom: 24 }}>
<div style={{ marginBottom: 16 }}>
<h3 style={{ color: colors.grayLight, fontSize: 20, fontWeight: 300, margin: 0, fontFamily: "'Rubik', sans-serif" }}>{title}</h3>
{subtitle && <p style={{ color: colors.grayMid, fontSize: 14, margin: "4px 0 0", fontFamily: "'Rubik', sans-serif", fontWeight: 400 }}>{subtitle}</p>}
</div>
<svg width={chartW} height={chartH} style={{ overflow: "visible" }}>
<defs>
{series.map((s, si) => (
<GradientDefs key={si} id={`gbar-${si}`} baseColor={s.color} />
))}
</defs>
{/* Grid */}
{Array.from({ length: yTicks + 1 }).map((_, i) => {
const y = padding.top + innerH - (i / yTicks) * innerH;
const val = Math.round((i / yTicks) * niceMax);
return (
<g key={i}>
<line x1={padding.left} y1={y} x2={padding.left + innerW} y2={y} stroke={colors.navy} strokeWidth={1} strokeDasharray={i === 0 ? "none" : "4,4"} opacity={i === 0 ? 0.8 : 0.3} />
<text x={padding.left - 10} y={y + 4} textAnchor="end" fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{val >= 1000 ? `${(val / 1000).toFixed(0)}k` : val}
</text>
</g>
);
})}
{/* Grouped bars */}
{data.map((d, di) => {
const groupX = padding.left + di * groupW + (groupW * groupPad) / 2;
return (
<g key={di}>
{series.map((s, si) => {
const val = d[s.key] || 0;
const barH = (val / niceMax) * innerH;
const x = groupX + si * subBarW;
const y = padding.top + innerH - barH;
const isHov = hovered === `${di}-${si}`;
return (
<g key={si} onMouseEnter={() => setHovered(`${di}-${si}`)} onMouseLeave={() => setHovered(null)}>
<rect x={x} y={y} width={subBarW - 2} height={barH} fill={`url(#gbar-${si}-v)`} opacity={isHov ? 1 : 0.9} />
<rect x={x} y={y} width={1.5} height={barH} fill="rgba(255,255,255,0.12)" />
{barH > 25 && (
<text x={x + (subBarW - 2) / 2} y={y - 6} textAnchor="middle" fill={colors.grayLight} fontSize={11} fontFamily="'Rubik', sans-serif" fontWeight={500} opacity={0.85}>
{val >= 1000 ? `${(val / 1000).toFixed(1)}k` : val}
</text>
)}
</g>
);
})}
<text x={padding.left + di * groupW + groupW / 2} y={padding.top + innerH + 20} textAnchor="middle" fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{d.label}
</text>
</g>
);
})}
{/* Legend */}
{series.map((s, i) => {
const legendX = padding.left + i * 140;
const legendY = chartH - 8;
return (
<g key={i}>
<rect x={legendX} y={legendY - 8} width={12} height={12} fill={s.color} />
<text x={legendX + 18} y={legendY + 3} fill={colors.grayMid} fontSize={12} fontFamily="'Rubik', sans-serif" fontWeight={400}>
{s.label}
</text>
</g>
);
})}
</svg>
</div>
);
};
// ─── GUIDELINES PANEL ──────────────────────────────
const GuidelinePanel = () => (
<div style={{ background: colors.navy, padding: "24px", marginBottom: 24, borderLeft: `3px solid ${colors.blue}` }}>
<h3 style={{ color: colors.blueLight, fontSize: 16, fontWeight: 300, margin: "0 0 16px", fontFamily: "'Rubik', sans-serif", letterSpacing: "0.05em", textTransform: "uppercase" }}>
Chart Standards
</h3>
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 20 }}>
{[
{ title: "Always include", items: ["Value labels on every bar", "Dashed grid lines (opacity 0.3)", "Rubik font, Light 300 headings", "Subtitle with context", "Hover states for interactivity"] },
{ title: "Never do", items: ["Flat solid fills (use subtle gradient)", "Missing value labels", "Overlapping axis text", "Rounded corners on bars", "Colors outside brand palette"] },
{ title: "Gradient formula", items: ["Vertical: lighten +30 top → darken -20 bottom", "Horizontal: darken -20 left → lighten +30 right", "Left/top highlight edge: rgba(255,255,255,0.12)", "Base opacity: 0.9, hover: 1.0"] },
{ title: "Color priority", items: ["1. A10 Blue #0057B7 (primary)", "2. Sky Blue #529EEC (secondary)", "3. Green #00B140 (success)", "4. Orange #E35205 (warning)", "5. Red #EF3340 (danger/error)"] },
].map((section, i) => (
<div key={i}>
<h4 style={{ color: colors.grayLight, fontSize: 13, fontWeight: 500, margin: "0 0 8px", fontFamily: "'Rubik', sans-serif" }}>{section.title}</h4>
{section.items.map((item, j) => (
<div key={j} style={{ color: colors.grayMid, fontSize: 12, fontFamily: "'Rubik', sans-serif", fontWeight: 400, padding: "2px 0", lineHeight: 1.5 }}>
{item}
</div>
))}
</div>
))}
</div>
</div>
);
// ─── MAIN COMPONENT ────────────────────────────────
export default function A10ChartReference() {
return (
<div style={{ background: colors.navyDark, minHeight: "100vh", padding: "32px", fontFamily: "'Rubik', sans-serif" }}>
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&display=swap" rel="stylesheet" />
{/* Header */}
<div style={{ marginBottom: 32 }}>
<div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 8 }}>
<div style={{ width: 4, height: 32, background: colors.blue }} />
<h1 style={{ color: colors.white, fontSize: 28, fontWeight: 300, margin: 0, fontFamily: "'Rubik', sans-serif" }}>
Chart Style Reference
</h1>
</div>
<p style={{ color: colors.grayMid, fontSize: 14, margin: "8px 0 0 16px", fontFamily: "'Rubik', sans-serif", fontWeight: 400 }}>
A10 Networks — Signal Horizon / Edge Protection Platform
</p>
</div>
<GuidelinePanel />
{/* Vertical Bar */}
<VerticalBarChart
title="Response Time Distribution"
subtitle="Request latency percentile buckets (last 24h)"
data={[
{ label: "0-50ms", value: 42500, color: colors.green },
{ label: "50-100ms", value: 28300, color: colors.blue },
{ label: "100-200ms", value: 8200, color: colors.sky },
{ label: "200-500ms", value: 3100, color: colors.orange },
{ label: "500ms-1s", value: 890, color: colors.orange },
{ label: "1s+", value: 210, color: colors.red },
]}
/>
{/* Horizontal Bar */}
<HorizontalBarChart
title="Request Methods"
subtitle="HTTP method distribution across all endpoints"
data={[
{ label: "GET", value: 45200, color: colors.blue },
{ label: "POST", value: 18900, color: colors.green },
{ label: "PUT", value: 4300, color: colors.sky },
{ label: "DELETE", value: 1800, color: colors.red },
{ label: "PATCH", value: 920, color: colors.orange },
{ label: "OPTIONS", value: 3400, color: colors.cloudBlue },
]}
/>
{/* Stacked Horizontal - Service Health */}
<StackedHorizontalBar
title="Service Health"
subtitle="Response codes breakdown by service"
data={[
{ label: "Auth", success: 8200, client: 1200, error: 45 },
{ label: "Users", success: 12500, client: 340, error: 12 },
{ label: "Products", success: 9800, client: 560, error: 8 },
{ label: "Orders", success: 7600, client: 890, error: 23 },
{ label: "Search", success: 5400, client: 1100, error: 67 },
{ label: "Payments", success: 3200, client: 180, error: 5 },
]}
series={[
{ key: "success", label: "2xx Success", color: colors.blue },
{ key: "client", label: "4xx Client Error", color: colors.orange },
{ key: "error", label: "5xx Server Error", color: colors.red },
]}
/>
{/* Grouped Vertical */}
<GroupedVerticalBar
title="Traffic Comparison"
subtitle="Allowed vs blocked requests by hour"
data={[
{ label: "00:00", allowed: 2800, blocked: 120 },
{ label: "04:00", allowed: 1200, blocked: 45 },
{ label: "08:00", allowed: 4500, blocked: 230 },
{ label: "12:00", allowed: 5200, blocked: 310 },
{ label: "16:00", allowed: 4800, blocked: 280 },
{ label: "20:00", allowed: 3600, blocked: 190 },
]}
series={[
{ key: "allowed", label: "Allowed", color: colors.blue },
{ key: "blocked", label: "Blocked", color: colors.red },
]}
/>
{/* Color Swatch Reference */}
<div style={{ background: colors.cardDark, padding: "24px" }}>
<h3 style={{ color: colors.grayLight, fontSize: 20, fontWeight: 300, margin: "0 0 16px", fontFamily: "'Rubik', sans-serif" }}>Data Series Palette</h3>
<div style={{ display: "flex", gap: 12, flexWrap: "wrap" }}>
{Object.entries(seriesColors).map(([name, color]) => (
<div key={name} style={{ display: "flex", alignItems: "center", gap: 8, background: colors.navy, padding: "8px 14px" }}>
<div style={{ width: 16, height: 16, background: color }} />
<div>
<div style={{ color: colors.grayLight, fontSize: 12, fontFamily: "'Rubik', sans-serif", fontWeight: 500, textTransform: "capitalize" }}>{name}</div>
<div style={{ color: colors.grayMid, fontSize: 11, fontFamily: "'Rubik', sans-serif", fontWeight: 400 }}>{color}</div>
</div>
</div>
))}
</div>
</div>
</div>
);
}
A10 Chart Standards — Complete Reference
Series Color Assignment
Always assign data series colors in this priority order:
| Priority | Name | HEX | Semantic |
|---|---|---|---|
| 1 | A10 Blue | #0057B7 | Primary series |
| 2 | Sky Blue | #529EEC | Secondary series |
| 3 | Green | #00B140 | Success / positive |
| 4 | Orange | #E35205 | Warning / caution |
| 5 | Red | #EF3340 | Danger / error |
| 6 | Magenta | #D62598 | Accent (if needed) |
| 7 | Cloud Blue | #5E8AB4 | Additional series |
| 8 | Purple | #440099 | Additional series |
For semantic data (success/failure, allowed/blocked), use the semantic mapping:
- Success/Allowed/Positive: Green or A10 Blue
- Warning/Caution: Orange
- Error/Blocked/Negative: Red
- Informational: Sky Blue or Cloud Blue
Gradient Formula
Bars should use subtle gradients, never flat fills. This adds depth and polish.
Vertical bars: Lighten +30 at top → Darken -20 at bottom
<linearGradient id="bar-v" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={lighten(baseColor, 30)} />
<stop offset="100%" stopColor={darken(baseColor, 20)} />
</linearGradient>Horizontal bars: Darken -20 at left → Lighten +30 at right
<linearGradient id="bar-h" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stopColor={darken(baseColor, 20)} />
<stop offset="100%" stopColor={lighten(baseColor, 30)} />
</linearGradient>Lighten/darken helper:
const lighten = (hex, amt) => {
const num = parseInt(hex.replace('#', ''), 16);
const r = Math.min(255, ((num >> 16) & 0xff) + amt);
const g = Math.min(255, ((num >> 8) & 0xff) + amt);
const b = Math.min(255, (num & 0xff) + amt);
return `rgb(${r},${g},${b})`;
};
const darken = (hex, amt) => lighten(hex, -amt);Bar Styling
- Highlight edge: Left edge (vertical) or top edge (horizontal) with
rgba(255,255,255,0.12), 1.5-2px wide - Base opacity: 0.9
- Hover opacity: 1.0
- Transition:
opacity 0.15s ease - Corner radius: 0 (never round bar corners)
- Gap ratio: ~0.3 between bars in a group
Grid Lines
- Style: Dashed (
strokeDasharray="4,4") - Color: Navy
#001E62on dark backgrounds - Opacity: 0.3 for grid lines, 0.8 for baseline (x-axis)
- Baseline: Solid, slightly more visible than grid
Labels
- Chart title: Rubik Light 300, 20px,
#F0F4F8(dark) or#001E62(light) - Subtitle: Rubik Regular 400, 14px,
#7F7F7F(Mid Gray), immediately below title - Axis labels: Rubik Regular 400, 12px,
#7F7F7F - Value labels: Rubik Medium 500, 13px,
#F0F4F8(dark) or#001E62(light) - Legend labels: Rubik Regular 400, 12px,
#7F7F7F - Legend markers: 12x12px squares (not circles, not rounded), filled with series color
Value formatting:
- Values ≥ 1000: Format as
X.Xk(e.g.,42.5k) - Values ≥ 10000: Format as
XXk(e.g.,42k) — drop decimal - Always show value labels on bars (above for vertical, right of for horizontal)
Chart Container
Dark theme (default for data viz):
.chart-container {
background: #0A1A3A; /* Card Dark */
padding: 24px;
margin-bottom: 24px;
/* No border-radius */
}Light theme:
.chart-container {
background: #FFFFFF;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 2px 8px rgba(0, 30, 98, 0.1);
}Chart Types Available
Production-ready React components in assets/chart-reference.jsx:
1. VerticalBarChart — Single-series vertical bars with individual colors per bar 2. HorizontalBarChart — Single-series horizontal bars 3. StackedHorizontalBar — Multi-series stacked horizontal bars with legend 4. GroupedVerticalBar — Multi-series grouped vertical bars with legend
Each component accepts: data, title, subtitle, optional height, showValues, and series-specific props. All follow the gradient, labeling, and interaction patterns above.
Recharts Integration
When using the recharts library in React artifacts:
const A10_CHART_COLORS = [
'#0057B7', '#529EEC', '#00B140', '#E35205',
'#EF3340', '#D62598', '#5E8AB4', '#440099'
];
// Apply to recharts
<BarChart>
<CartesianGrid strokeDasharray="4 4" stroke="#001E62" opacity={0.3} />
<XAxis tick={{ fill: '#7F7F7F', fontFamily: 'Rubik', fontSize: 12 }} />
<YAxis tick={{ fill: '#7F7F7F', fontFamily: 'Rubik', fontSize: 12 }} />
<Bar dataKey="value" fill="#0057B7" radius={0} /> {/* radius={0} critical */}
</BarChart>"Do / Don't" Summary
Always:
- Value labels on every data point
- Dashed grid lines (opacity 0.3)
- Rubik font (Light 300 titles, Regular 400 labels, Medium 500 values)
- Subtitle with temporal/contextual info
- Hover states with opacity change
- Gradient fills (not flat)
- Square legend markers
Never:
- Flat solid fills (use subtle gradient)
- Missing value labels
- Overlapping axis text
- Rounded corners on bars
- Colors outside brand palette
- 3D effects or shadows on data elements
- Pie charts with too many segments (max 6-8)
A10 Color System — Complete Reference
Primary Colors
| Name | HEX | RGB | Pantone | Usage |
|---|---|---|---|---|
| A10 Blue | #0057B7 | 0, 87, 183 | 2935 C | Primary brand, CTAs, links |
| Navy Blue | #001E62 | 0, 30, 98 | 2758 C | Dark backgrounds, headers, primary text |
| White | #FFFFFF | 255, 255, 255 | — | Light backgrounds, text on dark |
Secondary Colors
| Name | HEX | RGB | Pantone | Usage |
|---|---|---|---|---|
| Sky Blue | #529EEC | 82, 158, 236 | 292 C | Dark theme links, accents |
| Magenta | #D62598 | 214, 37, 152 | Pink C | Accent only — badges, highlights, buttons |
| Black | #000000 | 0, 0, 0 | Black | Dark backgrounds, body text |
Accent Colors (Data & Status Only)
| Name | HEX | RGB | Usage |
|---|---|---|---|
| Purple | #440099 | 68, 0, 153 | Charts, illustrations |
| Orange | #E35205 | 227, 82, 5 | Warnings, emphasis |
| Cloud Blue | #5E8AB4 | 94, 138, 180 | Charts, alternative to gray |
| Green | #00B140 | 0, 177, 64 | Success states |
| Red | #EF3340 | 239, 51, 64 | Error states |
Tints & Shades
| Base | Light Tint | Medium | Dark Shade | Darker |
|---|---|---|---|---|
A10 Blue #0057B7 | #F0F4F8 | #7CBAFF | #004189 | #00174A |
Navy #001E62 | #DFE8F0 | #003EC8 | #00174A | — |
Sky Blue #529EEC | #BEDDFF | — | #3D77B1 | — |
Magenta #D62598 | #E979C2 | — | #A01B72 | — |
UI Neutrals
| Name | HEX | Usage |
|---|---|---|
| Light Gray | #F0F4F8 | Section backgrounds (light theme) |
| Medium Gray | #DFE8F0 | Cards, subtle backgrounds, gridlines |
| Dark Gray | #404040 | Secondary text (light theme) |
| Mid Gray | #7F7F7F | Muted text, disabled states |
| Card Dark | #0A1A3A | Dark theme cards |
Hover States
| Context | Default | Hover |
|---|---|---|
| Blue button (light) | #0057B7 | #004189 |
| Blue button (dark) | #529EEC | #7CBAFF |
| Magenta button | #D62598 | #A01B72 |
| Navy button | #001E62 | #00174A |
| Link (light) | #0057B7 | #003EC8 |
| Link (dark) | #529EEC | #7CBAFF |
| Outlined button hover fill (light) | transparent | #DFE8F0 |
| Outlined button hover fill (dark) | transparent | #003EC8 |
Gradients (Approved)
| Name | Gradient | Usage |
|---|---|---|
| Navy → Blue | 135deg: #001E62 0% → #0057B7 100% | Hero backgrounds |
| Magenta → Dark | 135deg: #D62598 0% → #A01B72 100% | Accent CTAs |
| Blue Scale (3-stop) | 90deg: #0057B7 0% → #529EEC 50% → #7CBAFF 100% | Progress bars, accent strips |
| Purple → Magenta | 135deg: #440099 0% → #D62598 100% | Special feature highlights |
Contrast Rules
- White text safe on:
#001E62,#000000,#00174A,#0A1A3A,#0057B7,#D62598,#440099 - Dark text safe on:
#FFFFFF,#F0F4F8,#DFE8F0,#BEDDFF,#7CBAFF - Magenta: Accent only — never dominant, never behind body text
- Logo: Never on accent color backgrounds
- Minimum contrast: WCAG 2.1 AA — 4.5:1 for normal text, 3:1 for large text (≥24px or ≥18.66px bold)
Usage Proportions
Visual weight targets across any A10-branded surface:
| Tier | Colors | Target | Role |
|---|---|---|---|
| Primary | Navy, A10 Blue, White | ~80% | Structure, backgrounds, text |
| Secondary | Sky Blue, Magenta, Black | ~15% | Accents, secondary interactions |
| Accent | Purple, Cloud Blue, Orange, Green, Red | ~5% | Data viz, status, KPIs |
Magenta specifically should be ≤8% of total color presence. If magenta is the first thing you notice on every screen, reduce it.
CSS Custom Properties
:root {
/* Primary */
--a10-blue: #0057B7;
--a10-navy: #001E62;
--a10-white: #FFFFFF;
/* Secondary */
--a10-sky-blue: #529EEC;
--a10-magenta: #D62598;
--a10-black: #000000;
/* Accent */
--a10-purple: #440099;
--a10-orange: #E35205;
--a10-cloud-blue: #5E8AB4;
--a10-green: #00B140;
--a10-red: #EF3340;
/* Neutrals */
--a10-gray-light: #F0F4F8;
--a10-gray-medium: #DFE8F0;
--a10-gray-dark: #404040;
--a10-gray-mid: #7F7F7F;
--a10-card-dark: #0A1A3A;
/* Tints & Shades */
--a10-blue-light: #7CBAFF;
--a10-blue-dark: #004189;
--a10-blue-darker: #00174A;
--a10-sky-light: #BEDDFF;
--a10-sky-dark: #3D77B1;
--a10-magenta-light: #E979C2;
--a10-magenta-dark: #A01B72;
/* Hover */
--a10-hover-light: #003EC8;
--a10-hover-dark: #7CBAFF;
}A10 Components — Complete Reference
Buttons
Critical: border-radius: 0 on ALL buttons. No exceptions.
Primary Button (Large) — A10 Blue
.btn-primary {
font-family: 'Rubik', sans-serif;
font-weight: 500;
font-size: 16px;
height: 56px;
padding: 0 32px;
background-color: #0057B7;
color: #FFFFFF;
border: none;
border-radius: 0;
cursor: pointer;
transition: background-color 0.15s ease;
}
.btn-primary:hover { background-color: #004189; }Primary Button — Magenta Variant
Use sparingly for the single most important CTA on a page.
.btn-primary-magenta {
font-family: 'Rubik', sans-serif;
font-weight: 500;
font-size: 16px;
height: 56px;
padding: 0 32px;
background-color: #D62598;
color: #FFFFFF;
border: none;
border-radius: 0;
cursor: pointer;
transition: background-color 0.15s ease;
}
.btn-primary-magenta:hover { background-color: #A01B72; }Outlined Button (Medium)
.btn-outlined {
font-family: 'Rubik', sans-serif;
font-weight: 500;
font-size: 14px;
height: 48px;
padding: 0 24px;
background-color: transparent;
color: #0057B7;
border: 2px solid #0057B7;
border-radius: 0;
cursor: pointer;
transition: all 0.15s ease;
}
.btn-outlined:hover {
background-color: #D62598;
border-color: #D62598;
color: #FFFFFF;
}Secondary Button (Small)
.btn-secondary {
font-family: 'Rubik', sans-serif;
font-weight: 600;
font-size: 12px;
height: 40px;
padding: 0 20px;
background-color: #001E62;
color: #FFFFFF;
border: none;
border-radius: 0;
cursor: pointer;
transition: background-color 0.15s ease;
}
.btn-secondary:hover { background-color: #00174A; }Dark Theme Buttons
/* Primary - Dark */
.dark .btn-primary {
background-color: #529EEC;
}
.dark .btn-primary:hover { background-color: #7CBAFF; }
/* Outlined - Dark */
.dark .btn-outlined {
color: #F0F4F8;
border-color: #F0F4F8;
}
.dark .btn-outlined:hover {
background-color: #003EC8;
border-color: #003EC8;
color: #FFFFFF;
}Links
.link {
font-family: 'Rubik', sans-serif;
font-weight: 600;
font-size: 16px;
color: #0057B7;
text-decoration: none;
transition: color 0.15s ease;
}
.link::after { content: ' >'; }
.link:hover { color: #003EC8; }
.dark .link { color: #529EEC; }
.dark .link:hover { color: #7CBAFF; }Cards
.card {
background: #FFFFFF;
border: none;
border-radius: 0;
box-shadow: 0 2px 8px rgba(0, 30, 98, 0.1);
padding: 24px;
}
.dark .card {
background: #0A1A3A;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}Card variants from brand guide:
- Dark Card: Navy bg
#0A1A3A, light text, for product/dashboard contexts - Light Card: White bg, navy text, subtle shadow
- Status Card: Card with colored left border (3px) indicating status
- Alert Card: Card with colored top accent and icon
Alert Styles
.alert {
padding: 16px 20px;
border-radius: 0;
display: flex;
align-items: center;
gap: 12px;
font-family: 'Rubik', sans-serif;
font-size: 14px;
}
.alert-success {
background: rgba(0, 177, 64, 0.1);
border-left: 3px solid #00B140;
color: #001E62;
}
.alert-warning {
background: rgba(227, 82, 5, 0.1);
border-left: 3px solid #E35205;
color: #001E62;
}
.alert-error {
background: rgba(239, 51, 64, 0.1);
border-left: 3px solid #EF3340;
color: #001E62;
}
.alert-info {
background: rgba(0, 87, 183, 0.1);
border-left: 3px solid #0057B7;
color: #001E62;
}Status Badges
.badge {
font-family: 'Rubik', sans-serif;
font-weight: 500;
font-size: 12px;
padding: 4px 10px;
border-radius: 0; /* Square badges */
text-transform: uppercase;
letter-spacing: 0.05em;
}
.badge-success { background: #00B140; color: #FFFFFF; }
.badge-warning { background: #E35205; color: #FFFFFF; }
.badge-error { background: #EF3340; color: #FFFFFF; }
.badge-info { background: #0057B7; color: #FFFFFF; }
.badge-accent { background: #D62598; color: #FFFFFF; }
.badge-new { background: #529EEC; color: #FFFFFF; }Layout: Diagonal Split Hero
.hero {
position: relative;
background: #001E62;
min-height: 500px;
overflow: hidden;
padding: 80px 48px;
}
.hero-diagonal::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 100%;
background: #FFFFFF;
clip-path: polygon(20% 0, 100% 0, 100% 100%, 0 100%);
}Layout: Section Alternation
Cycle through these backgrounds in order to create visual rhythm:
1. White #FFFFFF 2. Light Gray #F0F4F8 3. Navy #001E62 (with white text) 4. A10 Blue #0057B7 (with white text)
Use padding 48px 0 or 64px 0 for section spacing. No visible borders between sections — the color change creates the separation.
Layout: Spacing Scale
| Token | Value | Usage |
|---|---|---|
| xs | 4px | Tight spacing, icon gaps |
| sm | 8px | Compact elements |
| md | 16px | Default component padding |
| lg | 24px | Card padding, section gaps |
| xl | 32px | Section padding, large gaps |
| 2xl | 48px | Section vertical padding |
| 3xl | 64px | Hero padding, major sections |
Form Inputs
input, select, textarea {
font-family: 'Rubik', sans-serif;
font-weight: 400;
font-size: 16px;
padding: 12px 16px;
border: 2px solid #DFE8F0;
border-radius: 0;
background: #FFFFFF;
color: #001E62;
transition: border-color 0.15s ease;
}
input:focus, select:focus, textarea:focus {
border-color: #0057B7;
outline: none;
}
.dark input, .dark select, .dark textarea {
background: #0A1A3A;
border-color: #003EC8;
color: #F0F4F8;
}
.dark input:focus { border-color: #529EEC; }Tables
table {
width: 100%;
border-collapse: collapse;
font-family: 'Rubik', sans-serif;
}
th {
background: #001E62;
color: #FFFFFF;
font-weight: 500;
font-size: 14px;
padding: 12px 16px;
text-align: left;
}
td {
padding: 12px 16px;
border-bottom: 1px solid #DFE8F0;
font-size: 14px;
color: #001E62;
}
tr:hover td { background: #F0F4F8; }
/* Dark theme */
.dark th { background: #00174A; }
.dark td {
color: #F0F4F8;
border-bottom-color: rgba(255, 255, 255, 0.08);
}
.dark tr:hover td { background: rgba(255, 255, 255, 0.04); }Global Resets
Apply to every A10 project:
button, .btn, .card, input, select, textarea,
.badge, .alert, .tooltip, .modal, img.framed {
border-radius: 0;
}A10 Brand Review Checklist — Expanded
Use this checklist when auditing any visual output for A10 brand compliance. Work through each section and report findings grouped by severity.
---
Critical (Must Fix)
These violations make the output instantly recognizable as "not A10." Fix before shipping.
Shape & Geometry
- [ ] No rounded corners on buttons (
border-radius: 0) - [ ] No rounded corners on cards
- [ ] No rounded corners on form inputs
- [ ] No rounded corners on badges/tags
- [ ] No rounded corners on images/containers
- [ ] No rounded corners on tooltips/modals
- [ ] No slanted/angled button edges
- [ ] No pill-shaped elements
Typography
- [ ] Rubik font loaded via Google Fonts
- [ ] Rubik actually rendering (not falling back to system font)
- [ ] H1-H4 using Light weight (300), NOT Bold or Regular
- [ ] No Bold headlines (only Light 300 for H1-H4)
- [ ] No Comic Sans, Papyrus, or novelty fonts (obviously)
Color
- [ ] All prominent colors from A10 brand palette
- [ ] No off-brand blues (watch for Tailwind blue-500/600, Bootstrap blue, Material blue)
- [ ] Magenta NOT used as a background color
- [ ] Magenta NOT dominant (should be ≤8% of color presence)
- [ ] Logo displayed in approved colors only (A10 Blue, Navy, White, or Black)
- [ ] Logo NOT on accent-colored backgrounds
Accessibility
- [ ] Text contrast meets WCAG 2.1 AA (4.5:1 normal, 3:1 large)
- [ ] No light text on light backgrounds
- [ ] No dark text on dark backgrounds
- [ ] Interactive elements have visible focus states
---
Major (Should Fix)
These issues are noticeable to someone familiar with the brand. Fix for polish.
Buttons
- [ ] Primary button height: 56px
- [ ] Outlined button height: 48px
- [ ] Secondary button height: 40px
- [ ] Correct padding per size (32px / 24px / 20px horizontal)
- [ ] Title Case labels ("Learn More" not "LEARN MORE")
- [ ] Hover states present and using correct dark/light variants
- [ ] Blue button hover:
#004189(light) or#7CBAFF(dark) - [ ] Magenta button hover:
#A01B72
Font Weights
- [ ] Body text: Regular 400
- [ ] Buttons/navigation: Medium 500
- [ ] Links: SemiBold 600
- [ ] Eyebrows: Bold 700, ALL-CAPS, letter-spacing 0.1em
- [ ] No Bold (700) used for headlines or body
Color Proportions
- [ ] Blues (Navy + A10 Blue) dominate the color landscape
- [ ] White used appropriately (backgrounds, text on dark)
- [ ] Accent colors (Purple, Orange, Cloud Blue, Green, Red) limited to data/status
- [ ] Accent colors NOT used for backgrounds or large decorative areas
- [ ] Sky Blue used as secondary, not competing with A10 Blue for primary
- [ ] Overall proportion feels: 80% primary / 15% secondary / 5% accent
Charts & Data Viz
- [ ] Value labels on every bar/data point
- [ ] Grid lines dashed (not solid) at low opacity
- [ ] Gradient fills (not flat solid fills) on bars
- [ ] No rounded corners on chart bars
- [ ] Series colors follow priority order (Blue → Sky → Green → Orange → Red...)
- [ ] Chart title in Light 300 with subtitle in Regular 400
- [ ] Rubik font used for all chart text
Typography Rules
- [ ] Ragged-right alignment (no justified text)
- [ ] No ALL-CAPS except eyebrows/small labels
- [ ] No hyphenation
- [ ] "A10 Networks" kept on same line (not breaking across lines)
- [ ] Body line-height: 24px (1.5)
- [ ] Reasonable line length (60-80 characters)
Theme Consistency
- [ ] Light theme: white/gray backgrounds with navy text
- [ ] Dark theme: navy/black backgrounds with light text and sky-blue links
- [ ] Not mixing light and dark theme elements inconsistently
- [ ] Links using correct theme color (
#0057B7light,#529EECdark)
---
Minor (Polish)
These are the details that separate good from great.
Spacing
- [ ] Using the scale: 4 / 8 / 16 / 24 / 32 / 48 / 64px
- [ ] Consistent padding across similar elements
- [ ] Generous whitespace (not cramped)
- [ ] Card padding: 24px
- [ ] Section padding: 48-64px vertical
Layout
- [ ] Section backgrounds alternating (White → Light Gray → Navy → Blue)
- [ ] No visible borders between sections (color change = separation)
- [ ] Cards using subtle box-shadow (not borders)
- [ ] Hero section has diagonal split opportunity utilized
Icons
- [ ] Consistent sizing across icon set
- [ ] Colored with brand palette only
- [ ] Clean lines, no drop shadows
- [ ] No gradients unless from approved gradient set
Links
- [ ] SemiBold 600 weight
- [ ] Correct color per theme
- [ ] Hover color change present
- [ ] Arrow suffix (" >") where appropriate
Charts (Detail)
- [ ] Subtitle with temporal/contextual info
- [ ] Hover states with opacity transition
- [ ] Legend markers are squares (not circles)
- [ ] Value labels formatted (X.Xk for thousands)
- [ ] Left/top highlight edge on bars (rgba white 0.12)
- [ ] Base opacity 0.9, hover 1.0
Eyebrows
- [ ] Letter-spacing: 0.1em
- [ ] Font-size: 16px
- [ ] Bold 700 weight
- [ ] ALL-CAPS
---
Spirit Check
Beyond mechanical compliance, does the output embody the A10 brand personality?
Confidence
- [ ] Clear visual hierarchy — one focal point per section
- [ ] Decisive color choices (not timid or washed out)
- [ ] Headlines feel authoritative yet elegant (Light 300 does this)
- [ ] CTAs are prominent and unambiguous
Cleanliness
- [ ] Whitespace is generous, not cramped
- [ ] No visual clutter or competing focal points
- [ ] Information density is appropriate for the medium
- [ ] Grid alignment is consistent
Engineering Aesthetic
- [ ] Feels precise and intentional
- [ ] Every element serves a purpose
- [ ] No decorative elements without function
- [ ] Data presentation is clear and well-labeled
Brand Cohesion
- [ ] Would this look at home next to a10networks.com?
- [ ] Color balance feels like "a page from the same book" as other A10 materials
- [ ] Typography creates the signature "lightweight elegance"
- [ ] The diagonal energy / sharp-edge identity is present where appropriate
Common Off-Brand Patterns to Watch For
- [ ] Tailwind defaults — rounded-lg, blue-500, gray-200 backgrounds
- [ ] Bootstrap defaults — rounded buttons, card-body padding, #007bff blue
- [ ] Material defaults — rounded corners, elevation shadows, Roboto font
- [ ] Generic "AI slop" — purple gradients, Inter font, excessive rounded corners
- [ ] Stock photography clichés — handshakes, puzzle pieces, hooded hackers
---
Reporting Format
When reporting audit results, structure as:
🔴 Critical Issues (X found)
For each: what's wrong, where, exact fix (with hex codes, CSS props, font weights)
🟡 Major Issues (X found)
For each: what's wrong, where, recommended fix
🔵 Minor Issues (X found)
For each: what could be improved, suggested approach
✅ Brand Spirit Assessment
2-3 sentences on overall brand alignment, calling out what works well and what feels off.
A10 Typography — Complete Reference
Font Family
Primary: Rubik (Google Font)
<link href="https://fonts.googleapis.com/css2?family=Rubik:wght@300;400;500;600;700&display=swap" rel="stylesheet">Office fallback: Calibri System fallback: -apple-system, BlinkMacSystemFont, sans-serif
Full stack: 'Rubik', 'Calibri', -apple-system, BlinkMacSystemFont, sans-serif
Font Weights
| Weight | Value | Usage |
|---|---|---|
| Light | 300 | H1, H2, H3, H4 — all large headlines |
| Regular | 400 | Body copy, paragraphs, subheads, chart labels |
| Medium | 500 | H5, H6, buttons, navigation, labels |
| SemiBold | 600 | Links, small buttons, emphasis |
| Bold | 700 | Eyebrows only (ALL-CAPS labels), sparingly |
The most common mistake is using Bold for headlines. A10 headlines use Light 300 — this creates the brand's distinctive elegant, modern feel. Bold is reserved almost exclusively for small uppercase eyebrow labels.
Type Scale
| Element | Size (px) | Size (rem) | Line Height | Weight | Additional |
|---|---|---|---|---|---|
| Eyebrow | 16px | 1rem | 1.2 | Bold 700 | ALL-CAPS, letter-spacing: 0.1em |
| H1 | 48px | 3rem | 56px | Light 300 | |
| H2 | 32px | 2rem | 40px | Light 300 | |
| H3 | 28px | 1.75rem | 36px | Light 300 | |
| H4 | 24px | 1.5rem | 32px | Light 300 | |
| H5 | 20px | 1.25rem | 28px | Medium 500 | |
| H6 | 16px | 1rem | 24px | Medium 500 | |
| Subhead | 20px | 1.25rem | 28px | Regular 400 | |
| Body | 16px | 1rem | 24px | Regular 400 | |
| Small | 14px | 0.875rem | 20px | Regular 400 |
Typography Rules
- Alignment: Ragged-right (left-aligned). Never justified text.
- Kerning: Optical kerning enabled (
font-kerning: normal; text-rendering: optimizeLegibility;) - Hyphenation: Never. (
hyphens: none;) - ALL-CAPS: Only for eyebrows and small labels. Never for body text or headlines.
- Quotes: Smart quotes (" ") for dialogue; straight quotes (") for measurements/code.
- Brand names: Keep "A10 Networks" and product names on the same line (
white-space: nowrap). - Line length: Aim for 60-80 characters per line for body text readability.
CSS Implementation
/* Base typography */
body {
font-family: 'Rubik', 'Calibri', -apple-system, BlinkMacSystemFont, sans-serif;
font-weight: 400;
font-size: 16px;
line-height: 1.5;
font-kerning: normal;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
hyphens: none;
}
/* Headlines — Light 300 */
h1 { font-size: 3rem; line-height: 56px; font-weight: 300; }
h2 { font-size: 2rem; line-height: 40px; font-weight: 300; }
h3 { font-size: 1.75rem; line-height: 36px; font-weight: 300; }
h4 { font-size: 1.5rem; line-height: 32px; font-weight: 300; }
/* Sub-headlines — Medium 500 */
h5 { font-size: 1.25rem; line-height: 28px; font-weight: 500; }
h6 { font-size: 1rem; line-height: 24px; font-weight: 500; }
/* Eyebrow */
.eyebrow {
font-size: 1rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
line-height: 1.2;
}
/* Links */
a {
font-weight: 600;
text-decoration: none;
}Office / Print Context
When Rubik is unavailable (PowerPoint, Word, print):
- Use Calibri as the primary font
- Maintain the same weight relationships (Light for headlines, Regular for body)
- Print minimum: 10pt body, 8pt captions
- Ensure 300 DPI for print output