feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink - #30

Closed
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow
Closed

feat(amicode): light-mode brand yellow — fill + edge, not a muddy gold ink#30
kateebonner wants to merge 20 commits into
local/amicodefrom
kate/light-mode-brand-yellow

Conversation

@kateebonner

Copy link
Copy Markdown
Contributor

Why

The default theme (oc-2) rendered the Harmoniqs yellow beautifully on dark but lost it on light. Because raw #FFF676 is unreadable on a light background (1.1:1), the light accent tokens were dimmed to a gold (#857A00 / hover #6B6200) and used as ink — accent text, icons, the H-mark, borders. Every branded moment read muddy on light.

The fix is the same principle shipped for the extension webviews in harmoniqs/amicode#140: yellow is a FILL, never an ink. On a light surface a light fill can't define its own edge, so the edge comes from a thin dark hairline — not from dimming the hue.

What

  • oc-2.json — LIGHT v2Overrides only (dark is byte-for-byte unchanged):
    v2-text-text-accent / v2-icon-icon-accent (+ hovers) move from the gold to a neutral dark ink (grey-1000 / grey-900). This eliminates the muddy gold from all accent text/icons/borders on light, and — elegantly — turns icon-accent into the edge role: dark on light, lemon on dark.
  • amicode.css — the solid brand dots (.amc-livedot, the anchored timeline node) now fill with bg-accent (true lemon) and take icon-accent as a 1px edge: a dark hairline on light, invisible (lemon-on-lemon) on dark. So the brand still pops as a fill on light, and the dark render is unchanged.

Net effect on light: no more gold. Accent text is legible neutral; the brand appears as crisp lemon fills with a dark hairline. Dark mode is untouched.

⚠️ Note for reviewers / builders

oc-2.json's v2Overrides is hand-maintained for the brand — theme.css is still upstream blue. Do not run generate:v2-oc2; it regenerates v2Overrides from theme.css and would revert every brand accent (this PR included) back to blue. Patch map (AMICODE-PATCHES.md#12) updated to record the new light values.

Testing

  • Preview: local static harness renders the real amicode.css + the real oc-2.json token values (tool cards, thinking line, timeline node, mode badge) with a light/dark toggle.
  • Full-fidelity: bun run dev:storybook / bun run dev:web, or rebuild the branded binary and re-vendor into amicode.
  • Dark theme unchanged (diff touches only the light block + two fill dots).

Follow-up: after merge, rebuild the branded binary and bump amicode's opencode.lock.json to vendor it.

