Skip to content

Colour Concept

xcentaurix edited this page Oct 15, 2026 · 2 revisions

Colour concept

The skin uses a Material Design 3 dark colour scheme. Every colour a screen uses is a symbolic role (md_surface, md_primary, ...) defined once in colors.ymlinc in src/skin/default/. Screens never contain hex values and never use the old colour names.

A light variant with the same role names is available as an alternative.

Principles

  1. Roles, not colours. A screen says what a colour is for (md_on_surface = primary text), not what it looks like. Changing the look of the whole skin means editing one file.
  2. Depth from lightness, not from colour. On a dark theme, surfaces that sit higher are lighter. Panels, rows and bars are told apart by seven grey steps, not by hue.
  3. One accent family. A single blue md_primary carries emphasis. A muted slate md_secondary carries supporting text. Everything else is neutral.
  4. Colour means something. Green, amber and red are used only for state (ok, caution, error/record) and for the remote's colour keys. They are not decoration.
  5. Readable first. Every text role reaches at least WCAG AA (4.5:1) on the surface it is used on (see Contrast).

Palette

Values are enigma2 #AARRGGBB; alpha 00 is opaque.

Surfaces (lighter = higher)

Role Value Use
md_surface #00121212 window and list background
md_surface_solid #00121212 same as md_surface, kept for existing uses
md_surface_container_lowest #000e0e0e top bars, deepest wells
md_surface_container_low #001d1d1d cards, secondary panels
md_surface_container #00232323 default container
md_surface_container_high #002c2c2c selected row, raised container
md_surface_container_highest #00363636 chips, bars, inactive fills

Overlays

Role Value Use
md_scrim #7f000000 dimming layer behind dialogs
md_surface_overlay_soft #18121212 light translucent surface
md_surface_overlay #2d121212 translucent surface
md_surface_overlay_strong #fa121212 almost opaque translucent surface

Outline and text

Role Value Use
md_outline #00919191 borders, inactive text
md_outline_variant #00424242 dividers, separators
md_on_surface #00e3e3e3 primary text
md_on_surface_variant #00c4c4c4 secondary text

Accents

Role Value Use
md_primary #00a8c7fa titles, key info, selected text, scrollbar sliders
md_primary_container #000842a0 selected / active container
md_primary_container_translucent #250842a0 progress track
md_primary_container_soft #080842a0 faint tonal wash
md_on_primary_container #00d3e3fd text on a primary container
md_secondary #00bdc7dc supporting text (next event, sub-lines)
md_secondary_container #003f4759 marked rows
md_on_secondary_container #00d9e3f8 text on a secondary container
md_tertiary #007fd6c8 times and durations

State

Role Value Use
md_success / md_success_container #0081c995 / #000f5223 ok, on
md_warning / md_warning_container #00ffb74d / #006b3f00 caution
md_error / md_error_container #00f28b82 / #008c1d18 error, recording

Remote colour keys

md_key_red #00f28b82, md_key_green #0081c995, md_key_yellow #00fdd663, md_key_blue #008ab4f8. These stay clearly recognisable on purpose, so the on-screen keys match the buttons on the remote.

Fixed

md_shadow #00000000 (black, for shadows and borders) and md_transparent #ff000000 (fully transparent).

Typical combinations

Element Background Text
Window, list md_surface md_on_surface
Window title md_surface md_primary
Selected list row md_surface_container_high md_primary
Marked row md_secondary_container md_on_secondary_container
Marked and selected row md_primary_container md_on_primary_container
Infobar event name md_surface md_primary
Infobar channel name md_surface md_on_surface
Next event, sub-lines md_surface md_secondary
Time, duration md_surface md_tertiary
Inactive / hint text any surface md_outline
Divider n/a md_outline_variant

Contrast

Measured against md_surface (#121212) unless noted. WCAG AA needs 4.5:1 for normal text.

Pair Ratio
md_on_surface 14.6
md_on_surface_variant 10.7
md_primary 10.9
md_secondary 11.0
md_tertiary 11.0
md_success 9.6
md_warning 10.8
md_error 7.8
md_key_yellow 13.4
md_outline 5.9
md_primary on md_surface_container_high 8.1
md_on_primary_container on md_primary_container 7.0
md_on_secondary_container on md_secondary_container 7.2

md_outline_variant on md_surface is only 1.9:1 by design. It is for dividers, never for text.

Rules for new and changed screens

  • Use only md_* names in colour attributes (backgroundColor, foregroundColor, borderColor, foregroundColors, ...).
  • Do not write hex values in screens. If a role is missing, add it to colors.ymlinc with a name that says what it is for.
  • Choose by role, not by looks: a title is md_primary, not "the blue one".
  • Do not use md_error, md_warning or md_success for decoration.
  • Raise emphasis with a lighter surface step, not a new colour.

Where hex values are still required

enigma2 reads some skin parameters as raw numbers, so a role name cannot be used there. They are in parameters.ymlinc (parameters_light.ymlinc for the light theme). If you change a role value, update these too. The role of each value is recorded in the table below.

Parameter Role
ChoicelistSeparatorColor md_outline_variant
VirtualKeyBoardShiftColors md_on_surface, md_on_surface, md_primary, md_tertiary
VirtualKeyBoardCellBackgroundColor md_surface_container_high
VirtualKeyBoardCellBorderColor md_surface
VirtualKeyBoardCellSelectedColor md_primary
VirtualKeyBoardCellEnterColor md_success
VirtualKeyBoardCellShiftColor md_warning
VirtualKeyBoardCellUpperColor md_key_blue
VirtualKeyBoardCellExitColor md_error
PlutoTvColors md_on_surface, md_primary

Legacy names

The earlier colour names (white, background, grey, yellow, selectedFG, ...) are no longer defined. Screens use only the md_* roles. A name that is not defined is not found by enigma2 when the skin is loaded, so the colour falls back to white. Look for leftover old names in colour attributes, in the Python of <applet> blocks (parseColor("..."), gRGB(0x...)) and in MultiContentEntryText(color=...), not only in the XML attributes. Plugin skins that look colours up by their old names from the active skin need to use the roles.

Pixmaps

The PNG and SVG artwork is recoloured to these roles by a script. See Pixmap colours. A few full-colour files (weather, age-rating badges, front-panel icons, photos) are deliberately left alone.

Changing the theme

Edit the values in colors.ymlinc and the matching hex values listed above, then regenerate the artwork (see Pixmap colours). The surface, container and outline roles are fully opaque (alpha 00). Keep them so: with a non-zero alpha enigma2 blends every fill pixel by pixel, which is slower, and on the EGL backend a rounded widget is drawn with the formula that lets the video plane show through its corners. Only the overlay roles are translucent, on purpose.