GH GambleHub

Color system and branded palettes

1) Why formalize color

Color is not a set of "good shades," but a manageable system for:
  • brand awareness and visual consistency,
  • readability and availability (WCAG),
  • scaling interfaces (themes, platforms, locales),
  • predictable A/B experiments (contrast, CTR, errors).

2) System foundations: models and metrics

OKLCH (recommended): perceptually uniform, it is convenient to control the lightness' L'and saturation' C'while maintaining the shade' H '.
Lab/LCH: also fit; OKLCH is more stable in perception.
sRGB: finite display space; totals are always validated in sRGB and WCAG.
Contrast (WCAG 2. 2): base text ≥ 4. 5:1, large ≥ 3:1; critical notifications - aim for AAA (7:1) where possible.

3) Layers of the system: from brand to semantics

1. Brand core: 1-2 branded shades (+ supporting accent).
2. Interface semantics: roles ('primary', 'secondary', 'success', 'warning', 'danger', 'info', 'neutral').
3. Tone scales: lightness steps (e.g. 25/50/100...900).
4. Темы: `light` / `dark` (+ high-contrast, AMOLED).
5. States: 'default/hover/active/focus/disabled'.
6. Context: surfaces ('bg/base', 'bg/subtle', 'bg/elevated') and text ('fg/primary', 'fg/secondary', 'fg/muted').
7. Data visualization: separate discrete and continuous palettes.

4) Brand core: choices and restraints

Select Hue and define the working lightness for the brand in light and dark themes (often 'L≈0. 60–0. 70 'for filling buttons in light and' L≈0. 70–0. 80 'for text/icons in dark).
Limit chrome 'C': high 'C' is beautiful on banners, but breaks readability in UI - keep 2 versions: "marketing" (rich) and "grocery" (more restrained).
Fix the variables: main ('brand/primary'), alternative ('brand/alt') and neutral support ('neutral').

5) Tone scales

The goal is to obtain uniform lightness steps with controlled saturation:
  • For OKLCH, move the'L'steps (e.g. 0. 98→0. 90→0. 80→…→0. 18), and 'C' slightly reduce to the edges of the scale to avoid "dirt" in light and "turbidity" in dark.
  • Fix the checkpoints: '50/100/300/500 (key )/700/900'.
  • At each step, check the contrast of the pair with the base background and with the expected text color.

Example of brand/primary scale (OKLCH, approximate)


brand.primary.50  = oklch(0.98 0.03 230)
brand.primary.100 = oklch(0.94 0.05 230)
brand.primary.300 = oklch(0.86 0.08 230)
brand.primary.500 = oklch(0.74 0.10 230) # ключевой тон brand.primary.700 = oklch(0.56 0.09 230)
brand.primary.900 = oklch(0.32 0.07 230)

6) Semantic roles and mapping

Separate brand and semantics: "success" does not have to be brand green.


role.primary.bg    -> brand.primary.500 role.primary.text   -> fg.on-primary     # ≥ 4.5:1 к role.primary.bg role.success.bg    -> green.500 role.warning.bg    -> amber.500 role.danger.bg    -> red.500 role.info.bg     -> blue.500 role.neutral.bg    -> gray.200/700 (light/dark)

The'on- 'texts are calculated automatically (see § 10).

7) Light/dark themes and surfaces

Define the base scale for surfaces and text:

light:
bg/base   = oklch(0.98 0.01 260)
bg/subtle  = oklch(0.96 0.01 260)
bg/elevated = oklch(0.93 0.01 260)
fg/primary  = oklch(0.18 0.03 260) # ≈7:1 к bg/base fg/secondary = oklch(0.32 0.03 260) # ≥4.5:1 border    = oklch(0.80 0.02 260)

dark:
bg/base   = oklch(0.16 0.01 260)
bg/subtle  = oklch(0.20 0.01 260)
bg/elevated = oklch(0.24 0.01 260)
fg/primary  = oklch(0.90 0.02 260)
fg/secondary = oklch(0.78 0.02 260)
border    = oklch(0.34 0.02 260)

Maintain equal contrast goals in both themes; avoid "blinding" white on pure black - raise the'L'background to ~ 0. 16.

8) States and interactivity

For each role, set the states to controlled 'Δ L' and 'Δ C':

button/primary:
default.bg = brand.primary.500 hover.bg  = brand.primary.500 with +ΔC(0.01) -ΔL(0.02)
active.bg = brand.primary.700 focus.ring = brand.primary.300 # контраст кольца ≥ 3:1 к окружению disabled.bg= neutral.200 (light) / neutral.700 (dark)
text.on  = auto-contrast(default.bg)    # ≥ 4.5:1

9) Liability and WCAG