…d ink
The default theme's light accent used a dimmed gold (`#857A00`/`#6B6200`) for
`text-accent`/`icon-accent` because raw `#FFF676` is unreadable on a light bg
(1.1:1). But that made every accent text/icon/border read muddy on light and
lost the brand. This mirrors the amicode webview fix (harmoniqs/amicode#140):
yellow is a FILL, never an ink.
- oc-2.json (LIGHT v2Overrides only; dark untouched): text/icon-accent gold →
neutral dark ink (grey-1000 / grey-900). This turns `icon-accent` into the
"edge" role — dark on light, lemon on dark — for free.
- amicode.css: the solid brand dots (.amc-livedot, anchored timeline node) now
fill with `bg-accent` (true lemon) and take `icon-accent` as a 1px edge — a
dark hairline on light, invisible (lemon-on-lemon) on dark. Dark render is
byte-for-byte unchanged.
oc-2.json's v2Overrides is hand-maintained for the brand (theme.css is still
upstream blue); do NOT run `generate:v2-oc2` — it would revert every brand
accent to blue. Patch map (AMICODE-PATCHES.md #12) updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@kateebonner
kateebonnerforce-pushed the kate/light-mode-brand-yellow branch from 536463f to bc73269CompareJuly 15, 2026 15:28
kateebonnerand others added 19 commits July 15, 2026 12:10
The MarkDetailed glyph read oversized next to the two-line identity block;
drop it from 48px to 40px so the mark supports the name rather than
competing with it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…maller face
The Open-chat CTA, the profile badge, and the save button used
`icon-accent` as their background. On light, PR2 neutralizes that token
(yellow-is-never-ink), so those FILLS went monochrome black — the brand
yellow vanished. A fill should ride `bg-accent` (#FFF676, both themes), not
the ink token. Point all three at `bg-accent` with fixed dark text (#000)
and a 1px `icon-accent` edge — a dark hairline on light, invisible
(lemon-on-lemon) on dark. Dark render is unchanged; light now shows the
real Harmoniqs yellow as bordered fills.
Also: Amico face on the Meet Amico card w-10 → w-8 (48→32px, noticeably smaller).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… half-size face
The dashboard cards are sandboxed widget iframes, and the token seam
(widget-tokens.ts) forwarded exactly ONE accent: --amc-accent ← icon-accent.
The light-mode neutral-ink change therefore turned every in-widget accent
near-black — including the Meet Amico "Open chat" CTA, which used the accent
as a solid BACKGROUND. Net effect on light: a black button and zero yellow
anywhere (the "black and white" dashboard).
- widget-tokens.ts: add --amc-accent-fill ← --v2-background-bg-accent
(fallback #FFF676) — the brand fill, lemon on every theme. --amc-accent
doubles as its 1px edge: dark hairline on light, invisible on dark.
- meet-amico.ts: the CTA rides the fill (lemon bg, #000 text, 1px accent
edge) instead of accent-as-background. Sole fill misuse across the seven
builtin widgets; all other accent uses are ink and stay correct.
- meet-amico.ts: face SVG was hardcoded 89x40 (why earlier host-side size
changes had no effect) → 44x20.
- widget-tokens.test.ts: cover the new token; count 15 → 16.
widget-tokens: 5/5 pass. amicode-widgets-src: 15 pre-existing temp-dir
import failures identical with and without this change (env-only).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on splash mark
Three places still carried the old dimmed-gold light treatment, and the
new-session splash had no brand yellow at all:
- brain.html (both light palette blocks): --thought #8f8000 / --thought-text
#7a6e00 → neutral ink (#22221f / #52524b). Live-signal strokes are an INK
role — yellow is a fill, never an ink; the lemon stays in the brain's
bordered --accent node fills, which light mode inherits unchanged.
- widget seam boot golds: widget-tokens.ts fallback and widget-frame-html.ts
BAKED_TOKENS --amc-accent #F2C94C → #FFF676 (the real dark value — no more
gold flash before amc:init lands); bake --amc-accent-fill too.
- run-card.tsx: the share PNG is fixed-dark, where the true lemon sings —
GOLD #F2C94C → #FFF676.
- logo.tsx: MarkDetailed gains a `brand` variant — the H tile becomes a lemon
FILL with a 1px icon-accent edge (dark hairline on light, invisible on
dark); the face stays currentColor. Both new-session splash views use it,
so the splash carries the brand yellow in both themes.
widget-tokens + run-card: 12/12 pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…me ink swap as the data-theme block
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… not the mark
Correcting the previous pass per Kate's direction:
- REVERT the lemon splash mark (logo.tsx brand variant + both session-new
views) — the amico.svg mark was not supposed to be colored; it returns to
currentColor exactly as before.
- Starter-prompt chips (getting-started.tsx, both the starters and Resume):
lemon fill (#FFF676 via bg-accent) + black text + the existing 1px
icon-accent edge — the bordered-fill treatment, both themes.
- The thinking brain gets its yellow BACK, legibly: --thought returns to the
true brand lemon on light, paired with a new light-only --thought-edge
(#22221f). brain.js draws every thought element two-pass — dark
under-stroke/hairline ring beneath the lemon core — for the survey lines,
pulse dots, node flash fills, claimed-node borders, survey rings, and the
where-we-are cursor. Dark themes skip the edge pass entirely (var unset)
and render byte-identically to before.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nk (Kate)
The dark under-strokes read too heavy on light. The edge keeps the exact
brand hue/chroma with lightness stepped 0.956→0.87 (OKLCH → #e3d958): a
lemon core with a slightly-darker-lemon halo, no black outlines. Same
two-pass mechanism in brain.js, dark themes still untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Full-lemon chips read as too much. The brand moment shrinks to a 20px lemon
tile leading each chip: bg-accent fill, 1px icon-accent edge (dark hairline
on light, invisible on dark), and a per-action stroke glyph in ink — pulse
trace, target, restart arc, bolt, question, play. One icon family (24-grid,
1.75px round strokes, SVG only), per the ui-ux-pro icon rules. The chip body
returns to neutral layer-02 + text-base.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The centered flex-wrap rows become a 2-column grid (equal-width cells,
540px max, labels ellipsize instead of overflowing). The chip outline drops
from icon-accent (near-black on light) to the theme's border-strong token;
the lemon glyph tile keeps its crisp icon-accent hairline — that edge IS the
brand treatment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The node/signal base is always the brand lemon (#fff676); the edge now
adapts per mode instead of being light-only: darker lemon (#e3d958) on
light, LIGHTER lemon (#fffa9e — the established brand hover step) on dark.
Same two-pass mechanism in brain.js; dark simply gains its pale halo.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…flash
The brain page's demo chrome (mast "amico is thinking" + transport controls
+ legend + colophon) is static HTML that embeds hide from brain.js — which
runs after first paint, so the chat's thinking strip flashed the whole demo
panel for a beat before the animation appeared (Kate: remove it).
An inline head script stamps the ?mode= on <html> before first paint and a
tiny stylesheet hides the chrome instantly (live/inline: all chrome +
transparent ground; loader: controls/legend/colophon). brain.js keeps its
idempotent post-boot hiding.
NOTE: brain.{html,js} are marked GENERATED from amicode
packages/extension/media/brain/ — this and the palette/edge commits need a
port-back to that source when the split is next regenerated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s inline JS
The previous pre-paint gate was an inline <script>, which this page's CSP
forbids (the very reason brain.js is external — the header says CSP-split;
missed it). The browser silently blocked the gate, so the demo chrome still
flashed in the chat's thinking strip.
Inverted, CSP-safe: .chrome starts visibility:hidden in the static CSS, and
brain.js (external, allowed) reveals it — html.standalone for the demo page,
html.loader-embed for the loader's mast. Live/inline embeds never see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…OM (Kate)
Hiding was the wrong shape ("it should just not be there"): the demo chrome
(mast/controls/legend/colophon) now lives in <template id="demo-chrome"> —
inert, unrendered, absent from the DOM and a11y tree. brain.js stamps it at
boot for standalone (all) or a loader embed (mast only); live/inline embeds
never instantiate it. The visibility-gate CSS and reveal classes are gone.
All chrome-element accesses in brain.js are guarded for the absent case
(setStatus, setTempoMark, auto/scenario, caret, controls/legend blocks,
boot autostart).
Verified against the built binary (headless, both modes): live —
controls/mast/legend NOT in DOM, canvas animating, zero console errors;
standalone — full chrome, 5 scenarios, zero errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent (Kate)
Complete rethink of where the thinking animation lives: instead of a boxed
strip inside the timeline, the amico brain runs FULL-BLEED behind the whole
chat, with chat components floating above on frosted surfaces.
- brain-backdrop.tsx (new): one pointer-transparent layer at the chat pane's
z-0 — mode=live with a session (the event bridge lifted verbatim from the
strip: touches, charts, theme, hover-glance, keyed remount per session),
mode=inline ambient traces without one. A vertical scrim gradient keeps
the content column legible (clearest up top, calmest at the composer).
- session.tsx: backdrop mounted in the chat pane behind timeline + composer
(both z-raised); covers live sessions and the classic new-session view.
- new-session.tsx + session-new-design-view.tsx: ambient backdrop behind the
landing; the opaque bg-deep goes; the composer floats in a frosted band
(blur 16px over the animation — the OCEAN band); starter chips frost too.
- The in-timeline BrainStrip is REMOVED (one brain, the background):
component deleted, Brain timeline row retired from data/render/keep-mounted.
App typecheck clean; session tests identical to base (33 pass + 1
pre-existing router/SSR failure with and without this change).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Kate)
The first pass only frosted the landing band — the session view kept opaque
surfaces. Now: the composer dock swaps its opaque bg for a translucent wash
+ 14px backdrop blur, and the message flow reads on ONE frosted column
inside the backdrop (centered to the timeline width, 12px blur) — a single
backdrop-filter element instead of per-card blurs, so the glass is uniform
and cheap; the brain stays crisp in the margins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The full-height frosted column blurred the whole brain into fog — removed.
The frost now lives in a single bounded glass block that expands and
collapses with its contents:
- in-session: the composer region's centered container becomes the block —
rounded 16px, hairline border, 58% wash + 16px blur — housing the input
and every interactive dock (question/follow-up/permission/todo), which
already size it by normal flow. The brain stays crisp everywhere else.
- landing: chips + composer unify into the SAME single glass block (the
gettingStarted moves inside the frosted panel); chips drop their own
backdrop-filters — they sit on the glass now.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eads (Kate)
The prompt-input card was opaque bg-base, filling the glass block edge to
edge — so the frost was invisible except a thin rim and the whole treatment
looked unchanged. The card goes translucent (52% mix); the block's own
backdrop blur provides the glass. Verified visually via headless screenshot
of the session landing against the built binary: ambient brain behind the
page, one frosted block housing tagline/steps/chips/composer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…learer glass (45% wash, 20px blur)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state (Kate)
Removes the OCEAN treatment wholesale: brain backdrop, glass blocks, frosted
chips/composer, strip removal (the in-timeline BrainStrip returns), and the
dial tweaks. Everything through the inert-template chrome fix (89fddaa)
stays — that is the reviewed light-mode yellow work.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kateebonner

Copy link
Copy Markdown
ContributorAuthor

Closing for now — the light-mode brand work is preserved on this branch (through the revert at 5cf9981) if we return to it.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@kateebonner