Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading
, '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
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bc73269
feat(amicode): light-mode brand yellow — fill + edge, not a muddy gol…
kateebonner Jul 15, 2026
822ccbf
fix(amicode): shrink the Amico face in the Meet Amico card (w-12 → w-10)
kateebonner Jul 15, 2026
32c63fe
fix(amicode): light-mode chat — bright-lemon FILLS for brand CTAs + s…
kateebonner Jul 15, 2026
c349822
fix(amicode): brand fill crosses the widget-iframe seam — lemon CTA +…
kateebonner Jul 15, 2026
37c7283
fix(amicode): purge the retired gold — brain ink, seam fallbacks, lem…
kateebonner Jul 15, 2026
d6028eb
fix(amicode): the @media light block in brain.html kept the gold — sa…
kateebonner Jul 15, 2026
84d32a2
fix(amicode): yellow goes to the starter chips and the brain signal —…
kateebonner Jul 15, 2026
f4748fb
style(amicode): brain signal edge softens — darker lemon instead of i…
kateebonner Jul 15, 2026
db7293c
style(amicode): starter chips — lemon icon tile, neutral body (Kate)
kateebonner Jul 15, 2026
99718fd
style(amicode): starter chips — two-column grid, softer chip border (…
kateebonner Jul 15, 2026
57a779c
style(amicode): brain nodes — lemon base with mode-adaptive halo (Kate)
kateebonner Jul 15, 2026
c8c9a70
fix(amicode): brain embeds — pre-paint chrome gate kills the demo-UI …
kateebonner Jul 15, 2026
9808028
fix(amicode): brain chrome gate must be CSS-only — the page CSP block…
kateebonner Jul 15, 2026
89fddaa
fix(amicode): demo chrome ships inert — embeds never have it in the D…
kateebonner Jul 15, 2026
ca665b1
feat(amicode): the brain becomes the chat's background — OCEAN treatm…
kateebonner Jul 16, 2026
3f471a5
style(amicode): frost the in-session chat components over the brain (…
kateebonner Jul 16, 2026
e9a3137
style(amicode): ONE glass block for the interactive components (Kate)
kateebonner Jul 16, 2026
9a10fdc
style(amicode): translucent composer card — the glass block finally r…
kateebonner Jul 16, 2026
fd7d902
style(amicode): stronger backdrop dials — lighter scrim (16/38/58), c…
kateebonner Jul 16, 2026
5cf9981
revert: the brain-background/glass experiment — back to the approved …
kateebonner Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AMICODE-PATCHES.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -106,7 +106,7 @@ Format: file:line — string/asset — replacement. [desktop] = ships only in th
| 10 | packages/app/src/desktop-menu.ts:75 [desktop] | menu label "OpenCode" | "Amicode" |
| 11 | packages/app/src/wsl/settings-model.ts:17-18 [desktop, Windows/WSL] | "Install OpenCode"/"Update OpenCode" | "Install/Update Amicode" |
| 13 | packages/ui/src/components/logo.css | `[data-component="logo-mark"]` aspect-ratio 4/5 (old 16x20 viewBox) | aspect-ratio 1/1 (new square amico mark) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676`, light text/icon-accent → derived dark shades `#857A00` / hover `#6B6200` (raw `#FFF676` is unreadable on light bg) |
| 12 | packages/ui/src/theme/themes/oc-2.json (default theme) | accent tokens `v2-{background,text,icon}-*accent*` = blue-600/700 (light), blue-400/300 (dark) | Harmoniqs accent `#FFF676` (brand.css `--color-accent`): dark text/icon/bg-accent → `#FFF676`, hover `#FFFA9E`; light bg-accent → `#FFF676` (fill; dark text sits on it), light text/icon-accent → neutral dark ink `grey-1000` / hover `grey-900` (yellow is a FILL, never an ink — raw `#FFF676` is unreadable on light bg, so brand shows as lemon fills with a 1px dark hairline edge, e.g. `.amc-livedot`; matches the webview treatment in harmoniqs/amicode#140) |

Deliberately left stock (and why):

Expand Down
23 changes: 19 additions & 4 deletions packages/app/public/brain.html
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@
--accent: #fff676;
--on-accent: #000000;
--thought: #fff676; /* live-signal color: pulses, flares, live survey lines */
--thought-edge: #fffa9e; /* dark: the halo is a LIGHTER lemon (the brand hover step) —
light mode flips it darker; the node base is always #fff676 */
--thought-text: #d8cf6a; /* accent-adjacent, legible as text on this surface */
--cat-knowledge: #3794ff; /* series-1 — notes, insights, charter, strategy */
--cat-results: #c17800; /* series-2 — experiments, catalog pulses */
Expand All@@ -47,8 +49,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -68,8 +73,11 @@
--edge-rest: rgba(0, 0, 0, 0.15);
--node-rest-fill: #eae7dd;
--node-rest-border: rgba(0, 0, 0, 0.26);
--thought: #8f8000;
--thought-text: #7a6e00;
--thought: #fff676; /* the TRUE brand lemon — brain.js pairs every thought stroke/fill
with a --thought-edge under-stroke so it reads on paper */
--thought-edge: #e3d958; /* light-only halo: the SAME hue/chroma as the lemon, lightness
stepped 0.956→0.87 (OKLCH) — a soft darker-lemon edge, not ink */
--thought-text: #52524b; /* signal TEXT stays ink — yellow is never text */
--cat-knowledge: #1866c9;
--cat-results: #8f5800;
--cat-skills: #7b4fa8;
Expand All@@ -90,6 +98,7 @@
--node-rest-border: rgba(255, 255, 255, 0.24);
--accent: #fff676;
--thought: #fff676;
--thought-edge: #fffa9e;
--thought-text: #d8cf6a;
--cat-knowledge: #3794ff;
--cat-results: #c17800;
Expand DownExpand Up@@ -245,6 +254,11 @@

<canvas id="stage" aria-label="animated map of the amico knowledge graph; live status is announced below"></canvas>

<!-- The demo chrome ships INERT: template content is not rendered, not in
the DOM, not in the a11y tree — embeds simply never have it (no flash,
nothing to hide). brain.js stamps it at boot for the standalone page
(all of it) or a loader embed (mast only). -->
<template id="demo-chrome">
<div class="chrome" id="mast">
<div id="wordmark">
<span class="amico">amico</span>
Expand All@@ -267,6 +281,7 @@
</div>

<div class="chrome" id="colophon">prototype &middot; nodes &amp; links sampled from the armonissima vault &middot; brand.css tokens &middot; JuliaMono</div>
</template>

<div id="tooltip" role="presentation"></div>

Expand Down
78 changes: 69 additions & 9 deletions packages/app/public/brain.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion packages/opencode/src/server/amicode/widget-frame-html.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,7 +22,8 @@ const BAKED_TOKENS: Record<string, string> = {
"--amc-text": "#E9ECF4",
"--amc-text-muted": "#8B94A9",
"--amc-text-faint": "#6A7286",
"--amc-accent": "#F2C94C",
"--amc-accent": "#FFF676",
"--amc-accent-fill": "#FFF676",
"--amc-success": "#5BC873",
"--amc-warning": "#E5B454",
"--amc-danger": "#E56A6A",
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,7 +26,7 @@ var CAN = [
// native ~2:1 proportions. Keep these element strings in sync with MarkDetailed
// by hand if the mark changes.
var FACE =
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="89" height="40" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<svg viewBox="621.31 1309.27 2415.32 1084.97" width="44" height="20" preserveAspectRatio="xMidYMid meet" aria-hidden="true" fill="var(--amc-accent)" style="flex-shrink:0;display:block" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="1778.31" y="1312.43" width="107.11" height="692.38"/>' +
'<polygon points="2769.41 1463.57 2903.01 1463.57 2903.01 1601.01 2769.39 1601.01 2769.39 1463.6 2635.79 1463.6 2635.79 1326.16 2769.41 1326.16 2769.41 1463.57"/>' +
'<polygon points="3036.63 1738.45 2903.03 1738.45 2903.03 1875.89 2769.41 1875.89 2769.41 1738.45 2903.01 1738.45 2903.01 1601.01 3036.63 1601.01 3036.63 1738.45"/>' +
Expand DownExpand Up@@ -73,7 +73,7 @@ export default {
'<div style="height:1px;background:var(--amc-border);margin:12px 0"></div>' +
'<div style="font-size:11px;color:var(--amc-text-muted);margin-bottom:6px">I can help you</div>' +
'<div style="display:flex;flex-direction:column;gap:3px;margin-bottom:12px">' + bullets + '</div>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:none;border-radius:10px;cursor:pointer;background:var(--amc-accent);color:var(--amc-bg);font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'<button type="button" data-cta style="align-self:flex-start;display:inline-flex;align-items:center;gap:10px;margin-top:auto;padding:12px 22px;border:1px solid var(--amc-accent);box-sizing:border-box;border-radius:10px;cursor:pointer;background:var(--amc-accent-fill, #FFF676);color:#000;font-size:15px;font-weight:650">Open chat <span aria-hidden="true" style="font-size:16px;line-height:1">&#8599;</span></button>' +
'</div>'
on('[data-cta]', function (e) {
e.stopPropagation()
Expand Down
11 changes: 9 additions & 2 deletions packages/ui/src/amicode/amicode.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -235,8 +235,13 @@
[data-component="amicode-card"] .amc-livedot {
width: 6px;
height: 6px;
box-sizing: border-box;
border-radius: 50%;
background: var(--v2-icon-icon-accent);
/* Brand fill + edge: lemon on both themes. The edge is a 1px dark hairline on
light (icon-accent resolves to a neutral dark there) and lemon-on-lemon —
invisible — on dark. Yellow stays a fill, never an ink. */
background: var(--v2-background-bg-accent);
border: 1px solid var(--v2-icon-icon-accent);
}
@media (prefers-reduced-motion: no-preference) {
[data-component="amicode-card"][data-state="running"] .amc-livedot { animation: amc-blip 1.2s ease-in-out infinite; }
Expand DownExpand Up@@ -479,7 +484,9 @@
background: color-mix(in srgb, var(--v2-icon-icon-accent) 9%, transparent);
}
[data-component="amicode-entity-view"] .amc-event[data-anchored]::before {
background: var(--v2-icon-icon-accent);
/* Lemon fill + edge (see .amc-livedot): the anchored timeline node keeps the
brand lemon on both themes, gaining a dark hairline on light. */
background: var(--v2-background-bg-accent);
border-color: var(--v2-icon-icon-accent);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--v2-icon-icon-accent) 18%, transparent);
}
Expand Down
84 changes: 73 additions & 11 deletions packages/ui/src/amicode/getting-started.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,32 +13,79 @@ import { AmicodeTagline } from "./tagline"
// The set spans the lifetime: onboard (first run routes any chip into the
// overture) → design with memory/recommendations → warm-start from the pulse
// bank → go fast with Veloce.
export const AMICODE_STARTERS: readonly { label: string; prompt: string }[] = [
// Each starter carries a stroke-icon path (24-grid, one family: 1.75px round
// strokes) suggesting its action — rendered on a small lemon tile so the chip
// reads branded without the whole component going yellow (Kate).
export const AMICODE_STARTERS: readonly { label: string; prompt: string; icon: string }[] = [
{
label: "Design a pulse — walk me through it",
prompt: "walk me through designing a pulse",
icon: "M2 12h4l3-7 4 14 3-7h6", // a pulse trace
},
{
label: "Optimize an X gate on my transmon",
prompt: "optimize an X gate on my transmon — use what you know from my history",
icon: "M12 4a8 8 0 1 0 0 16 8 8 0 0 0 0-16M12 10.5a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3", // a target
},
// NOTE(spec B): the static "Resume my pulse design" chip was replaced by the
// conditional resumeName-driven chip below — Resume renders only when a
// problem workspace actually exists (no empty chrome).
{
label: "Warm-start from my pulse bank",
prompt: "warm-start a new solve from my pulse bank",
icon: "M20 12a8 8 0 1 1-2.3-5.7M20 3v4h-4", // restart arc
},
{
label: "Go fast with Veloce",
prompt: "turn on Veloce — auto-accept your high-confidence recommendations, and still confirm before any solve",
icon: "M13 3 5 14h5l-1 7 8-11h-5l1-7Z", // a bolt
},
{
label: "What can Amico do?",
prompt: "what can Amico do?",
icon: "M9.3 9.3a2.8 2.8 0 1 1 3.9 2.6c-.9.4-1.2.9-1.2 1.9M12 17.2v.1", // a question
},
]

// Resume is play-shaped.
const RESUME_ICON = "M8 5.5v13l10.5-6.5Z"

// The one place the chip carries the brand: a small lemon tile (fill + 1px
// icon-accent edge — dark hairline on light, invisible on dark) holding the
// action glyph in ink. SVG only, never emoji; 12px glyph on a 20px tile.
const GLYPH_TILE: Record<string, string> = {
display: "inline-flex",
"align-items": "center",
"justify-content": "center",
width: "20px",
height: "20px",
"box-sizing": "border-box",
"flex-shrink": "0",
"border-radius": "5px",
background: "var(--v2-background-bg-accent, #FFF676)",
border: "1px solid var(--v2-icon-icon-accent)",
color: "#000",
}

function StarterGlyph(props: { d: string }) {
return (
<span style={GLYPH_TILE} aria-hidden="true">
<svg
viewBox="0 0 24 24"
width="12"
height="12"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d={props.d} />
</svg>
</span>
)
}

// The three-beat arc of a pulse-design session, from setup to hardware.
const STEPS = ["① Define your system and problem", "② Optimize and iterate", "③ Execute and tune on hardware"]

Expand DownExpand Up@@ -95,10 +142,11 @@ export function AmicodeGettingStarted(props: {
<div
data-slot="amicode-gs-starters"
style={{
display: "flex",
"flex-wrap": "wrap",
"justify-content": "center",
gap: "6px",
display: "grid",
"grid-template-columns": "repeat(2, minmax(0, 1fr))",
gap: "6px 8px",
width: "100%",
"max-width": "540px",
}}
>
<For each={AMICODE_STARTERS}>
Expand All@@ -108,17 +156,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-starter"
onClick={() => props.onStart(starter.prompt)}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
{starter.label}
<StarterGlyph d={starter.icon} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
{starter.label}
</span>
</button>
)}
</For>
Expand All@@ -128,17 +183,24 @@ export function AmicodeGettingStarted(props: {
data-slot="amicode-gs-resume"
onClick={() => props.onResume?.()}
style={{
border: "1px solid var(--v2-icon-icon-accent)",
display: "inline-flex",
"align-items": "center",
gap: "7px",
"min-width": "0",
border: "1px solid var(--v2-border-border-strong)",
"border-radius": "6px",
background: "var(--v2-background-bg-layer-02)",
color: "var(--v2-text-text-base)",
padding: "4px 12px",
padding: "4px 12px 4px 5px",
"font-size": "12px",
"line-height": "16px",
cursor: "pointer",
}}
>
Resume “{props.resumeName}”
<StarterGlyph d={RESUME_ICON} />
<span style={{ overflow: "hidden", "text-overflow": "ellipsis", "white-space": "nowrap" }}>
Resume “{props.resumeName}”
</span>
</button>
)}
</div>
Expand Down
24 changes: 14 additions & 10 deletions packages/ui/src/amicode/home-cards.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -245,7 +245,7 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
data-slot="amicode-meet-identity"
style={{ display: "flex", gap: "12px", "align-items": "center", "margin-top": "10px" }}
>
<MarkDetailed class="w-12 h-auto shrink-0" />
<MarkDetailed class="w-8 h-auto shrink-0" />
<div style={{ "min-width": "0" }}>
<div style={{ "font-size": "18px", "font-weight": "600", color: "var(--v2-text-text-base)" }}>Amico</div>
<div style={{ "font-size": "12px", "line-height": "16px", color: "var(--v2-text-text-muted)" }}>
Expand DownExpand Up@@ -285,14 +285,15 @@ function MeetAmicoCard(props: { onStart: (prompt: string) => void }) {
gap: "10px",
"margin-top": "4px",
padding: "12px 22px",
border: "none",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "10px",
cursor: "pointer",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
"font-size": "15px",
"font-weight": "650",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-icon-icon-accent) 35%, transparent)",
"box-shadow": "0 2px 10px color-mix(in srgb, var(--v2-background-bg-accent) 30%, transparent)",
}}
>
Open chat
Expand DownExpand Up@@ -596,8 +597,10 @@ function AboutYouCard(props: {
height: "44px",
"border-radius": "8px",
flex: "none",
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"font-size": "15px",
"font-weight": "700",
"letter-spacing": "0.5px",
Expand DownExpand Up@@ -837,9 +840,10 @@ function AboutYouCard(props: {
disabled={saving() || resolvingLogo() > 0}
onClick={() => void save()}
style={{
background: "var(--v2-icon-icon-accent)",
color: "var(--v2-background-bg-base, #000)",
border: "none",
background: "var(--v2-background-bg-accent)",
color: "#000",
border: "1px solid var(--v2-icon-icon-accent)",
"box-sizing": "border-box",
"border-radius": "6px",
padding: "4px 10px",
"font-size": "12px",
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -36,7 +36,7 @@ describe("renderRunCardSvg", () => {
expect(svg).toContain("harmoniqs.ai")
expect(svg).toContain("AMICODE")
// 2 drives → 2 pulse paths (second at companion opacity)
expect(svg.match(/stroke="#F2C94C" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg.match(/stroke="#FFF676" stroke-width="2\.5"/g)?.length).toBe(2)
expect(svg).toContain('opacity="0.55"')
})
test("pulse panel reads first (left column), convergence second", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/amicode/run-card.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,7 +66,7 @@ const PANEL = "#111624"
const LINE = "#2A3245"
const TEXT = "#E9ECF4"
const MUTED = "#8B94A9"
const GOLD = "#F2C94C"
const GOLD = "#FFF676" // the brand lemon — card bg is fixed-dark, where the true accent sings
const CURVE = "#7FD1FF"

const W = 1200
Expand Down
5 changes: 3 additions & 2 deletions packages/ui/src/amicode/widget-tokens.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,9 +30,10 @@ describe("resolveTokens", () => {
const tokens = resolveTokens((name) => (name === "--v2-text-text-base" ? " #fff " : ""), "normal")
expect(tokens["--amc-text"]).toBe("#fff")
expect(tokens["--amc-bg"]).toBe("#0B0E15") // fallback
expect(tokens["--amc-accent"]).toBe("#F2C94C")
expect(tokens["--amc-accent"]).toBe("#FFF676")
expect(tokens["--amc-accent-fill"]).toBe("#FFF676") // brand fill fallback
expect(tokens["--amc-font-mono"]).toContain("monospace")
expect(Object.keys(tokens)).toHaveLength(15) // 11 colors + 2 fonts + 2 pads
expect(Object.keys(tokens)).toHaveLength(16) // 12 colors + 2 fonts + 2 pads
})
test("padding tokens follow density", () => {
expect(resolveTokens(() => "", "normal")["--amc-pad"]).toBe("14px 16px")
Expand Down
Loading
Loading