37
Token counter
A sentence splits into token chips while a counter climbs

Add the "Token counter" video component (Input vs output, light) from everestchris.com to this project.
1. Download https://ai-component-library-dun.vercel.app/projects/token-counter.zip?v=d4be1a07866a and unzip it into components/token-counter/. Read the README.md and CLAUDE.md in it.
2. Render it: cd components/token-counter && npx hyperframes@0.8.162 render . --variables '{"variant":"2","theme":"light"}' -o token-counter.mp4
3. Give me the path of the MP4. The text, names and timings live in the CONFIG block at the top of the script in index.html; change nothing there unless I ask.Code
One file. The project download adds the fonts, skins and motion kit it runs on.
Open full file1<!doctype html>2<html lang="en" data-composition-variables='[3 {"id":"variant","type":"enum","label":"Variant","default":"0","options":[{"value":"0","label":"Tokenizing"},{"value":"1","label":"Live run counter"},{"value":"2","label":"Input vs output"}]},4 {"id":"theme","type":"enum","label":"Theme","default":"light","options":[{"value":"light","label":"Light"},{"value":"dark","label":"Dark"}]}5]'>6 <head>7 <meta charset="UTF-8" />8 <meta name="viewport" content="width=1920, height=1080" />9 <link rel="stylesheet" href="assets/fonts/fonts.css" />10 <link rel="stylesheet" href="assets/skins/chatgpt/skin.css" />11 <link rel="stylesheet" href="assets/skins/claude/skin.css" />12 <link rel="stylesheet" href="assets/skins/claude-code/skin.css" />13 <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>14 <script src="assets/kit/motion/motion.js"></script>15 <script src="assets/skins/chatgpt/icons.js"></script>16 <script src="assets/skins/claude/icons.js"></script>17 <script src="assets/skins/claude-code/icons.js"></script>18 <style>19 * { margin: 0; padding: 0; box-sizing: border-box; }20 html, body { margin: 0; width: 1920px; height: 1080px; overflow: hidden; background: #f5f5f4; }21 #root { position: relative; width: 100%; height: 100%; overflow: hidden; font-family: "Inter", sans-serif; }2223 /* ---------- library stage tokens (DESIGN.md) + token-chip tints ---------- */24 #stage { position: absolute; inset: 0; background: var(--stage); }25 #stage[data-theme="light"] {26 --stage: #F5F5F4; --surface: #FFFFFF; --ink: #0A0A0A; --ink-2: #6B6B6B; --ink-3: #A3A3A3;27 --hair: rgba(0, 0, 0, 0.08);28 --ro-ring: rgba(0, 0, 0, 0.07);29 --ro-lift: 0 1px 2px rgba(0, 0, 0, .06), 0 2px 6px -2px rgba(0, 0, 0, .05), 0 22px 48px -22px rgba(0, 0, 0, .26);30 /* each chip family has a base tint (a word's first token) and a deeper one (the pieces glued to it):31 a word that splits reads as one segmented pill, and only sub-word cuts change tint */32 --chip-n: rgba(10, 10, 10, 0.095); --chip-n2: rgba(10, 10, 10, 0.2); /* neutral: monochrome products (OpenAI) */33 --chip-k: rgba(20, 20, 19, 0.075); --chip-k2: rgba(20, 20, 19, 0.19); /* your words on Claude's grey bubble (input) */34 --chip-c: rgba(217, 119, 87, 0.2); --chip-c2: rgba(217, 119, 87, 0.4); /* clay: what Claude writes (output) */35 --ring-n: transparent; --ring-k: transparent; --ring-c: transparent;36 --dot-in: #9A9A97;37 }38 #stage[data-theme="dark"] {39 --stage: #0E0E0F; --surface: #18181A; --ink: #FAFAFA; --ink-2: #A1A1A1; --ink-3: #5E5E60;40 --hair: rgba(255, 255, 255, 0.10);41 --ro-ring: rgba(255, 255, 255, 0.07);42 --ro-lift: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 2px 6px -2px rgba(0, 0, 0, .5), 0 24px 56px -20px rgba(0, 0, 0, .85);43 /* dark: a lighter fill plus a 1px edge in the family colour, so clay reads as clay, not brown */44 --chip-n: rgba(255, 255, 255, 0.085); --chip-n2: rgba(255, 255, 255, 0.2);45 --chip-k: rgba(255, 255, 255, 0.07); --chip-k2: rgba(255, 255, 255, 0.22);46 --chip-c: rgba(217, 119, 87, 0.18); --chip-c2: rgba(217, 119, 87, 0.36);47 --ring-n: rgba(255, 255, 255, 0.10); --ring-k: rgba(255, 255, 255, 0.10); --ring-c: rgba(217, 119, 87, 0.36);48 --dot-in: #7A7A78;