> ## Documentation Index
> Fetch the complete documentation index at: https://openidea.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Themes

> Write a colour theme plugin: the theme and editor scheme files, how themes are applied, importing IntelliJ themes, porting VS Code themes, and the full token reference.

OpenIDEA ships seven built-in themes: Islands Light, Islands Dark, High Contrast,
Solarized Light, Solarized Dark, One Light and One Dark. Other themes come from **theme
plugins**.

A theme plugin is data only. Like an IntelliJ theme (a `.theme.json` plus an optional
`.icls` editor scheme), it has no code: no WebAssembly, nothing to compile, no
capabilities.

```text theme={null}
my-theme/
├─ plugin.toml                    # manifest
└─ themes/
   ├─ my-theme.theme.json         # UI colours (IntelliJ: .theme.json)
   └─ my-theme.scheme.json        # editor colours, optional (IntelliJ: .icls)
```

The quickest start is `openidea-plugin new my-theme --template theme`, which copies
[Harbor Night](https://github.com/l0ng-ai/openidea/tree/main/plugins/official/harbor-night),
a complete dark theme that sets every themeable token.

## The manifest

```toml theme={null}
id = "acme.harbor-night"
name = "Harbor Night"
version = "1.0.0"
description = "A dark theme: slate surfaces, a teal accent and a warm syntax palette."
authors = ["You <you@example.com>"]
license = "MIT"
engines.openidea = "^1.0"
categories = ["themes"]

[[contributes.themes]]             # one entry per theme; a plugin may ship several
path = "themes/harbor-night.theme.json"
editor-scheme = "themes/harbor-night.scheme.json"   # optional
```

There is no `wasm` and no `[capabilities]`. Paths are relative to the package directory
and may not leave it. The other manifest fields are on [Manifest](https://openidea.sh/en/plugins/manifest.md).

## The theme file

```jsonc theme={null}
{
  "id": "harbor-night", // unique within the plugin
  "name": "Harbor Night", // shown in Settings
  "kind": "dark", // "dark" or "light": the built-in base
  "tokens": {
    "--bg-app": "#14171c",
    "--accent": "#2b9e93",
  },
}
```

* **`tokens`** are the CSS variables of
  [`src/styles/tokens.css`](https://github.com/l0ng-ai/openidea/blob/main/src/styles/tokens.css),
  the IDE's single source of colours. Components never use colour literals, so every
  surface, border, text colour, syntax colour and status colour can be themed. The
  [reference](#token-reference) lists them all.
* **`kind`** picks the built-in base. While the theme is active the IDE runs on Islands Dark
  or Islands Light, and every token the theme leaves out keeps that base's value. Icons use
  the light or dark set that matches the kind. A partial theme still looks consistent, but
  listing every token keeps it stable when the IDE's own palette changes.
* Token names are `--` followed by lowercase letters, digits and `-` (at most 64 bytes).
* Values are plain CSS values: hex (`#rgb`, `#rrggbb`, `#rrggbbaa`), `rgb()`, `hsl()`,
  `color-mix()`, `var(--other-token)`, or for the few non-colour tokens a keyword
  (`italic`, `normal`, `none`) or a shadow list. `url()`, `image()`, `;`, braces, `<`, `>`,
  `\` and line breaks are rejected.
* `//` and `/* */` comments are allowed, as in VS Code theme files.
* Tokens that tokens.css derives from others (for example `--bg-editor` is
  `var(--bg-island)`, and the coverage and flame graph colours are mixed from the status
  colours) follow automatically. You may still set them.
* Metrics (`--fs-*`, `--h-*`, `--radius-*`) and fonts (`--font-ui`, `--font-mono`) can be
  overridden too, but a theme normally leaves them alone so that compact mode and the user's
  font settings keep working.

### The editor colour scheme file

```jsonc theme={null}
{
  "name": "Harbor Night",
  "tokens": { "--syn-keyword": "#e0a46e", "--caret": "#5ce0d2" },
}
```

Its tokens are merged over the theme's, and the scheme wins where both set a token. By
convention it holds the *Syntax*, *Editor* and *ANSI palette* groups of the reference, the
parts IntelliJ keeps in an `.icls` file. The split only organises the files: a theme can
put everything in its theme file.

## How a theme is applied

The selected theme is injected as one stylesheet on `:root` that outranks the built-in
theme blocks, and `data-theme` is switched to the theme's `kind`. Three things still layer on
top of it:

* an **Accent colour** picked in **Settings › Appearance & Behavior › Appearance** (other
  than the default),
* an explicit scheme or attribute overrides in **Settings › Editor › Color Scheme**,
* the appearance options that change only metrics (compact mode).

The selection is remembered. When the plugin is disabled or uninstalled, the built-in theme
returns.

Stripe tooltips use `--bg-stripe-tooltip`, `--fg-stripe-tooltip`, `--border-stripe-tooltip`
and `--shadow-stripe-tooltip`. A theme that omits them inherits the corresponding base
tooltip tokens.

## Install, apply and iterate

There is no build step: the package is the folder.

**1. Start from the template**

Run `openidea-plugin new my-theme --template theme` (or copy `plugins/official/harbor-night`) and rename `id`,
`name` and the theme files.

**2. Edit the colours**

Keep `kind` truthful (`light` for light backgrounds).

**3. Install**

In **Settings › Plugins**, open the gear menu and choose **Install Plugin from Disk…** (also an action in Find
Action) and pick the package folder, or **Install Plugin from Package File…** and pick its `plugin.toml` or a `.zip`
of the folder.

**4. Apply**

In **Settings › Plugins**, select the plugin and press **Apply** next to the theme. **Use Default Theme** switches
back. Plugin themes are also listed under **Theme** in **Settings › Appearance & Behavior › Appearance**.

To iterate without reinstalling, link the folder with `openidea-plugin link` (it is read in
place), or put or symlink it in `<project>/.openidea/plugins/<name>/` of a trusted project.
Then press **Reload** on the plugin, or run the **Reload Plugins** action, to pick up your
edits. If a file or value is invalid, **Settings › Plugins** shows the load error with the
file and line.

To share a theme, publish it like any plugin; see [Packaging](https://openidea.sh/en/plugins/publishing/packaging.md).

## Importing IntelliJ themes

To use a theme you already have in a JetBrains IDE, open the gear menu in **Settings ›
Plugins** (a project must be open):

* **Import Theme from JetBrains IDE…** lists the theme plugins installed in the JetBrains IDEs
  (and Android Studio) on this computer, one row per plugin of each IDE, with the plugins of
  the themes the IDEs use first. It reads the settings folder of each IDE's newest version:
  `~/Library/Application Support/JetBrains` (macOS), `%APPDATA%\JetBrains` (Windows),
  `~/.config/JetBrains` and `~/.local/share/JetBrains` (Linux).
* **Import IntelliJ Theme from File…** takes a theme plugin downloaded from the JetBrains
  Marketplace (`.jar`, or a `.zip` with the plugin's `lib/*.jar`) or a `.theme.json` (its
  `editorScheme` file is read from the same folder).

The whole plugin becomes one OpenIDEA theme plugin, `intellij.<plugin id>`, with each of its
themes and their editor schemes. It is installed through the usual install page, and the
theme in use doesn't change: choose one of its themes under **Theme** in **Settings ›
Appearance & Behavior › Appearance**. Importing the plugin again replaces it. Both commands
are also actions (`plugins.importInstalledIntellijTheme`, `plugins.importIntellijTheme`).

### Porting an IntelliJ theme for publishing

Only port themes whose licence allows redistribution, keep their licence file, and credit
the original authors in `authors` and `description`.

`scripts/theme/import-intellij-theme.ts` in the repository converts an IntelliJ
`.theme.json`, and optionally its `.icls` editor scheme, into a plugin folder you can edit
before publishing. It needs only Node 22.

```sh theme={null}
pnpm theme:import-intellij path/to/MyTheme.theme.json path/to/MyTheme.icls --out ~/my-theme --author "Original Author"
# or: node scripts/theme/import-intellij-theme.ts …
```

It maps the keys in the tables below, resolves named colours from the theme's `colors`
section and `*` wildcards, and takes `kind` from `"dark"` (or the `.icls` `parent_scheme`).
Tokens without an IntelliJ counterpart keep the built-in values for that kind. Themes that
ship only a `.theme.json` with an `editorScheme` path need that `.icls` passed as the second
argument; themes that ship no `.icls` keep the built-in syntax colours.

#### `.theme.json` to UI theme

| OpenIDEA token | IntelliJ `ui` key (first present wins) |
| - | - |
| `--bg-app` | `Panel.background` |
| `--bg-frame` | `MainWindow.background`, `MainToolbar.background` |
| `--bg-island`, `--bg-elev` | `ToolWindow.background` |
| `--bg-popup` | `Popup.background`, `PopupMenu.background` |
| `--bg-hover` | `List.hoverBackground`, `Tree.hoverBackground` |
| `--bg-selected`, `--bg-tree-selected` | `List.selectionBackground`, `Tree.selectionBackground` |
| `--bg-tree-selected-inactive` | `Tree.selectionInactiveBackground` |
| `--bg-input`, `--bg-field` | `TextField.background` |
| `--border` | `Borders.color` |
| `--border-strong`, `--border-window` | `Component.borderColor`, `Borders.ContrastBorderColor` |
| `--fg`, `--fg-emphasis` | `Label.foreground` |
| `--fg-secondary`, `--fg-muted` | `Label.infoForeground`, `Component.infoForeground` |
| `--fg-subtle`, `--fg-faint` | `Label.disabledForeground` |
| `--accent` | `Button.default.startBackground`, `Component.focusColor` |
| `--fg-on-accent`, `--fg-button-primary` | `Button.default.foreground` |
| `--link`, `--link-hover` | `Link.activeForeground`, `Link.hoverForeground` |
| `--danger`, `--warning` | `Component.errorFocusColor`, `Component.warningFocusColor` |
| `--bg-tooltip`, `--fg-tooltip`, `--border-tooltip` | `ToolTip.background`, `.foreground`, `.borderColor` |
| `--bg-button`, `--border-button` | `Button.startBackground`, `Button.startBorderColor` |
| `--bg-tab-selected` | `EditorTabs.underlinedTabBackground` |
| `--border-tab-selected` | `EditorTabs.underlinedBorderColor` (Islands), `EditorTabs.underlineColor` |
| `--fg-completion-match` | `CompletionPopup.matchForeground` |
| `--bg-toolbar-hover`, `--bg-toolbar-pressed` | `ActionButton.hoverBackground`, `ActionButton.pressedBackground` |
| `--bg-stripe-hover`, `--bg-stripe-selected` | `ToolWindow.Button.hoverBackground`, `.selectedBackground` |
| `--scrollbar-thumb`, `--scrollbar-thumb-hover` | `ScrollBar.Mac.thumbColor`, `ScrollBar.Mac.hoverThumbColor` |
| `--bg-toggle-*` | `ToggleButton.onBackground`, `.offBackground`, `.buttonColor` |
| `--bg-feedback-*`, `--border-feedback-*` | `Banner.infoBackground`, `Banner.errorBorderColor`, … |

The full table is `UI_KEYS` in
[`src/features/plugins/intellijTheme.ts`](https://github.com/l0ng-ai/openidea/blob/main/src/features/plugins/intellijTheme.ts).

#### `.icls` to editor scheme

| OpenIDEA token | `.icls` option |
| - | - |
| `--fg-editor`, `--bg-editor` | attribute `TEXT` (foreground, background) |
| `--caret`, `--bg-current-line` | colour `CARET_COLOR`, `CARET_ROW_COLOR` |
| `--bg-editor-selection`, `--fg-editor-selection` | colour `SELECTION_BACKGROUND`, `SELECTION_FOREGROUND` |
| `--fg-line-number`, `--fg-line-number-current` | colour `LINE_NUMBERS_COLOR`, `LINE_NUMBER_ON_CARET_ROW_COLOR` |
| `--bg-editor-gutter` | colour `EDITOR_GUTTER_BACKGROUND`, else the editor background (as the new UI paints it; `GUTTER_BACKGROUND` is the classic UI's) |
| `--border-indent-guide`, `--border-right-margin`, `--fg-whitespace` | colour `INDENT_GUIDE`, `RIGHT_MARGIN_COLOR`, `WHITESPACES` |
| `--vcs-*`, `--gutter-*` | colour `FILESTATUS_*`, `MODIFIED_LINES_COLOR`, `ADDED_LINES_COLOR`, `DELETED_LINES_COLOR` |
| `--syn-keyword`, `--syn-string`, `--syn-number` | `DEFAULT_KEYWORD`, `DEFAULT_STRING`, `DEFAULT_NUMBER` |
| `--syn-comment` (+ `--syn-comment-style`), `--syn-doc-comment` | `DEFAULT_LINE_COMMENT` (+ `FONT_TYPE`), `DEFAULT_DOC_COMMENT` |
| `--syn-doc-comment-tag`, `--syn-doc-comment-tag-value`, `--syn-doc-markup` (+ `-bg`) | `DEFAULT_DOC_COMMENT_TAG`, `DEFAULT_DOC_COMMENT_TAG_VALUE`, `DEFAULT_DOC_MARKUP` |
| `--syn-function`, `--syn-function-call` | `DEFAULT_FUNCTION_DECLARATION`, `DEFAULT_FUNCTION_CALL` |
| `--syn-type`, `--syn-constant`, `--syn-property` | `DEFAULT_CLASS_NAME`, `DEFAULT_CONSTANT`, `DEFAULT_INSTANCE_FIELD` |
| `--syn-variable`, `--syn-param`, `--syn-builtin` | `DEFAULT_LOCAL_VARIABLE`, `DEFAULT_PARAMETER`, `DEFAULT_PREDEFINED_SYMBOL` |
| `--syn-annotation`, `--syn-decorator` | `DEFAULT_METADATA` |
| `--syn-punct`, `--syn-escape` | `DEFAULT_OPERATION_SIGN`, `DEFAULT_VALID_STRING_ESCAPE` |
| `--syn-tag`, `--syn-attribute`, `--syn-todo`, `--syn-invalid` | `DEFAULT_TAG`, `DEFAULT_ATTRIBUTE`, `TODO_DEFAULT_ATTRIBUTES`, `BAD_CHARACTER` |
| `--syn-rainbow-1` … `--syn-rainbow-5` (Semantic highlighting) | `RAINBOW_COLOR1` … `RAINBOW_COLOR5` |
| `--wave-error`, `--wave-warning` | `ERRORS_ATTRIBUTES`, `WARNING_ATTRIBUTES` (effect colour) |
| `--bg-matched-brace`, `--bg-identifier-under-caret` | `MATCHED_BRACE_ATTRIBUTES`, `IDENTIFIER_UNDER_CARET_ATTRIBUTES` |
| `--bg-text-search-result`, `--bg-search-match` | `TEXT_SEARCH_RESULT_ATTRIBUTES`, `SEARCH_RESULT_ATTRIBUTES` |
| `--syn-self`, `--syn-keyword-arg`, `--syn-docstring`, `--syn-predefined` | `PY.SELF_PARAMETER`, `PY.KEYWORD_ARGUMENT`, `PY.DOC_COMMENT`, `PY.BUILTIN_NAME` |
| `--ansi-*` | `CONSOLE_*_OUTPUT` (`CONSOLE_DARKGRAY_OUTPUT` is bright black, `CONSOLE_GRAY_OUTPUT` white) |

The full tables are `ICLS_COLORS` and `ICLS_ATTRIBUTES` in the same file. An attribute
written as `<value />` has no colours of its own and shows as plain text (`TEXT`'s
foreground), as in IntelliJ, not with the parent scheme's colour.

## Porting a VS Code theme

A VS Code theme (`themes/*.json` in the extension) has `type` (`dark` / `light` / `hc`),
`colors` (workbench) and `tokenColors` (TextMate scopes). Set `kind` from `type`, then map
by hand:

| OpenIDEA token | VS Code `colors` key |
| - | - |
| `--bg-frame` | `titleBar.activeBackground`, `activityBar.background` |
| `--bg-island`, `--bg-app` | `editor.background`, `sideBar.background` |
| `--bg-elev` | `sideBarSectionHeader.background`, `editorGroupHeader.tabsBackground` |
| `--bg-popup`, `--border-popup` | `editorWidget.background`, `editorWidget.border` |
| `--bg-hover` | `list.hoverBackground` |
| `--bg-selected`, `--bg-tree-selected` | `list.activeSelectionBackground` |
| `--bg-tree-selected-inactive` | `list.inactiveSelectionBackground` |
| `--border` | `panel.border`, `sideBar.border` |
| `--fg` | `foreground`, `sideBar.foreground` |
| `--fg-muted`, `--fg-subtle` | `descriptionForeground`, `disabledForeground` |
| `--accent`, `--fg-on-accent` | `button.background`, `button.foreground` |
| `--focus-ring-soft` | `focusBorder` |
| `--link` | `textLink.foreground` |
| `--bg-input`, `--bg-field` | `input.background` |
| `--bg-tab-selected`, `--border-tab-selected` | `tab.activeBackground`, `tab.activeBorderTop` |
| `--scrollbar-thumb`, `--scrollbar-thumb-hover` | `scrollbarSlider.background`, `scrollbarSlider.hoverBackground` |
| `--danger`, `--warning`, `--info` | `errorForeground`, `editorWarning.foreground`, `editorInfo.foreground` |
| `--vcs-modified`, `--vcs-added`, `--vcs-deleted`, `--vcs-untracked`, `--vcs-ignored`, `--vcs-conflict` | `gitDecoration.modifiedResourceForeground`, `.addedResourceForeground`, `.deletedResourceForeground`, `.untrackedResourceForeground`, `.ignoredResourceForeground`, `.conflictingResourceForeground` |
| `--fg-editor` | `editor.foreground` |
| `--caret` | `editorCursor.foreground` |
| `--bg-current-line` | `editor.lineHighlightBackground` |
| `--bg-editor-selection`, `--bg-editor-selection-inactive`, `--fg-editor-selection` | `editor.selectionBackground`, `editor.inactiveSelectionBackground`, `editor.selectionForeground` |
| `--fg-line-number`, `--fg-line-number-current` | `editorLineNumber.foreground`, `editorLineNumber.activeForeground` |
| `--border-indent-guide`, `--border-indent-guide-active` | `editorIndentGuide.background1`, `editorIndentGuide.activeBackground1` |
| `--fg-whitespace` | `editorWhitespace.foreground` |
| `--bg-text-search-result`, `--bg-text-search-result-current` | `editor.findMatchHighlightBackground`, `editor.findMatchBackground` |
| `--bg-matched-brace` | `editorBracketMatch.background` |
| `--syn-bracket-1` … `--syn-bracket-3` (Rainbow brackets) | `editorBracketHighlight.foreground1` … `foreground3` |
| `--bg-identifier-under-caret`, `-write` | `editor.wordHighlightBackground`, `editor.wordHighlightStrongBackground` |
| `--wave-error`, `--wave-warning` | `editorError.foreground`, `editorWarning.foreground` |
| `--gutter-modified`, `--gutter-added`, `--gutter-deleted` | `editorGutter.modifiedBackground`, `.addedBackground`, `.deletedBackground` |
| `--fg-inlay`, `--bg-inlay` | `editorInlayHint.foreground`, `editorInlayHint.background` |
| `--ansi-*` | `terminal.ansiBlack` … `terminal.ansiBrightWhite` |

`tokenColors` to syntax tokens, by TextMate scope:

| OpenIDEA token | Scope |
| - | - |
| `--syn-keyword` | `keyword`, `storage.type`, `storage.modifier` |
| `--syn-string` | `string` |
| `--syn-escape` | `constant.character.escape` |
| `--syn-number` | `constant.numeric` |
| `--syn-constant` | `constant.language`, `variable.other.constant` |
| `--syn-comment`, `--syn-doc-comment` | `comment`, `comment.block.documentation` |
| `--syn-function`, `--syn-function-call` | `entity.name.function`, `meta.function-call` |
| `--syn-type` | `entity.name.type`, `entity.name.class`, `support.class` |
| `--syn-variable`, `--syn-param` | `variable`, `variable.parameter` |
| `--syn-property` | `variable.other.property`, `variable.other.member` |
| `--syn-builtin`, `--syn-predefined` | `support.function`, `support.variable` |
| `--syn-self` | `variable.language.self`, `variable.language.this` |
| `--syn-annotation`, `--syn-decorator` | `meta.decorator`, `storage.type.annotation` |
| `--syn-punct` | `punctuation`, `keyword.operator` |
| `--syn-tag`, `--syn-attribute` | `entity.name.tag`, `entity.other.attribute-name` |
| `--syn-regexp` | `string.regexp` |
| `--syn-markup-heading`, `--syn-markup-code`, `--syn-link` | `markup.heading`, `markup.inline.raw`, `markup.underline.link` |
| `--syn-invalid` | `invalid` |

A `fontStyle: "italic"` on comments maps to `"--syn-comment-style": "italic"`.

## Testing a theme

* Install it (or link it), apply it, and walk through: the Project tool window with a
  selection, the editor with a few languages, Search Everywhere, a popup menu, a tooltip,
  Settings, the terminal (`ls --color`), a diff, and the VCS colours in the Commit tool
  window.
* Text should keep at least WCAG AA contrast (4.5:1) on its surfaces. The built-in themes
  are checked by `src/features/settings/__tests__/contrast.test.ts`.
* For changes to the repository's own template: `pnpm vitest run scripts/theme` validates
  the template against tokens.css and keeps the token reference current, and
  `cargo test -p ide-plugin` loads the template through the plugin host.

## Token reference

The values of the two base themes, generated from `src/styles/tokens.css` (`pnpm
gen:theme-docs` regenerates the copy in `plugins/themes.md`). Groups marked *UI theme*
conventionally go in the theme file, groups marked *editor scheme* in the scheme file.

256 themeable tokens: 125 in the UI theme file, 131 in the editor colour scheme file.

### Surfaces (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--bg-app` | `#191a1c` | `#ffffff` |
| `--bg-elev` | `#212326` | `#f7f8f9` |
| `--bg-popup` | `#26282c` | `#ffffff` |
| `--bg-floating-toolbar` | `#33353b` | `#ffffff` |
| `--bg-hover` | `#2e2f30` | `#ededed` |
| `--bg-selected` | `#2a4371` | `#d0dffe` |
| `--bg-selected-strong` | `#2e4d89` | `#bdd3ff` |
| `--bg-current-line` | `#1f2024` | `#f5f8fe` |
| `--bg-debug-line` | `#2a5091` | `#d4e2ff` |
| `--bg-backdrop` | `#26282c` | `#e9eaee` |
| `--bg-input` | `#191a1c` | `#ffffff` |

### Lines (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--border` | `#26282c` | `#e9eaee` |
| `--border-popup` | `#33353b` | `#d1d3d9` |
| `--border-strong` | `#40434a` | `#d1d3d9` |
| `--border-window` | `#40434a` | `#d1d3d9` |
| `--control-off` | `#5f6269` | `#c3c5cb` |

### Text (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--fg-strong` | `#dfe1e5` | `#000000` |
| `--fg-emphasis` | `#d1d3d9` | `#000000` |
| `--fg` | `#d1d3d9` | `#000000` |
| `--fg-secondary` | `#9fa2a8` | `#5f6269` |
| `--fg-muted` | `#8c8f95` | `#6c707e` |
| `--fg-subtle` | `#73767c` | `#73767c` |
| `--fg-faint` | `#5f6269` | `#9fa2a8` |
| `--fg-gutter` | `#4b5059` | `#aeb3c2` |
| `--fg-icon` | `#ced0d6` | `#6c707e` |

### Accent (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--accent` | `#3871e1` | `#3871e1` |
| `--link` | `#71a1fe` | `#2f5eb9` |
| `--link-hover` | `#92b7ff` | `#2e4d89` |

### Charts (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--chart-series` | `#e07a7c` | `#d9686a` |

### Status (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--danger` | `#f57e84` | `#c54e58` |
| `--warning` | `#d59637` | `#a56906` |
| `--success` | `#6db083` | `#338555` |
| `--db-connected` | `#2fe02f` | `#00ff00` |
| `--db-connected-ring` | `#1d6b1d` | `#5b995b` |
| `--info` | `#548af7` | `#3871e1` |

### Vcs (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--vcs-modified` | `#70aeff` | `#0033b3` |
| `--vcs-added` | `#73bd79` | `#067d17` |
| `--vcs-deleted` | `#6f737a` | `#6c707e` |
| `--vcs-untracked` | `#e88f89` | `#b23247` |
| `--vcs-ignored` | `#d69a6b` | `#8c4f00` |
| `--vcs-conflict` | `#de6a66` | `#de1b2e` |
| `--gutter-modified` | `#375fad` | `#88adf7` |
| `--gutter-added` | `#549159` | `#7fc784` |
| `--gutter-deleted` | `#868a91` | `#767a8a` |
| `--diff-modified` | `#385570` | `#c2d8f2` |
| `--diff-inserted` | `#294436` | `#bee6be` |
| `--diff-deleted` | `#484a4a` | `#d6d6d6` |
| `--diff-modified-stripe` | `#43698d` | `#b6d2f2` |
| `--diff-inserted-stripe` | `#447152` | `#aadeaa` |
| `--diff-deleted-stripe` | `#656e76` | `#c8c8c8` |
| `--diff-conflict-stripe` | `#8f5247` | `#ffc8bd` |

### Syntax (editor scheme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--syn-keyword` | `#cf8e6d` | `#0033b3` |
| `--syn-string` | `#6aab73` | `#067d17` |
| `--syn-type` | `#bcbec4` | `#000000` |
| `--syn-function` | `#56a8f5` | `#00627a` |
| `--syn-function-call` | `#bcbec4` | `#080808` |
| `--syn-comment` | `#7a7e85` | `#8c8c8c` |
| `--syn-comment-style` | `normal` | `italic` |
| `--syn-doc-comment` | `#5f826b` | `#8c8c8c` |
| `--syn-doc-comment-tag` | `#67a37c` | `#8c8c8c` |
| `--syn-doc-comment-tag-effect` | `none` | `underline #999999` |
| `--syn-doc-comment-tag-value` | `#abadb3` | `#3d3d3d` |
| `--syn-doc-markup` | `#68a67e` | `#8c8c8c` |
| `--syn-doc-markup-bg` | `transparent` | `#e2ffe2` |
| `--syn-docstring` | `#5f826b` | `#067d17` |
| `--syn-annotation` | `#b3ae60` | `#9e880d` |
| `--syn-decorator` | `#b3ae60` | `#9e880d` |
| `--syn-number` | `#2aacb8` | `#1750eb` |
| `--syn-punct` | `#bcbec4` | `#080808` |
| `--syn-variable` | `#bcbec4` | `#080808` |
| `--syn-global` | `var(--syn-variable)` | `var(--syn-variable)` |
| `--syn-namespace` | `var(--fg-editor)` | `var(--fg-editor)` |
| `--syn-param` | `#bcbec4` | `#080808` |
| `--syn-property` | `#c77dbb` | `#871094` |
| `--syn-constant` | `#c77dbb` | `#871094` |
| `--syn-python-local-variable` | `var(--syn-variable)` | `var(--syn-variable)` |
| `--syn-python-global-variable` | `var(--syn-global)` | `var(--syn-global)` |
| `--syn-python-instance-attribute` | `var(--syn-variable)` | `var(--syn-variable)` |
| `--syn-python-class-attribute` | `var(--syn-property)` | `var(--syn-property)` |
| `--syn-python-constant` | `var(--syn-constant)` | `var(--syn-constant)` |
| `--syn-python-property` | `var(--syn-property)` | `var(--syn-property)` |
| `--syn-python-type-parameter` | `var(--syn-type)` | `var(--syn-type)` |
| `--syn-python-builtin` | `var(--syn-builtin)` | `var(--syn-builtin)` |
| `--syn-python-predefined-definition` | `var(--syn-predefined)` | `var(--syn-predefined)` |
| `--syn-python-predefined-usage` | `var(--syn-predefined)` | `var(--syn-predefined)` |
| `--syn-python-fstring` | `#a5c261` | `var(--syn-string)` |
| `--syn-python-bytes` | `#a5c261` | `var(--syn-string)` |
| `--syn-python-docstring-tag` | `var(--syn-doc-comment-tag)` | `var(--syn-doc-comment-tag)` |
| `--syn-python-docstring-tag-effect` | `var(--syn-doc-comment-tag-effect)` | `var(--syn-doc-comment-tag-effect)` |
| `--syn-python-docstring-keyword` | `var(--syn-doc-comment-tag-value)` | `var(--syn-doc-comment-tag-value)` |
| `--syn-php-variable` | `var(--syn-property)` | `var(--syn-property)` |
| `--syn-php-function-call` | `var(--syn-function)` | `var(--syn-function)` |
| `--syn-builtin` | `#8888c6` | `#000080` |
| `--syn-self` | `#94558d` | `#94558d` |
| `--syn-keyword-arg` | `#aa4926` | `#660099` |
| `--syn-predefined` | `#b200b2` | `#b200b2` |
| `--syn-escape` | `#cf8e6d` | `#0037a6` |
| `--syn-regexp` | `#42c3d4` | `#264eff` |
| `--syn-tag` | `#d5b778` | `#0033b3` |
| `--syn-attribute` | `#bcbec4` | `#174ad4` |
| `--syn-todo` | `#8bb33d` | `#008dde` |
| `--syn-link` | `#548af7` | `#006dcc` |
| `--syn-markup-heading` | `#cf8e6d` | `#871094` |
| `--syn-markup-code` | `#6aab73` | `#067d17` |
| `--syn-invalid` | `#f75464` | `#f50000` |
| `--syn-inline-value` | `#868a91` | `#8c8c8c` |
| `--syn-rainbow-1` | `#6fafbd` | `#9b3b6a` |
| `--syn-rainbow-2` | `#d79b6e` | `#114d77` |
| `--syn-rainbow-3` | `#9fbf6b` | `#9c6a2c` |
| `--syn-rainbow-4` | `#c98bc6` | `#005910` |
| `--syn-rainbow-5` | `#8e9cf0` | `#bc5150` |
| `--syn-bracket-1` | `#e8c25b` | `#0431fa` |
| `--syn-bracket-2` | `#d78bd6` | `#319331` |
| `--syn-bracket-3` | `#4ea7f0` | `#7b3814` |

### Editor (editor scheme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--fg-editor` | `#bcbec4` | `#080808` |
| `--caret` | `#ced0d6` | `#000000` |
| `--fg-line-number` | `#4b5059` | `#aeb3c2` |
| `--fg-line-number-current` | `#a1a3ab` | `#767a8a` |
| `--border-gutter` | `#26282c` | `#ebecf0` |
| `--border-indent-guide` | `#323438` | `#ebecf0` |
| `--border-indent-guide-active` | `#4e5157` | `#aeb3c2` |
| `--border-right-margin` | `#323438` | `#ebecf0` |
| `--bg-editor-selection` | `#214283` | `#a6d2ff` |
| `--bg-editor-selection-inactive` | `#1d3460` | `#c9e3ff` |
| `--fg-editor-selection` | `inherit` | `inherit` |
| `--bg-text-search-result` | `#114957` | `#fcd47e` |
| `--bg-text-search-result-current` | `#165e70` | `#f2bf57` |
| `--bg-matched-brace` | `#43454a` | `#93d9d9` |
| `--matched-brace-weight` | `var(--fw-code-bold)` | `inherit` |
| `--bg-matched-tag` | `#3f4045` | `#c9ecec` |
| `--bg-fold-placeholder` | `#393b40` | `#e9f5e6` |
| `--fg-fold-placeholder` | `#868991` | `#414d41` |
| `--fg-fold-marker` | `#6f737a` | `#8b8e94` |
| `--fg-whitespace` | `#6f737a` | `#b5b7bd` |
| `--fg-unused` | `#6f737a` | `#8c8c8c` |
| `--bg-identifier-under-caret` | `#373b39` | `#edebfc` |
| `--bg-identifier-under-caret-write` | `#402f33` | `#fce8f4` |
| `--fg-inlay` | `#868a91` | `#73767c` |
| `--bg-inlay` | `#393b40` | `#00000012` |
| `--wave-error` | `#fa6675` | `#f50000` |
| `--wave-warning` | `#f2c55c` | `#f2bf57` |
| `--editor-error-decoration` | `underline wavy #fa6675` | `underline wavy #f50000` |
| `--editor-warning-decoration` | `underline wavy #f2c55c` | `none` |
| `--editor-warning-background` | `transparent` | `#fcf4d4` |
| `--bg-breakpoint-line` | `#40252b` | `#faeae6` |
| `--fg-completion-match` | `#538af9` | `#2f5eb9` |
| `--bg-editor-inline` | `#212326` | `#f7f8f9` |
| `--bg-editor-banner` | `#233558` | `#f7f8ff` |
| `--fg-weak-warning` | `#6f737a` | `#a8adbd` |
| `--fg-bulb` | `#f2c55c` | `#ffaf0f` |

### ANSI palette (editor scheme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--ansi-black` | `#000000` | `#000000` |
| `--ansi-red` | `#f0524f` | `#e5372a` |
| `--ansi-green` | `#5c962c` | `#367a29` |
| `--ansi-yellow` | `#a68a0d` | `#ad8d2b` |
| `--ansi-blue` | `#3993d4` | `#3866d1` |
| `--ansi-magenta` | `#a771bf` | `#a33cae` |
| `--ansi-cyan` | `#00a3a3` | `#3c8b8d` |
| `--ansi-white` | `#808080` | `#8b8e94` |
| `--ansi-bright-black` | `#595959` | `#73767c` |
| `--ansi-bright-red` | `#ff4050` | `#f05046` |
| `--ansi-bright-green` | `#4fc414` | `#2e9b3f` |
| `--ansi-bright-yellow` | `#e5bf00` | `#b58e00` |
| `--ansi-bright-blue` | `#1fb0ff` | `#3d82f0` |
| `--ansi-bright-magenta` | `#ed7eed` | `#c04bcf` |
| `--ansi-bright-cyan` | `#00e5e5` | `#1b9ea3` |
| `--ansi-bright-white` | `#ffffff` | `#5f6269` |

### Terminal ANSI palette (editor scheme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--terminal-ansi-black` | `#000000` | `#000000` |
| `--terminal-ansi-red` | `#f27481` | `#c93645` |
| `--terminal-ansi-green` | `#6bcc62` | `#357d1f` |
| `--terminal-ansi-yellow` | `#e0ce70` | `#b2a400` |
| `--terminal-ansi-blue` | `#5594fa` | `#225cd6` |
| `--terminal-ansi-magenta` | `#c092fa` | `#6e32e5` |
| `--terminal-ansi-cyan` | `#47ccbd` | `#007a80` |
| `--terminal-ansi-white` | `#ced0d6` | `#bec0c5` |
| `--terminal-ansi-bright-black` | `#4e5157` | `#6c707e` |
| `--terminal-ansi-bright-red` | `#ff6b7a` | `#ff5462` |
| `--terminal-ansi-bright-green` | `#67ff59` | `#3dcc3d` |
| `--terminal-ansi-bright-yellow` | `#ffec1a` | `#d4bb00` |
| `--terminal-ansi-bright-blue` | `#3399ff` | `#009dff` |
| `--terminal-ansi-bright-magenta` | `#d970ff` | `#d659ff` |
| `--terminal-ansi-bright-cyan` | `#40ffe9` | `#31c4b3` |
| `--terminal-ansi-bright-white` | `#ffffff` | `#d2d4d9` |

### Shadows and window controls (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--shadow-popup` | `0 6px 20px rgba(0, 0, 0, 0.45)` | `0 6px 20px rgba(0, 0, 0, 0.12)` |
| `--shadow-dialog` | `0 0 0 0.5px rgba(0, 0, 0, 0.6), 0 10px 24px rgba(0, 0, 0, 0.35), 0 24px 72px rgba(0, 0, 0, 0.45)` | `0 0 0 0.5px rgba(0, 0, 0, 0.1), 0 10px 24px rgba(0, 0, 0, 0.1), 0 24px 72px rgba(0, 0, 0, 0.2)` |
| `--traffic-close` | `#ff5f57` | `#ff5f57` |
| `--traffic-close-border` | `#e0443e` | `#e0443e` |
| `--traffic-close-pressed` | `#bf4942` | `#bf4942` |
| `--traffic-glyph` | `#4d0000` | `#4d0000` |
| `--traffic-off` | `#4b4c4f` | `#dddddd` |
| `--traffic-off-border` | `#404144` | `#c8c8c8` |

### Additive (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--bg-stripe-tooltip` | `var(--bg-tooltip)` | `#27282e` |
| `--fg-stripe-tooltip` | `var(--fg-tooltip)` | `#ffffff` |
| `--border-stripe-tooltip` | `var(--border-tooltip)` | `#383a42` |
| `--shadow-stripe-tooltip` | `var(--shadow-tooltip)` | `0 2px 8px rgba(0, 0, 0, 0.24)` |
| `--bg-tooltip` | `#33353b` | `#ffffff` |
| `--fg-tooltip` | `#d1d3d9` | `#000000` |
| `--border-tooltip` | `#33353b` | `#d1d3d9` |
| `--bg-control` | `#26282c` | `#ffffff` |
| `--bg-control-hover` | `#33353b` | `#f7f8f9` |
| `--bg-active` | `#40434a` | `#dddfe4` |
| `--bg-scrim` | `rgba(0, 0, 0, 0.45)` | `rgba(0, 0, 0, 0.16)` |
| `--fg-on-accent` | `#ffffff` | `#ffffff` |
| `--shadow-tooltip` | `0 4px 12px rgba(0, 0, 0, 0.4)` | `0 4px 12px rgba(0, 0, 0, 0.12)` |
| `--shadow-balloon` | `0 8px 24px rgba(0, 0, 0, 0.45)` | `0 8px 24px rgba(0, 0, 0, 0.14)` |

### Islands contract (UI theme)

| Token | Islands Dark | Islands Light |
| - | - | - |
| `--bg-frame` | `#26282c` | `#e9eaee` |
| `--bg-island` | `#191a1c` | `#ffffff` |
| `--bg-stripe-hover` | `#ffffff17` | `#00000012` |
| `--bg-stripe-selected` | `#ffffff29` | `#00000020` |
| `--fg-stripe-selected-active` | `#ffffff` | `#ffffff` |
| `--fg-stripe-label` | `#9fa2a8` | `#5f6269` |
| `--bg-tab-selected` | `#233558` | `#e3ebfe` |
| `--border-tab-selected` | `#2e4d89` | `#a7c5ff` |
| `--bg-tab-selected-inactive` | `#26282c` | `#e9eaee` |
| `--border-tab-selected-inactive` | `#40434a` | `#d1d3d9` |
| `--bg-tab-hover` | `#ffffff17` | `#00000012` |
| `--border-editor-tabs` | `#26282c` | `#e9eaee` |
| `--bg-tree-selected` | `#2a4371` | `#d0dffe` |
| `--bg-tree-selected-inactive` | `#33353b` | `#e9eaee` |
| `--bg-tree-hover` | `#ffffff10` | `#00000008` |
| `--bg-toolbar-hover` | `#ffffff17` | `#00000012` |
| `--bg-toolbar-pressed` | `#ffffff29` | `#00000020` |
| `--bg-toolbar-selected` | `#2e4d89` | `#d0dffe` |
| `--bg-toolbar-selected-hover` | `#2f5eb9` | `#bdd3ff` |
| `--bg-button-primary-hover` | `var(--accent-hover)` | `var(--accent-hover)` |
| `--fg-button-primary` | `#ffffff` | `#ffffff` |
| `--bg-button` | `transparent` | `#ffffff` |
| `--border-button` | `#40434a` | `#d1d3d9` |
| `--bg-field` | `#191a1c` | `#ffffff` |
| `--bg-checkbox` | `#191a1c` | `#ffffff` |
| `--border-checkbox` | `#5f6269` | `#a8adbd` |
| `--bg-toggle-on` | `#338555` | `#4e9d6c` |
| `--fg-toggle-on` | `#ffffff` | `#ffffff` |
| `--bg-toggle-off` | `#191a1c` | `#f7f8f9` |
| `--fg-toggle-off` | `#73767c` | `#73767c` |
| `--border-toggle` | `#5f6269` | `#c3c5cb` |
| `--bg-toggle-knob` | `#5f6269` | `#c3c5cb` |
| `--focus-ring-soft` | `#3d6185` | `#97c3f3` |
| `--scrollbar-thumb` | `#ffffff33` | `#00000033` |
| `--scrollbar-thumb-hover` | `#ffffff59` | `#00000080` |
| `--bg-search-match` | `#ba9752` | `#fee6b1` |
| `--bg-search-match-current` | `#f2c55c` | `#fcd47e` |
| `--fg-search-match` | `#191a1c` | `#000000` |
| `--bg-dialog` | `#191a1c` | `#f7f8f9` |
| `--bg-popup-inline` | `#26282c` | `#f7f8f9` |
| `--bg-popup-advertiser` | `#26282c` | `#f7f8f9` |
| `--bg-feedback-info` | `#233558` | `#f7f8ff` |
| `--border-feedback-info` | `#2e4d89` | `#bdd3ff` |
| `--bg-feedback-error` | `#56272b` | `#fff6f5` |
| `--border-feedback-error` | `#80383e` | `#ffc4c5` |
| `--bg-feedback-warning` | `#44321d` | `#fff6e9` |
| `--border-feedback-warning` | `#694820` | `#f4cd9a` |
| `--bg-feedback-success` | `#203b2a` | `#f5faf3` |
| `--border-feedback-success` | `#29583c` | `#bbdbc2` |
| `--bg-counter` | `#73767c` | `#8b8e94` |
| `--fg-counter` | `#000000` | `#ffffff` |
| `--bg-progress-track` | `#40434a` | `#dddfe4` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.