sai-assets可复用网页资产库 GitHub

Gruvbox · 暖灰底 + 米黄字(经典 / Material / Baby 十变体)

gruvbox-darkv2.0.0 主题 MIT

工具型暗色面板、终端风 UI、需要暖灰底 + 米黄字 + 橙强调,或需要 hard/medium/soft 与 material/baby 变体

不适用场景

纸媒社论风、明亮内容站(改用 ouuut-editorial)

新窗口 ↗
载入预览…

卡片与舞台里跑的是包内真实的预览页;WebGL 类需点“运行预览”才会建立渲染上下文。

元数据

类目
主题 · 配色与字体
版本
v2.0.0
许可
MIT
规模
33 文件 · 157 KB
来源项目
sai-assets · packs/gruvbox-dark/

标签

  • gruvbox
  • retro
  • warm-dark
  • terminal
  • multi-variant
  • dashboard

验证证据

2026-11-04 · python packs/gruvbox-dark/scripts/assert_tokens.py

PASS assert_tokens · themes=10 absolute=36 default=classic-dark-medium

归属与许可

  • morhetz/gruvbox · 来源 · MIT/X11
    经典原色板
  • sainnhe/gruvbox-material · 来源 · MIT
    material 强调色
  • luisiacc/gruvbox-baby · 来源 · MIT
    baby 参考

取用方式

固定版本(CDN)
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/nakamotosai/sai-assets@pack/gruvbox-dark@2.0.0/packs/gruvbox-dark/css/default.css">
raw 直取(跟随 main)
curl -O https://raw.githubusercontent.com/nakamotosai/sai-assets/main/packs/gruvbox-dark/SKILL.md
仓库内落地
python scripts/apply.py gruvbox-dark --to <项目目录>
整包下载
https://assets.ouuut.com/downloads/gruvbox-dark.zip

源码与规则

pack.json
{
  "schema": 1,
  "id": "gruvbox-dark",
  "title": "Gruvbox · 暖灰底 + 米黄字(经典 / Material / Baby 十变体)",
  "kind": "theme",
  "category": "themes",
  "version": "2.0.0",
  "license": "MIT",
  "attribution": [
    {
      "name": "morhetz/gruvbox",
      "url": "https://github.com/morhetz/gruvbox",
      "license": "MIT/X11",
      "what": "经典原色板"
    },
    {
      "name": "sainnhe/gruvbox-material",
      "url": "https://github.com/sainnhe/gruvbox-material",
      "license": "MIT",
      "what": "material 强调色"
    },
    {
      "name": "luisiacc/gruvbox-baby",
      "url": "https://github.com/luisiacc/gruvbox-baby",
      "license": "MIT",
      "what": "baby 参考"
    }
  ],
  "origin": {
    "project": "sai-assets",
    "path": "packs/gruvbox-dark/",
    "derived_from": "github.com/nakamotosai/gruvbox-theme"
  },
  "entry": "SKILL.md",
  "files": {
    "tokens": [
      "tokens/absolute.json",
      "tokens/index.json",
      "tokens/semantic/baby-dark-medium.json",
      "tokens/semantic/classic-dark-hard.json",
      "tokens/semantic/classic-dark-medium.json",
      "tokens/semantic/classic-dark-soft.json",
      "tokens/semantic/classic-light-hard.json",
      "tokens/semantic/classic-light-medium.json",
      "tokens/semantic/classic-light-soft.json",
      "tokens/semantic/material-dark-hard.json",
      "tokens/semantic/material-dark-medium.json",
      "tokens/semantic/material-dark-soft.json"
    ],
    "css": [
      "css/absolute.css",
      "css/all.css",
      "css/apply.css",
      "css/default.css",
      "css/themes.css"
    ],
    "usage": "docs/usage.md",
    "assert": "scripts/assert_tokens.py",
    "preview": "preview/index.html"
  },
  "tags": [
    "gruvbox",
    "retro",
    "warm-dark",
    "terminal",
    "multi-variant",
    "dashboard"
  ],
  "when": "工具型暗色面板、终端风 UI、需要暖灰底 + 米黄字 + 橙强调,或需要 hard/medium/soft 与 material/baby 变体",
  "not_for": "纸媒社论风、明亮内容站(改用 ouuut-editorial)",
  "default_variant": "classic-dark-medium",
  "verified": {
    "date": "2026-11-04",
    "how": "python packs/gruvbox-dark/scripts/assert_tokens.py",
    "evidence": "PASS assert_tokens · themes=10 absolute=36 default=classic-dark-medium"
  },
  "changelog": [
    "2.0.0 · 内容整体入库(原 gruvbox-theme 外部仓退役):css/tokens/preview/docs/SKILL/assert 全套进本仓,外部索引项取消",
    "1.0.0 · 作为外部包登记索引:内容不在本仓,取用请去 canonical_home"
  ]
}
css/absolute.css
/* Official absolute palette — morhetz/gruvbox (MIT/X11) */
:root {
  --gruvbox-abs-dark0-hard: #1d2021;
  --gruvbox-abs-dark0: #282828;
  --gruvbox-abs-dark0-soft: #32302f;
  --gruvbox-abs-dark1: #3c3836;
  --gruvbox-abs-dark2: #504945;
  --gruvbox-abs-dark3: #665c54;
  --gruvbox-abs-dark4: #7c6f64;
  --gruvbox-abs-gray: #928374;
  --gruvbox-abs-light0-hard: #f9f5d7;
  --gruvbox-abs-light0: #fbf1c7;
  --gruvbox-abs-light0-soft: #f2e5bc;
  --gruvbox-abs-light1: #ebdbb2;
  --gruvbox-abs-light2: #d5c4a1;
  --gruvbox-abs-light3: #bdae93;
  --gruvbox-abs-light4: #a89984;
  --gruvbox-abs-bright-red: #fb4934;
  --gruvbox-abs-bright-green: #b8bb26;
  --gruvbox-abs-bright-yellow: #fabd2f;
  --gruvbox-abs-bright-blue: #83a598;
  --gruvbox-abs-bright-purple: #d3869b;
  --gruvbox-abs-bright-aqua: #8ec07c;
  --gruvbox-abs-bright-orange: #fe8019;
  --gruvbox-abs-neutral-red: #cc241d;
  --gruvbox-abs-neutral-green: #98971a;
  --gruvbox-abs-neutral-yellow: #d79921;
  --gruvbox-abs-neutral-blue: #458588;
  --gruvbox-abs-neutral-purple: #b16286;
  --gruvbox-abs-neutral-aqua: #689d6a;
  --gruvbox-abs-neutral-orange: #d65d0e;
  --gruvbox-abs-faded-red: #9d0006;
  --gruvbox-abs-faded-green: #79740e;
  --gruvbox-abs-faded-yellow: #b57614;
  --gruvbox-abs-faded-blue: #076678;
  --gruvbox-abs-faded-purple: #8f3f71;
  --gruvbox-abs-faded-aqua: #427b58;
  --gruvbox-abs-faded-orange: #af3a03;
}

