Buttons
On dark surfaces (#000000), use inverted button styles: white solid (21:1 AAA) and white outline at 50% opacity. These are custom one-off instances — not part of the standard two-variant system.
White label (#FFFFFF) on solid black button (#000000). Exceeds AAA for all text sizes. The highest possible contrast in the system.
Black label (#000000) on transparent background (white canvas). Outline itself inherits the same black. Maximum contrast on white.
White label on taupe hover state (#757263). Meets AA for all normal text. The solid button hover shifts to taupe — still fully compliant.
/* ── BUTTON DESIGN TOKENS ────────────────────────────────── */
:root {
--btn-font: 'Noto Sans', sans-serif;
--btn-weight: 600;
--btn-size: 1rem;
--btn-ls: 0;
--btn-transform: none;
--btn-radius: 9999px; /* Pill */
--btn-pad-v-sm: 8px; --btn-pad-h-sm: 20px;
--btn-pad-v: 12px; --btn-pad-h: 28px; /* ← DEFAULT */
--btn-pad-v-lg: 16px; --btn-pad-h-lg: 40px;
--btn-pad-v-xl: 20px; --btn-pad-h-xl: 52px;
--btn-transition: all 0.18s ease;
--btn-focus-ring: 0 0 0 3px rgba(117,114,99,0.35);
/* Primary Solid */
--btn-solid-bg: #000000;
--btn-solid-text: #FFFFFF;
--btn-solid-bg-hover: #757263;
--btn-solid-bg-active: rgba(0,0,0,0.82);
--btn-solid-bg-disabled: rgba(0,0,0,0.10);
--btn-solid-text-disabled:rgba(0,0,0,0.28);
/* Primary Outline */
--btn-outline-border: #000000;
--btn-outline-text: #000000;
--btn-outline-bg-hover: #000000;
--btn-outline-text-hover: #FFFFFF;
--btn-outline-border-disabled:rgba(0,0,0,0.16);
--btn-outline-text-disabled: rgba(0,0,0,0.28);
}
Use Primary Solid for the single most important action per view — the final CTA. Use Primary Outline for secondary actions placed alongside. Never show two solid buttons at the same hierarchy level; one action must always be dominant.
The outline is implemented as box-shadow: inset 0 0 0 2px, not a CSS border. This keeps padding consistent between solid and outline variants — both maintain identical physical size, preventing layout shifts when switching states.
Button labels use Noto Sans 600 at 1rem with no letter spacing and no text transform. Keep labels short: 1–4 words maximum. Never use Poppins for button text.
MD (default) fits most UI contexts. Use SM inside data tables, toolbars, and inline actions. Use LG for hero sections and primary landing CTAs. Use XL for standalone feature callouts only — never in a group with other buttons.
All button text meets WCAG AAA (21:1) in default state and AA (4.82:1) on hover. Focus states use the taupe focus ring — never remove :focus-visible styles. Icon-only buttons must include an aria-label.
All state transitions animate at 0.18s ease. Active state uses scale(0.975) for tactile press feedback. Loading state hides the label and shows a CSS spinner; keep the button at its natural width to prevent layout jumps.
Inline prose links use the same taupe palette as Outline Taupe buttons. They are weight 600, underlined, and taupe-colored — so they read as interactive without breaking the rhythm of body copy. On hover they shift to black for stronger affordance.
See the live AI Tutor shipped at Numerade — built end-to-end with the ML team.
See the live AI Tutor shipped at Numerade — built end-to-end with the ML team.
/* ── TEXT-LINK STYLES (global, in base.css) ──────────── */
a {
color: var(--c-taupe);
font-weight: 600;
text-decoration: underline;
text-decoration-color: var(--c-taupe);
text-underline-offset: 2px;
transition: color 0.15s, text-decoration-color 0.15s;
}
a:hover {
color: var(--text-primary);
text-decoration-color: var(--text-primary);
}
Use text-link styling for any inline anchor in prose — paragraphs, descriptions, card body copy, footer credits. Also use it for standalone "named" links that aren't buttons (e.g. AI Tutor, AI Flash Cards, Lecture Recorder titles that deep-link to live products).
Buttons, nav items, sidebar identity (the "Natalia Koldaeva"
name in the left column), card-as-link surfaces (.preview-card,
.ds-link-card, .blog-preview-cell), and CTA
chips opt out — they have their own component styles and should
never inherit the prose-link underline.
Taupe on white meets WCAG AA (5.05:1) for normal body text. The persistent underline ensures links remain identifiable for users with reduced color vision — never rely on color alone. On hover, contrast rises to 21:1 (black).
Off-site links get target="_blank" rel="noopener". The
underline + taupe color are sufficient affordance — do not append
arrow glyphs to prose links (reserve ↗ for button labels
and card meta rows).