The basic text and icons in the controls are ≥ 4. 5:1.
Key system notifications (KYC/AML, 18 +, payment errors) - aim at AAA (7:1).
Field states and boundaries - at least 3:1.
Distinguish links not only by color (underscore/focus-style).

10) Auto-fit contrast text ('on-')

Logic: when selecting the fill of the component, calculate 'on-color':

1. According to OKLCH, determine the predlag. text'L _ on'so that' (L_text vs L_bg) ≥ 4. 5:1`.

2. If chromium is high, lower'C _ text'to 0. 01–0. 03.

3. For a dark theme, raise 'L _ on' another 0. 02–0. 04 to offset the glare.

Pseudo token:

fg.on(colorX) = auto(colorX, targetContrast=4.5)

11) Data visualization

Categorical palettes: 8-12 colors resistant to color blindness (avoid red-green pairs without alternative signs).
Continuous: from 'bg/elevated' to accent with contrast control of signatures.
Add patterns/markers for discernibility without color.

12) International context (cultural associations)

Consider local connotations (e.g. red - danger/attention; gold - win/prize).

For iGaming: Avoid success/danger conflicts with branded accents in one screen; iconography and signature are more important than "brightness."

13) Integration into the design system

13. 1 Naming tokens


color.{theme}.{role    surface    brand}.{state    step}
примеры color.light.brand.primary.500 color.dark.role.success.bg color.light.surface.bg.base color.light.fg.on-primary

13. 2 Tokens (JSON/Style Dictionary)

json
{
"color": {
"light": {
"surface": { "bg": { "base": "oklch(0.98 0.01 260)"} },
"brand":  { "primary": { "500": "oklch(0.74 0.10 230)" } },
"role":  { "primary": { "bg": "{color.light.brand.primary.500}" },
"danger": { "bg": "oklch(0.62 0.12 25)" } },
"fg": { "primary": "oklch(0.18 0.03 260)",
"on-primary": "auto({color.light.role.primary.bg},4.5)" }
}
}
}

13. 3 CSS variables (theme layer)

css
:root[data-theme="light"] {
--bg-base: oklch(0.98 0.01 260);
--brand-primary-500: oklch(0.74 0.10 230);
--fg-primary: oklch(0.18 0.03 260);
--on-primary: color-contrast(var(--brand-primary-500)); / автоподбор /
}
[data-theme="dark"] {
--bg-base: oklch(0.16 0.01 260);
--brand-primary-500: oklch(0.74 0.10 230);
--fg-primary: oklch(0.90 0.02 260);
--on-primary: color-contrast(var(--brand-primary-500));
}

13. 4 Figma/documentation

Components use only tokens, direct HEX/SRGB are prohibited by linters.
In the library - page "Contrast matrix": table 'fg × bg' with actual coefficients.

14) Quality control processes

In design: contrast check on artboards (both modes), separate presets for color blindness.
In code: unit helpers compute contrast and fall in violations; visual snapshots for critical screens.
In CI/CD: checking all pairs of tokens and states, report with component, theme and actual value.

15) The specifics of iGaming

Promos and tournaments: Use the overlay and 'C' constraint on the backgrounds to prevent the text from 'sinking'.
Responsible notifications (limits, 18 +, risks) - sincerely AAA.
Metrics/tables: Distinguish between numbers and signs of changes (↑/↓) by shape and contrast, not just color.

16) Implementation checklist

  • Brand shades and their tonal scales (OKLCH) are defined.
  • Roles, states, and surfaces are set for the two themes.
  • Auto-generation 'on-' with target contrast.
  • 'fg × bg' matrix and WCAG tests in CI.
  • Individual palettes for dataviz (with color blindness support).
  • Linter styles prohibit "raw" colors.
  • Exceptions and Reasons page in the guideline.

17) Anti-patterns

Mix brand emphasis with success/error in one UX signal.
Rely only on saturation for hierarchy.
Do not synchronize light/dark (contrast "left" in one of the themes).
Hard HEX without tokens → uncontrolled interface drift.


Brief summary

Build a palette from top to bottom: brand core → semantic roles → tone scales → themes → states. Work in OKLCH, pin tokens, automate'on- 'and WCAG checks. Separately, enter the palettes for dataviz. This will give brand consistency, readability and product scalability.

Contact

Get in Touch

Reach out with any questions or support needs.We are always ready to help!

Start Integration

Email is required. Telegram or WhatsApp — optional.

Your Name optional
Email optional
Subject optional
Message optional
Telegram optional
@
If you include Telegram — we will reply there as well, in addition to Email.
WhatsApp optional
Format: +country code and number (e.g., +380XXXXXXXXX).

By clicking this button, you agree to data processing.