diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d2c62a..ad758df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,15 @@ jobs: - name: Discover installable Skills run: npm test + - name: Pack bundled theme sources + run: | + npx --yes --package=@codedrobe/core@latest codedrobe theme pack \ + skills/codedrobe-theme/assets/theme-starter/theme.json \ + --output /tmp/theme-starter.codedrobe-theme + npx --yes --package=@codedrobe/core@latest codedrobe theme pack \ + skills/codedrobe-theme/assets/examples/doll-sister/theme.json \ + --output /tmp/doll-sister.codedrobe-theme + - name: Reject unfinished Skill placeholders shell: bash run: | diff --git a/.gitignore b/.gitignore index 4cb9f11..9a50142 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,6 @@ wechat-codedrobe-launch.md cover-image/ imgs/ .baoyu-skills/ + +# Local verification screenshots +/examples/*.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9d00ed2..a236b3c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ 5. Keep runtime code out of Skills. Add CLI, adapters, package parsing, CDP, host settings, and deterministic runtime behavior to [`CodeDrobe/core`](https://github.com/CodeDrobe/core). 6. Include matching `agents/openai.yaml` metadata with a default prompt that names the Skill. 7. Do not add a root `SKILL.md`; it can shadow the multi-Skill catalog during discovery. -8. Do not commit generated themes, screenshots, credentials, tokens, private reference images, or application binaries. +8. Do not commit generated `.codedrobe-theme` packages, screenshots, credentials, tokens, private reference images, or application binaries. Curated source-theme assets are allowed only when their provenance and redistribution status are documented in a directly linked Skill reference. ## Validate diff --git a/README.md b/README.md index 17cd24c..9956db9 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,21 @@ bunx @codedrobe/core@latest apps Example: ```bash +codedrobe dom snapshot --app workbuddy --output /absolute/workbuddy-dom.json codedrobe apply --app workbuddy --theme /absolute/theme.codedrobe-theme codedrobe verify --app workbuddy --theme /absolute/theme.codedrobe-theme --screenshot /absolute/preview.png codedrobe restore --app workbuddy ``` +## Theme authoring resources + +The installed `codedrobe-theme` Skill includes two copyable source resources: + +- `assets/theme-starter/`: a complete neutral Codex/WorkBuddy CSS starting point. +- `assets/examples/doll-sister/`: the complete Doll Sister / 玩偶姐姐 multi-app theme with generated hero and texture artwork. + +Templates are not treated as permanent application DOM contracts. The Skill captures a privacy-preserving `codedrobe dom snapshot` from each live home/conversation context, selects semantic candidates from that snapshot, then packs, probes, applies, screenshots, and repairs the theme. + ## Repository layout ```text @@ -81,7 +91,8 @@ skills/ ├── codedrobe-theme/ │ ├── SKILL.md │ ├── agents/openai.yaml -│ └── references/ +│ ├── references/ +│ └── assets/ └── codedrobe-adapter-dev/ ├── SKILL.md ├── agents/openai.yaml diff --git a/README_zh.md b/README_zh.md index ea330a5..755042c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -69,11 +69,21 @@ bunx @codedrobe/core@latest apps 示例: ```bash +codedrobe dom snapshot --app workbuddy --output /absolute/workbuddy-dom.json codedrobe apply --app workbuddy --theme /absolute/theme.codedrobe-theme codedrobe verify --app workbuddy --theme /absolute/theme.codedrobe-theme --screenshot /absolute/preview.png codedrobe restore --app workbuddy ``` +## 主题制作资源 + +安装后的 `codedrobe-theme` Skill 包含两套可复制源码: + +- `assets/theme-starter/`:覆盖 Codex/WorkBuddy 主要界面的完整中性 CSS 起始模板。 +- `assets/examples/doll-sister/`:完整的“玩偶姐姐”双应用主题,包含生成的 hero 和 texture 素材。 + +模板不会被当作永久 DOM 合约。Skill 会在应用首页和会话页分别采集保护隐私的 `codedrobe dom snapshot`,从实机快照选择语义节点,再完成打包、预检、应用、截图和修正。 + ## 仓库结构 ```text @@ -81,7 +91,8 @@ skills/ ├── codedrobe-theme/ │ ├── SKILL.md │ ├── agents/openai.yaml -│ └── references/ +│ ├── references/ +│ └── assets/ └── codedrobe-adapter-dev/ ├── SKILL.md ├── agents/openai.yaml diff --git a/skills/codedrobe-adapter-dev/SKILL.md b/skills/codedrobe-adapter-dev/SKILL.md index 5ac129d..c82ac55 100644 --- a/skills/codedrobe-adapter-dev/SKILL.md +++ b/skills/codedrobe-adapter-dev/SKILL.md @@ -19,7 +19,7 @@ Work in the `@codedrobe/core` repository. Keep the adapter lightweight and prove 1. Inspect the current Core tree, adapter registry, tests, CLI help, and working-tree changes. 2. Locate the actual installed app and record its app version/build. Do not overwrite unrelated local changes. 3. Launch the real app with loopback CDP on a configurable, unoccupied port. Do not restart or terminate it without authorization. -4. Inspect `/json/list`, select the actual renderer, and collect semantic DOM evidence from every relevant route. +4. Inspect `/json/list`, select the actual renderer, and run `codedrobe dom snapshot` on every relevant route to collect privacy-preserving semantic DOM evidence. 5. Choose only cross-route landmarks for the adapter: root, sidebar/navigation, workspace/content, and composer/input. 6. Put app- or theme-specific layout nodes in theme verification contexts, not the adapter. 7. Implement the adapter, registry export, types, and focused tests. Add a renderer profile or host-settings module only when the application requires that behavior. diff --git a/skills/codedrobe-adapter-dev/references/dom-inspection.md b/skills/codedrobe-adapter-dev/references/dom-inspection.md index af51f3a..4b33ca5 100644 --- a/skills/codedrobe-adapter-dev/references/dom-inspection.md +++ b/skills/codedrobe-adapter-dev/references/dom-inspection.md @@ -10,6 +10,15 @@ Do not expose CDP on public interfaces. +After the adapter can identify the renderer, prefer Core's read-only snapshot over arbitrary page dumps: + +```bash +codedrobe dom snapshot --app --port \ + --max-nodes 1500 --output /absolute/dom-.json +``` + +Capture each route separately. The snapshot excludes text, form values, accessible names, links, and media sources while retaining selector candidates, match counts, geometry, computed style, and adapter landmark results. + ## Collect evidence Inspect every route the adapter must support: diff --git a/skills/codedrobe-theme/SKILL.md b/skills/codedrobe-theme/SKILL.md index 7be108b..6bac575 100644 --- a/skills/codedrobe-theme/SKILL.md +++ b/skills/codedrobe-theme/SKILL.md @@ -1,6 +1,6 @@ --- name: codedrobe-theme -description: Create, inspect, convert, apply, replace, verify, troubleshoot, update, or restore reversible CodeDrobe themes for supported Chromium/Electron AI desktop apps, including OpenAI Codex and Tencent WorkBuddy. Use for .codedrobe-theme packages, app-specific CDP ports or installation paths, theme images and CSS, DOM compatibility failures, screenshots, or migration from legacy .codex-theme files. +description: Create, inspect, convert, apply, replace, verify, troubleshoot, update, or restore reversible CodeDrobe themes for supported Chromium/Electron AI desktop apps, including OpenAI Codex and Tencent WorkBuddy. Use for .codedrobe-theme packages, live CDP DOM snapshots, starter or example CSS, app-specific ports or installation paths, theme images, DOM compatibility failures, screenshots, or migration from legacy .codex-theme files. --- # CodeDrobe Theme @@ -15,7 +15,9 @@ Use the published `@codedrobe/core` CLI as the only runtime. Keep this Skill ins - Codex: [references/codex.md](references/codex.md) - WorkBuddy: [references/workbuddy.md](references/workbuddy.md) 4. For theme creation, images, CSS, packaging, or legacy conversion, read [references/theme-authoring.md](references/theme-authoring.md). -5. For probe, verification, screenshots, missing nodes, CDP failures, or app updates, read [references/verification.md](references/verification.md). +5. For new or repaired CSS, read [references/dom-snapshot.md](references/dom-snapshot.md) and [references/css-templates.md](references/css-templates.md). +6. For the complete Doll Sister / 玩偶姐姐 example, read [references/doll-sister-example.md](references/doll-sister-example.md). +7. For probe, verification, screenshots, missing nodes, CDP failures, or app updates, read [references/verification.md](references/verification.md). ## Apply an existing theme @@ -37,11 +39,13 @@ codedrobe verify --app --theme /absolute/theme.codedrobe-theme --screen ## Create or repair a theme -1. Start from a source `theme.json`, app-specific CSS files, and local image assets. -2. Keep shared artwork in named `images`; keep app-specific selectors under the relevant target CSS. -3. Keep adapter landmarks generic and theme layout assumptions in theme-specific verification nodes. -4. Pack with Core, inspect the output, then probe and apply it on a real renderer. -5. Iterate from screenshots. Do not claim success from static CSS or package validation alone. +1. Copy `assets/theme-starter/` for a neutral base or `assets/examples/doll-sister/` for a complete multi-app example. Never edit the installed Skill in place. +2. Open each app context the theme will style and capture a separate `codedrobe dom snapshot`; do not infer selectors from the template alone. +3. Select semantic candidates from the snapshot, then write app-specific CSS under `html.codedrobe-host-`. +4. Keep shared artwork in named `images`; keep app-specific selectors under the relevant target CSS. +5. Keep adapter landmarks generic and theme layout assumptions in theme-specific verification nodes. +6. Pack with Core, inspect the output, then probe and apply it on a real renderer. +7. Iterate from home and conversation screenshots. Do not claim success from static CSS, a snapshot, or package validation alone. ## Restore diff --git a/skills/codedrobe-theme/assets/examples/doll-sister/assets/hero.png b/skills/codedrobe-theme/assets/examples/doll-sister/assets/hero.png new file mode 100644 index 0000000..b689d1a Binary files /dev/null and b/skills/codedrobe-theme/assets/examples/doll-sister/assets/hero.png differ diff --git a/skills/codedrobe-theme/assets/examples/doll-sister/assets/texture.png b/skills/codedrobe-theme/assets/examples/doll-sister/assets/texture.png new file mode 100644 index 0000000..b667a82 Binary files /dev/null and b/skills/codedrobe-theme/assets/examples/doll-sister/assets/texture.png differ diff --git a/skills/codedrobe-theme/assets/examples/doll-sister/codex.css b/skills/codedrobe-theme/assets/examples/doll-sister/codex.css new file mode 100644 index 0000000..d4b9e1a --- /dev/null +++ b/skills/codedrobe-theme/assets/examples/doll-sister/codex.css @@ -0,0 +1,530 @@ +:root.codedrobe-codex-skin { + color-scheme: light !important; + --doll-ink: #49384f; + --doll-ink-soft: #765f7d; + --doll-plum: #76507e; + --doll-lavender: #b688ba; + --doll-pink: #dc9fb6; + --doll-blush: #f8e8ed; + --doll-cream: #fffaf7; + --doll-line: rgba(145, 99, 151, .24); + --doll-shadow: rgba(86, 55, 91, .14); + + --color-token-bg-primary: #fff9f7 !important; + --color-token-bg-secondary: rgba(255, 250, 248, .94) !important; + --color-token-bg-tertiary: rgba(248, 232, 237, .72) !important; + --color-token-main-surface-primary: #fffaf8 !important; + --color-token-side-bar-background: #fff7f5 !important; + --color-token-foreground: #49384f !important; + --color-token-text-primary: #49384f !important; + --color-token-text-secondary: rgba(73, 56, 79, .72) !important; + --color-token-text-tertiary: rgba(73, 56, 79, .58) !important; + --color-token-description-foreground: #765f7d !important; + --color-token-icon-foreground: #76507e !important; + --color-token-input-background: rgba(255, 253, 251, .95) !important; + --color-token-input-foreground: #49384f !important; + --color-token-input-placeholder-foreground: rgba(73, 56, 79, .48) !important; + --color-token-input-border: rgba(145, 99, 151, .25) !important; + --color-token-border: rgba(145, 99, 151, .18) !important; + --color-token-border-default: rgba(145, 99, 151, .18) !important; + --color-token-border-heavy: rgba(145, 99, 151, .28) !important; + --color-token-border-light: rgba(145, 99, 151, .11) !important; + --color-token-list-hover-background: rgba(220, 159, 182, .16) !important; + --color-token-list-active-selection-background: rgba(203, 166, 207, .28) !important; + --color-token-list-active-selection-foreground: #49384f !important; + --color-token-toolbar-hover-background: rgba(220, 159, 182, .18) !important; + --color-token-button-background: #8e6397 !important; + --color-token-button-foreground: #fff !important; + --color-token-button-border: rgba(118, 80, 126, .28) !important; + --color-token-link: #895b92 !important; + --color-token-text-link-foreground: #895b92 !important; + --color-token-text-link-active-foreground: #6e4078 !important; + --color-token-primary: #895b92 !important; + --color-token-focus-border: rgba(142, 99, 151, .62) !important; + --color-token-dropdown-background: rgba(255, 250, 248, .98) !important; + --color-token-dropdown-foreground: #49384f !important; + --color-token-menu-background: rgba(255, 250, 248, .98) !important; + --color-token-menu-border: rgba(145, 99, 151, .20) !important; + --color-token-checkbox-background: #fffaf8 !important; + --color-token-checkbox-border: rgba(145, 99, 151, .28) !important; + --color-token-checkbox-foreground: #76507e !important; + --color-token-badge-background: rgba(182, 136, 186, .20) !important; + --color-token-badge-foreground: #6f4778 !important; + --color-token-scrollbar-slider-background: rgba(182, 136, 186, .22) !important; + --color-token-scrollbar-slider-hover-background: rgba(182, 136, 186, .34) !important; + --color-token-scrollbar-slider-active-background: rgba(182, 136, 186, .46) !important; + --color-token-conversation-header: rgba(73, 56, 79, .40) !important; + --color-token-conversation-body: rgba(73, 56, 79, .72) !important; + --color-token-conversation-summary-leading: rgba(73, 56, 79, .68) !important; + --color-token-conversation-summary-trailing: rgba(73, 56, 79, .45) !important; + --color-token-non-assistant-body-descendant: rgba(73, 56, 79, .64) !important; + --color-token-text-preformat-foreground: #664d6e !important; + --color-token-text-preformat-background: rgba(236, 215, 231, .54) !important; + --color-token-text-code-block-background: rgba(255, 252, 250, .88) !important; +} + +html.codedrobe-codex-skin body { + background: + linear-gradient(rgba(255, 250, 248, .86), rgba(253, 242, 245, .92)), + var(--codedrobe-image-texture) center / 720px auto repeat !important; + color: var(--doll-ink) !important; + font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei UI", sans-serif !important; +} + +html.codedrobe-codex-skin body::before { + content: ""; + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + background: + radial-gradient(circle at 86% 7%, rgba(255, 255, 255, .96) 0 2px, transparent 3px), + radial-gradient(circle at 14% 18%, rgba(220, 159, 182, .46) 0 1px, transparent 2px); + background-size: 83px 83px, 67px 67px; + opacity: .44; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel { + background: + linear-gradient(180deg, rgba(255, 251, 249, .94), rgba(249, 233, 239, .91)), + var(--codedrobe-image-texture) center / 620px auto !important; + border: 1px solid rgba(145, 99, 151, .22) !important; + border-left: 0 !important; + border-radius: 0 24px 24px 0 !important; + box-shadow: 12px 0 34px rgba(86, 55, 91, .09), inset -1px 0 rgba(255, 255, 255, .92) !important; + color: var(--doll-ink) !important; + backdrop-filter: blur(18px) saturate(1.06) !important; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel nav { + background: transparent !important; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel :is(a, button, div, p, span, svg) { + color: var(--doll-ink) !important; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel svg { + stroke: currentColor !important; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel button { + color: var(--doll-ink) !important; + border-radius: 12px !important; + transition: transform .18s ease, background .18s ease, box-shadow .18s ease !important; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel button:hover { + background: linear-gradient(90deg, rgba(238, 216, 234, .70), rgba(252, 241, 244, .82)) !important; + box-shadow: inset 0 0 0 1px rgba(145, 99, 151, .14), 0 4px 14px rgba(86, 55, 91, .07) !important; + transform: translateX(2px); +} + +html.codedrobe-codex-skin aside.app-shell-left-panel button[aria-label^="切换模式"] { + background: transparent !important; + border-color: transparent !important; + color: #76507e !important; + font: 700 20px/1.1 "Iowan Old Style", "Songti SC", serif !important; + text-shadow: 0 2px 12px rgba(182, 136, 186, .24); +} + +html.codedrobe-codex-skin aside.app-shell-left-panel button[aria-label^="切换模式"]::after { + content: " ✦"; + color: #d59ab1; +} + +html.codedrobe-codex-skin aside.app-shell-left-panel [class~="bg-token-list-hover-background"], +html.codedrobe-codex-skin aside.app-shell-left-panel [aria-current="page"] { + background: linear-gradient(90deg, rgba(235, 211, 232, .90), rgba(252, 240, 244, .92)) !important; + border: 1px solid rgba(145, 99, 151, .25) !important; + box-shadow: 0 5px 17px rgba(86, 55, 91, .09), inset 0 0 0 2px rgba(255, 255, 255, .46) !important; +} + +html.codedrobe-codex-skin main.main-surface { + position: relative; + background: + linear-gradient(rgba(255, 251, 249, .92), rgba(255, 247, 247, .94)), + var(--codedrobe-image-texture) center / 840px auto !important; + border: 1px solid rgba(145, 99, 151, .18) !important; + border-right: 0 !important; + border-bottom: 0 !important; + border-radius: 24px 0 0 0 !important; + box-shadow: inset 0 1px rgba(255, 255, 255, .96), -8px 0 28px rgba(86, 55, 91, .07) !important; + overflow: hidden !important; +} + +html.codedrobe-codex-skin main.main-surface > header.app-header-tint { + background: + linear-gradient(90deg, rgba(255, 251, 249, .96), rgba(250, 235, 241, .92), rgba(236, 216, 235, .87)) !important; + border-bottom: 1px solid rgba(145, 99, 151, .20) !important; + color: var(--doll-ink) !important; + backdrop-filter: blur(18px) saturate(1.08) !important; +} + +html.codedrobe-codex-skin [role="main"] { + background: transparent !important; + color: var(--doll-ink) !important; + scrollbar-color: rgba(182, 136, 186, .42) transparent; +} + +#codedrobe-codex-skin-chrome { + position: fixed; + z-index: 31; + pointer-events: none; + overflow: hidden; + border-radius: 24px 0 0 0; +} + +.dream-brand { + position: absolute; + left: 24px; + top: 3px; + height: 42px; + display: none; + align-items: center; + gap: 10px; + color: #704779; + text-shadow: 0 1px 0 white; +} + +#codedrobe-codex-skin-chrome.dream-home-shell .dream-brand { display: flex; } +.dream-brand .dream-note { font-size: 28px; color: #bc89c0; filter: drop-shadow(0 3px 5px rgba(86, 55, 91, .18)); } +.dream-brand b { display: block; font: 700 16px/1.05 "Iowan Old Style", "Songti SC", serif; letter-spacing: .07em; } +.dream-brand small { display: block; margin-top: 4px; color: #8f748f; font-size: 10px; letter-spacing: .05em; } + +.dream-signature { + position: absolute; + right: 86px; + top: 7px; + display: none; + color: #8b5f91; + font: italic 19px/1.2 "Snell Roundhand", "Segoe Script", cursive; + text-shadow: 0 0 8px white, 0 2px 8px rgba(86, 55, 91, .15); + transform: rotate(-3deg); +} + +#codedrobe-codex-skin-chrome.dream-home-shell .dream-signature { display: block; } + +.dream-sparkles { position: absolute; inset: 49px 0 0; opacity: .74; } +.dream-sparkles i { position: absolute; width: 5px; height: 5px; border-radius: 50%; background: #fff9dd; box-shadow: 0 0 10px 3px rgba(196, 151, 188, .34); animation: doll-twinkle 3.8s ease-in-out infinite; } +.dream-sparkles i::before, +.dream-sparkles i::after { content: ""; position: absolute; left: 2px; top: -6px; width: 1px; height: 17px; background: linear-gradient(transparent, rgba(255, 255, 255, .98), transparent); } +.dream-sparkles i::after { transform: rotate(90deg); } +.dream-sparkles i:nth-child(1) { left: 7%; top: 12%; } +.dream-sparkles i:nth-child(2) { left: 29%; top: 6%; animation-delay: .8s; } +.dream-sparkles i:nth-child(3) { left: 54%; top: 18%; animation-delay: 1.5s; } +.dream-sparkles i:nth-child(4) { left: 78%; top: 8%; animation-delay: 2.1s; } +.dream-sparkles i:nth-child(5) { left: 92%; top: 28%; animation-delay: 2.8s; } +.dream-sparkles i:nth-child(6) { left: 66%; top: 68%; animation-delay: 1.1s; } + +@keyframes doll-twinkle { + 0%, 100% { opacity: .42; transform: scale(.82); } + 50% { opacity: 1; transform: scale(1.16); } +} + +.dream-polaroid { + position: absolute; + right: 14px; + bottom: 76px; + width: 118px; + height: 152px; + display: none; + background-image: var(--codedrobe-image-hero); + background-size: 285% auto; + background-position: 82% center; + border: 8px solid rgba(255, 253, 252, .97); + border-bottom-width: 22px; + border-radius: 3px; + box-shadow: 0 10px 24px rgba(86, 55, 91, .18), 0 0 0 1px rgba(145, 99, 151, .20); + transform: rotate(-6deg); +} + +#codedrobe-codex-skin-chrome.dream-home-shell .dream-polaroid { display: block; } +.dream-polaroid::before { content: "🎀"; position: absolute; left: -23px; top: -25px; font-size: 29px; filter: drop-shadow(0 3px 5px rgba(86, 55, 91, .22)); } + +.dream-ribbon { + position: absolute; + left: 50%; + bottom: 69px; + display: none; + align-items: center; + gap: 8px; + color: #a876af; + font-size: 27px; + transform: translateX(-50%); + filter: drop-shadow(0 4px 6px rgba(86, 55, 91, .16)); +} + +#codedrobe-codex-skin-chrome.dream-home-shell .dream-ribbon { display: flex; } +.dream-ribbon span { font-size: 14px; color: #d59ab1; } + +html.codedrobe-codex-skin .dream-home { + --thread-content-max-width: min(980px, calc(100cqw - 44px)) !important; + overflow-x: hidden !important; +} + +.dream-home > div:first-child { + padding-top: 15px !important; + min-height: 100% !important; +} + +.dream-home > div:first-child > div:first-child { + flex: 0 0 440px !important; + min-height: 440px !important; + align-items: flex-start !important; + padding-bottom: 0 !important; +} + +.dream-home > div:first-child > div:first-child > div:first-child { + position: relative !important; + isolation: isolate; + width: calc(100% - 42px) !important; + max-width: none !important; + height: 266px !important; + min-height: 266px !important; + flex: 0 1 auto !important; + padding: 0 !important; + border: 1px solid rgba(145, 99, 151, .30) !important; + border-radius: 28px !important; + overflow: visible !important; + background-color: #fff9f7 !important; + background-image: + linear-gradient(90deg, #fff9f7 0%, rgba(255, 249, 247, .99) 46%, rgba(255, 249, 247, .76) 62%, rgba(255, 249, 247, .08) 82%), + var(--codedrobe-image-hero) !important; + background-repeat: no-repeat, no-repeat !important; + background-size: 100% 100%, auto 220% !important; + background-position: center, right 12% !important; + box-shadow: 0 16px 38px rgba(86, 55, 91, .16), inset 0 0 0 4px rgba(255, 255, 255, .34) !important; +} + +.dream-home > div:first-child > div:first-child > div:first-child::before { + content: ""; + position: absolute; + z-index: 0; + inset: 0 auto 0 0; + width: 64%; + border-radius: 27px 0 0 27px; + pointer-events: none; + background: linear-gradient(90deg, rgba(255, 250, 248, .97) 0%, rgba(255, 250, 248, .91) 58%, rgba(255, 250, 248, .62) 82%, transparent 100%); +} + +.dream-home > div:first-child > div:first-child > div:first-child > div:first-child { + position: relative; + z-index: 1; + height: 100%; + align-items: center !important; + justify-content: flex-start !important; + padding-left: 42px; +} + +.dream-home > div:first-child > div:first-child > div:first-child > div:first-child > div:first-child { + width: 55% !important; + align-items: flex-start !important; + gap: 0 !important; +} + +.dream-home [data-testid="home-icon"] { display: none !important; } + +.dream-home [data-feature="game-source"] { + display: flex !important; + flex-direction: column !important; + align-items: flex-start !important; + max-width: 100% !important; + color: #49384f !important; + font: 750 clamp(21px, 2.1vw, 31px)/1.28 "Iowan Old Style", "Songti SC", serif !important; + text-align: left !important; + text-shadow: 0 1px 0 rgba(255, 255, 255, .94); + opacity: 1 !important; + pointer-events: auto !important; +} + +.dream-home [data-feature="game-source"]::after { + content: var(--dream-tagline, "把灵感缝进每一天 ♡"); + display: block; + margin-top: 14px; + color: #765f7d; + font: 500 14px/1.55 "Avenir Next", "PingFang SC", sans-serif; + letter-spacing: .025em; +} + +.dream-home [data-feature="game-source"] button { + margin: 0 5px; + padding: 3px 10px 4px; + border: 1px solid rgba(145, 99, 151, .27); + border-radius: 999px; + background: rgba(255, 253, 251, .74); + color: #76507e !important; + text-decoration-color: rgba(145, 99, 151, .46) !important; + text-underline-offset: 5px; + box-shadow: inset 0 0 14px rgba(255, 255, 255, .72); +} + +.dream-home [data-feature="game-source"] button::before { + content: var(--dream-project-prefix, "灵感衣橱 · "); + font-size: .46em; + font-weight: 650; + vertical-align: middle; + opacity: .88; +} + +.dream-home > div:first-child > div:first-child > div:first-child > div:nth-child(2) { + left: 14px !important; + right: 14px !important; + top: 100% !important; + margin-top: 14px !important; +} + +.dream-home .group\/home-suggestions { overflow: visible !important; } + +.dream-home .group\/home-suggestions button { + position: relative !important; + min-height: 128px !important; + padding: 15px 13px 12px !important; + align-items: stretch !important; + justify-content: flex-start !important; + text-align: center !important; + border: 1px solid rgba(145, 99, 151, .25) !important; + border-radius: 24px !important; + background: + linear-gradient(rgba(255, 253, 251, .91), rgba(251, 239, 244, .92)), + var(--codedrobe-image-texture) center / 520px auto !important; + color: #49384f !important; + font-weight: 650 !important; + line-height: 1.45 !important; + box-shadow: 0 9px 20px rgba(86, 55, 91, .10), inset 0 0 0 3px rgba(255, 255, 255, .56) !important; + transition: transform .20s ease, box-shadow .20s ease !important; +} + +.dream-home .group\/home-suggestions button:hover { + transform: translateY(-5px) rotate(-.3deg) !important; + box-shadow: 0 15px 28px rgba(86, 55, 91, .16), 0 0 0 2px rgba(182, 136, 186, .14) !important; +} + +.dream-home .group\/home-suggestions button > span:first-child > span:first-child { + width: 40px; + height: 40px; + display: grid !important; + place-items: center; + margin: 0 auto; + border-radius: 50%; + color: white !important; + background: linear-gradient(145deg, #d9a4bd, #a976b0); + box-shadow: 0 0 0 7px rgba(236, 215, 231, .70), 0 6px 13px rgba(86, 55, 91, .19); +} + +.dream-home .group\/home-suggestions button svg { + width: 21px !important; + height: 21px !important; + color: white !important; +} + +.dream-home .group\/home-suggestions button > span:first-child { justify-content: center !important; } +.dream-home .group\/home-suggestions button > span:last-child { align-items: center !important; text-align: center !important; } + +html.codedrobe-codex-skin .composer-surface-chrome { + border: 1px solid rgba(145, 99, 151, .30) !important; + border-radius: 27px !important; + background: + linear-gradient(145deg, rgba(255, 253, 251, .96), rgba(248, 231, 238, .93)), + var(--codedrobe-image-texture) center / 620px auto !important; + box-shadow: 0 12px 29px rgba(86, 55, 91, .13), inset 0 0 0 4px rgba(255, 255, 255, .52) !important; + backdrop-filter: blur(18px) saturate(1.06) !important; + overflow: visible !important; + color: var(--doll-ink) !important; +} + +html.codedrobe-codex-skin .composer-surface-chrome::before { + content: "🎀"; + position: absolute; + left: -16px; + top: -18px; + z-index: 20; + width: 32px; + height: 32px; + display: grid; + place-items: center; + border-radius: 50%; + font-size: 18px; + background: linear-gradient(145deg, #f7dce6, #c99dce); + box-shadow: 0 5px 14px rgba(86, 55, 91, .18), 0 0 0 3px rgba(255, 255, 255, .72); +} + +html.codedrobe-codex-skin .ProseMirror { + color: #49384f !important; + caret-color: #895b92 !important; +} + +html.codedrobe-codex-skin button[class~="bg-token-foreground"] { + background: linear-gradient(145deg, #bd8fc2, #86578f) !important; + color: white !important; + box-shadow: 0 6px 14px rgba(86, 55, 91, .22) !important; +} + +html.codedrobe-codex-skin :is(article, [data-message-author-role]) { + border-radius: 20px; + color: var(--doll-ink) !important; +} + +html.codedrobe-codex-skin :is(article, [data-message-author-role]) :is(p, span, li, h1, h2, h3, h4, h5, h6) { + color: inherit; +} + +html.codedrobe-codex-skin pre, +html.codedrobe-codex-skin code { + border-color: rgba(145, 99, 151, .16) !important; +} + +.dream-home div:has(> .horizontal-scroll-fade-mask .group\/project-selector) { + position: relative; + padding-top: 29px !important; + border: 1px solid rgba(145, 99, 151, .22); + border-bottom: 0; + background: linear-gradient(180deg, rgba(255, 253, 251, .96), rgba(248, 231, 238, .91)) !important; +} + +.dream-home div:has(> .horizontal-scroll-fade-mask .group\/project-selector)::before { + content: var(--dream-project-label, "🎀 选择今天的创作项目"); + position: absolute; + left: 13px; + top: 6px; + z-index: 2; + color: #76507e; + font-size: 13px; + font-weight: 700; + letter-spacing: .04em; + text-shadow: 0 1px white; + white-space: nowrap; +} + +.dream-home .group\/project-selector > button { + border-color: rgba(145, 99, 151, .25) !important; + background: linear-gradient(135deg, rgba(255, 255, 255, .96), rgba(245, 226, 236, .90)) !important; + color: #6f5175 !important; + box-shadow: 0 4px 11px rgba(86, 55, 91, .08) !important; +} + +@media (max-width: 1120px) { + .dream-polaroid { display: none !important; } + .dream-ribbon { bottom: 70px; font-size: 24px; } + .dream-home { --thread-content-max-width: min(860px, calc(100cqw - 30px)) !important; } + .dream-home > div:first-child > div:first-child > div:first-child { width: calc(100% - 28px) !important; } +} + +@media (max-width: 900px) { + .dream-signature { display: none !important; } + .dream-brand { left: 15px; } + .dream-brand b { font-size: 13px; } + .dream-home > div:first-child > div:first-child { flex-basis: 398px !important; min-height: 398px !important; } + .dream-home > div:first-child > div:first-child > div:first-child { height: 226px !important; min-height: 226px !important; } + .dream-home > div:first-child > div:first-child > div:first-child > div:first-child { padding-left: 26px; } + .dream-home > div:first-child > div:first-child > div:first-child > div:first-child > div:first-child { width: 66% !important; } + .dream-home [data-feature="game-source"] { font-size: 18px !important; } + .dream-home [data-feature="game-source"]::after { font-size: 12px; margin-top: 10px; } + .dream-home .group\/home-suggestions button { min-height: 114px !important; font-size: 12px !important; } +} + +@media (prefers-reduced-motion: reduce) { + .dream-sparkles i { animation: none !important; } + html.codedrobe-codex-skin aside.app-shell-left-panel button, + .dream-home .group\/home-suggestions button { transition: none !important; } +} diff --git a/skills/codedrobe-theme/assets/examples/doll-sister/theme.json b/skills/codedrobe-theme/assets/examples/doll-sister/theme.json new file mode 100644 index 0000000..2af7780 --- /dev/null +++ b/skills/codedrobe-theme/assets/examples/doll-sister/theme.json @@ -0,0 +1,120 @@ +{ + "schemaVersion": 1, + "id": "doll-sister", + "displayName": "Doll Sister / 玩偶姐姐", + "version": "1.0.0", + "images": { + "hero": "assets/hero.png", + "texture": "assets/texture.png" + }, + "copy": { + "brandTitle": "玩偶姐姐专属定制皮肤", + "brandSubtitle": "Codex App 娃娃屋限定版 ✦", + "signature": "Doll Sister ♡", + "tagline": "与玩偶姐姐一起,把灵感缝进每一行代码 ♡", + "projectPrefix": "灵感衣橱 · ", + "projectLabel": "🎀 选择今天的创作项目", + "ribbon": "🎀" + }, + "targets": { + "codex": { + "css": "codex.css", + "options": { + "rendererProfile": "codex-theme-v1", + "baseTheme": { + "mode": "light", + "codeTheme": "codex", + "accent": "#B688BA", + "contrast": 76, + "ink": "#4C3658", + "surface": "#FFF9F7", + "opaqueWindows": true, + "fonts": { + "windowsCode": "Cascadia Code", + "windowsUi": "Microsoft YaHei UI", + "macCode": "SF Mono", + "macUi": "PingFang SC" + }, + "semanticColors": { + "diffAdded": "#CDE8D7", + "diffRemoved": "#F2CCD7", + "skill": "#C39AC9" + } + } + }, + "verification": { + "contexts": [ + { + "name": "home", + "when": { + "any": ["[role='main']:has([data-testid='home-icon'])"] + }, + "required": [ + { + "name": "home-hero-shell", + "any": ["[role='main']:has([data-testid='home-icon']) > div:first-child > div:first-child > div:first-child"] + } + ], + "recommended": [ + { + "name": "home-suggestions", + "any": [".group\\/home-suggestions"] + } + ] + } + ] + } + }, + "workbuddy": { + "css": "workbuddy.css", + "verification": { + "required": [ + { + "name": "chat-surface", + "any": [".chat-container", ".wb-cb-chat"] + } + ], + "contexts": [ + { + "name": "home", + "when": { + "any": [".wb-home-page"] + }, + "required": [ + { + "name": "home-hero", + "any": [".wb-home-header"] + }, + { + "name": "home-composer", + "any": [".wb-home-composer"] + } + ], + "recommended": [ + { + "name": "scene-tabs", + "any": [".wb-scene-tabs"] + }, + { + "name": "quick-actions", + "any": [".quick-actions"] + } + ] + }, + { + "name": "conversation", + "when": { + "any": [".chat-container:not(.chat-container--welcome)"] + }, + "required": [ + { + "name": "conversation-composer-shell", + "any": [".chat-container:not(.chat-container--welcome) section:has([role='textbox'][contenteditable='true'])"] + } + ] + } + ] + } + } + } +} diff --git a/skills/codedrobe-theme/assets/examples/doll-sister/workbuddy.css b/skills/codedrobe-theme/assets/examples/doll-sister/workbuddy.css new file mode 100644 index 0000000..0912fa2 --- /dev/null +++ b/skills/codedrobe-theme/assets/examples/doll-sister/workbuddy.css @@ -0,0 +1,521 @@ +:root.codedrobe-host-workbuddy { + color-scheme: light !important; + --doll-wb-ink: #4b3851; + --doll-wb-muted: #806b84; + --doll-wb-plum: #76507e; + --doll-wb-lavender: #b688ba; + --doll-wb-pink: #d99ab3; + --doll-wb-cream: #fffaf7; + --doll-wb-line: rgba(145, 99, 151, .23); + --doll-wb-shadow: rgba(86, 55, 91, .13); +} + +html.codedrobe-host-workbuddy, +html.codedrobe-host-workbuddy body, +html.codedrobe-host-workbuddy #root, +html.codedrobe-host-workbuddy .teams-container { + background: + linear-gradient(rgba(255, 250, 248, .88), rgba(251, 239, 244, .92)), + var(--codedrobe-image-texture) center / 720px auto repeat !important; + color: var(--doll-wb-ink) !important; + font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei UI", sans-serif !important; +} + +html.codedrobe-host-workbuddy body::before { + content: ""; + position: fixed; + inset: 0; + z-index: 0; + pointer-events: none; + background: + radial-gradient(circle at 86% 8%, rgba(255, 255, 255, .98) 0 2px, transparent 3px), + radial-gradient(circle at 16% 19%, rgba(220, 159, 182, .42) 0 1px, transparent 2px); + background-size: 83px 83px, 67px 67px; + opacity: .42; +} + +html.codedrobe-host-workbuddy .conversation-sidebar, +html.codedrobe-host-workbuddy .conversation-list { + background: + linear-gradient(180deg, rgba(255, 252, 250, .95), rgba(248, 231, 238, .92)), + var(--codedrobe-image-texture) center / 590px auto repeat !important; + border-right: 1px solid var(--doll-wb-line) !important; + box-shadow: 12px 0 32px rgba(86, 55, 91, .08), inset -1px 0 rgba(255, 255, 255, .92) !important; + color: var(--doll-wb-ink) !important; + backdrop-filter: blur(18px) saturate(1.06) !important; +} + +html.codedrobe-host-workbuddy .conversation-sidebar :is(a, button, div, p, span, svg) { + color: var(--doll-wb-ink) !important; +} + +html.codedrobe-host-workbuddy .conversation-sidebar svg { + stroke: currentColor !important; +} + +html.codedrobe-host-workbuddy :is( + .conversation-list-topbar, + .conversation-list-header, + .conversation-list-content, + .conversation-list-footer +) { + background: transparent !important; +} + +html.codedrobe-host-workbuddy .conversation-list-logo { + color: #754e7d !important; + font-family: "Iowan Old Style", "Songti SC", serif !important; + font-weight: 750 !important; + letter-spacing: .02em; + text-shadow: 0 1px 0 white; +} + +html.codedrobe-host-workbuddy .conversation-list-logo::after { + content: " ♡"; + color: #d391aa; +} + +html.codedrobe-host-workbuddy :is( + .conversation-list-version-badge, + .conversation-section-label, + .conversation-show-more-button, + .conversation-list-tab-button-sub +) { + color: rgba(75, 56, 81, .52) !important; +} + +html.codedrobe-host-workbuddy .conversation-list-tab-button, +html.codedrobe-host-workbuddy .conversation-agent-card, +html.codedrobe-host-workbuddy .conversation-list-topbar button { + border: 1px solid transparent !important; + border-radius: 12px !important; + background: transparent !important; + transition: transform .18s ease, background .18s ease, box-shadow .18s ease !important; +} + +html.codedrobe-host-workbuddy :is( + .conversation-list-tab-button:hover, + .conversation-agent-card:hover, + .conversation-list-topbar button:hover +) { + background: linear-gradient(90deg, rgba(237, 214, 232, .75), rgba(253, 242, 246, .88)) !important; + border-color: rgba(145, 99, 151, .15) !important; + box-shadow: 0 4px 13px rgba(86, 55, 91, .07) !important; + transform: translateX(2px); +} + +html.codedrobe-host-workbuddy :is( + .conversation-list-tab-button.active, + .conversation-agent-card[aria-selected="true"], + .conversation-agent-card.active +) { + background: linear-gradient(90deg, rgba(231, 204, 226, .93), rgba(251, 237, 242, .94)) !important; + border-color: rgba(145, 99, 151, .27) !important; + box-shadow: 0 5px 16px rgba(86, 55, 91, .09), inset 0 0 0 2px rgba(255, 255, 255, .46) !important; +} + +html.codedrobe-host-workbuddy :is( + .teams-content-wrapper, + .teams-main-content, + .main-content, + .chat-container, + .wb-cb-chat +) { + background: transparent !important; + color: var(--doll-wb-ink) !important; +} + +html.codedrobe-host-workbuddy .teams-content-wrapper { + position: relative; + border-radius: 26px 0 0 0; + box-shadow: inset 1px 1px rgba(255, 255, 255, .92), -7px 0 25px rgba(86, 55, 91, .06); + overflow: hidden; +} + +html.codedrobe-host-workbuddy .main-content--welcome { + background: + linear-gradient(rgba(255, 251, 249, .90), rgba(255, 247, 248, .94)), + var(--codedrobe-image-texture) center / 820px auto repeat !important; +} + +html.codedrobe-host-workbuddy .wb-home-page { + width: min(860px, calc(100% - 32px)) !important; + max-width: none !important; + min-height: 638px !important; + height: 638px !important; + display: flex !important; + flex-direction: column !important; + gap: 13px !important; + justify-content: flex-start !important; + overflow: visible !important; +} + +html.codedrobe-host-workbuddy .wb-home-header { + position: relative !important; + isolation: isolate; + box-sizing: border-box !important; + width: 100% !important; + height: 244px !important; + min-height: 244px !important; + display: flex !important; + flex: 0 0 244px !important; + flex-direction: column !important; + align-items: flex-start !important; + justify-content: center !important; + padding: 0 0 0 42px !important; + overflow: hidden !important; + border: 1px solid rgba(145, 99, 151, .30) !important; + border-radius: 28px !important; + background-color: #fff9f7 !important; + background-image: + linear-gradient(90deg, #fff9f7 0%, rgba(255, 249, 247, .99) 45%, rgba(255, 249, 247, .75) 62%, rgba(255, 249, 247, .06) 83%), + var(--codedrobe-image-hero) !important; + background-repeat: no-repeat, no-repeat !important; + background-size: 100% 100%, auto 222% !important; + background-position: center, right 12% !important; + box-shadow: 0 16px 38px rgba(86, 55, 91, .15), inset 0 0 0 4px rgba(255, 255, 255, .34) !important; +} + +html.codedrobe-host-workbuddy .wb-home-header::before { + content: ""; + position: absolute; + inset: 0; + z-index: -1; + pointer-events: none; + background: + radial-gradient(circle at 55% 27%, rgba(255, 249, 219, .95) 0 2px, transparent 3px), + radial-gradient(circle at 28% 75%, rgba(218, 158, 182, .50) 0 1px, transparent 2px); + background-size: 73px 73px, 91px 91px; + opacity: .72; +} + +html.codedrobe-host-workbuddy .wb-home-header::after { + content: "Doll Sister ♡ WorkBuddy"; + position: absolute; + left: 42px; + bottom: 28px; + color: #9a719f; + font: italic 15px/1.2 "Snell Roundhand", "Segoe Script", cursive; + letter-spacing: .04em; + text-shadow: 0 1px white; +} + +html.codedrobe-host-workbuddy .wb-home-header__title, +html.codedrobe-host-workbuddy .wb-home-header__subtitle { + width: 56% !important; + height: auto !important; + margin: 0 !important; + text-align: left !important; + color: var(--doll-wb-ink) !important; + text-shadow: 0 1px rgba(255, 255, 255, .96) !important; +} + +html.codedrobe-host-workbuddy .wb-home-header__title { + font-size: 0 !important; + line-height: 1 !important; +} + +html.codedrobe-host-workbuddy .wb-home-header__title::before { + content: "玩偶姐姐 × WorkBuddy"; + display: block; + font: 760 clamp(25px, 3vw, 34px)/1.22 "Iowan Old Style", "Songti SC", serif; + letter-spacing: .025em; +} + +html.codedrobe-host-workbuddy .wb-home-header__subtitle { + margin-top: 13px !important; + font-size: 0 !important; + line-height: 1 !important; +} + +html.codedrobe-host-workbuddy .wb-home-header__subtitle::before { + content: "把灵感缝进今天的每一项工作 ♡"; + display: block; + color: #765f7d; + font: 540 14px/1.55 "Avenir Next", "PingFang SC", sans-serif; + letter-spacing: .035em; +} + +html.codedrobe-host-workbuddy .wb-home-page > div:has(> .wb-scene-tabs) { + box-sizing: border-box !important; + width: 100% !important; + height: 52px !important; + min-height: 52px !important; + display: flex !important; + align-items: center !important; + padding: 6px 10px !important; + border: 1px solid rgba(145, 99, 151, .20) !important; + border-radius: 18px !important; + background: linear-gradient(90deg, rgba(255, 253, 251, .91), rgba(245, 225, 235, .86)) !important; + box-shadow: 0 7px 18px rgba(86, 55, 91, .08), inset 0 0 0 3px rgba(255, 255, 255, .44) !important; +} + +html.codedrobe-host-workbuddy .wb-scene-tabs { + width: auto !important; + height: 38px !important; + padding: 3px !important; + border: 0 !important; + border-radius: 14px !important; + background: rgba(235, 211, 231, .68) !important; +} + +html.codedrobe-host-workbuddy .wb-scene-tabs__pill { + height: 32px !important; + border: 1px solid transparent !important; + border-radius: 11px !important; + background: transparent !important; + color: #735778 !important; + transition: transform .18s ease, box-shadow .18s ease !important; +} + +html.codedrobe-host-workbuddy .wb-scene-tabs__pill:hover { + transform: translateY(-1px); +} + +html.codedrobe-host-workbuddy .wb-scene-tabs__pill--active { + border-color: rgba(145, 99, 151, .21) !important; + background: linear-gradient(145deg, #d9a5bd, #a976b0) !important; + color: white !important; + box-shadow: 0 5px 13px rgba(86, 55, 91, .18), inset 0 1px rgba(255, 255, 255, .35) !important; +} + +html.codedrobe-host-workbuddy .wb-scene-tabs__pill--active :is(span, svg) { + color: white !important; + stroke: currentColor !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer { + position: relative !important; + box-sizing: border-box !important; + width: 100% !important; + height: 303px !important; + min-height: 303px !important; + display: flex !important; + flex: 0 0 303px !important; + flex-direction: column !important; + gap: 10px !important; + padding: 0 !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer__chips { + width: calc(100% - 126px) !important; + height: 36px !important; + min-height: 36px !important; + overflow: visible !important; +} + +html.codedrobe-host-workbuddy .quick-actions, +html.codedrobe-host-workbuddy .quick-actions-container, +html.codedrobe-host-workbuddy .quick-actions__list { + width: 100% !important; + height: 36px !important; + overflow: visible !important; +} + +html.codedrobe-host-workbuddy .quick-actions__item { + min-height: 34px !important; + border: 1px solid rgba(145, 99, 151, .23) !important; + border-radius: 13px !important; + background: + linear-gradient(rgba(255, 253, 251, .92), rgba(249, 232, 240, .90)), + var(--codedrobe-image-texture) center / 480px auto !important; + color: #66506c !important; + box-shadow: 0 5px 13px rgba(86, 55, 91, .08), inset 0 1px rgba(255, 255, 255, .85) !important; + transition: transform .18s ease, box-shadow .18s ease !important; +} + +html.codedrobe-host-workbuddy .quick-actions__item:hover { + transform: translateY(-3px) rotate(-.25deg) !important; + box-shadow: 0 10px 19px rgba(86, 55, 91, .13) !important; +} + +html.codedrobe-host-workbuddy .quick-actions__item :is(span, svg) { + color: #76507e !important; + stroke: currentColor !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer__input-slot { + position: relative !important; + box-sizing: border-box !important; + width: 100% !important; + height: 247px !important; + min-height: 247px !important; + padding: 0 !important; + overflow: visible !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer__input-slot > section { + box-sizing: border-box !important; + width: 100% !important; + height: 236px !important; + min-height: 236px !important; + border: 1px solid rgba(145, 99, 151, .30) !important; + border-radius: 27px !important; + background: + linear-gradient(145deg, rgba(255, 253, 251, .96), rgba(248, 231, 238, .93)), + var(--codedrobe-image-texture) center / 620px auto !important; + color: var(--doll-wb-ink) !important; + box-shadow: 0 12px 29px rgba(86, 55, 91, .13), inset 0 0 0 4px rgba(255, 255, 255, .52) !important; + backdrop-filter: blur(18px) saturate(1.06) !important; + overflow: hidden !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer__input-slot::before { + content: "🎀"; + position: absolute; + left: -15px; + top: -15px; + z-index: 20; + width: 34px; + height: 34px; + display: grid; + place-items: center; + border-radius: 50%; + font-size: 19px; + background: linear-gradient(145deg, #f7dce6, #c99dce); + box-shadow: 0 5px 14px rgba(86, 55, 91, .18), 0 0 0 3px rgba(255, 255, 255, .72); + pointer-events: none; +} + +html.codedrobe-host-workbuddy .wb-home-composer__input-slot::after { + content: ""; + position: absolute; + right: 19px; + top: -95px; + z-index: 10; + width: 91px; + height: 116px; + border: 7px solid rgba(255, 253, 252, .98); + border-bottom-width: 19px; + border-radius: 3px; + background-image: var(--codedrobe-image-hero); + background-repeat: no-repeat; + background-size: 285% auto; + background-position: 82% center; + box-shadow: 0 10px 24px rgba(86, 55, 91, .18), 0 0 0 1px rgba(145, 99, 151, .20); + transform: rotate(5deg); + pointer-events: none; +} + +html.codedrobe-host-workbuddy .wb-home-composer__input-slot img { + opacity: 0 !important; + pointer-events: none !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer [role="textbox"][contenteditable="true"] { + color: var(--doll-wb-ink) !important; + caret-color: #895b92 !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer [role="textbox"][contenteditable="true"] :is(p, span) { + color: rgba(75, 56, 81, .56) !important; +} + +html.codedrobe-host-workbuddy .wb-home-composer button, +html.codedrobe-host-workbuddy .wb-input-footer button { + border-color: rgba(145, 99, 151, .18) !important; + border-radius: 11px !important; + color: #66506c !important; +} + +html.codedrobe-host-workbuddy .wb-input-footer { + border-top-color: rgba(145, 99, 151, .12) !important; + background: rgba(255, 250, 248, .35) !important; +} + +html.codedrobe-host-workbuddy .main-content:not(.main-content--welcome), +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) { + background: + linear-gradient(rgba(255, 251, 249, .90), rgba(255, 247, 248, .94)), + var(--codedrobe-image-texture) center / 820px auto repeat !important; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) [role="textbox"][contenteditable="true"] { + color: var(--doll-wb-ink) !important; + caret-color: #895b92 !important; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) section:has([role="textbox"][contenteditable="true"]) { + position: relative !important; + border: 1px solid rgba(145, 99, 151, .28) !important; + border-radius: 24px !important; + background: + linear-gradient(145deg, rgba(255, 253, 251, .96), rgba(248, 231, 238, .92)), + var(--codedrobe-image-texture) center / 620px auto !important; + color: var(--doll-wb-ink) !important; + box-shadow: 0 11px 27px rgba(86, 55, 91, .12), inset 0 0 0 3px rgba(255, 255, 255, .50) !important; + overflow: visible !important; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) section:has([role="textbox"][contenteditable="true"])::before { + content: "🎀"; + position: absolute; + left: -13px; + top: -14px; + z-index: 10; + width: 29px; + height: 29px; + display: grid; + place-items: center; + border-radius: 50%; + font-size: 16px; + background: linear-gradient(145deg, #f7dce6, #c99dce); + box-shadow: 0 4px 12px rgba(86, 55, 91, .16), 0 0 0 3px rgba(255, 255, 255, .70); + pointer-events: none; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) :is(table, th, td) { + border-color: rgba(145, 99, 151, .16) !important; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) th { + background: rgba(240, 221, 234, .55) !important; + color: #5e4864 !important; +} + +@media (max-width: 1050px) { + html.codedrobe-host-workbuddy .wb-home-page { + width: calc(100% - 24px) !important; + } + + html.codedrobe-host-workbuddy .wb-home-header { + background-size: 100% 100%, auto 205% !important; + } +} + +@media (max-height: 720px) { + html.codedrobe-host-workbuddy .wb-home-page { + min-height: 566px !important; + height: 566px !important; + } + + html.codedrobe-host-workbuddy .wb-home-header { + height: 195px !important; + min-height: 195px !important; + flex-basis: 195px !important; + background-size: 100% 100%, auto 230% !important; + } + + html.codedrobe-host-workbuddy .wb-home-composer { + height: 254px !important; + min-height: 254px !important; + flex-basis: 254px !important; + } + + html.codedrobe-host-workbuddy .wb-home-composer__input-slot, + html.codedrobe-host-workbuddy .wb-home-composer__input-slot > section { + height: 198px !important; + min-height: 198px !important; + } +} + +@media (prefers-reduced-motion: reduce) { + html.codedrobe-host-workbuddy :is( + .conversation-list-tab-button, + .conversation-agent-card, + .wb-scene-tabs__pill, + .quick-actions__item + ) { + transition: none !important; + } +} diff --git a/skills/codedrobe-theme/assets/theme-starter/codex.css b/skills/codedrobe-theme/assets/theme-starter/codex.css new file mode 100644 index 0000000..a2d2ba2 --- /dev/null +++ b/skills/codedrobe-theme/assets/theme-starter/codex.css @@ -0,0 +1,165 @@ +/* Replace selectors that are not present in the current `codedrobe dom snapshot`. */ +:root.codedrobe-host-codex { + color-scheme: light !important; + --theme-bg: #f8f7fc; + --theme-surface: rgba(255, 255, 255, .92); + --theme-surface-strong: #ffffff; + --theme-sidebar: rgba(244, 241, 250, .94); + --theme-text: #2f2b3a; + --theme-muted: #756f82; + --theme-accent: #7867a8; + --theme-accent-soft: rgba(120, 103, 168, .15); + --theme-border: rgba(74, 62, 98, .16); + --theme-shadow: rgba(47, 43, 58, .12); + + --color-token-bg-primary: var(--theme-bg) !important; + --color-token-bg-secondary: var(--theme-surface) !important; + --color-token-main-surface-primary: var(--theme-surface) !important; + --color-token-side-bar-background: var(--theme-sidebar) !important; + --color-token-foreground: var(--theme-text) !important; + --color-token-text-primary: var(--theme-text) !important; + --color-token-text-secondary: var(--theme-muted) !important; + --color-token-border: var(--theme-border) !important; + --color-token-input-background: var(--theme-surface-strong) !important; + --color-token-input-border: var(--theme-border) !important; + --color-token-list-hover-background: var(--theme-accent-soft) !important; + --color-token-list-active-selection-background: rgba(120, 103, 168, .24) !important; + --color-token-link: var(--theme-accent) !important; + --color-token-primary: var(--theme-accent) !important; + --color-token-focus-border: rgba(120, 103, 168, .62) !important; +} + +html.codedrobe-host-codex body { + background: + linear-gradient(rgba(248, 247, 252, .88), rgba(244, 241, 250, .94)), + var(--codedrobe-image-texture, none) center / 720px auto repeat !important; + color: var(--theme-text) !important; +} + +html.codedrobe-host-codex aside.app-shell-left-panel { + background: var(--theme-sidebar) !important; + border-right: 1px solid var(--theme-border) !important; + box-shadow: 10px 0 28px rgba(47, 43, 58, .06) !important; + color: var(--theme-text) !important; + backdrop-filter: blur(18px) saturate(1.06); +} + +html.codedrobe-host-codex aside.app-shell-left-panel :is(a, button) { + border-radius: 10px !important; + color: var(--theme-text) !important; + transition: background-color .16s ease, transform .16s ease !important; +} + +html.codedrobe-host-codex aside.app-shell-left-panel :is(a, button):hover { + background: var(--theme-accent-soft) !important; + transform: translateX(2px); +} + +html.codedrobe-host-codex aside.app-shell-left-panel :is([aria-current="page"], [aria-selected="true"]) { + background: rgba(120, 103, 168, .22) !important; + box-shadow: inset 0 0 0 1px var(--theme-border) !important; +} + +html.codedrobe-host-codex main.main-surface { + position: relative; + background: var(--theme-surface) !important; + border: 1px solid var(--theme-border) !important; + border-right: 0 !important; + border-bottom: 0 !important; + border-radius: 20px 0 0 !important; + box-shadow: -8px 0 28px rgba(47, 43, 58, .05) !important; +} + +html.codedrobe-host-codex main.main-surface > header, +html.codedrobe-host-codex header.app-header-tint { + background: rgba(255, 255, 255, .82) !important; + border-bottom: 1px solid var(--theme-border) !important; + color: var(--theme-text) !important; + backdrop-filter: blur(16px); +} + +html.codedrobe-host-codex [role="main"] { + background: transparent !important; + color: var(--theme-text) !important; +} + +/* Home hero: use the live snapshot to replace this structural selector if Codex changes. */ +html.codedrobe-host-codex [role="main"]:has([data-testid="home-icon"]) > div:first-child > div:first-child > div:first-child { + position: relative !important; + overflow: hidden !important; + border: 1px solid var(--theme-border) !important; + border-radius: 24px !important; + background-color: var(--theme-surface-strong) !important; + background-image: + linear-gradient(90deg, rgba(255, 255, 255, .98) 0 42%, rgba(255, 255, 255, .72) 64%, transparent 88%), + var(--codedrobe-image-hero, linear-gradient(135deg, #ece7f7, #f8f7fc)) !important; + background-repeat: no-repeat !important; + background-position: center, right center !important; + background-size: 100% 100%, cover !important; + box-shadow: 0 16px 36px var(--theme-shadow) !important; +} + +html.codedrobe-host-codex .group\/home-suggestions > * { + border: 1px solid var(--theme-border) !important; + border-radius: 16px !important; + background: var(--theme-surface) !important; + box-shadow: 0 8px 20px rgba(47, 43, 58, .07) !important; +} + +html.codedrobe-host-codex .composer-surface-chrome { + border: 1px solid var(--theme-border) !important; + border-radius: 20px !important; + background: var(--theme-surface-strong) !important; + color: var(--theme-text) !important; + box-shadow: 0 12px 30px var(--theme-shadow) !important; +} + +html.codedrobe-host-codex .composer-surface-chrome :is(textarea, .ProseMirror, [contenteditable="true"]) { + color: var(--theme-text) !important; + caret-color: var(--theme-accent) !important; +} + +html.codedrobe-host-codex :is(button, [role="button"]):focus-visible, +html.codedrobe-host-codex :is(a, input, textarea, [contenteditable="true"]):focus-visible { + outline: 2px solid rgba(120, 103, 168, .68) !important; + outline-offset: 2px !important; +} + +html.codedrobe-host-codex :is(article, [data-message-author-role]) { + color: var(--theme-text) !important; +} + +html.codedrobe-host-codex :is(pre, table, blockquote) { + border: 1px solid var(--theme-border) !important; + border-radius: 12px !important; + background: rgba(255, 255, 255, .78) !important; +} + +html.codedrobe-host-codex pre { + overflow: auto !important; + box-shadow: inset 0 1px rgba(255, 255, 255, .8) !important; +} + +html.codedrobe-host-codex :is(a, button, input, textarea, [contenteditable="true"]) { + accent-color: var(--theme-accent); +} + +html.codedrobe-host-codex * { + scrollbar-color: rgba(120, 103, 168, .38) transparent; +} + +@media (max-width: 820px) { + html.codedrobe-host-codex [role="main"]:has([data-testid="home-icon"]) > div:first-child > div:first-child > div:first-child { + background-image: linear-gradient(rgba(255, 255, 255, .86), rgba(255, 255, 255, .92)), var(--codedrobe-image-hero, none) !important; + } +} + +@media (prefers-reduced-motion: reduce) { + html.codedrobe-host-codex *, + html.codedrobe-host-codex *::before, + html.codedrobe-host-codex *::after { + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + transition-duration: .01ms !important; + } +} diff --git a/skills/codedrobe-theme/assets/theme-starter/theme.json b/skills/codedrobe-theme/assets/theme-starter/theme.json new file mode 100644 index 0000000..eace8cb --- /dev/null +++ b/skills/codedrobe-theme/assets/theme-starter/theme.json @@ -0,0 +1,58 @@ +{ + "schemaVersion": 1, + "id": "my-theme", + "displayName": "My CodeDrobe Theme", + "version": "1.0.0", + "targets": { + "codex": { + "css": "codex.css", + "options": { + "baseTheme": { + "mode": "light", + "accent": "#7867A8", + "ink": "#2F2B3A", + "surface": "#F8F7FC" + } + }, + "verification": { + "contexts": [ + { + "name": "home", + "when": { "any": ["[role='main']:has([data-testid='home-icon'])"] }, + "recommended": [ + { "name": "home-suggestions", "any": [".group\\/home-suggestions"] } + ] + } + ] + } + }, + "workbuddy": { + "css": "workbuddy.css", + "verification": { + "contexts": [ + { + "name": "home", + "when": { "any": [".wb-home-page"] }, + "required": [ + { "name": "home-header", "any": [".wb-home-header"] }, + { "name": "home-composer", "any": [".wb-home-composer"] } + ], + "recommended": [ + { "name": "quick-actions", "any": [".quick-actions"] } + ] + }, + { + "name": "conversation", + "when": { "any": [".chat-container:not(.chat-container--welcome)"] }, + "required": [ + { + "name": "conversation-composer", + "any": [".chat-container:not(.chat-container--welcome) [role='textbox'][contenteditable='true']"] + } + ] + } + ] + } + } + } +} diff --git a/skills/codedrobe-theme/assets/theme-starter/workbuddy.css b/skills/codedrobe-theme/assets/theme-starter/workbuddy.css new file mode 100644 index 0000000..f899dcc --- /dev/null +++ b/skills/codedrobe-theme/assets/theme-starter/workbuddy.css @@ -0,0 +1,168 @@ +/* Replace selectors that are not present in the current `codedrobe dom snapshot`. */ +:root.codedrobe-host-workbuddy { + color-scheme: light !important; + --theme-bg: #f8f7fc; + --theme-surface: rgba(255, 255, 255, .92); + --theme-surface-strong: #ffffff; + --theme-sidebar: rgba(244, 241, 250, .94); + --theme-text: #2f2b3a; + --theme-muted: #756f82; + --theme-accent: #7867a8; + --theme-accent-soft: rgba(120, 103, 168, .15); + --theme-border: rgba(74, 62, 98, .16); + --theme-shadow: rgba(47, 43, 58, .12); +} + +html.codedrobe-host-workbuddy, +html.codedrobe-host-workbuddy body, +html.codedrobe-host-workbuddy #root, +html.codedrobe-host-workbuddy .teams-container { + background: + linear-gradient(rgba(248, 247, 252, .88), rgba(244, 241, 250, .94)), + var(--codedrobe-image-texture, none) center / 720px auto repeat !important; + color: var(--theme-text) !important; +} + +html.codedrobe-host-workbuddy :is(.conversation-sidebar, .conversation-list) { + background: var(--theme-sidebar) !important; + border-right: 1px solid var(--theme-border) !important; + box-shadow: 10px 0 28px rgba(47, 43, 58, .06) !important; + color: var(--theme-text) !important; + backdrop-filter: blur(18px) saturate(1.06); +} + +html.codedrobe-host-workbuddy .conversation-sidebar :is(a, button, [role="button"]) { + border-radius: 10px !important; + color: var(--theme-text) !important; + transition: background-color .16s ease, transform .16s ease !important; +} + +html.codedrobe-host-workbuddy .conversation-sidebar :is(a, button, [role="button"]):hover { + background: var(--theme-accent-soft) !important; + transform: translateX(2px); +} + +html.codedrobe-host-workbuddy .conversation-sidebar :is(.active, [aria-current="page"], [aria-selected="true"]) { + background: rgba(120, 103, 168, .22) !important; + box-shadow: inset 0 0 0 1px var(--theme-border) !important; +} + +html.codedrobe-host-workbuddy :is(.teams-content-wrapper, .teams-main-content, .main-content, .chat-container, .wb-cb-chat) { + background: transparent !important; + color: var(--theme-text) !important; +} + +html.codedrobe-host-workbuddy .teams-content-wrapper { + border-radius: 20px 0 0 !important; + box-shadow: -8px 0 28px rgba(47, 43, 58, .05) !important; + overflow: hidden; +} + +html.codedrobe-host-workbuddy .wb-home-page { + width: min(920px, calc(100% - 32px)) !important; + max-width: none !important; + gap: 14px !important; +} + +html.codedrobe-host-workbuddy .wb-home-header { + position: relative !important; + isolation: isolate; + min-height: 220px !important; + padding: 36px 42px !important; + overflow: hidden !important; + border: 1px solid var(--theme-border) !important; + border-radius: 24px !important; + background-color: var(--theme-surface-strong) !important; + background-image: + linear-gradient(90deg, rgba(255, 255, 255, .98) 0 42%, rgba(255, 255, 255, .72) 64%, transparent 88%), + var(--codedrobe-image-hero, linear-gradient(135deg, #ece7f7, #f8f7fc)) !important; + background-repeat: no-repeat !important; + background-position: center, right center !important; + background-size: 100% 100%, cover !important; + box-shadow: 0 16px 36px var(--theme-shadow) !important; +} + +html.codedrobe-host-workbuddy :is(.wb-home-header__title, .wb-home-header__subtitle) { + position: relative; + z-index: 1; + width: 56% !important; + color: var(--theme-text) !important; + text-align: left !important; +} + +html.codedrobe-host-workbuddy :is(.wb-scene-tabs, .quick-actions__item) { + border: 1px solid var(--theme-border) !important; + border-radius: 14px !important; + background: var(--theme-surface) !important; + color: var(--theme-text) !important; + box-shadow: 0 7px 18px rgba(47, 43, 58, .07) !important; +} + +html.codedrobe-host-workbuddy .quick-actions__item { + transition: transform .16s ease, box-shadow .16s ease !important; +} + +html.codedrobe-host-workbuddy .quick-actions__item:hover { + transform: translateY(-2px) !important; + box-shadow: 0 11px 24px var(--theme-shadow) !important; +} + +html.codedrobe-host-workbuddy :is(.wb-home-composer__input-slot > section, .chat-container section:has([role="textbox"])) { + border: 1px solid var(--theme-border) !important; + border-radius: 20px !important; + background: var(--theme-surface-strong) !important; + color: var(--theme-text) !important; + box-shadow: 0 12px 30px var(--theme-shadow) !important; + backdrop-filter: blur(16px); +} + +html.codedrobe-host-workbuddy [role="textbox"][contenteditable="true"] { + color: var(--theme-text) !important; + caret-color: var(--theme-accent) !important; +} + +html.codedrobe-host-workbuddy :is(button, [role="button"]):focus-visible, +html.codedrobe-host-workbuddy :is(a, input, textarea, [contenteditable="true"]):focus-visible { + outline: 2px solid rgba(120, 103, 168, .68) !important; + outline-offset: 2px !important; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) :is(table, pre, blockquote) { + border: 1px solid var(--theme-border) !important; + border-radius: 12px !important; + background: rgba(255, 255, 255, .78) !important; +} + +html.codedrobe-host-workbuddy .chat-container:not(.chat-container--welcome) pre { + overflow: auto !important; + box-shadow: inset 0 1px rgba(255, 255, 255, .8) !important; +} + +html.codedrobe-host-workbuddy :is(a, button, input, textarea, [contenteditable="true"]) { + accent-color: var(--theme-accent); +} + +html.codedrobe-host-workbuddy * { + scrollbar-color: rgba(120, 103, 168, .38) transparent; +} + +@media (max-width: 820px) { + html.codedrobe-host-workbuddy .wb-home-header { + padding: 28px !important; + background-image: linear-gradient(rgba(255, 255, 255, .86), rgba(255, 255, 255, .92)), var(--codedrobe-image-hero, none) !important; + } + + html.codedrobe-host-workbuddy :is(.wb-home-header__title, .wb-home-header__subtitle) { + width: 100% !important; + } +} + +@media (prefers-reduced-motion: reduce) { + html.codedrobe-host-workbuddy *, + html.codedrobe-host-workbuddy *::before, + html.codedrobe-host-workbuddy *::after { + animation-duration: .01ms !important; + animation-iteration-count: 1 !important; + transition-duration: .01ms !important; + } +} diff --git a/skills/codedrobe-theme/references/cli.md b/skills/codedrobe-theme/references/cli.md index 0cd2640..7ea7c81 100644 --- a/skills/codedrobe-theme/references/cli.md +++ b/skills/codedrobe-theme/references/cli.md @@ -41,6 +41,7 @@ codedrobe apply --app --app-path /custom/application/path --port ```bash codedrobe launch --app --port +codedrobe dom snapshot --app --port --output /absolute/dom.json codedrobe probe --app --port --timeout-ms 5000 codedrobe apply --app --port --theme /absolute/theme.codedrobe-theme codedrobe apply --app --port --theme /absolute/theme.codedrobe-theme --watch @@ -50,6 +51,8 @@ codedrobe restore --app --port Add `--no-launch` only when the renderer is already reachable. Add `--restart-existing` only after the user authorizes restarting the app. +`dom snapshot` is read-only and excludes text, form values, accessible names, links, and media sources. Use `--max-nodes 1500` when the default snapshot reports `summary.truncated: true`; use `--include-hidden` only for a hidden route or dialog that must be styled. + ## Theme operations ```bash diff --git a/skills/codedrobe-theme/references/codex.md b/skills/codedrobe-theme/references/codex.md index 911e5d1..3ff75e7 100644 --- a/skills/codedrobe-theme/references/codex.md +++ b/skills/codedrobe-theme/references/codex.md @@ -15,6 +15,8 @@ Codex themes may declare a `baseTheme`. Core updates only its managed `[desktop] Keep the adapter limited to cross-route landmarks such as the main surface, left sidebar, and composer. Keep home hero, suggestion-card, project-selector, and other layout assumptions in the theme package. +Capture separate home and normal-task snapshots before adapting `assets/theme-starter/codex.css` or `assets/examples/doll-sister/codex.css`. Do not assume the example's structural home selectors survived a Codex update. + Verify at least: 1. Home context, hero, suggestion cards, project selector, and composer. diff --git a/skills/codedrobe-theme/references/css-templates.md b/skills/codedrobe-theme/references/css-templates.md new file mode 100644 index 0000000..bc08c7e --- /dev/null +++ b/skills/codedrobe-theme/references/css-templates.md @@ -0,0 +1,46 @@ +# CSS templates + +## Neutral starter + +Copy the complete multi-app starter from `assets/theme-starter/` into a new writable project directory. It contains: + +- `theme.json`: Codex and WorkBuddy targets with context validation. +- `codex.css`: tokens, sidebar, main surface, header, home hero, suggestions, composer, content, focus, responsive, and reduced-motion rules. +- `workbuddy.css`: shell, sidebar, workspace, home hero, tabs/actions, home and conversation composers, content, focus, responsive, and reduced-motion rules. + +Add named images to the copied manifest when needed: + +```json +"images": { + "hero": "assets/hero.png", + "texture": "assets/texture.png" +} +``` + +The CSS already uses optional `--codedrobe-image-hero` and `--codedrobe-image-texture` variables. Missing optional images fall back to gradients or no texture. + +## Adapt rather than copy blindly + +1. Capture home and conversation DOM snapshots. +2. Compare every non-token selector in the selected app CSS with snapshot candidates. +3. Remove selectors for features the theme does not style. +4. Replace stale or generated selectors with semantic candidates from the current renderer. +5. Add named verification requirements for essential theme layout nodes. +6. Keep rules scoped under `html.codedrobe-host-codex` or `html.codedrobe-host-workbuddy`. + +Do not place application-independent color and spacing decisions in the adapter. Do not turn a full example's layout selectors into Core landmarks. + +## CSS order + +Keep CSS in this order so later repairs remain local: + +1. theme tokens and host root +2. application shell and background +3. sidebar/navigation +4. workspace/header +5. route-specific home layout +6. composer and controls +7. conversation/markdown/code content +8. focus, scrolling, responsive, and reduced motion + +Use `!important` only where the host application's specificity or inline theme variables require it. Preserve native hit targets, scrolling, focus rings, menus, and composer behavior. diff --git a/skills/codedrobe-theme/references/doll-sister-example.md b/skills/codedrobe-theme/references/doll-sister-example.md new file mode 100644 index 0000000..40eec7e --- /dev/null +++ b/skills/codedrobe-theme/references/doll-sister-example.md @@ -0,0 +1,24 @@ +# Doll Sister / 玩偶姐姐 example + +`assets/examples/doll-sister/` is a complete source theme for Codex and WorkBuddy. Copy the directory to a writable location before modifying it. + +It demonstrates: + +- one portable `theme.json` with two app targets; +- full Codex and WorkBuddy CSS rather than a screenshot overlay; +- shared `hero` and `texture` named images; +- Codex transactional `baseTheme` settings and the trusted `codex-theme-v1` renderer profile; +- app- and context-specific verification nodes; +- home, sidebar, composer, conversation, code/table, responsive, and reduced-motion styling. + +Package it: + +```bash +codedrobe theme pack /absolute/doll-sister/theme.json \ + --output /absolute/doll-sister-1.0.0.codedrobe-theme +codedrobe theme inspect /absolute/doll-sister-1.0.0.codedrobe-theme +``` + +Before applying it to a newer app version, capture fresh home and conversation snapshots and compare its detailed selectors with the live renderer. Treat the example as an authored design and learning resource, not a permanent DOM contract. + +The bundled hero and texture were generated with OpenAI image generation on 2026-07-16. A user-supplied screenshot was used only as composition, wardrobe, motif, and palette reference; the bundled images contain original generated artwork without copied UI, typography, logos, or screenshot framing. diff --git a/skills/codedrobe-theme/references/dom-snapshot.md b/skills/codedrobe-theme/references/dom-snapshot.md new file mode 100644 index 0000000..f1412cd --- /dev/null +++ b/skills/codedrobe-theme/references/dom-snapshot.md @@ -0,0 +1,72 @@ +# Dynamic CSS from a live DOM snapshot + +Use Core's read-only snapshot before creating or repairing detailed CSS. A template is a starting structure, not current compatibility evidence. + +## Capture every context + +Start the application with loopback CDP when needed, then navigate the application manually to each relevant context and capture separate files: + +```bash +codedrobe launch --app --port +codedrobe dom snapshot --app --port \ + --output /absolute/dom-home.json +codedrobe dom snapshot --app --port \ + --max-nodes 1500 --output /absolute/dom-conversation.json +``` + +The command does not launch, restart, or mutate the app. Never add `--restart-existing` to the launch step without user authorization. Add `--include-hidden` only when a hidden dialog or route must be styled. + +## Read the snapshot + +Each target contains: + +- `activeTheme`: whether computed styles include an already applied CodeDrobe theme. +- `landmarks`: adapter root, sidebar, workspace, and composer selector results. +- `nodes[].parentIndex` and `depth`: structural relationships without text content. +- `semanticClasses`: classes after common CSS-module/hash classes are removed. +- `selectors`: candidate selectors with document match counts and syntax validity. +- `rect`, `states`, and `styles`: geometry, interaction state, and theme-relevant computed style. +- `summary.truncated`: whether `--max-nodes` must be increased. + +Useful queries: + +```bash +jq '.targets[].result.summary' /absolute/dom-home.json +jq '.targets[].result.landmarks' /absolute/dom-home.json +jq '.targets[].result.nodes[] | select(.semanticClasses | length > 0) | + {index, parentIndex, tag, semanticClasses, selectors, rect}' /absolute/dom-home.json +jq '.targets[].result.nodes[] | select(.states.editable)' /absolute/dom-home.json +``` + +## Choose selectors + +Prefer, in order: + +1. product-owned stable ids, semantic classes, or `data-testid`/`data-feature` attributes; +2. stable roles combined with nonlocalized state attributes; +3. a short structural selector anchored to a stable semantic parent; +4. generated or positional selectors only when no alternative exists. + +Prefer candidates with a small expected match count. Recheck selectors in every context where the rule applies. Never use snapshot order or `node.index` as a CSS selector. + +For a new theme, capture the unthemed application baseline. If `activeTheme.installed` is true, do not silently treat themed computed styles as native values; either use the snapshot only for selector discovery or ask before restoring the active theme and recapturing. For repairing that same active theme, themed styles are useful evidence. + +If a necessary selector is brittle, put it in target CSS and add a named theme verification requirement. Do not move page-layout assumptions into the Core adapter. + +## Privacy boundary + +The snapshot excludes text, input values, accessible names, query/hash data, links, and media sources. Do not replace it with arbitrary `document.body.innerText`, `outerHTML`, or form-value dumps. Ask for explicit permission before collecting content beyond the Core snapshot contract. + +## Iterate + +After editing CSS: + +```bash +codedrobe theme pack /absolute/theme.json --output /absolute/theme.codedrobe-theme --force +codedrobe probe --app --theme /absolute/theme.codedrobe-theme +codedrobe apply --app --theme /absolute/theme.codedrobe-theme +codedrobe verify --app --theme /absolute/theme.codedrobe-theme \ + --screenshot /absolute/theme.png +``` + +When `adapter:` fails, inspect and repair Core. When `theme:` fails, update the target CSS and theme verification nodes from a fresh snapshot. diff --git a/skills/codedrobe-theme/references/theme-authoring.md b/skills/codedrobe-theme/references/theme-authoring.md index 907716b..66c9a67 100644 --- a/skills/codedrobe-theme/references/theme-authoring.md +++ b/skills/codedrobe-theme/references/theme-authoring.md @@ -51,6 +51,8 @@ Use a manifest shaped like: Only include supported targets. A single package may support multiple apps and shares its embedded named images across targets. +For a new theme, copy `assets/theme-starter/`. For a complete authored example, copy `assets/examples/doll-sister/`. Read `references/dom-snapshot.md` and replace detailed selectors from a fresh snapshot before treating either source as compatible with the installed app version. + ## Image variables Reference named images from CSS: @@ -102,6 +104,7 @@ Use `required` when missing nodes make the theme unusable. Use `recommended` for ## Package and iterate ```bash +codedrobe dom snapshot --app workbuddy --output /absolute/workbuddy-home-dom.json codedrobe theme pack /absolute/my-theme/theme.json --output /absolute/my-theme.codedrobe-theme codedrobe theme inspect /absolute/my-theme.codedrobe-theme codedrobe probe --app workbuddy --theme /absolute/my-theme.codedrobe-theme diff --git a/skills/codedrobe-theme/references/workbuddy.md b/skills/codedrobe-theme/references/workbuddy.md index a3d9d99..a8dbb22 100644 --- a/skills/codedrobe-theme/references/workbuddy.md +++ b/skills/codedrobe-theme/references/workbuddy.md @@ -21,6 +21,8 @@ Keep the adapter limited to stable cross-route landmarks: Keep home layout rules in the theme package. For a theme that styles the WorkBuddy home and conversation screens, verify at least: +Capture separate home and conversation snapshots before adapting `assets/theme-starter/workbuddy.css` or `assets/examples/doll-sister/workbuddy.css`. Prefer the live semantic classes over any stale example selector. + 1. Home header/hero, scene tabs, quick actions, home composer, and named images. 2. A conversation with long text, tables or code, scrolling, and the conversation composer shell. 3. Sidebar selection, hover states, menus, input, microphone, model selector, and send controls.