Files
gitea-MIRROR/web_src/css/themes/theme-gitea-dark.css
silverwind bd8fd71bc1 enhance(theme): derive theme colors with color-mix and unify shades (#40113)
Derive theme colors from a few base colors with `color-mix(in srgb, …)`
and make the colorful palette coherent, so custom themes that import a
Gitea theme can override a base color and get matching shades.

- Every `-light`, `-dark-1` and `-dark-2` shade follows one rule for all
hues, fixing dark orange shades copied from the light theme, black
shades that barely moved and neon tints
- Base colors move at most 4 OKLab units toward a common lightness, the
median in dark and red in light, yellow stays unchanged
- Text, secondary, console, message, surface and alpha colors derive
from their own base, alpha variants now match their names
- Added and removed diff colors share one lightness per level in all
themes, including colorblind ones
- Chart.js and the external render iframe resolve `color-mix()` values
to hex through `getComputedStyle`
- Remove unused `secondary-dark-12`, `-13`, `shadow-opaque` and
`workflow-edge-hover`

Fixes: https://github.com/go-gitea/gitea/issues/30160

<img width="880" alt="Components with the largest color changes, dark
and light, before and after"
src="https://github.com/user-attachments/assets/a9d27636-e3bb-46fa-a3ac-3fec33fd9806"
/>
<img width="880" alt="All theme colors per family, before and after,
unchanged ones dimmed"
src="https://github.com/user-attachments/assets/9977dde3-0749-4926-b110-18c0dc31d632"
/>

---------

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2026-11-07 23:39:15 +00:00

331 lines
18 KiB
CSS

gitea-theme-meta-info {
--theme-display-name: "Dark";
--theme-color-scheme: "dark";
}
:root {
--is-dark-theme: true;
--color-primary: #4183c4;
--color-primary-contrast: #ffffff;
--color-primary-dark-1: color-mix(in srgb, var(--color-primary) 90%, white);
--color-primary-dark-2: color-mix(in srgb, var(--color-primary) 80%, white);
--color-primary-dark-3: color-mix(in srgb, var(--color-primary) 70%, white);
--color-primary-dark-4: color-mix(in srgb, var(--color-primary) 60%, white);
--color-primary-dark-5: color-mix(in srgb, var(--color-primary) 40%, white);
--color-primary-dark-6: color-mix(in srgb, var(--color-primary) 20%, white);
--color-primary-dark-7: color-mix(in srgb, var(--color-primary) 6%, white);
--color-primary-light-1: color-mix(in srgb, var(--color-primary) 90%, black);
--color-primary-light-2: color-mix(in srgb, var(--color-primary) 80%, black);
--color-primary-light-3: color-mix(in srgb, var(--color-primary) 70%, black);
--color-primary-light-4: color-mix(in srgb, var(--color-primary) 60%, black);
--color-primary-light-5: color-mix(in srgb, var(--color-primary) 40%, black);
--color-primary-light-6: color-mix(in srgb, var(--color-primary) 20%, black);
--color-primary-light-7: color-mix(in srgb, var(--color-primary) 6%, black);
--color-primary-alpha-10: color-mix(in srgb, var(--color-primary) 10%, transparent);
--color-primary-alpha-20: color-mix(in srgb, var(--color-primary) 20%, transparent);
--color-primary-alpha-30: color-mix(in srgb, var(--color-primary) 30%, transparent);
--color-primary-alpha-40: color-mix(in srgb, var(--color-primary) 40%, transparent);
--color-primary-alpha-50: color-mix(in srgb, var(--color-primary) 50%, transparent);
--color-primary-alpha-60: color-mix(in srgb, var(--color-primary) 60%, transparent);
--color-primary-alpha-70: color-mix(in srgb, var(--color-primary) 70%, transparent);
--color-primary-alpha-80: color-mix(in srgb, var(--color-primary) 80%, transparent);
--color-primary-alpha-90: color-mix(in srgb, var(--color-primary) 90%, transparent);
--color-primary-hover: var(--color-primary-light-1);
--color-primary-active: var(--color-primary-light-2);
--color-secondary: #3f4248;
--color-secondary-dark-1: color-mix(in srgb, var(--color-secondary) 96%, var(--color-text-dark));
--color-secondary-dark-2: color-mix(in srgb, var(--color-secondary) 91%, var(--color-text-dark));
--color-secondary-dark-3: color-mix(in srgb, var(--color-secondary) 82%, var(--color-text-dark));
--color-secondary-dark-4: color-mix(in srgb, var(--color-secondary) 73%, var(--color-text-dark));
--color-secondary-dark-5: color-mix(in srgb, var(--color-secondary) 65%, var(--color-text-dark));
--color-secondary-dark-6: color-mix(in srgb, var(--color-secondary) 58%, var(--color-text-dark));
--color-secondary-dark-7: color-mix(in srgb, var(--color-secondary) 50%, var(--color-text-dark));
--color-secondary-dark-8: color-mix(in srgb, var(--color-secondary) 42%, var(--color-text-dark));
--color-secondary-dark-9: color-mix(in srgb, var(--color-secondary) 39%, var(--color-text-dark));
--color-secondary-dark-10: color-mix(in srgb, var(--color-secondary) 32%, var(--color-text-dark));
--color-secondary-dark-11: color-mix(in srgb, var(--color-secondary) 25%, var(--color-text-dark));
--color-secondary-light-1: color-mix(in srgb, var(--color-secondary) 84%, black);
--color-secondary-light-2: color-mix(in srgb, var(--color-secondary) 70%, black);
--color-secondary-light-3: color-mix(in srgb, var(--color-secondary) 50%, black);
--color-secondary-light-4: color-mix(in srgb, var(--color-secondary) 39%, black);
--color-secondary-alpha-10: color-mix(in srgb, var(--color-secondary) 10%, transparent);
--color-secondary-alpha-20: color-mix(in srgb, var(--color-secondary) 20%, transparent);
--color-secondary-alpha-30: color-mix(in srgb, var(--color-secondary) 30%, transparent);
--color-secondary-alpha-40: color-mix(in srgb, var(--color-secondary) 40%, transparent);
--color-secondary-alpha-50: color-mix(in srgb, var(--color-secondary) 50%, transparent);
--color-secondary-alpha-60: color-mix(in srgb, var(--color-secondary) 60%, transparent);
--color-secondary-alpha-70: color-mix(in srgb, var(--color-secondary) 70%, transparent);
--color-secondary-alpha-80: color-mix(in srgb, var(--color-secondary) 80%, transparent);
--color-secondary-alpha-90: color-mix(in srgb, var(--color-secondary) 90%, transparent);
--color-secondary-button: var(--color-secondary-dark-4);
--color-secondary-hover: var(--color-secondary-dark-3);
--color-secondary-active: var(--color-secondary-dark-2);
/* console colors - used for actions console and console files */
--color-console-fg: #f8f8f8;
--color-console-fg-subtle: color-mix(in srgb, var(--color-console-fg) 76%, var(--color-console-bg));
--color-console-bg: color-mix(in srgb, var(--color-secondary) 39%, black);
--color-console-hover-bg: color-mix(in srgb, var(--color-console-fg) 8%, var(--color-console-bg));
--color-console-active-bg: color-mix(in srgb, var(--color-console-fg) 11%, var(--color-console-bg));
--color-console-link: color-mix(in srgb, var(--color-console-fg) 58%, var(--color-console-bg));
/* named colors */
--color-red: #d65150;
--color-orange: #d05c14;
--color-yellow: #cc9903;
--color-olive: #859605;
--color-green: #7b9e57;
--color-teal: #149790;
--color-blue: #3a8ac6;
--color-violet: #8e68df;
--color-purple: #b057cd;
--color-pink: #da3792;
--color-brown: #a97756;
--color-black: #202225;
/* light variants - produced via Sass scale-color(color, $lightness: +10%) */
--color-red-light: color-mix(in srgb, var(--color-red) 88%, white);
--color-orange-light: color-mix(in srgb, var(--color-orange) 88%, white);
--color-yellow-light: color-mix(in srgb, var(--color-yellow) 85%, white);
--color-olive-light: color-mix(in srgb, var(--color-olive) 89%, white);
--color-green-light: color-mix(in srgb, var(--color-green) 89%, white);
--color-teal-light: color-mix(in srgb, var(--color-teal) 88%, white);
--color-blue-light: color-mix(in srgb, var(--color-blue) 89%, white);
--color-violet-light: color-mix(in srgb, var(--color-violet) 89%, white);
--color-purple-light: color-mix(in srgb, var(--color-purple) 89%, white);
--color-pink-light: color-mix(in srgb, var(--color-pink) 86%, white);
--color-brown-light: color-mix(in srgb, var(--color-brown) 90%, white);
--color-black-light: color-mix(in srgb, var(--color-black) 96%, white);
/* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */
--color-red-dark-1: color-mix(in srgb, var(--color-red) 90%, black);
--color-orange-dark-1: color-mix(in srgb, var(--color-orange) 90%, black);
--color-yellow-dark-1: color-mix(in srgb, var(--color-yellow) 91%, black);
--color-olive-dark-1: color-mix(in srgb, var(--color-olive) 91%, black);
--color-green-dark-1: color-mix(in srgb, var(--color-green) 91%, black);
--color-teal-dark-1: color-mix(in srgb, var(--color-teal) 90%, black);
--color-blue-dark-1: color-mix(in srgb, var(--color-blue) 90%, black);
--color-violet-dark-1: color-mix(in srgb, var(--color-violet) 90%, black);
--color-purple-dark-1: color-mix(in srgb, var(--color-purple) 90%, black);
--color-pink-dark-1: color-mix(in srgb, var(--color-pink) 90%, black);
--color-brown-dark-1: color-mix(in srgb, var(--color-brown) 90%, black);
--color-black-dark-1: color-mix(in srgb, var(--color-black) 69%, black);
/* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */
--color-red-dark-2: color-mix(in srgb, var(--color-red) 80%, black);
--color-orange-dark-2: color-mix(in srgb, var(--color-orange) 80%, black);
--color-yellow-dark-2: color-mix(in srgb, var(--color-yellow) 83%, black);
--color-olive-dark-2: color-mix(in srgb, var(--color-olive) 81%, black);
--color-green-dark-2: color-mix(in srgb, var(--color-green) 81%, black);
--color-teal-dark-2: color-mix(in srgb, var(--color-teal) 80%, black);
--color-blue-dark-2: color-mix(in srgb, var(--color-blue) 80%, black);
--color-violet-dark-2: color-mix(in srgb, var(--color-violet) 80%, black);
--color-purple-dark-2: color-mix(in srgb, var(--color-purple) 80%, black);
--color-pink-dark-2: color-mix(in srgb, var(--color-pink) 80%, black);
--color-brown-dark-2: color-mix(in srgb, var(--color-brown) 80%, black);
--color-black-dark-2: color-mix(in srgb, var(--color-black) 40%, black);
/* ansi colors used for actions console and console files */
--color-ansi-black: #202225;
--color-ansi-red: #cc4848;
--color-ansi-green: #87ab63;
--color-ansi-yellow: #cc9903;
--color-ansi-blue: #3a8ac6;
--color-ansi-magenta: #d22e8b;
--color-ansi-cyan: #00918a;
--color-ansi-white: var(--color-console-fg-subtle);
--color-ansi-bright-black: color-mix(in srgb, var(--color-ansi-black) 83%, white);
--color-ansi-bright-red: color-mix(in srgb, var(--color-ansi-red) 90%, white);
--color-ansi-bright-green: color-mix(in srgb, var(--color-ansi-green) 90%, white);
--color-ansi-bright-yellow: #eaaf03;
--color-ansi-bright-blue: color-mix(in srgb, var(--color-ansi-blue) 90%, white);
--color-ansi-bright-magenta: color-mix(in srgb, var(--color-ansi-magenta) 90%, white);
--color-ansi-bright-cyan: #00b6ad;
--color-ansi-bright-white: var(--color-console-fg);
/* 16-color series */
--color-series-16-0: #7db233;
--color-series-16-1: #499a37;
--color-series-16-2: #ce4751;
--color-series-16-3: #8f9121;
--color-series-16-4: #ac32a6;
--color-series-16-5: #7445e9;
--color-series-16-6: #c67d28;
--color-series-16-7: #4db392;
--color-series-16-8: #aa4d30;
--color-series-16-9: #2a6f84;
--color-series-16-10: #c45327;
--color-series-16-11: #3d965c;
--color-series-16-12: #792a93;
--color-series-16-13: #439d73;
--color-series-16-14: #103aad;
--color-series-16-15: #982e85;
/* other colors */
--color-grey: color-mix(in srgb, var(--color-secondary) 95%, black);
--color-grey-light: color-mix(in srgb, var(--color-secondary) 59%, var(--color-text-dark));
--color-gold: #b1983b;
--color-white: #ffffff;
--color-diff-added-fg: color-mix(in srgb, var(--color-green) 90%, white);
--color-diff-added-linenum-bg: #2c472c;
--color-diff-added-row-bg: #1a2c1f;
--color-diff-added-row-border: #314a37;
--color-diff-added-word-bg: #2b542c;
--color-diff-moved-row-bg: #818044;
--color-diff-moved-row-border: #bcca6f;
--color-diff-removed-fg: #fb5f5b;
--color-diff-removed-linenum-bg: #5b3231;
--color-diff-removed-row-bg: #342222;
--color-diff-removed-row-border: #634343;
--color-diff-removed-word-bg: #703434;
--color-diff-inactive: color-mix(in srgb, var(--color-secondary) 59%, black);
--color-error-border: color-mix(in srgb, var(--color-error-text) 38%, var(--color-body));
--color-error-bg: color-mix(in srgb, var(--color-error-text) 13%, var(--color-body));
--color-error-bg-active: color-mix(in srgb, var(--color-error-text) 23%, var(--color-body));
--color-error-bg-hover: color-mix(in srgb, var(--color-error-text) 18%, var(--color-body));
--color-error-text: #f85149;
--color-success-border: color-mix(in srgb, var(--color-success-text) 38%, var(--color-body));
--color-success-bg: color-mix(in srgb, var(--color-success-text) 13%, var(--color-body));
--color-success-text: #3fb950;
--color-warning-border: color-mix(in srgb, var(--color-warning-text) 38%, var(--color-body));
--color-warning-bg: color-mix(in srgb, var(--color-warning-text) 13%, var(--color-body));
--color-warning-text: #d29922;
--color-info-border: color-mix(in srgb, var(--color-info-text) 38%, var(--color-body));
--color-info-bg: color-mix(in srgb, var(--color-info-text) 13%, var(--color-body));
--color-info-text: #2f81f7;
--color-priority-border: #4a268d;
--color-priority-bg: #251c39;
--color-priority-text: #a371f7;
--color-red-badge: #db2828;
--color-red-badge-bg: color-mix(in srgb, var(--color-red-badge) 10%, transparent);
--color-red-badge-hover-bg: color-mix(in srgb, var(--color-red-badge) 30%, transparent);
--color-green-badge: #21ba45;
--color-green-badge-bg: color-mix(in srgb, var(--color-green-badge) 10%, transparent);
--color-green-badge-hover-bg: color-mix(in srgb, var(--color-green-badge) 30%, transparent);
--color-yellow-badge: #fbbd08;
--color-yellow-badge-bg: color-mix(in srgb, var(--color-yellow-badge) 10%, transparent);
--color-yellow-badge-hover-bg: color-mix(in srgb, var(--color-yellow-badge) 30%, transparent);
--color-orange-badge: #f2711c;
--color-orange-badge-bg: color-mix(in srgb, var(--color-orange-badge) 10%, transparent);
--color-orange-badge-hover-bg: color-mix(in srgb, var(--color-orange-badge) 30%, transparent);
--color-git: #f05133;
--color-logo: #609926;
/* target-based colors */
--color-body: #1e1f20;
--color-box-header: color-mix(in srgb, var(--color-secondary) 42%, black);
--color-box-body: color-mix(in srgb, var(--color-body) 74%, black);
--color-box-body-highlight: color-mix(in srgb, var(--color-primary) 2%, var(--color-body));
--color-text-dark: #f8f8f8;
--color-text: color-mix(in srgb, var(--color-text-dark) 80%, var(--color-secondary));
--color-text-light: color-mix(in srgb, var(--color-text-dark) 71%, var(--color-secondary));
--color-text-light-1: color-mix(in srgb, var(--color-text-dark) 59%, var(--color-secondary));
--color-text-light-2: color-mix(in srgb, var(--color-text-dark) 48%, var(--color-secondary));
--color-text-light-3: color-mix(in srgb, var(--color-text-dark) 37%, var(--color-secondary));
--color-footer: var(--color-nav-bg);
--color-timeline: color-mix(in srgb, var(--color-secondary) 89%, black);
--color-input-text: var(--color-text-dark);
--color-input-background: color-mix(in srgb, var(--color-secondary) 39%, black);
--color-input-toggle-background: color-mix(in srgb, var(--color-secondary) 78%, black);
--color-input-border: var(--color-secondary-dark-1);
--color-light: #0b0b0c28;
--color-light-border: #f3f3f428;
--color-hover: #f3f3f419;
--color-hover-opaque: color-mix(in srgb, var(--color-secondary) 56%, black);
--color-active: #f3f3f424;
--color-menu: color-mix(in srgb, var(--color-secondary) 39%, black);
--color-card: color-mix(in srgb, var(--color-secondary) 39%, black);
--color-markup-table-row: #f3f3f40f;
--color-markup-code-block: #f3f3f412;
--color-markup-code-inline: #f3f3f428;
--color-button: color-mix(in srgb, var(--color-secondary) 39%, black);
--color-code-bg: color-mix(in srgb, var(--color-body) 74%, black);
--color-shadow: #0b0b0c58;
--color-secondary-bg: color-mix(in srgb, var(--color-secondary) 72%, black);
--color-expand-button: color-mix(in srgb, var(--color-secondary) 80%, black);
--color-placeholder-text: var(--color-text-light-3);
--color-editor-line-highlight: var(--color-secondary-alpha-40);
--color-editor-selection: var(--color-primary-alpha-50);
--color-project-column-bg: var(--color-secondary-light-2);
--color-caret: var(--color-text); /* should ideally be --color-text-dark, see #15651 */
--color-reaction-bg: #f3f3f412;
--color-reaction-hover-bg: var(--color-primary-light-4);
--color-reaction-active-bg: var(--color-primary-light-5);
--color-tooltip-text: #fafafa;
--color-tooltip-bg: color-mix(in srgb, var(--color-secondary) 70%, black);
--color-nav-bg: color-mix(in srgb, var(--color-secondary) 38%, black);
--color-nav-hover-bg: var(--color-secondary-light-1);
--color-nav-text: var(--color-text);
--color-secondary-nav-bg: color-mix(in srgb, var(--color-secondary) 41%, black);
--color-label-text: var(--color-text);
--color-label-bg: color-mix(in srgb, var(--color-label-active-bg) 30%, transparent);
--color-label-hover-bg: color-mix(in srgb, var(--color-label-active-bg) 63%, transparent);
--color-label-active-bg: #7a7f8aff;
--color-accent: var(--color-primary-light-1);
--color-small-accent: var(--color-primary-light-5);
--color-highlight-fg: #87651e;
--color-highlight-bg: #443a27;
--color-overlay-backdrop: #080808c0;
--color-danger: var(--color-red);
--color-transparency-grid-light: #2a2a2a;
--color-transparency-grid-dark: #1a1a1a;
--color-syntax-keyword: #ff8854;
--color-syntax-bool: #25bbc9;
--color-syntax-control: #dd9e17;
--color-syntax-name: #fabd2f;
--color-syntax-type: #eb8cb3;
--color-syntax-number: #63b2dd;
--color-syntax-operator: #ff8854;
--color-syntax-regexp: #b89de4;
--color-syntax-string: #95b62a;
--color-syntax-comment: #8898b0;
--color-syntax-invalid: #ff8686;
--color-syntax-link: var(--color-primary);
--color-syntax-tag: #ff8854;
--color-syntax-attribute: #c792ff;
--color-syntax-property: #55afff;
--color-syntax-variable: #e29b33;
--color-syntax-string-special: #dd9e17;
--color-syntax-escape: #c7a618;
--color-syntax-entity: #c792ff;
--color-syntax-preproc: #4cbe7a;
--color-syntax-preproc-file: #63b2dd;
--color-syntax-decorator: #4cbe7a;
--color-syntax-namespace: #c9d1d9;
--color-syntax-name-pseudo: #c792ff;
--color-syntax-comment-special: #b89de4;
--color-syntax-text: #c9d1d9;
--color-syntax-text-alt: color-mix(in srgb, var(--color-syntax-whitespace) 55%, white);
--color-syntax-punctuation: color-mix(in srgb, var(--color-syntax-whitespace) 35%, white);
--color-syntax-whitespace: #7f8699;
--color-syntax-diff-fg: #ffffff;
--color-syntax-deleted-bg: #5f3737;
--color-syntax-inserted-bg: #3a523a;
--color-syntax-emph: #d1a242;
--color-syntax-strong: #e29b33;
--color-syntax-heading: #dd9e17;
--color-syntax-subheading: #95b62a;
--color-syntax-output: #8898b0;
--color-syntax-prompt: #e29b33;
--color-syntax-traceback: #ff8686;
--color-syntax-matching-bracket-bg: color-mix(in srgb, var(--color-teal) 28%, transparent);
--color-syntax-nonmatching-bracket-bg: color-mix(in srgb, var(--color-red) 28%, transparent);
accent-color: var(--color-accent);
color-scheme: dark;
}
/* invert emojis that are hard to read otherwise */
.emoji[data-alias="heavy_check_mark"],
.emoji[data-alias="currency_exchange"],
.emoji[data-alias="top"],
.emoji[data-alias="end"],
.emoji[data-alias="on"],
.emoji[data-alias="soon"],
.emoji[data-alias="heavy_dollar_sign"],
.emoji[data-alias="copyright"],
.emoji[data-alias="registered"],
.emoji[data-alias="tm"],
.emoji[data-alias="heavy_multiplication_x"],
.emoji[data-alias="heavy_plus_sign"],
.emoji[data-alias="heavy_minus_sign"],
.emoji[data-alias="heavy_division_sign"],
.emoji[data-alias="curly_loop"],
.emoji[data-alias="loop"],
.emoji[data-alias="wavy_dash"],
.emoji[data-alias="feet"],
.emoji[data-alias="musical_note"],
.emoji[data-alias="notes"] {
filter: invert(100%) hue-rotate(180deg);
}