open-design/plugins/_official/examples/codex-interactive-capability-map/example.html
Tuola-waj 0ba88a064d
Add Codex interactive capability map example (#2657)
* Add Codex interactive capability map example

* Fix Codex map preview entry

---------

Co-authored-by: tuolaji <tuola@tuolajideMacBook-Air.local>
2026-05-22 15:49:16 +08:00

672 lines
23 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Codex Interactive Capability Map</title>
<style>
:root {
--ink: #070914;
--muted: rgba(7, 9, 20, .58);
--panel: rgba(255, 255, 255, .72);
--panel-strong: rgba(255, 255, 255, .88);
--line: rgba(25, 36, 94, .12);
--blue: #4d6bff;
--blue-2: #87b7ff;
--violet: #8f8cff;
--lavender: #c8b8ff;
--pink: #e7c8ff;
--radius: 22px;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
color: var(--ink);
background: #a9c3ff;
overflow-x: hidden;
}
body::before {
content: "";
position: fixed;
inset: -24%;
z-index: -3;
background:
radial-gradient(circle at 18% 24%, rgba(216, 232, 255, .95) 0 18%, transparent 34%),
radial-gradient(circle at 72% 18%, rgba(77, 99, 255, .70) 0 20%, transparent 42%),
radial-gradient(circle at 88% 54%, rgba(114, 97, 255, .55) 0 18%, transparent 38%),
radial-gradient(circle at 46% 76%, rgba(208, 195, 255, .80) 0 18%, transparent 39%),
linear-gradient(135deg, #9fbdff 0%, #b4c8ff 34%, #6d7cff 67%, #c8b8ff 100%);
filter: blur(10px) saturate(118%);
animation: codexFlow 13s ease-in-out infinite alternate;
}
body::after {
content: "";
position: fixed;
inset: 0;
z-index: -2;
background:
radial-gradient(circle at 24% 12%, rgba(255,255,255,.36), transparent 28%),
linear-gradient(120deg, rgba(255,255,255,.15), transparent 44%, rgba(255,255,255,.16));
backdrop-filter: blur(18px);
pointer-events: none;
}
.flow-field {
position: fixed;
inset: 0;
z-index: -1;
overflow: hidden;
pointer-events: none;
mix-blend-mode: soft-light;
}
.flow-field span {
position: absolute;
width: 58vw;
aspect-ratio: 1;
border-radius: 42% 58% 60% 40% / 44% 35% 65% 56%;
opacity: .48;
filter: blur(48px);
animation: liquid 15s ease-in-out infinite alternate;
}
.flow-field span:nth-child(1) { left: -18vw; top: 4vh; background: #ffffff; }
.flow-field span:nth-child(2) { right: -20vw; top: 8vh; background: #344dff; animation-delay: -5s; }
.flow-field span:nth-child(3) { left: 34vw; bottom: -30vh; background: #e4d7ff; animation-delay: -9s; }
@keyframes codexFlow {
0% { transform: translate3d(-3%, -2%, 0) scale(1) rotate(0deg); }
50% { transform: translate3d(3%, 2%, 0) scale(1.07) rotate(3deg); }
100% { transform: translate3d(1%, -3%, 0) scale(1.04) rotate(-3deg); }
}
@keyframes liquid {
from { transform: translate3d(-5%, 2%, 0) rotate(0deg) scale(1); border-radius: 42% 58% 60% 40% / 44% 35% 65% 56%; }
to { transform: translate3d(8%, -7%, 0) rotate(24deg) scale(1.18); border-radius: 60% 40% 42% 58% / 52% 62% 38% 48%; }
}
button { font: inherit; color: inherit; }
.mono {
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
font-size: 12px;
letter-spacing: 0;
text-transform: uppercase;
color: var(--muted);
}
.page {
width: min(1440px, 100%);
margin: 0 auto;
padding: 26px;
}
.hero {
min-height: 72vh;
display: grid;
place-items: center;
text-align: center;
padding: 52px 0 34px;
}
.logo-card {
width: 118px;
height: 118px;
border-radius: 30px;
margin: 0 auto 24px;
display: grid;
place-items: center;
background:
radial-gradient(circle at 34% 30%, rgba(255,255,255,.94), transparent 30%),
linear-gradient(145deg, rgba(255,255,255,.88), rgba(235,239,255,.72));
box-shadow: 0 24px 70px rgba(35, 54, 140, .18), inset 0 1px 0 rgba(255,255,255,.85);
}
.logo-mark {
width: 72px;
height: 58px;
border-radius: 24px 26px 22px 24px;
display: grid;
place-items: center;
background:
radial-gradient(circle at 36% 20%, rgba(255,255,255,.62), transparent 34%),
linear-gradient(145deg, #9db8ff, #4d6bff 58%, #334dff);
color: white;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: 34px;
font-weight: 800;
letter-spacing: 0;
filter: drop-shadow(0 22px 42px rgba(51, 72, 215, .24));
}
h1 {
margin: 0;
font-size: clamp(76px, 12vw, 168px);
line-height: .86;
letter-spacing: 0;
color: #070914;
}
.hero p {
margin: 28px auto 0;
max-width: 780px;
font-size: clamp(20px, 2.3vw, 32px);
line-height: 1.24;
color: rgba(7, 9, 20, .78);
}
.byline {
margin: 18px auto 0;
width: max-content;
max-width: 100%;
border: 1px solid rgba(25,36,94,.12);
border-radius: 999px;
background: rgba(255,255,255,.36);
padding: 9px 14px;
color: rgba(7,9,20,.62);
}
.hero-actions {
margin-top: 32px;
display: flex;
justify-content: center;
gap: 14px;
flex-wrap: wrap;
}
.cta {
border: 0;
border-radius: 999px;
padding: 14px 24px;
cursor: pointer;
background: rgba(255, 255, 255, .34);
color: rgba(7, 9, 20, .82);
box-shadow: inset 0 1px 0 rgba(255,255,255,.42);
}
.cta.primary {
background: #05060b;
color: white;
box-shadow: 0 18px 44px rgba(21, 30, 80, .22);
}
.workspace {
margin: -8vh auto 0;
width: min(1120px, calc(100vw - 52px));
max-width: 1120px;
min-height: 560px;
border: 1px solid var(--line);
border-radius: 28px;
background: var(--panel);
backdrop-filter: blur(26px) saturate(138%);
box-shadow: 0 34px 110px rgba(31, 46, 128, .22);
overflow: hidden;
}
.window-bar {
height: 54px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 18px;
border-bottom: 1px solid var(--line);
background: rgba(255,255,255,.52);
}
.traffic { display: flex; gap: 8px; }
.traffic span { width: 12px; height: 12px; border-radius: 50%; display: block; }
.traffic span:nth-child(1) { background: #ff6b5f; }
.traffic span:nth-child(2) { background: #ffcb49; }
.traffic span:nth-child(3) { background: #35c75a; }
.window-title {
display: flex;
align-items: center;
gap: 10px;
color: rgba(7,9,20,.72);
font-weight: 600;
min-width: 0;
}
.window-title span:first-child {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.window-actions { display: flex; gap: 8px; }
.small-btn {
border: 1px solid var(--line);
background: rgba(255,255,255,.54);
border-radius: 999px;
padding: 8px 12px;
cursor: pointer;
}
.canvas {
display: grid;
grid-template-columns: 220px minmax(0, 1fr) 270px;
min-height: 506px;
}
.rail {
border-right: 1px solid var(--line);
padding: 18px;
background: rgba(255,255,255,.22);
}
.rail button {
width: 100%;
min-height: 44px;
border: 0;
background: transparent;
border-radius: 12px;
padding: 10px 12px;
text-align: left;
cursor: pointer;
color: rgba(7,9,20,.70);
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid transparent;
transition: transform .18s ease, background .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.rail button:hover, .rail button.active {
background:
linear-gradient(90deg, rgba(var(--accent-rgb), .18), rgba(255,255,255,.54));
color: var(--ink);
border-color: rgba(var(--accent-rgb), .25);
box-shadow: 0 10px 28px rgba(var(--accent-rgb), .13);
transform: translateX(3px);
}
.diagram {
padding: 24px;
display: grid;
align-content: center;
gap: 18px;
min-width: 0;
}
.loop {
display: grid;
grid-template-columns: repeat(7, minmax(62px, 1fr));
gap: 7px;
align-items: center;
}
.node {
min-height: 76px;
border: 1px solid rgba(25,36,94,.14);
background: rgba(255,255,255,.42);
border-radius: 18px;
padding: 10px 8px;
cursor: pointer;
text-align: center;
position: relative;
overflow: hidden;
transition: transform .18s ease, background .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.node::before,
.cell::before,
.level::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(circle at 18% 18%, rgba(255,255,255,.76), transparent 22%),
linear-gradient(135deg, rgba(var(--accent-rgb), .18), transparent 58%);
opacity: 0;
transition: opacity .18s ease;
pointer-events: none;
}
.node:not(:last-child)::after {
content: "";
position: absolute;
top: 50%;
right: -10px;
width: 12px;
height: 2px;
background: rgba(7,9,20,.28);
}
.node:hover, .node.active {
transform: translateY(-3px);
background: rgba(255,255,255,.78);
border-color: rgba(var(--accent-rgb), .38);
box-shadow: 0 18px 40px rgba(var(--accent-rgb), .18);
}
.node:hover::before,
.node.active::before,
.cell:hover::before,
.cell.active::before,
.level:hover::before,
.level.active::before {
opacity: 1;
}
.node.active::after,
.cell.active::after,
.level.active::after {
content: "";
position: absolute;
inset: -45%;
background: conic-gradient(from 120deg, transparent, rgba(var(--accent-rgb), .24), transparent 38%);
animation: pulseWash .82s ease-out;
pointer-events: none;
}
@keyframes pulseWash {
from { transform: scale(.6); opacity: .9; }
to { transform: scale(1.45); opacity: 0; }
}
.node b { display: block; font-size: 13px; }
.node span { display: block; margin-top: 5px; font-size: 11px; color: var(--muted); }
.matrix {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.cell {
min-height: 68px;
border: 1px solid rgba(25,36,94,.12);
background: rgba(255,255,255,.32);
border-radius: 16px;
padding: 12px;
text-align: left;
cursor: pointer;
color: rgba(7,9,20,.76);
position: relative;
overflow: hidden;
transition: transform .18s ease, background .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.cell .cell-title {
position: relative;
z-index: 1;
display: block;
font-weight: 650;
}
.cell .cell-code {
position: relative;
z-index: 1;
display: block;
margin-top: 8px;
color: rgba(7,9,20,.48);
}
.cell:hover, .cell.active {
background: rgba(255,255,255,.74);
color: var(--ink);
transform: translateY(-4px) scale(1.015);
border-color: rgba(var(--accent-rgb), .38);
box-shadow: 0 18px 42px rgba(var(--accent-rgb), .18);
}
.detail {
border-left: 1px solid var(--line);
padding: 18px;
background: rgba(255,255,255,.28);
display: grid;
align-content: center;
gap: 18px;
min-width: 0;
}
.detail-card {
border: 1px solid rgba(var(--detail-rgb), .28);
border-radius: 20px;
padding: 18px 16px;
background:
radial-gradient(circle at var(--detail-x, 86%) 12%, rgba(var(--detail-rgb), .34), transparent 34%),
linear-gradient(145deg, rgba(255,255,255,.82), rgba(255,255,255,.46));
box-shadow: inset 0 1px 0 rgba(255,255,255,.72);
position: relative;
overflow: hidden;
transition: transform .22s ease, opacity .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.detail-card::before {
content: "";
position: absolute;
right: 16px;
top: 16px;
width: 54px;
height: 54px;
border-radius: var(--detail-mark-radius, 18px);
background:
linear-gradient(135deg, rgba(var(--detail-rgb), .94), rgba(255,255,255,.42));
box-shadow: 0 16px 32px rgba(var(--detail-rgb), .22);
}
.detail-card::after {
content: "";
position: absolute;
right: 34px;
top: 34px;
width: 18px;
height: 18px;
border-radius: 50%;
background: rgba(255,255,255,.82);
}
.detail-card.flash {
transform: translateX(-9px) scale(1.02);
box-shadow: 0 22px 48px rgba(var(--detail-rgb), .22);
}
.detail-card > * { position: relative; z-index: 1; }
.detail-card h2 {
margin: 8px 0 10px;
padding-right: 58px;
font-size: clamp(22px, 2.1vw, 28px);
line-height: 1.05;
overflow-wrap: anywhere;
}
.detail-card p { margin: 0; color: rgba(7,9,20,.67); line-height: 1.42; }
.prompt {
border-radius: 16px;
background:
linear-gradient(135deg, rgba(7,9,20,.92), rgba(var(--detail-rgb), .74));
color: #eef2ff;
padding: 14px;
line-height: 1.4;
font-size: 14px;
overflow-wrap: anywhere;
box-shadow: 0 18px 34px rgba(var(--detail-rgb), .20);
transition: transform .22s ease, opacity .22s ease, box-shadow .22s ease;
}
.prompt.flash {
transform: translateX(-9px);
box-shadow: 0 24px 44px rgba(var(--detail-rgb), .30);
}
.mini-ladder {
margin-top: 22px;
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 8px;
}
.level {
border: 0;
border-radius: 999px;
padding: 10px;
background: rgba(255,255,255,.35);
cursor: pointer;
color: rgba(7,9,20,.68);
position: relative;
overflow: hidden;
transition: transform .18s ease, background .18s ease, box-shadow .18s ease;
}
.level.active, .level:hover {
background: rgba(255,255,255,.80);
color: var(--ink);
transform: translateY(-2px);
box-shadow: 0 14px 32px rgba(var(--accent-rgb), .14);
}
footer {
max-width: 1080px;
margin: 24px auto 0;
color: rgba(7,9,20,.46);
text-align: center;
padding-bottom: 20px;
}
@media (max-width: 980px) {
.workspace { margin-top: 20px; }
.canvas { grid-template-columns: 1fr; }
.rail, .detail { border: 0; }
.loop, .matrix, .mini-ladder { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 1180px) {
.workspace { width: min(1040px, calc(100vw - 32px)); }
.canvas { grid-template-columns: 200px minmax(0, 1fr) 240px; }
.window-actions { display: none; }
.rail button { font-size: 14px; }
}
</style>
</head>
<body>
<div class="flow-field" aria-hidden="true"><span></span><span></span><span></span></div>
<main class="page">
<section class="hero">
<div>
<div class="logo-card"><div class="logo-mark">&gt;_</div></div>
<h1>Codex</h1>
<p>Build a working loop: context, tools, artifacts, review, automation, and memory.</p>
<div class="byline">Article by Jason Liu · visual operating model by Codex</div>
<div class="hero-actions">
<button class="cta primary" data-focus="loop">Explore the loop</button>
<button class="cta" data-focus="matrix">Open operating model</button>
</div>
</div>
</section>
<section class="workspace" id="workspace">
<div class="window-bar">
<div class="traffic"><span></span><span></span><span></span></div>
<div class="window-title"><span>Getting the most out of Codex</span> <span class="mono">Jason Liu / @jxnlco</span></div>
<div class="window-actions"><button class="small-btn">Open</button><button class="small-btn">Commit</button></div>
</div>
<div class="canvas">
<aside class="rail" id="rail"></aside>
<section class="diagram">
<div>
<div class="mono">Instruction to durable memory</div>
<div class="loop" id="loop"></div>
</div>
<div>
<div class="mono">Use-case matrix</div>
<div class="matrix" id="matrix"></div>
</div>
<div class="mini-ladder" id="ladder"></div>
</section>
<aside class="detail">
<div class="detail-card">
<div class="mono" id="detailType">Selected capability</div>
<h2 id="detailTitle">Durable Thread</h2>
<p id="detailCopy">A persistent workspace that can be revisited, steered, queued, automated, and connected to memory.</p>
</div>
<div class="prompt" id="detailPrompt">Keep this thread alive as the working context for the launch review.</div>
</aside>
</div>
</section>
<footer class="mono">Long-form ideas converted into a visual, clickable operating map.</footer>
</main>
<script>
const themes = [
{ rgb: "77,107,255", mark: "18px", x: "86%" },
{ rgb: "62,142,255", mark: "999px", x: "78%" },
{ rgb: "127,100,255", mark: "12px 28px 12px 28px", x: "92%" },
{ rgb: "73,116,204", mark: "10px", x: "72%" },
{ rgb: "102,92,235", mark: "50% 35% 50% 35%", x: "82%" },
{ rgb: "68,139,218", mark: "16px", x: "88%" },
{ rgb: "112,123,255", mark: "999px 999px 10px 10px", x: "74%" },
{ rgb: "89,82,220", mark: "22px 8px 22px 8px", x: "90%" },
{ rgb: "80,121,238", mark: "999px", x: "80%" }
];
const capabilities = [
["Durable Thread", "Context", "A persistent workspace that can be revisited, steered, queued, automated, and connected to memory.", "Keep this thread alive as the working context for the launch review."],
["Voice", "Input", "Capture rough thought before it becomes a thin written prompt.", "I think someone mentioned this in Slack. Go look and report back."],
["Steering", "Control", "Interrupt the current direction before the task finishes.", "Stop. Make the structure more visual and reduce the copy."],
["Queuing", "Next", "Add the next action without disturbing current work.", "After this finishes, send the preview link to the reviewer."],
["Tools", "Reach", "Act across browser, Chrome, desktop GUI, MCP, and connectors.", "Open the page, inspect the issue, then patch the file."],
["Side Panel", "Artifact", "Keep output next to the conversation that created it.", "Open the artifact, mark layout issues, and repair them."],
["Automation", "Cadence", "Wake the thread on a schedule to keep work moving.", "Every hour, check for PR comments and draft replies."],
["Goals", "Verifier", "Push toward a finish line with a measurable condition.", "Stop only when the tests pass and the bug no longer reproduces."],
["Memory", "Persistence", "Write durable context outside the chat transcript.", "Update the vault only if decisions or blockers changed."]
];
const loop = ["Input", "Thread", "Tools", "Artifact", "Review", "Goal", "Memory"];
const matrix = ["Thread + Browser", "Goal + Tests", "Automation + Slack", "Artifact + Review", "Memory + Vault", "Mobile + Approval", "Queue + Handoff", "Voice + Search"];
const levels = ["Code", "Environment", "Context", "Continuity", "System"];
const rail = document.getElementById("rail");
const loopEl = document.getElementById("loop");
const matrixEl = document.getElementById("matrix");
const ladderEl = document.getElementById("ladder");
function applyTheme(themeIndex) {
const theme = themes[themeIndex % themes.length];
const detail = document.querySelector(".detail");
detail.style.setProperty("--detail-rgb", theme.rgb);
detail.style.setProperty("--detail-mark-radius", theme.mark);
detail.style.setProperty("--detail-x", theme.x);
}
function setAccent(button, themeIndex) {
button.style.setProperty("--accent-rgb", themes[themeIndex % themes.length].rgb);
}
function setDetail(item, activeLabel, themeIndex = 0) {
applyTheme(themeIndex);
document.getElementById("detailTitle").textContent = item[0];
document.getElementById("detailType").textContent = item[1];
document.getElementById("detailCopy").textContent = item[2];
document.getElementById("detailPrompt").textContent = item[3];
document.querySelectorAll("button[data-key]").forEach(button => button.classList.toggle("active", button.dataset.key === activeLabel));
const card = document.querySelector(".detail-card");
const prompt = document.querySelector(".prompt");
card.classList.remove("flash");
prompt.classList.remove("flash");
void card.offsetWidth;
card.classList.add("flash");
prompt.classList.add("flash");
setTimeout(() => {
card.classList.remove("flash");
prompt.classList.remove("flash");
}, 260);
}
capabilities.forEach((item, index) => {
const button = document.createElement("button");
button.dataset.key = `cap-${index}`;
setAccent(button, index);
button.innerHTML = `<span>${item[0]}</span><span class="mono">${item[1]}</span>`;
button.addEventListener("click", () => setDetail(item, `cap-${index}`, index));
rail.appendChild(button);
});
loop.forEach((name, index) => {
const button = document.createElement("button");
const item = capabilities[index] || capabilities[0];
button.className = "node";
button.dataset.key = `loop-${index}`;
setAccent(button, index);
button.innerHTML = `<b>${name}</b><span>${item[1]}</span>`;
button.addEventListener("click", () => setDetail(item, `loop-${index}`, index));
loopEl.appendChild(button);
});
matrix.forEach((name, index) => {
const button = document.createElement("button");
const item = capabilities[(index + 1) % capabilities.length];
button.className = "cell";
button.dataset.key = `matrix-${index}`;
const themeIndex = (index + 1) % themes.length;
setAccent(button, themeIndex);
button.innerHTML = `<span class="cell-title">${name}</span><span class="cell-code mono">${item[1]}</span>`;
button.addEventListener("click", () => setDetail([name, item[1], item[2], item[3]], `matrix-${index}`, themeIndex));
matrixEl.appendChild(button);
});
levels.forEach((name, index) => {
const button = document.createElement("button");
button.className = "level";
button.dataset.key = `level-${index}`;
const themeIndex = (index + 4) % themes.length;
setAccent(button, themeIndex);
button.textContent = name;
button.addEventListener("click", () => setDetail([name, "Maturity", `Level ${index + 1}: ${name} describes how deeply Codex is embedded into the work loop.`, "Move from isolated prompts toward durable, verifiable workflows."], `level-${index}`, themeIndex));
ladderEl.appendChild(button);
});
document.querySelectorAll("[data-focus]").forEach(button => {
button.addEventListener("click", () => document.getElementById("workspace").scrollIntoView({ behavior: "smooth", block: "start" }));
});
setDetail(capabilities[0], "cap-0", 0);
</script>
</body>
</html>