Guide

Theme Creator

Pick a color for every PhoenixPaper token, for light and dark, and watch real components repaint. When it looks right, copy the CSS into your app.css. See the Theming guide for how the tokens work.

From a seed color

The seed generates every role for light and dark with phoenix_paper's MD3 color science (the same as mix phoenix_paper.gen.theme). Then fine-tune any token below; you're editing the light palette.

Primary
Secondary
Tertiary
Error
Surface
Outline
Inverse
Fixed
Other
AL Ada Lovelace
Surface containers, tonal and filled
Volume 60
Your changes were saved.
3

Your CSS

Paste this into assets/css/app.css after the phoenix_paper import. It sets every token for light (:root) and dark ([data-theme="dark"]); delete any line you want to keep at the library default.

/* assets/css/app.css, after the phoenix_paper import */

/* Light (default) */
:root {
  /* Primary */
  --color-pp-primary: #6750a4;
  --color-pp-on-primary: #ffffff;
  --color-pp-primary-container: #eaddff;
  --color-pp-on-primary-container: #4f378b;

  /* Secondary */
  --color-pp-secondary: #625b71;
  --color-pp-on-secondary: #ffffff;
  --color-pp-secondary-container: #e8def8;
  --color-pp-on-secondary-container: #4a4458;

  /* Tertiary */
  --color-pp-tertiary: #7d5260;
  --color-pp-on-tertiary: #ffffff;
  --color-pp-tertiary-container: #ffd8e4;
  --color-pp-on-tertiary-container: #633b48;

  /* Error */
  --color-pp-error: #b3261e;
  --color-pp-on-error: #ffffff;
  --color-pp-error-container: #f9dedc;
  --color-pp-on-error-container: #8c1d18;

  /* Surface */
  --color-pp-surface: #fef7ff;
  --color-pp-surface-dim: #ded8e1;
  --color-pp-surface-bright: #fef7ff;
  --color-pp-surface-container-lowest: #ffffff;
  --color-pp-surface-container-low: #f7f2fa;
  --color-pp-surface-container: #f3edf7;
  --color-pp-surface-container-high: #ece6f0;
  --color-pp-surface-container-highest: #e6e0e9;
  --color-pp-surface-variant: #e7e0ec;
  --color-pp-on-surface: #1d1b20;
  --color-pp-on-surface-variant: #49454f;

  /* Outline */
  --color-pp-outline: #79747e;
  --color-pp-outline-variant: #cac4d0;

  /* Inverse */
  --color-pp-inverse-surface: #322f35;
  --color-pp-inverse-on-surface: #f5eff7;
  --color-pp-inverse-primary: #d0bcff;

  /* Fixed */
  --color-pp-primary-fixed: #eaddff;
  --color-pp-primary-fixed-dim: #d0bcff;
  --color-pp-on-primary-fixed: #21005d;
  --color-pp-on-primary-fixed-variant: #4f378b;
  --color-pp-secondary-fixed: #e8def8;
  --color-pp-secondary-fixed-dim: #ccc2dc;
  --color-pp-on-secondary-fixed: #1d192b;
  --color-pp-on-secondary-fixed-variant: #4a4458;
  --color-pp-tertiary-fixed: #ffd8e4;
  --color-pp-tertiary-fixed-dim: #efb8c8;
  --color-pp-on-tertiary-fixed: #31111d;
  --color-pp-on-tertiary-fixed-variant: #633b48;

  /* Other */
  --color-pp-shadow: #000000;
  --color-pp-scrim: #000000;
}

/* Dark */
[data-theme="dark"] {
  /* Primary */
  --color-pp-primary: #d0bcff;
  --color-pp-on-primary: #381e72;
  --color-pp-primary-container: #4f378b;
  --color-pp-on-primary-container: #eaddff;

  /* Secondary */
  --color-pp-secondary: #ccc2dc;
  --color-pp-on-secondary: #332d41;
  --color-pp-secondary-container: #4a4458;
  --color-pp-on-secondary-container: #e8def8;

  /* Tertiary */
  --color-pp-tertiary: #efb8c8;
  --color-pp-on-tertiary: #492532;
  --color-pp-tertiary-container: #633b48;
  --color-pp-on-tertiary-container: #ffd8e4;

  /* Error */
  --color-pp-error: #f2b8b5;
  --color-pp-on-error: #601410;
  --color-pp-error-container: #8c1d18;
  --color-pp-on-error-container: #f9dedc;

  /* Surface */
  --color-pp-surface: #141218;
  --color-pp-surface-dim: #141218;
  --color-pp-surface-bright: #3b383e;
  --color-pp-surface-container-lowest: #0f0d13;
  --color-pp-surface-container-low: #1d1b20;
  --color-pp-surface-container: #211f26;
  --color-pp-surface-container-high: #2b2930;
  --color-pp-surface-container-highest: #36343b;
  --color-pp-surface-variant: #49454f;
  --color-pp-on-surface: #e6e0e9;
  --color-pp-on-surface-variant: #cac4d0;

  /* Outline */
  --color-pp-outline: #938f99;
  --color-pp-outline-variant: #49454f;

  /* Inverse */
  --color-pp-inverse-surface: #e6e0e9;
  --color-pp-inverse-on-surface: #322f35;
  --color-pp-inverse-primary: #6750a4;

  /* Fixed */
  --color-pp-primary-fixed: #eaddff;
  --color-pp-primary-fixed-dim: #d0bcff;
  --color-pp-on-primary-fixed: #21005d;
  --color-pp-on-primary-fixed-variant: #4f378b;
  --color-pp-secondary-fixed: #e8def8;
  --color-pp-secondary-fixed-dim: #ccc2dc;
  --color-pp-on-secondary-fixed: #1d192b;
  --color-pp-on-secondary-fixed-variant: #4a4458;
  --color-pp-tertiary-fixed: #ffd8e4;
  --color-pp-tertiary-fixed-dim: #efb8c8;
  --color-pp-on-tertiary-fixed: #31111d;
  --color-pp-on-tertiary-fixed-variant: #633b48;

  /* Other */
  --color-pp-shadow: #000000;
  --color-pp-scrim: #000000;
}

z7ealth 2026