/* Default aliases = classic-dark-medium */
:root {
  --gb-bg0: var(--gruvbox-abs-dark0);
  --gb-bg0-h: var(--gruvbox-abs-dark0-hard);
  --gb-bg0-s: var(--gruvbox-abs-dark0-soft);
  --gb-bg1: var(--gruvbox-abs-dark1);
  --gb-bg2: var(--gruvbox-abs-dark2);
  --gb-bg3: var(--gruvbox-abs-dark3);
  --gb-bg4: var(--gruvbox-abs-dark4);
  --gb-fg0: var(--gruvbox-abs-light0);
  --gb-fg1: var(--gruvbox-abs-light1);
  --gb-fg2: var(--gruvbox-abs-light2);
  --gb-fg3: var(--gruvbox-abs-light3);
  --gb-fg4: var(--gruvbox-abs-light4);
  --gb-gray: var(--gruvbox-abs-gray);
  --gb-red: var(--gruvbox-abs-bright-red);
  --gb-green: var(--gruvbox-abs-bright-green);
  --gb-yellow: var(--gruvbox-abs-bright-yellow);
  --gb-blue: var(--gruvbox-abs-bright-blue);
  --gb-purple: var(--gruvbox-abs-bright-purple);
  --gb-aqua: var(--gruvbox-abs-bright-aqua);
  --gb-orange: var(--gruvbox-abs-bright-orange);
}
css/all.css
/* Official absolute palette — morhetz/gruvbox (MIT/X11) */
:root {
  --gruvbox-abs-dark0-hard: #1d2021;
  --gruvbox-abs-dark0: #282828;
  --gruvbox-abs-dark0-soft: #32302f;
  --gruvbox-abs-dark1: #3c3836;
  --gruvbox-abs-dark2: #504945;
  --gruvbox-abs-dark3: #665c54;
  --gruvbox-abs-dark4: #7c6f64;
  --gruvbox-abs-gray: #928374;
  --gruvbox-abs-light0-hard: #f9f5d7;
  --gruvbox-abs-light0: #fbf1c7;
  --gruvbox-abs-light0-soft: #f2e5bc;
  --gruvbox-abs-light1: #ebdbb2;
  --gruvbox-abs-light2: #d5c4a1;
  --gruvbox-abs-light3: #bdae93;
  --gruvbox-abs-light4: #a89984;
  --gruvbox-abs-bright-red: #fb4934;
  --gruvbox-abs-bright-green: #b8bb26;
  --gruvbox-abs-bright-yellow: #fabd2f;
  --gruvbox-abs-bright-blue: #83a598;
  --gruvbox-abs-bright-purple: #d3869b;
  --gruvbox-abs-bright-aqua: #8ec07c;
  --gruvbox-abs-bright-orange: #fe8019;
  --gruvbox-abs-neutral-red: #cc241d;
  --gruvbox-abs-neutral-green: #98971a;
  --gruvbox-abs-neutral-yellow: #d79921;
  --gruvbox-abs-neutral-blue: #458588;
  --gruvbox-abs-neutral-purple: #b16286;
  --gruvbox-abs-neutral-aqua: #689d6a;
  --gruvbox-abs-neutral-orange: #d65d0e;
  --gruvbox-abs-faded-red: #9d0006;
  --gruvbox-abs-faded-green: #79740e;
  --gruvbox-abs-faded-yellow: #b57614;
  --gruvbox-abs-faded-blue: #076678;
  --gruvbox-abs-faded-purple: #8f3f71;
  --gruvbox-abs-faded-aqua: #427b58;
  --gruvbox-abs-faded-orange: #af3a03;
}

/* Default aliases = classic-dark-medium */
:root {
  --gb-bg0: var(--gruvbox-abs-dark0);
  --gb-bg0-h: var(--gruvbox-abs-dark0-hard);
  --gb-bg0-s: var(--gruvbox-abs-dark0-soft);
  --gb-bg1: var(--gruvbox-abs-dark1);
  --gb-bg2: var(--gruvbox-abs-dark2);
  --gb-bg3: var(--gruvbox-abs-dark3);
  --gb-bg4: var(--gruvbox-abs-dark4);
  --gb-fg0: var(--gruvbox-abs-light0);
  --gb-fg1: var(--gruvbox-abs-light1);
  --gb-fg2: var(--gruvbox-abs-light2);
  --gb-fg3: var(--gruvbox-abs-light3);
  --gb-fg4: var(--gruvbox-abs-light4);
  --gb-gray: var(--gruvbox-abs-gray);
  --gb-red: var(--gruvbox-abs-bright-red);
  --gb-green: var(--gruvbox-abs-bright-green);
  --gb-yellow: var(--gruvbox-abs-bright-yellow);
  --gb-blue: var(--gruvbox-abs-bright-blue);
  --gb-purple: var(--gruvbox-abs-bright-purple);
  --gb-aqua: var(--gruvbox-abs-bright-aqua);
  --gb-orange: var(--gruvbox-abs-bright-orange);
}

/* ---- semantic themes ---- */
/* Gruvbox Classic Dark Hard — morhetz/gruvbox absolute palette */
[data-theme="classic-dark-hard"],
.theme-classic-dark-hard,
:root.theme-classic-dark-hard {
  color-scheme: dark;
  --bg: #1d2021;
  --gb-bg: #1d2021;
  --bg-deep: #141617;
  --gb-bg-deep: #141617;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Dark Medium — morhetz/gruvbox absolute palette */
[data-theme="classic-dark-medium"],
.theme-classic-dark-medium,
:root.theme-classic-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #1d2021;
  --gb-bg-deep: #1d2021;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Dark Soft — morhetz/gruvbox absolute palette */
[data-theme="classic-dark-soft"],
.theme-classic-dark-soft,
:root.theme-classic-dark-soft {
  color-scheme: dark;
  --bg: #32302f;
  --gb-bg: #32302f;
  --bg-deep: #282828;
  --gb-bg-deep: #282828;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Light Hard — morhetz/gruvbox absolute palette */
[data-theme="classic-light-hard"],
.theme-classic-light-hard,
:root.theme-classic-light-hard {
  color-scheme: light;
  --bg: #f9f5d7;
  --gb-bg: #f9f5d7;
  --bg-deep: #fbf1c7;
  --gb-bg-deep: #fbf1c7;
  --surface: #ebdbb2;
  --gb-surface: #ebdbb2;
  --surface-2: #d5c4a1;
  --gb-surface-2: #d5c4a1;
  --border: #bdae93;
  --gb-border: #bdae93;
  --ink: #3c3836;
  --gb-ink: #3c3836;
  --ink-muted: #665c54;
  --gb-ink-muted: #665c54;
  --ink-dim: #7c6f64;
  --gb-ink-dim: #7c6f64;
  --accent: #af3a03;
  --gb-accent: #af3a03;
  --accent-2: #b57614;
  --gb-accent-2: #b57614;
  --on-accent: #f9f5d7;
  --gb-on-accent: #f9f5d7;
  --red: #9d0006;
  --gb-red: #9d0006;
  --green: #79740e;
  --gb-green: #79740e;
  --aqua: #427b58;
  --gb-aqua: #427b58;
  --blue: #076678;
  --gb-blue: #076678;
  --purple: #8f3f71;
  --gb-purple: #8f3f71;
  --link: #427b58;
  --gb-link: #427b58;
  --code-bg: #d5c4a1;
  --gb-code-bg: #d5c4a1;
  --shadow: 0 8px 24px rgba(60,56,54,.12);
  --gb-shadow: 0 8px 24px rgba(60,56,54,.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Light Medium — morhetz/gruvbox absolute palette */
[data-theme="classic-light-medium"],
.theme-classic-light-medium,
:root.theme-classic-light-medium {
  color-scheme: light;
  --bg: #fbf1c7;
  --gb-bg: #fbf1c7;
  --bg-deep: #f9f5d7;
  --gb-bg-deep: #f9f5d7;
  --surface: #ebdbb2;
  --gb-surface: #ebdbb2;
  --surface-2: #d5c4a1;
  --gb-surface-2: #d5c4a1;
  --border: #bdae93;
  --gb-border: #bdae93;
  --ink: #3c3836;
  --gb-ink: #3c3836;
  --ink-muted: #665c54;
  --gb-ink-muted: #665c54;
  --ink-dim: #7c6f64;
  --gb-ink-dim: #7c6f64;
  --accent: #af3a03;
  --gb-accent: #af3a03;
  --accent-2: #b57614;
  --gb-accent-2: #b57614;
  --on-accent: #f9f5d7;
  --gb-on-accent: #f9f5d7;
  --red: #9d0006;
  --gb-red: #9d0006;
  --green: #79740e;
  --gb-green: #79740e;
  --aqua: #427b58;
  --gb-aqua: #427b58;
  --blue: #076678;
  --gb-blue: #076678;
  --purple: #8f3f71;
  --gb-purple: #8f3f71;
  --link: #427b58;
  --gb-link: #427b58;
  --code-bg: #d5c4a1;
  --gb-code-bg: #d5c4a1;
  --shadow: 0 8px 24px rgba(60,56,54,.12);
  --gb-shadow: 0 8px 24px rgba(60,56,54,.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Light Soft — morhetz/gruvbox absolute palette */
[data-theme="classic-light-soft"],
.theme-classic-light-soft,
:root.theme-classic-light-soft {
  color-scheme: light;
  --bg: #f2e5bc;
  --gb-bg: #f2e5bc;
  --bg-deep: #ebdbb2;
  --gb-bg-deep: #ebdbb2;
  --surface: #ebdbb2;
  --gb-surface: #ebdbb2;
  --surface-2: #d5c4a1;
  --gb-surface-2: #d5c4a1;
  --border: #bdae93;
  --gb-border: #bdae93;
  --ink: #3c3836;
  --gb-ink: #3c3836;
  --ink-muted: #665c54;
  --gb-ink-muted: #665c54;
  --ink-dim: #7c6f64;
  --gb-ink-dim: #7c6f64;
  --accent: #af3a03;
  --gb-accent: #af3a03;
  --accent-2: #b57614;
  --gb-accent-2: #b57614;
  --on-accent: #f9f5d7;
  --gb-on-accent: #f9f5d7;
  --red: #9d0006;
  --gb-red: #9d0006;
  --green: #79740e;
  --gb-green: #79740e;
  --aqua: #427b58;
  --gb-aqua: #427b58;
  --blue: #076678;
  --gb-blue: #076678;
  --purple: #8f3f71;
  --gb-purple: #8f3f71;
  --link: #427b58;
  --gb-link: #427b58;
  --code-bg: #d5c4a1;
  --gb-code-bg: #d5c4a1;
  --shadow: 0 8px 24px rgba(60,56,54,.12);
  --gb-shadow: 0 8px 24px rgba(60,56,54,.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Material Dark Hard — sainnhe/gruvbox-material palette=material */
[data-theme="material-dark-hard"],
.theme-material-dark-hard,
:root.theme-material-dark-hard {
  color-scheme: dark;
  --bg: #1d2021;
  --gb-bg: #1d2021;
  --bg-deep: #141617;
  --gb-bg-deep: #141617;
  --surface: #282828;
  --gb-surface: #282828;
  --surface-2: #3c3836;
  --gb-surface-2: #3c3836;
  --border: #504945;
  --gb-border: #504945;
  --ink: #d4be98;
  --gb-ink: #d4be98;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #e78a4e;
  --gb-accent: #e78a4e;
  --accent-2: #d8a657;
  --gb-accent-2: #d8a657;
  --on-accent: #141617;
  --gb-on-accent: #141617;
  --red: #ea6962;
  --gb-red: #ea6962;
  --green: #a9b665;
  --gb-green: #a9b665;
  --aqua: #89b482;
  --gb-aqua: #89b482;
  --blue: #7daea3;
  --gb-blue: #7daea3;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #89b482;
  --gb-link: #89b482;
  --code-bg: #141617;
  --gb-code-bg: #141617;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Material Dark Medium — sainnhe/gruvbox-material palette=material */
[data-theme="material-dark-medium"],
.theme-material-dark-medium,
:root.theme-material-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #1b1b1b;
  --gb-bg-deep: #1b1b1b;
  --surface: #32302f;
  --gb-surface: #32302f;
  --surface-2: #45403d;
  --gb-surface-2: #45403d;
  --border: #5a524c;
  --gb-border: #5a524c;
  --ink: #d4be98;
  --gb-ink: #d4be98;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #e78a4e;
  --gb-accent: #e78a4e;
  --accent-2: #d8a657;
  --gb-accent-2: #d8a657;
  --on-accent: #1b1b1b;
  --gb-on-accent: #1b1b1b;
  --red: #ea6962;
  --gb-red: #ea6962;
  --green: #a9b665;
  --gb-green: #a9b665;
  --aqua: #89b482;
  --gb-aqua: #89b482;
  --blue: #7daea3;
  --gb-blue: #7daea3;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #89b482;
  --gb-link: #89b482;
  --code-bg: #1b1b1b;
  --gb-code-bg: #1b1b1b;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Material Dark Soft — sainnhe/gruvbox-material palette=material */
[data-theme="material-dark-soft"],
.theme-material-dark-soft,
:root.theme-material-dark-soft {
  color-scheme: dark;
  --bg: #32302f;
  --gb-bg: #32302f;
  --bg-deep: #252423;
  --gb-bg-deep: #252423;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #d4be98;
  --gb-ink: #d4be98;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #e78a4e;
  --gb-accent: #e78a4e;
  --accent-2: #d8a657;
  --gb-accent-2: #d8a657;
  --on-accent: #252423;
  --gb-on-accent: #252423;
  --red: #ea6962;
  --gb-red: #ea6962;
  --green: #a9b665;
  --gb-green: #a9b665;
  --aqua: #89b482;
  --gb-aqua: #89b482;
  --blue: #7daea3;
  --gb-blue: #7daea3;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #89b482;
  --gb-link: #89b482;
  --code-bg: #252423;
  --gb-code-bg: #252423;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Baby Dark Medium — luisiacc/gruvbox-baby (simplified semantic) */
[data-theme="baby-dark-medium"],
.theme-baby-dark-medium,
:root.theme-baby-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #242424;
  --gb-bg-deep: #242424;
  --surface: #32302f;
  --gb-surface: #32302f;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #d65d0e;
  --gb-accent: #d65d0e;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #8ec07c;
  --gb-green: #8ec07c;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d4879c;
  --gb-purple: #d4879c;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #202020;
  --gb-code-bg: #202020;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}

/* Drop-in body chrome for panels / tools — opt-in via .gruvbox-apply */
.gruvbox-apply,
[data-gruvbox-apply] {
  background: var(--bg, var(--gb-bg, #282828));
  color: var(--ink, var(--gb-ink, #ebdbb2));
  font-family: system-ui, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}

.gruvbox-apply a,
[data-gruvbox-apply] a {
  color: var(--link, var(--gb-link, #8ec07c));
}

.gruvbox-apply code,
.gruvbox-apply pre,
[data-gruvbox-apply] code,
[data-gruvbox-apply] pre {
  background: var(--code-bg, var(--gb-code-bg, #1d2021));
  color: var(--ink, var(--gb-ink, #ebdbb2));
  border-radius: var(--radius-sm, 6px);
}

.gruvbox-apply .panel,
[data-gruvbox-apply] .panel {
  background: var(--surface, var(--gb-surface, #3c3836));
  border: 1px solid var(--border, var(--gb-border, #665c54));
  border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow, none);
}

.gruvbox-apply .btn-primary,
[data-gruvbox-apply] .btn-primary {
  background: var(--accent, var(--gb-accent, #fe8019));
  color: var(--on-accent, var(--gb-on-accent, #1d2021));
  border: none;
  border-radius: var(--radius-sm, 6px);
}

/* Scrollbar (optional chrome) */
.gruvbox-scrollbar,
.gruvbox-apply {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink, #ebdbb2) 28%, transparent) transparent;
}
.gruvbox-scrollbar::-webkit-scrollbar,
.gruvbox-apply::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
.gruvbox-scrollbar::-webkit-scrollbar-track,
.gruvbox-apply::-webkit-scrollbar-track {
  background: transparent;
}
.gruvbox-scrollbar::-webkit-scrollbar-thumb,
.gruvbox-apply::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink, #ebdbb2) 22%, transparent);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
css/apply.css
/* Drop-in body chrome for panels / tools — opt-in via .gruvbox-apply */
.gruvbox-apply,
[data-gruvbox-apply] {
  background: var(--bg, var(--gb-bg, #282828));
  color: var(--ink, var(--gb-ink, #ebdbb2));
  font-family: system-ui, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}

.gruvbox-apply a,
[data-gruvbox-apply] a {
  color: var(--link, var(--gb-link, #8ec07c));
}

.gruvbox-apply code,
.gruvbox-apply pre,
[data-gruvbox-apply] code,
[data-gruvbox-apply] pre {
  background: var(--code-bg, var(--gb-code-bg, #1d2021));
  color: var(--ink, var(--gb-ink, #ebdbb2));
  border-radius: var(--radius-sm, 6px);
}

.gruvbox-apply .panel,
[data-gruvbox-apply] .panel {
  background: var(--surface, var(--gb-surface, #3c3836));
  border: 1px solid var(--border, var(--gb-border, #665c54));
  border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow, none);
}

.gruvbox-apply .btn-primary,
[data-gruvbox-apply] .btn-primary {
  background: var(--accent, var(--gb-accent, #fe8019));
  color: var(--on-accent, var(--gb-on-accent, #1d2021));
  border: none;
  border-radius: var(--radius-sm, 6px);
}

/* Scrollbar (optional chrome) */
.gruvbox-scrollbar,
.gruvbox-apply {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink, #ebdbb2) 28%, transparent) transparent;
}
.gruvbox-scrollbar::-webkit-scrollbar,
.gruvbox-apply::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
.gruvbox-scrollbar::-webkit-scrollbar-track,
.gruvbox-apply::-webkit-scrollbar-track {
  background: transparent;
}
.gruvbox-scrollbar::-webkit-scrollbar-thumb,
.gruvbox-apply::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink, #ebdbb2) 22%, transparent);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
css/default.css
/* Default = classic-dark-medium — link this alone for fastest apply */
/* Gruvbox Classic Dark Medium — morhetz/gruvbox absolute palette */
:root,
[data-theme="classic-dark-medium"],
.theme-classic-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #1d2021;
  --gb-bg-deep: #1d2021;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}

/* Drop-in body chrome for panels / tools — opt-in via .gruvbox-apply */
.gruvbox-apply,
[data-gruvbox-apply] {
  background: var(--bg, var(--gb-bg, #282828));
  color: var(--ink, var(--gb-ink, #ebdbb2));
  font-family: system-ui, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}

.gruvbox-apply a,
[data-gruvbox-apply] a {
  color: var(--link, var(--gb-link, #8ec07c));
}

.gruvbox-apply code,
.gruvbox-apply pre,
[data-gruvbox-apply] code,
[data-gruvbox-apply] pre {
  background: var(--code-bg, var(--gb-code-bg, #1d2021));
  color: var(--ink, var(--gb-ink, #ebdbb2));
  border-radius: var(--radius-sm, 6px);
}

.gruvbox-apply .panel,
[data-gruvbox-apply] .panel {
  background: var(--surface, var(--gb-surface, #3c3836));
  border: 1px solid var(--border, var(--gb-border, #665c54));
  border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow, none);
}

.gruvbox-apply .btn-primary,
[data-gruvbox-apply] .btn-primary {
  background: var(--accent, var(--gb-accent, #fe8019));
  color: var(--on-accent, var(--gb-on-accent, #1d2021));
  border: none;
  border-radius: var(--radius-sm, 6px);
}

/* Scrollbar (optional chrome) */
.gruvbox-scrollbar,
.gruvbox-apply {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--ink, #ebdbb2) 28%, transparent) transparent;
}
.gruvbox-scrollbar::-webkit-scrollbar,
.gruvbox-apply::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
.gruvbox-scrollbar::-webkit-scrollbar-track,
.gruvbox-apply::-webkit-scrollbar-track {
  background: transparent;
}
.gruvbox-scrollbar::-webkit-scrollbar-thumb,
.gruvbox-apply::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--ink, #ebdbb2) 22%, transparent);
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
css/themes.css
/* ---- semantic themes ---- */
/* Gruvbox Classic Dark Hard — morhetz/gruvbox absolute palette */
[data-theme="classic-dark-hard"],
.theme-classic-dark-hard,
:root.theme-classic-dark-hard {
  color-scheme: dark;
  --bg: #1d2021;
  --gb-bg: #1d2021;
  --bg-deep: #141617;
  --gb-bg-deep: #141617;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Dark Medium — morhetz/gruvbox absolute palette */
[data-theme="classic-dark-medium"],
.theme-classic-dark-medium,
:root.theme-classic-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #1d2021;
  --gb-bg-deep: #1d2021;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Dark Soft — morhetz/gruvbox absolute palette */
[data-theme="classic-dark-soft"],
.theme-classic-dark-soft,
:root.theme-classic-dark-soft {
  color-scheme: dark;
  --bg: #32302f;
  --gb-bg: #32302f;
  --bg-deep: #282828;
  --gb-bg-deep: #282828;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #fe8019;
  --gb-accent: #fe8019;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #b8bb26;
  --gb-green: #b8bb26;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #1d2021;
  --gb-code-bg: #1d2021;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Light Hard — morhetz/gruvbox absolute palette */
[data-theme="classic-light-hard"],
.theme-classic-light-hard,
:root.theme-classic-light-hard {
  color-scheme: light;
  --bg: #f9f5d7;
  --gb-bg: #f9f5d7;
  --bg-deep: #fbf1c7;
  --gb-bg-deep: #fbf1c7;
  --surface: #ebdbb2;
  --gb-surface: #ebdbb2;
  --surface-2: #d5c4a1;
  --gb-surface-2: #d5c4a1;
  --border: #bdae93;
  --gb-border: #bdae93;
  --ink: #3c3836;
  --gb-ink: #3c3836;
  --ink-muted: #665c54;
  --gb-ink-muted: #665c54;
  --ink-dim: #7c6f64;
  --gb-ink-dim: #7c6f64;
  --accent: #af3a03;
  --gb-accent: #af3a03;
  --accent-2: #b57614;
  --gb-accent-2: #b57614;
  --on-accent: #f9f5d7;
  --gb-on-accent: #f9f5d7;
  --red: #9d0006;
  --gb-red: #9d0006;
  --green: #79740e;
  --gb-green: #79740e;
  --aqua: #427b58;
  --gb-aqua: #427b58;
  --blue: #076678;
  --gb-blue: #076678;
  --purple: #8f3f71;
  --gb-purple: #8f3f71;
  --link: #427b58;
  --gb-link: #427b58;
  --code-bg: #d5c4a1;
  --gb-code-bg: #d5c4a1;
  --shadow: 0 8px 24px rgba(60,56,54,.12);
  --gb-shadow: 0 8px 24px rgba(60,56,54,.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Light Medium — morhetz/gruvbox absolute palette */
[data-theme="classic-light-medium"],
.theme-classic-light-medium,
:root.theme-classic-light-medium {
  color-scheme: light;
  --bg: #fbf1c7;
  --gb-bg: #fbf1c7;
  --bg-deep: #f9f5d7;
  --gb-bg-deep: #f9f5d7;
  --surface: #ebdbb2;
  --gb-surface: #ebdbb2;
  --surface-2: #d5c4a1;
  --gb-surface-2: #d5c4a1;
  --border: #bdae93;
  --gb-border: #bdae93;
  --ink: #3c3836;
  --gb-ink: #3c3836;
  --ink-muted: #665c54;
  --gb-ink-muted: #665c54;
  --ink-dim: #7c6f64;
  --gb-ink-dim: #7c6f64;
  --accent: #af3a03;
  --gb-accent: #af3a03;
  --accent-2: #b57614;
  --gb-accent-2: #b57614;
  --on-accent: #f9f5d7;
  --gb-on-accent: #f9f5d7;
  --red: #9d0006;
  --gb-red: #9d0006;
  --green: #79740e;
  --gb-green: #79740e;
  --aqua: #427b58;
  --gb-aqua: #427b58;
  --blue: #076678;
  --gb-blue: #076678;
  --purple: #8f3f71;
  --gb-purple: #8f3f71;
  --link: #427b58;
  --gb-link: #427b58;
  --code-bg: #d5c4a1;
  --gb-code-bg: #d5c4a1;
  --shadow: 0 8px 24px rgba(60,56,54,.12);
  --gb-shadow: 0 8px 24px rgba(60,56,54,.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Classic Light Soft — morhetz/gruvbox absolute palette */
[data-theme="classic-light-soft"],
.theme-classic-light-soft,
:root.theme-classic-light-soft {
  color-scheme: light;
  --bg: #f2e5bc;
  --gb-bg: #f2e5bc;
  --bg-deep: #ebdbb2;
  --gb-bg-deep: #ebdbb2;
  --surface: #ebdbb2;
  --gb-surface: #ebdbb2;
  --surface-2: #d5c4a1;
  --gb-surface-2: #d5c4a1;
  --border: #bdae93;
  --gb-border: #bdae93;
  --ink: #3c3836;
  --gb-ink: #3c3836;
  --ink-muted: #665c54;
  --gb-ink-muted: #665c54;
  --ink-dim: #7c6f64;
  --gb-ink-dim: #7c6f64;
  --accent: #af3a03;
  --gb-accent: #af3a03;
  --accent-2: #b57614;
  --gb-accent-2: #b57614;
  --on-accent: #f9f5d7;
  --gb-on-accent: #f9f5d7;
  --red: #9d0006;
  --gb-red: #9d0006;
  --green: #79740e;
  --gb-green: #79740e;
  --aqua: #427b58;
  --gb-aqua: #427b58;
  --blue: #076678;
  --gb-blue: #076678;
  --purple: #8f3f71;
  --gb-purple: #8f3f71;
  --link: #427b58;
  --gb-link: #427b58;
  --code-bg: #d5c4a1;
  --gb-code-bg: #d5c4a1;
  --shadow: 0 8px 24px rgba(60,56,54,.12);
  --gb-shadow: 0 8px 24px rgba(60,56,54,.12);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Material Dark Hard — sainnhe/gruvbox-material palette=material */
[data-theme="material-dark-hard"],
.theme-material-dark-hard,
:root.theme-material-dark-hard {
  color-scheme: dark;
  --bg: #1d2021;
  --gb-bg: #1d2021;
  --bg-deep: #141617;
  --gb-bg-deep: #141617;
  --surface: #282828;
  --gb-surface: #282828;
  --surface-2: #3c3836;
  --gb-surface-2: #3c3836;
  --border: #504945;
  --gb-border: #504945;
  --ink: #d4be98;
  --gb-ink: #d4be98;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #e78a4e;
  --gb-accent: #e78a4e;
  --accent-2: #d8a657;
  --gb-accent-2: #d8a657;
  --on-accent: #141617;
  --gb-on-accent: #141617;
  --red: #ea6962;
  --gb-red: #ea6962;
  --green: #a9b665;
  --gb-green: #a9b665;
  --aqua: #89b482;
  --gb-aqua: #89b482;
  --blue: #7daea3;
  --gb-blue: #7daea3;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #89b482;
  --gb-link: #89b482;
  --code-bg: #141617;
  --gb-code-bg: #141617;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Material Dark Medium — sainnhe/gruvbox-material palette=material */
[data-theme="material-dark-medium"],
.theme-material-dark-medium,
:root.theme-material-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #1b1b1b;
  --gb-bg-deep: #1b1b1b;
  --surface: #32302f;
  --gb-surface: #32302f;
  --surface-2: #45403d;
  --gb-surface-2: #45403d;
  --border: #5a524c;
  --gb-border: #5a524c;
  --ink: #d4be98;
  --gb-ink: #d4be98;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #e78a4e;
  --gb-accent: #e78a4e;
  --accent-2: #d8a657;
  --gb-accent-2: #d8a657;
  --on-accent: #1b1b1b;
  --gb-on-accent: #1b1b1b;
  --red: #ea6962;
  --gb-red: #ea6962;
  --green: #a9b665;
  --gb-green: #a9b665;
  --aqua: #89b482;
  --gb-aqua: #89b482;
  --blue: #7daea3;
  --gb-blue: #7daea3;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #89b482;
  --gb-link: #89b482;
  --code-bg: #1b1b1b;
  --gb-code-bg: #1b1b1b;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Material Dark Soft — sainnhe/gruvbox-material palette=material */
[data-theme="material-dark-soft"],
.theme-material-dark-soft,
:root.theme-material-dark-soft {
  color-scheme: dark;
  --bg: #32302f;
  --gb-bg: #32302f;
  --bg-deep: #252423;
  --gb-bg-deep: #252423;
  --surface: #3c3836;
  --gb-surface: #3c3836;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #d4be98;
  --gb-ink: #d4be98;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #e78a4e;
  --gb-accent: #e78a4e;
  --accent-2: #d8a657;
  --gb-accent-2: #d8a657;
  --on-accent: #252423;
  --gb-on-accent: #252423;
  --red: #ea6962;
  --gb-red: #ea6962;
  --green: #a9b665;
  --gb-green: #a9b665;
  --aqua: #89b482;
  --gb-aqua: #89b482;
  --blue: #7daea3;
  --gb-blue: #7daea3;
  --purple: #d3869b;
  --gb-purple: #d3869b;
  --link: #89b482;
  --gb-link: #89b482;
  --code-bg: #252423;
  --gb-code-bg: #252423;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
/* Gruvbox Baby Dark Medium — luisiacc/gruvbox-baby (simplified semantic) */
[data-theme="baby-dark-medium"],
.theme-baby-dark-medium,
:root.theme-baby-dark-medium {
  color-scheme: dark;
  --bg: #282828;
  --gb-bg: #282828;
  --bg-deep: #242424;
  --gb-bg-deep: #242424;
  --surface: #32302f;
  --gb-surface: #32302f;
  --surface-2: #504945;
  --gb-surface-2: #504945;
  --border: #665c54;
  --gb-border: #665c54;
  --ink: #ebdbb2;
  --gb-ink: #ebdbb2;
  --ink-muted: #a89984;
  --gb-ink-muted: #a89984;
  --ink-dim: #928374;
  --gb-ink-dim: #928374;
  --accent: #d65d0e;
  --gb-accent: #d65d0e;
  --accent-2: #fabd2f;
  --gb-accent-2: #fabd2f;
  --on-accent: #1d2021;
  --gb-on-accent: #1d2021;
  --red: #fb4934;
  --gb-red: #fb4934;
  --green: #8ec07c;
  --gb-green: #8ec07c;
  --aqua: #8ec07c;
  --gb-aqua: #8ec07c;
  --blue: #83a598;
  --gb-blue: #83a598;
  --purple: #d4879c;
  --gb-purple: #d4879c;
  --link: #8ec07c;
  --gb-link: #8ec07c;
  --code-bg: #202020;
  --gb-code-bg: #202020;
  --shadow: 0 8px 24px rgba(0,0,0,.45);
  --gb-shadow: 0 8px 24px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
}
tokens/absolute.json
{
  "id": "gruvbox-absolute",
  "source": "morhetz/gruvbox colors/gruvbox.vim",
  "license": "MIT/X11",
  "colors": {
    "dark0_hard": "#1d2021",
    "dark0": "#282828",
    "dark0_soft": "#32302f",
    "dark1": "#3c3836",
    "dark2": "#504945",
    "dark3": "#665c54",
    "dark4": "#7c6f64",
    "gray": "#928374",
    "light0_hard": "#f9f5d7",
    "light0": "#fbf1c7",
    "light0_soft": "#f2e5bc",
    "light1": "#ebdbb2",
    "light2": "#d5c4a1",
    "light3": "#bdae93",
    "light4": "#a89984",
    "bright_red": "#fb4934",
    "bright_green": "#b8bb26",
    "bright_yellow": "#fabd2f",
    "bright_blue": "#83a598",
    "bright_purple": "#d3869b",
    "bright_aqua": "#8ec07c",
    "bright_orange": "#fe8019",
    "neutral_red": "#cc241d",
    "neutral_green": "#98971a",
    "neutral_yellow": "#d79921",
    "neutral_blue": "#458588",
    "neutral_purple": "#b16286",
    "neutral_aqua": "#689d6a",
    "neutral_orange": "#d65d0e",
    "faded_red": "#9d0006",
    "faded_green": "#79740e",
    "faded_yellow": "#b57614",
    "faded_blue": "#076678",
    "faded_purple": "#8f3f71",
    "faded_aqua": "#427b58",
    "faded_orange": "#af3a03"
  }
}
tokens/index.json
{
  "default": "classic-dark-medium",
  "themes": [
    {
      "id": "classic-dark-hard",
      "name": "Gruvbox Classic Dark Hard",
      "family": "classic",
      "mode": "dark",
      "contrast": "hard",
      "path": "tokens/semantic/classic-dark-hard.json",
      "default": false
    },
    {
      "id": "classic-dark-medium",
      "name": "Gruvbox Classic Dark Medium",
      "family": "classic",
      "mode": "dark",
      "contrast": "medium",
      "path": "tokens/semantic/classic-dark-medium.json",
      "default": true
    },
    {
      "id": "classic-dark-soft",
      "name": "Gruvbox Classic Dark Soft",
      "family": "classic",
      "mode": "dark",
      "contrast": "soft",
      "path": "tokens/semantic/classic-dark-soft.json",
      "default": false
    },
    {
      "id": "classic-light-hard",
      "name": "Gruvbox Classic Light Hard",
      "family": "classic",
      "mode": "light",
      "contrast": "hard",
      "path": "tokens/semantic/classic-light-hard.json",
      "default": false
    },
    {
      "id": "classic-light-medium",
      "name": "Gruvbox Classic Light Medium",
      "family": "classic",
      "mode": "light",
      "contrast": "medium",
      "path": "tokens/semantic/classic-light-medium.json",
      "default": false
    },
    {
      "id": "classic-light-soft",
      "name": "Gruvbox Classic Light Soft",
      "family": "classic",
      "mode": "light",
      "contrast": "soft",
      "path": "tokens/semantic/classic-light-soft.json",
      "default": false
    },
    {
      "id": "material-dark-hard",
      "name": "Gruvbox Material Dark Hard",
      "family": "material",
      "mode": "dark",
      "contrast": "hard",
      "path": "tokens/semantic/material-dark-hard.json",
      "default": false
    },
    {
      "id": "material-dark-medium",
      "name": "Gruvbox Material Dark Medium",
      "family": "material",
      "mode": "dark",
      "contrast": "medium",
      "path": "tokens/semantic/material-dark-medium.json",
      "default": false
    },
    {
      "id": "material-dark-soft",
      "name": "Gruvbox Material Dark Soft",
      "family": "material",
      "mode": "dark",
      "contrast": "soft",
      "path": "tokens/semantic/material-dark-soft.json",
      "default": false
    },
    {
      "id": "baby-dark-medium",
      "name": "Gruvbox Baby Dark Medium",
      "family": "baby",
      "mode": "dark",
      "contrast": "medium",
      "path": "tokens/semantic/baby-dark-medium.json",
      "default": false
    }
  ],
  "families": {
    "classic": "Official morhetz palette; dark uses bright_* accents; light uses faded_*.",
    "material": "sainnhe gruvbox-material palette=material (softer accents).",
    "baby": "luisiacc gruvbox-baby medium — deeper chrome, slightly different orange."
  }
}
tokens/semantic/baby-dark-medium.json
{
  "id": "baby-dark-medium",
  "name": "Gruvbox Baby Dark Medium",
  "family": "baby",
  "mode": "dark",
  "contrast": "medium",
  "source": "luisiacc/gruvbox-baby (simplified semantic)",
  "colors": {
    "bg": "#282828",
    "bgDeep": "#242424",
    "surface": "#32302f",
    "surface2": "#504945",
    "border": "#665c54",
    "ink": "#ebdbb2",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#d65d0e",
    "accent2": "#fabd2f",
    "onAccent": "#1d2021",
    "red": "#fb4934",
    "green": "#8ec07c",
    "aqua": "#8ec07c",
    "blue": "#83a598",
    "purple": "#d4879c",
    "link": "#8ec07c",
    "codeBg": "#202020",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/classic-dark-hard.json
{
  "id": "classic-dark-hard",
  "name": "Gruvbox Classic Dark Hard",
  "family": "classic",
  "mode": "dark",
  "contrast": "hard",
  "source": "morhetz/gruvbox absolute palette",
  "colors": {
    "bg": "#1d2021",
    "bgDeep": "#141617",
    "surface": "#3c3836",
    "surface2": "#504945",
    "border": "#665c54",
    "ink": "#ebdbb2",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#fe8019",
    "accent2": "#fabd2f",
    "onAccent": "#1d2021",
    "red": "#fb4934",
    "green": "#b8bb26",
    "aqua": "#8ec07c",
    "blue": "#83a598",
    "purple": "#d3869b",
    "link": "#8ec07c",
    "codeBg": "#1d2021",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/classic-dark-medium.json
{
  "id": "classic-dark-medium",
  "name": "Gruvbox Classic Dark Medium",
  "family": "classic",
  "mode": "dark",
  "contrast": "medium",
  "source": "morhetz/gruvbox absolute palette",
  "colors": {
    "bg": "#282828",
    "bgDeep": "#1d2021",
    "surface": "#3c3836",
    "surface2": "#504945",
    "border": "#665c54",
    "ink": "#ebdbb2",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#fe8019",
    "accent2": "#fabd2f",
    "onAccent": "#1d2021",
    "red": "#fb4934",
    "green": "#b8bb26",
    "aqua": "#8ec07c",
    "blue": "#83a598",
    "purple": "#d3869b",
    "link": "#8ec07c",
    "codeBg": "#1d2021",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/classic-dark-soft.json
{
  "id": "classic-dark-soft",
  "name": "Gruvbox Classic Dark Soft",
  "family": "classic",
  "mode": "dark",
  "contrast": "soft",
  "source": "morhetz/gruvbox absolute palette",
  "colors": {
    "bg": "#32302f",
    "bgDeep": "#282828",
    "surface": "#3c3836",
    "surface2": "#504945",
    "border": "#665c54",
    "ink": "#ebdbb2",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#fe8019",
    "accent2": "#fabd2f",
    "onAccent": "#1d2021",
    "red": "#fb4934",
    "green": "#b8bb26",
    "aqua": "#8ec07c",
    "blue": "#83a598",
    "purple": "#d3869b",
    "link": "#8ec07c",
    "codeBg": "#1d2021",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/classic-light-hard.json
{
  "id": "classic-light-hard",
  "name": "Gruvbox Classic Light Hard",
  "family": "classic",
  "mode": "light",
  "contrast": "hard",
  "source": "morhetz/gruvbox absolute palette",
  "colors": {
    "bg": "#f9f5d7",
    "bgDeep": "#fbf1c7",
    "surface": "#ebdbb2",
    "surface2": "#d5c4a1",
    "border": "#bdae93",
    "ink": "#3c3836",
    "inkMuted": "#665c54",
    "inkDim": "#7c6f64",
    "accent": "#af3a03",
    "accent2": "#b57614",
    "onAccent": "#f9f5d7",
    "red": "#9d0006",
    "green": "#79740e",
    "aqua": "#427b58",
    "blue": "#076678",
    "purple": "#8f3f71",
    "link": "#427b58",
    "codeBg": "#d5c4a1",
    "shadow": "0 8px 24px rgba(60,56,54,.12)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/classic-light-medium.json
{
  "id": "classic-light-medium",
  "name": "Gruvbox Classic Light Medium",
  "family": "classic",
  "mode": "light",
  "contrast": "medium",
  "source": "morhetz/gruvbox absolute palette",
  "colors": {
    "bg": "#fbf1c7",
    "bgDeep": "#f9f5d7",
    "surface": "#ebdbb2",
    "surface2": "#d5c4a1",
    "border": "#bdae93",
    "ink": "#3c3836",
    "inkMuted": "#665c54",
    "inkDim": "#7c6f64",
    "accent": "#af3a03",
    "accent2": "#b57614",
    "onAccent": "#f9f5d7",
    "red": "#9d0006",
    "green": "#79740e",
    "aqua": "#427b58",
    "blue": "#076678",
    "purple": "#8f3f71",
    "link": "#427b58",
    "codeBg": "#d5c4a1",
    "shadow": "0 8px 24px rgba(60,56,54,.12)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/classic-light-soft.json
{
  "id": "classic-light-soft",
  "name": "Gruvbox Classic Light Soft",
  "family": "classic",
  "mode": "light",
  "contrast": "soft",
  "source": "morhetz/gruvbox absolute palette",
  "colors": {
    "bg": "#f2e5bc",
    "bgDeep": "#ebdbb2",
    "surface": "#ebdbb2",
    "surface2": "#d5c4a1",
    "border": "#bdae93",
    "ink": "#3c3836",
    "inkMuted": "#665c54",
    "inkDim": "#7c6f64",
    "accent": "#af3a03",
    "accent2": "#b57614",
    "onAccent": "#f9f5d7",
    "red": "#9d0006",
    "green": "#79740e",
    "aqua": "#427b58",
    "blue": "#076678",
    "purple": "#8f3f71",
    "link": "#427b58",
    "codeBg": "#d5c4a1",
    "shadow": "0 8px 24px rgba(60,56,54,.12)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/material-dark-hard.json
{
  "id": "material-dark-hard",
  "name": "Gruvbox Material Dark Hard",
  "family": "material",
  "mode": "dark",
  "contrast": "hard",
  "source": "sainnhe/gruvbox-material palette=material",
  "colors": {
    "bg": "#1d2021",
    "bgDeep": "#141617",
    "surface": "#282828",
    "surface2": "#3c3836",
    "border": "#504945",
    "ink": "#d4be98",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#e78a4e",
    "accent2": "#d8a657",
    "onAccent": "#141617",
    "red": "#ea6962",
    "green": "#a9b665",
    "aqua": "#89b482",
    "blue": "#7daea3",
    "purple": "#d3869b",
    "link": "#89b482",
    "codeBg": "#141617",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/material-dark-medium.json
{
  "id": "material-dark-medium",
  "name": "Gruvbox Material Dark Medium",
  "family": "material",
  "mode": "dark",
  "contrast": "medium",
  "source": "sainnhe/gruvbox-material palette=material",
  "colors": {
    "bg": "#282828",
    "bgDeep": "#1b1b1b",
    "surface": "#32302f",
    "surface2": "#45403d",
    "border": "#5a524c",
    "ink": "#d4be98",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#e78a4e",
    "accent2": "#d8a657",
    "onAccent": "#1b1b1b",
    "red": "#ea6962",
    "green": "#a9b665",
    "aqua": "#89b482",
    "blue": "#7daea3",
    "purple": "#d3869b",
    "link": "#89b482",
    "codeBg": "#1b1b1b",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
tokens/semantic/material-dark-soft.json
{
  "id": "material-dark-soft",
  "name": "Gruvbox Material Dark Soft",
  "family": "material",
  "mode": "dark",
  "contrast": "soft",
  "source": "sainnhe/gruvbox-material palette=material",
  "colors": {
    "bg": "#32302f",
    "bgDeep": "#252423",
    "surface": "#3c3836",
    "surface2": "#504945",
    "border": "#665c54",
    "ink": "#d4be98",
    "inkMuted": "#a89984",
    "inkDim": "#928374",
    "accent": "#e78a4e",
    "accent2": "#d8a657",
    "onAccent": "#252423",
    "red": "#ea6962",
    "green": "#a9b665",
    "aqua": "#89b482",
    "blue": "#7daea3",
    "purple": "#d3869b",
    "link": "#89b482",
    "codeBg": "#252423",
    "shadow": "0 8px 24px rgba(0,0,0,.45)"
  },
  "fonts": {
    "display": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "body": "system-ui, \"Segoe UI\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif",
    "mono": "\"JetBrains Mono\", \"Cascadia Code\", Consolas, monospace"
  },
  "radius": {
    "sm": "6px",
    "md": "10px",
    "lg": "14px"
  }
}
docs/usage.md
# 用法:色令牌怎么落到网页组件

> 本仓库**不是**完整 UI 组件库,而是 **Gruvbox 色板合同 + 搭配说明书**。  
> 下面用语义令牌(`--bg` / `--ink` / `--accent` …)说明「页面各层该用哪几个色」。  
> 默认主题:`classic-dark-medium`(`#282828` / `#ebdbb2` / `#fe8019`)。

英文版:[usage.en.md](usage.en.md)

---

## 1. 先建立三层背景

Gruvbox 好看,靠的是**暖灰阶梯**,不是纯黑 + 冷灰。

| 层级 | 令牌 | 默认 hex | 用在哪 |
|------|------|----------|--------|
| 最深底 | `bgDeep` / `--bg-deep` | `#1d2021` | 侧栏外更深处、代码块底、全屏沉浸 |
| 页面底 | `bg` / `--bg` | `#282828` | `<body>` / 主画布 |
| 抬起面 | `surface` / `--surface` | `#3c3836` | 卡片、面板、弹层、输入框底板 |
| 再抬一层 | `surface2` / `--surface-2` | `#504945` | 悬停条、次级工具条、嵌套小块 |
| 描边 | `border` / `--border` | `#665c54` | 分割线、卡片边、输入框边 |

**规则**:同屏最多用 3 层背景(底 / 卡 / 悬停)。不要再叠 `#000` 或 Tailwind slate。

```css
body { background: var(--bg); color: var(--ink); }
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
}
.card:hover { background: var(--surface-2); }
```

---

## 2. 文字:主 / 次 / 弱

| 角色 | 令牌 | 默认 | 用在哪 |
|------|------|------|--------|
| 正文 | `ink` | `#ebdbb2` | 标题、段落、列表主文 |
| 次要 | `inkMuted` | `#a89984` | 说明、时间戳、表格次列 |
| 更弱 | `inkDim` | `#928374` | 占位符、禁用提示、图例小字 |
| 链接触发 | `link` / `aqua` | `#8ec07c` | `<a>`、可点标签(**不要**用橙色做默认链接) |

**对比纪律(暗色)**:

- 正文永远 `ink` 在 `bg` / `surface` 上;不要用 `inkDim` 写长文。
- 占位符才用 `inkDim`。
- 亮色主题(`classic-light-*`)换成深棕字 + 褪色强调色,规则相同、hex 不同。

```css
h1, h2, p { color: var(--ink); }
.meta, .hint { color: var(--ink-muted); }
::placeholder { color: var(--ink-dim); }
a { color: var(--link); }
a:hover { filter: brightness(1.08); }
```

---

## 3. 按钮与主操作

| 类型 | 背景 | 字色 | 边框 | 何时用 |
|------|------|------|------|--------|
| **主按钮** | `accent` `#fe8019` | `onAccent` `#1d2021` | 无 | 唯一主 CTA(每区最多 1 个) |
| **次按钮** | `surface` / `surface2` | `ink` | `border` | 取消、次要动作 |
| **幽灵** | 透明 | `ink` | `border` | 工具条、表头 |
| **危险** | 透明或极淡 red | `red` | `red` 或 `border` | 删除;**慎用**实心大红块 |
| **成功提示** | 不用大绿底 | `green` 字 / 小点 | — | 状态点、toast 文案 |

```css
.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
  border: none;
  border-radius: 6px;
  font-weight: 600;
}
.btn-secondary {
  background: var(--surface-2);
  color: var(--ink);
  border: 1px solid var(--border);
}
.btn-danger {
  background: transparent;
  color: var(--red);
  border: 1px solid var(--border);
}
```

**别做**:主按钮用蓝紫渐变;橙色上再叠冷白字(对比发灰)——用 `onAccent`。

---

## 4. 表单

| 部件 | 建议 |
|------|------|
| 输入框底 | `surface` 或略深于页面的 `bgDeep` |
| 边框默认 | `border` |
| 聚焦环 | `accent`(`outline` / `box-shadow`) |
| 标签 | `inkMuted` 小字 + `ink` 必填星可用 `red` |
| 校验错误 | 边框/`help` 用 `red`;不要整框刷成大红底 |
| 开关开 | 轨道 `accent`,拇指 `onAccent` / 浅色块 |

```css
input, select, textarea {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: 6px;
}
input:focus {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
```

---

## 5. 导航 / 侧栏 / Tab

| 部件 | 令牌 |
|------|------|
| 侧栏底 | `bgDeep` 或 `bg`(比主区深一档更稳) |
| 当前项 | 左条 `accent` **或** 底 `surface` + 字 `ink` |
| 非当前 | 字 `inkMuted`,悬停 `surface` |
| 顶栏 | `bg` / `surface`,底部分割 `border` |
| Badge | 小底 `surface2`,字 `accent` 或 `aqua` |

**原则**:导航不要整条刷成橙色;橙色只做「当前」指示。

---

## 6. 状态色(点 / 标签 / 图表)

| 语义 | 令牌 | 默认 | 用法 |
|------|------|------|------|
| 错 / 删 / 危 | `red` | `#fb4934` | 错误文案、危险图标、图表负向 |
| 成 / 过 | `green` | `#b8bb26` | 成功、通过(文案/点,少做满底按钮) |
| 信息 / 链 | `aqua` / `link` | `#8ec07c` | 链接、info、正向次强调 |
| 警告 | `accent2` | `#fabd2f` | 警告、注意(黄) |
| 次强调 | `blue` | `#83a598` | 信息系列、图表系列 2 |
| 特殊 | `purple` | `#d3869b` | 图表系列 3、标签 |

**图表**:背景 `bg`/`surface`,轴线 `border`,系列优先 `accent` → `aqua` → `blue` → `purple` → `red` → `green`。

---

## 7. 代码块 / 终端感面板

| 部件 | 令牌 |
|------|------|
| 代码底 | `codeBg` / `bgDeep` |
| 代码字 | `ink` |
| 关键字点缀 | `accent` / `aqua` / `red`(按高亮主题,别一次用满) |
| 行号 | `inkDim` |

工具型面板(监控台、参数板)优先 **暗色 classic**,信息密度高时用 `inkMuted` 降噪,不要把整页做成高饱和色块墙。

---

## 8. 一张对照表(classic-dark-medium)

| UI 部位 | 用 |
|---------|-----|
| 页面背景 | `--bg` |
| 卡片 / 弹窗 | `--surface` + `--border` |
| 主文字 | `--ink` |
| 说明文字 | `--ink-muted` |
| 主按钮 | `--accent` + `--on-accent` |
| 链接 | `--link` |
| 错误 | `--red` |
| 成功点 | `--green` |
| 警告 | `--accent-2` |
| 代码底 | `--code-bg` |

---

## 9. 反模式(看起来就不像 Gruvbox)

1. 把暖灰换成冷灰 / slate / `#111827`「伪深色」。  
2. 正文用半透明白字叠在黑底上(发雾)。  
3. 主按钮、链接、选中态**全用橙色**——链接请用 aqua。  
4. 大面积纯 `#000` 或纯白,丢掉 soft/medium 层次。  
5. 亮色模式仍用 bright 橙字(应改用 light 的 faded 强调色,见 `classic-light-*`)。  
6. 把 Material 的 `#e78a4e` 静默塞进 classic 背景却不声明家族。

---

## 10. 最小可用 HTML

```html
<link rel="stylesheet" href="css/all.css" />
<html data-theme="classic-dark-medium" class="gruvbox-apply">
<body>
  <main class="panel" style="margin:24px;padding:16px;max-width:420px">
    <h1 style="margin:0 0 8px">面板标题</h1>
    <p style="margin:0 0 12px;color:var(--ink-muted)">次要说明用 muted。</p>
    <button class="btn-primary" type="button">主操作</button>
    <p style="margin:12px 0 0"><a href="#">链接用 aqua</a></p>
  </main>
</body>
</html>
```

本地对照墙:[preview/index.html](../preview/index.html)  
令牌 JSON:`tokens/semantic/<id>.json`  
Agent 接线:根目录 [SKILL.md](../SKILL.md)
SKILL.md
---
name: gruvbox-theme
description: Apply official Gruvbox (and Material/Baby variants) color tokens to web panels, dashboards, and HTML apps. Use when the user asks for gruvbox, retro groove palette, warm dark tool UI, or to retheme a page/panel with classic-dark-medium / hard / soft / light / material.
---

# gruvbox-theme

Make any web UI look like **Gruvbox** without the agent inventing hex values.

## When to use

- User says gruvbox / 格鲁夫 / retro groove / warm dark panel
- Need a full palette (bg/surface/ink/accent + status colors)
- Switching contrast: hard / medium / soft, or dark / light
- Prefer Material (softer accents) or Baby (deeper chrome)

## When not to use

- Full brand design system with custom fonts/components → use a design skill
- Non-Gruvbox themes (Catppuccin, Nord, etc.)
- Terminal-only configs (this skill targets CSS/web; absolute hex still usable)

## Default

**`classic-dark-medium`**

| role | hex |
|------|-----|
| bg | `#282828` |
| bgDeep | `#1d2021` |
| surface | `#3c3836` |
| ink | `#ebdbb2` |
| accent | `#fe8019` |
| link/aqua | `#8ec07c` |

## Sub-themes (id → when)

| id | family | mode | contrast | pick when |
|----|--------|------|----------|-----------|
| `classic-dark-medium` | classic | dark | medium | **default** tool panels |
| `classic-dark-hard` | classic | dark | hard | max contrast, deeper bg0 `#1d2021` |
| `classic-dark-soft` | classic | dark | soft | softer bg0 `#32302f` |
| `classic-light-medium` | classic | light | medium | paper cream light |
| `classic-light-hard` | classic | light | hard | brightest light |
| `classic-light-soft` | classic | light | soft | muted light |
| `material-dark-medium` | material | dark | medium | softer Material accents |
| `material-dark-hard` | material | dark | hard | material + hard bg |
| `material-dark-soft` | material | dark | soft | material + soft bg |
| `baby-dark-medium` | baby | dark | medium | baby chrome / alt orange |

Contrast only swaps **bg0** (and related deep/surface steps). Accents stay bright_* in dark classic, faded_* in light classic.

## Files

| path | use |
|------|-----|
| `tokens/absolute.json` | Full official hex table |
| `tokens/index.json` | Catalog + default id |
| `tokens/semantic/<id>.json` | Semantic map for agents |
| `css/default.css` | One file: classic-dark-medium on `:root` + apply helpers |
| `css/all.css` | Absolute + all themes + apply |
| `css/themes.css` | Only `[data-theme="<id>"]` blocks |
| `preview/index.html` | Swatch wall |

## Agent apply steps

1. **Pick id** — user named a variant → that id; else `classic-dark-medium`.
2. **Read tokens** — `tokens/semantic/<id>.json` (or `tokens/index.json` to list).
3. **Write CSS variables** into the target project:
   - Prefer existing names if the project already uses `--bg/--ink/--accent` (Theme Lab style).
   - Else set both semantic and `--gb-*` aliases from the JSON `colors` object.
4. **Attach theme selector** on `<html>` or root:
   - `data-theme="<id>"` **or** class `theme-<id>`
   - Optionally add class `gruvbox-apply` on body for base chrome.
5. **Link or paste CSS**:
   - Fastest: copy contents of `css/default.css` (default only)
   - Multi-variant: link `css/all.css` and switch `data-theme`
6. **Map components** (full recipe: `docs/usage.md` / `docs/usage.en.md`):
   - page bg → `bg` / `bgDeep`
   - cards/panels → `surface` / `border` / `shadow`
   - body text → `ink`; secondary → `inkMuted` / `inkDim`
   - primary button / hot accent → `accent` + `onAccent` (one primary CTA per region)
   - links → `link` / `aqua` (**not** orange — orange is for primary actions)
   - danger → `red`; warn → `accent2` (yellow); success dots → `green`
7. **Do not invent hex.** If a color is missing, re-read absolute.json; do not approximate with cool grays or blue-purple SaaS gradients.
8. **Sanity check**: background warm charcoal/cream (not pure `#000` / cold gray); text cream/beige on dark; orange accent present; links aqua not orange.

### Minimal `:root` snippet (classic-dark-medium)

```css
:root {
  color-scheme: dark;
  --bg: #282828;
  --bg-deep: #1d2021;
  --surface: #3c3836;
  --surface-2: #504945;
  --border: #665c54;
  --ink: #ebdbb2;
  --ink-muted: #a89984;
  --ink-dim: #928374;
  --accent: #fe8019;
  --accent-2: #fabd2f;
  --on-accent: #1d2021;
  --red: #fb4934;
  --green: #b8bb26;
  --aqua: #8ec07c;
  --blue: #83a598;
  --purple: #d3869b;
  --link: #8ec07c;
  --code-bg: #1d2021;
}
```

### HTML switch

```html
<html data-theme="classic-dark-medium" class="gruvbox-apply">
  <link rel="stylesheet" href="path/to/css/all.css">
```

## Hard rules for agents

- Never replace Gruvbox warm neutrals with cool gray (`#111827`, Tailwind slate) unless the user abandons Gruvbox.
- Dark mode accents = **bright_***; light mode accents = **faded_*** (classic family).
- Material family uses different accent hex (e.g. orange `#e78a4e`); do not mix Material accents onto classic bg without saying so.
- Keep scrollbar subtle (transparent track, low-opacity thumb from ink) if styling chrome.

## Install (Claude Code)

```bash
git clone https://github.com/nakamotosai/gruvbox-theme.git ~/.claude/skills/gruvbox-theme
```

Or copy this folder into a project’s `.claude/skills/gruvbox-theme/`.

## Credits

- Classic palette: [morhetz/gruvbox](https://github.com/morhetz/gruvbox) (MIT/X11)
- Material accents: [sainnhe/gruvbox-material](https://github.com/sainnhe/gruvbox-material) (MIT)
- Baby reference: [luisiacc/gruvbox-baby](https://github.com/luisiacc/gruvbox-baby)

← 回目录