tfrere HF Staff Cursor commited on
Commit
1d5de93
·
1 Parent(s): 41739ad

Demo polish: SEO/AI-agent discoverability + new hexagonal logo + §1 helix per-letter fade + sandbox empty-state

Browse files

- Discoverability surface: robots.txt, sitemap.xml, llms.txt, JSON-LD/OG/Twitter
metadata in demo.html; app.py templates demo + social-banner with {{SITE_URL}}
resolved per-request from X-Forwarded-*; Dockerfile COPYs the new files.
- New hexagonal Carbon mark (img/logo.svg) plus black square/rectangle lockups
used by the social-banner contact sheet.
- social-banner: noindex, doubles as a brand contact sheet under the stage with
native-size square and rectangle lockups for one-shot screenshots.
- §1 intro helix: per-letter depth-aware fade — front-strand letter at each
crossing stays readable while its back-strand sibling recedes, instead of both
going equally ghosted.
- Sandbox empty-state: centered, white-on-white, lighter contrast so the
placeholder reads as a hint rather than a block.
- New §X efficiency section script wired into demo.html.

Co-authored-by: Cursor <cursoragent@cursor.com>

Dockerfile CHANGED
@@ -6,6 +6,11 @@ COPY requirements.txt .
6
  RUN pip install --no-cache-dir -r requirements.txt
7
 
8
  COPY app.py index.html demo.html social-banner.html ./
 
 
 
 
 
9
  COPY data/ ./data/
10
  COPY img/ ./img/
11
  COPY annotations/ ./annotations/
 
6
  RUN pip install --no-cache-dir -r requirements.txt
7
 
8
  COPY app.py index.html demo.html social-banner.html ./
9
+ # Discoverability surface (SEO + AI agents + social previews). These are
10
+ # read once at startup by app.py, with {{SITE_URL}} substituted in at
11
+ # request time. Without this COPY the production image 404s on every
12
+ # crawler / answer-engine probe.
13
+ COPY robots.txt llms.txt sitemap.xml ./
14
  COPY data/ ./data/
15
  COPY img/ ./img/
16
  COPY annotations/ ./annotations/
app.py CHANGED
@@ -6,7 +6,7 @@ import os
6
  import httpx
7
  from fastapi import FastAPI, Request
8
  from fastapi.middleware.gzip import GZipMiddleware
9
- from fastapi.responses import FileResponse, StreamingResponse
10
  from fastapi.staticfiles import StaticFiles
11
  from openai import OpenAI
12
 
@@ -44,6 +44,50 @@ _FOLD_CACHE_MAX = 256
44
 
45
  HERE = os.path.dirname(os.path.abspath(__file__))
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
  def get_api_key():
49
  key = os.environ.get("HF_TOKEN")
@@ -132,13 +176,13 @@ async def no_cache_dev_assets(request: Request, call_next):
132
 
133
 
134
  @app.get("/")
135
- def root():
136
- return FileResponse(os.path.join(HERE, "demo.html"))
137
 
138
 
139
  @app.get("/demo")
140
- def demo():
141
- return FileResponse(os.path.join(HERE, "demo.html"))
142
 
143
 
144
  @app.get("/sandbox-only")
@@ -148,12 +192,48 @@ def sandbox_only():
148
 
149
 
150
  @app.get("/social-banner")
151
- def social_banner():
152
  # Standalone hero — wordmark + subtitle + specs + animated DNA helix,
153
  # sized to fit common social-media canvases (Twitter / OG / LinkedIn /
154
  # HF). Used to grab cover-art screenshots without firing up the full
155
  # demo page.
156
- return FileResponse(os.path.join(HERE, "social-banner.html"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
 
159
  @app.get("/config")
 
6
  import httpx
7
  from fastapi import FastAPI, Request
8
  from fastapi.middleware.gzip import GZipMiddleware
9
+ from fastapi.responses import FileResponse, HTMLResponse, PlainTextResponse, RedirectResponse, Response, StreamingResponse
10
  from fastapi.staticfiles import StaticFiles
11
  from openai import OpenAI
12
 
 
44
 
45
  HERE = os.path.dirname(os.path.abspath(__file__))
46
 
47
+ # Absolute base URL used to fill {{SITE_URL}} placeholders in demo.html,
48
+ # sitemap.xml and robots.txt (og:image, canonical, sitemap reference…).
49
+ # If unset, we derive it per-request from the X-Forwarded-* headers (HF
50
+ # Spaces sits behind a proxy that sets them) so og:image, canonical and
51
+ # the sitemap stay correct on whatever host the page is served from.
52
+ SITE_URL_ENV = os.environ.get("SITE_URL", "").rstrip("/")
53
+
54
+
55
+ def site_url_for(request: Request) -> str:
56
+ """Return the absolute origin (scheme://host, no trailing slash)."""
57
+ if SITE_URL_ENV:
58
+ return SITE_URL_ENV
59
+ scheme = request.headers.get("x-forwarded-proto") or request.url.scheme or "http"
60
+ # X-Forwarded-Host may carry a comma-separated chain when multiple
61
+ # proxies are involved; the original client-visible host is the
62
+ # first entry. Host header is the fallback.
63
+ fwd_host = request.headers.get("x-forwarded-host")
64
+ if fwd_host:
65
+ host = fwd_host.split(",")[0].strip()
66
+ else:
67
+ host = request.headers.get("host") or request.url.netloc
68
+ return f"{scheme}://{host}"
69
+
70
+
71
+ def _load_text(path: str) -> str:
72
+ with open(path, encoding="utf-8") as f:
73
+ return f.read()
74
+
75
+
76
+ # Templates loaded once at startup. demo.html and social-banner.html are
77
+ # large; reading them on every request would add ~100 us of syscall +
78
+ # parse overhead each time, which adds up under load. The substitution
79
+ # itself (a single str.replace) is cheap. Reloading on edit happens via
80
+ # uvicorn --reload in dev, which restarts the worker.
81
+ _DEMO_HTML = _load_text(os.path.join(HERE, "demo.html"))
82
+ _SOCIAL_BANNER_HTML = _load_text(os.path.join(HERE, "social-banner.html"))
83
+ _ROBOTS_TXT = _load_text(os.path.join(HERE, "robots.txt"))
84
+ _SITEMAP_XML = _load_text(os.path.join(HERE, "sitemap.xml"))
85
+ _LLMS_TXT = _load_text(os.path.join(HERE, "llms.txt"))
86
+
87
+
88
+ def render(template: str, site_url: str) -> str:
89
+ return template.replace("{{SITE_URL}}", site_url)
90
+
91
 
92
  def get_api_key():
93
  key = os.environ.get("HF_TOKEN")
 
176
 
177
 
178
  @app.get("/")
179
+ def root(request: Request):
180
+ return HTMLResponse(render(_DEMO_HTML, site_url_for(request)))
181
 
182
 
183
  @app.get("/demo")
184
+ def demo(request: Request):
185
+ return HTMLResponse(render(_DEMO_HTML, site_url_for(request)))
186
 
187
 
188
  @app.get("/sandbox-only")
 
192
 
193
 
194
  @app.get("/social-banner")
195
+ def social_banner(request: Request):
196
  # Standalone hero — wordmark + subtitle + specs + animated DNA helix,
197
  # sized to fit common social-media canvases (Twitter / OG / LinkedIn /
198
  # HF). Used to grab cover-art screenshots without firing up the full
199
  # demo page.
200
+ return HTMLResponse(render(_SOCIAL_BANNER_HTML, site_url_for(request)))
201
+
202
+
203
+ # ---------------------------------------------------------------------
204
+ # Discoverability surface: robots.txt, sitemap.xml, llms.txt, favicon.
205
+ # These are tiny files but they are what indexers, AI answer engines
206
+ # (Perplexity, ChatGPT browsing…) and social previews look for first.
207
+ # ---------------------------------------------------------------------
208
+
209
+
210
+ @app.get("/robots.txt", response_class=PlainTextResponse)
211
+ def robots_txt(request: Request):
212
+ return PlainTextResponse(render(_ROBOTS_TXT, site_url_for(request)))
213
+
214
+
215
+ @app.get("/sitemap.xml")
216
+ def sitemap_xml(request: Request):
217
+ return Response(
218
+ content=render(_SITEMAP_XML, site_url_for(request)),
219
+ media_type="application/xml",
220
+ )
221
+
222
+
223
+ @app.get("/llms.txt", response_class=PlainTextResponse)
224
+ def llms_txt():
225
+ # llms.txt (https://llmstxt.org/) — Markdown index aimed at LLM-based
226
+ # agents that need a compact map of the site without scraping the
227
+ # whole editorial page. No {{SITE_URL}} substitution: links are
228
+ # either site-relative or absolute to canonical external URLs.
229
+ return PlainTextResponse(_LLMS_TXT, media_type="text/markdown; charset=utf-8")
230
+
231
+
232
+ @app.get("/favicon.ico")
233
+ def favicon():
234
+ # Browsers ask for /favicon.ico whether or not the page declared one.
235
+ # Redirect to the SVG logo so we don't ship a 404 on every cold load.
236
+ return RedirectResponse(url="/img/logo.svg", status_code=301)
237
 
238
 
239
  @app.get("/config")
assets/js/sections/efficiency.js ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // =========================================================================
2
+ // §13, Efficiency: inference throughput vs number of prompts
3
+ // =========================================================================
4
+ // Numbers come from the public release dataset:
5
+ // HuggingFaceBio/carbon-inference-evals (data/train-00000-of-00001.parquet),
6
+ // filtered to non-remote prompt-scan runs through 512 prompts. Carbon and
7
+ // GENERator runs use vLLM dynamic batching (so batch ≡ num_prompts).
8
+ // Evo2 caps batch size to fit a single H100: Evo2 1B caps at 34 prompts,
9
+ // 7B at 13, 20B and 40B at 4. Past those caps the throughput curve flattens
10
+ // because additional prompts spill into a second sequential mini-batch
11
+ // instead of widening the live one.
12
+ //
13
+ // Two-family palette: cool greens for the Carbon checkpoints (light → dark
14
+ // = small → large), warm browns for the Evo2 baselines. Echoes the rest of
15
+ // the demo so "Carbon vs Evo2" reads at a glance even when several lines
16
+ // stack inside the lower decade of the log axis.
17
+ (function initDemo13() {
18
+ const host = document.getElementById("d13-throughput");
19
+ if (!host) return;
20
+
21
+ const PROMPTS = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512];
22
+
23
+ // throughput in output bp/s, indexed positionally against PROMPTS above.
24
+ // Source: carbon-inference-evals · output_bp_per_second column.
25
+ const SERIES = [
26
+ { name: "Carbon-500M", color: "#A8DCB4", weight: 2.8,
27
+ throughput: [3416.78, 5395.16, 11071.54, 21723.72, 43443.40, 74971.36, 110803.57, 161581.87, 146471.03, 152044.37] },
28
+ { name: "Carbon-3B", color: "#6DBF7E", weight: 3.0,
29
+ throughput: [1489.33, 2916.85, 5561.60, 11309.62, 20109.93, 40027.81, 65218.26, 100126.89, 125130.82, 122840.91] },
30
+ { name: "Carbon-8B", color: "#1A7A40", weight: 3.2,
31
+ throughput: [ 811.71, 1737.51, 3274.83, 6576.03, 12675.68, 22560.89, 39248.04, 46435.76, 76582.70, 85084.69] },
32
+ { name: "Evo2 1B", color: "#C9A06A", weight: 2.6, capLabel: "min(n, 34)",
33
+ throughput: [ 42.32, 86.48, 176.82, 351.63, 705.34, 1409.67, 1436.89, 1435.27, 1342.48, 1400.36] },
34
+ { name: "Evo2 7B", color: "#8C7355", weight: 2.6, capLabel: "min(n, 13)",
35
+ throughput: [ 33.28, 68.78, 132.86, 269.00, 267.13, 360.91, 441.94, 432.32, 453.76, 444.48] },
36
+ { name: "Evo2 20B", color: "#5A4A38", weight: 2.6, capLabel: "min(n, 4)",
37
+ throughput: [ 43.97, 86.04, 169.45, 175.90, 176.45, 177.16, 177.88, 180.47, 177.46, 177.17] },
38
+ { name: "Evo2 40B", color: "#2A211A", weight: 2.6, capLabel: "min(n, 4)",
39
+ throughput: [ 21.75, 43.01, 85.12, 85.74, 84.94, 87.20, 87.93, 85.63, 87.07, 86.78] },
40
+ ];
41
+
42
+ // ----- Layout ----------------------------------------------------------
43
+ // Right gutter is wider than longcontext.js's NIAH chart because we have
44
+ // 7 lines to label end-on (instead of 3) and Evo2 capLabels add a second
45
+ // line under each model name. Font sizes are bumped one notch above the
46
+ // §6 NIAH chart because this figure renders inside the same ~828 px
47
+ // section column as a 1000 px viewBox, so the type optically lands at
48
+ // ~10–11 px on screen — too small for a 7-series log–log plot. Sticking
49
+ // with the 1000×460 viewBox keeps the section grid intact and just
50
+ // restyles the contents.
51
+ const W = 1000, H = 460;
52
+ const padL = 86, padR = 178, padT = 30, padB = 64;
53
+ const innerW = W - padL - padR;
54
+ const innerH = H - padT - padB;
55
+
56
+ const xLo = Math.log2(1), xHi = Math.log2(512);
57
+ const yLo = Math.log10(10), yHi = Math.log10(300000);
58
+ const xFor = n => padL + ((Math.log2(n) - xLo) / (xHi - xLo)) * innerW;
59
+ const yFor = v => padT + ((yHi - Math.log10(v)) / (yHi - yLo)) * innerH;
60
+
61
+ // ----- Render ----------------------------------------------------------
62
+ function render() {
63
+ let svg = "";
64
+
65
+ // y-axis gridlines + labels (1-3-1-3 log decades, matches the source ref)
66
+ const Y_TICKS = [10, 30, 100, 300, 1000, 3000, 10000, 30000, 100000, 300000];
67
+ Y_TICKS.forEach(v => {
68
+ const y = yFor(v);
69
+ const isMajor = v === 10 || v === 100 || v === 1000 || v === 10000 || v === 100000;
70
+ svg += `<line x1="${padL}" y1="${y.toFixed(1)}" x2="${(W - padR).toFixed(1)}" y2="${y.toFixed(1)}" stroke="${isMajor ? "#e5e5e5" : "#f4f4f1"}" stroke-width="1"/>`;
71
+ svg += `<text x="${padL - 10}" y="${(y + 4).toFixed(1)}" font-family="JetBrains Mono" font-size="13" fill="${isMajor ? "#666" : "#b5b5b5"}" text-anchor="end">${formatY(v)}</text>`;
72
+ });
73
+ // Axis title (rotated, left side)
74
+ svg += `<text x="22" y="${(padT + innerH / 2).toFixed(1)}" font-family="JetBrains Mono" font-size="12" fill="#666" text-anchor="middle" transform="rotate(-90 22 ${(padT + innerH / 2).toFixed(1)})" letter-spacing="1.2">THROUGHPUT · BP/S · LOG</text>`;
75
+
76
+ // x-axis ticks + labels
77
+ PROMPTS.forEach(n => {
78
+ const x = xFor(n);
79
+ svg += `<line x1="${x.toFixed(1)}" y1="${(padT + innerH).toFixed(1)}" x2="${x.toFixed(1)}" y2="${(padT + innerH + 5).toFixed(1)}" stroke="#666" stroke-width="1"/>`;
80
+ svg += `<text x="${x.toFixed(1)}" y="${(padT + innerH + 22).toFixed(1)}" font-family="JetBrains Mono" font-size="13" fill="#1f1f1d" text-anchor="middle">${n}</text>`;
81
+ });
82
+ // x-axis title
83
+ svg += `<text x="${(padL + innerW / 2).toFixed(1)}" y="${(padT + innerH + 50).toFixed(1)}" font-family="JetBrains Mono" font-size="12" fill="#666" text-anchor="middle" letter-spacing="1.2">NUMBER OF PROMPTS · LOG</text>`;
84
+
85
+ // baseline at the bottom of the plot zone
86
+ svg += `<line x1="${padL}" y1="${(padT + innerH).toFixed(1)}" x2="${(W - padR).toFixed(1)}" y2="${(padT + innerH).toFixed(1)}" stroke="#1f1f1d" stroke-width="1.2"/>`;
87
+
88
+ // lines (drawn lightest → darkest so the dark Carbon-8B sits on top of
89
+ // its lighter Carbon siblings where the curves cross at low n)
90
+ const drawOrder = [
91
+ "Carbon-500M", "Evo2 1B", "Evo2 20B", "Evo2 40B", "Evo2 7B",
92
+ "Carbon-3B", "Carbon-8B"
93
+ ];
94
+ drawOrder.forEach(name => {
95
+ const s = SERIES.find(s => s.name === name);
96
+ let d = "";
97
+ s.throughput.forEach((v, i) => {
98
+ const x = xFor(PROMPTS[i]);
99
+ const y = yFor(v);
100
+ d += (i === 0 ? "M" : "L") + x.toFixed(1) + " " + y.toFixed(1);
101
+ });
102
+ svg += `<path d="${d}" fill="none" stroke="${s.color}" stroke-width="${s.weight}" stroke-linejoin="round" stroke-linecap="round"/>`;
103
+ s.throughput.forEach((v, i) => {
104
+ const x = xFor(PROMPTS[i]);
105
+ const y = yFor(v);
106
+ svg += `<circle cx="${x.toFixed(1)}" cy="${y.toFixed(1)}" r="3.6" fill="${s.color}" stroke="#fff" stroke-width="1.2"/>`;
107
+ });
108
+ });
109
+
110
+ // End-of-line labels in the right gutter. Each label sits at the y of
111
+ // the n=512 data point; we then nudge overlapping labels apart so the
112
+ // 7-line stack stays legible (Carbon-500M / Carbon-3B are within 0.09
113
+ // log-decades of each other).
114
+ const xEnd = xFor(512) + 14;
115
+ const labels = SERIES.map(s => {
116
+ const last = s.throughput[s.throughput.length - 1];
117
+ return { name: s.name, color: s.color, capLabel: s.capLabel, value: last, y: yFor(last) };
118
+ }).sort((a, b) => a.y - b.y);
119
+
120
+ const minGap = 36; // px, room for two text lines per label
121
+ for (let i = 1; i < labels.length; i++) {
122
+ if (labels[i].y - labels[i - 1].y < minGap) {
123
+ labels[i].y = labels[i - 1].y + minGap;
124
+ }
125
+ }
126
+
127
+ labels.forEach(l => {
128
+ svg += `<text x="${xEnd.toFixed(1)}" y="${l.y.toFixed(1)}" font-family="JetBrains Mono" font-size="14" fill="${l.color}" font-weight="600">${l.name}</text>`;
129
+ const sub = l.capLabel
130
+ ? `<tspan fill="#aaa">batch </tspan>${l.capLabel}`
131
+ : `<tspan fill="#aaa">${formatBp(l.value)} bp/s</tspan>`;
132
+ svg += `<text x="${xEnd.toFixed(1)}" y="${(l.y + 16).toFixed(1)}" font-family="JetBrains Mono" font-size="11" fill="#888">${sub}</text>`;
133
+ });
134
+
135
+ host.setAttribute("viewBox", `0 0 ${W} ${H}`);
136
+ host.innerHTML = svg;
137
+ }
138
+
139
+ // 10 → "10", 1000 → "1k", 30000 → "30k", 100000 → "100k"
140
+ function formatY(v) {
141
+ if (v >= 1000) return (v / 1000) + "k";
142
+ return String(v);
143
+ }
144
+ function formatBp(v) {
145
+ if (v >= 10000) return Math.round(v / 1000) + "k";
146
+ if (v >= 1000) return (v / 1000).toFixed(1) + "k";
147
+ return Math.round(v).toLocaleString();
148
+ }
149
+
150
+ render();
151
+ })();
assets/js/sections/intro.js CHANGED
@@ -192,6 +192,11 @@
192
  sep: Math.abs(yA - yB),
193
  top: topSeq[seqIdx],
194
  bot: comp[topSeq[seqIdx]],
 
 
 
 
 
195
  });
196
  seqIdx++;
197
  }
@@ -357,15 +362,38 @@
357
  }
358
 
359
  // 4. Letter glyphs themselves (no haloes, since the rung is already
360
- // interrupted around each letter). fade tracks fadeForSep so the
361
- // glyphs at the crossings sit as ghosted "out of focus" letters
362
- // rather than disappearing entirely — fills the visual gap at the
363
- // helix waist without competing with the rungs at full opacity.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
  for (const r of rungs) {
365
- const fade = fadeForSep(r.sep);
366
  const [yA, yB] = rungLetterYs(r);
367
- text(svg, r.x, yA, r.top, { mono: true, size: 10, weight: 600, fill: GREEN, opacity: fade });
368
- text(svg, r.x, yB, r.bot, { mono: true, size: 10, weight: 600, fill: GREEN, opacity: fade });
 
 
369
  }
370
 
371
  // 5′ / 3′ end tags. Each label is placed *outside* the higher/lower
 
192
  sep: Math.abs(yA - yB),
193
  top: topSeq[seqIdx],
194
  bot: comp[topSeq[seqIdx]],
195
+ // Which strand currently sits visually higher? Used by letterFade
196
+ // to map each glyph to its attaching strand's depth. The flag flips
197
+ // every time the strands cross, which is what drives the alternating
198
+ // bright/dim pattern of adjacent rungs around the helix waist.
199
+ topOnA: yA <= yB,
200
  });
201
  seqIdx++;
202
  }
 
362
  }
363
 
364
  // 4. Letter glyphs themselves (no haloes, since the rung is already
365
+ // interrupted around each letter). Each glyph fades independently
366
+ // of its rung-mate via letterFade: the rung-wide sep fade still
367
+ // sets the baseline, but each letter is then biased by the depth
368
+ // (z) of the strand it attaches to. Net result: instead of two
369
+ // equally-ghosted letters stacked on top of each other at the
370
+ // crossings, the front-strand letter holds clearly readable while
371
+ // the back-strand letter recedes to a barely-there ghost. And
372
+ // because the "front" strand flips at every half-period, the
373
+ // bright letter alternates between the upper and lower rung
374
+ // position from one rung to the next around the helix waist —
375
+ // echoes the strand back-arc gradients painted in step 1.
376
+ function letterFade(r, isTop) {
377
+ const onA = isTop ? r.topOnA : !r.topOnA;
378
+ const z = zAt(r.x, onA ? phaseA : phaseB); // -1 (back) … +1 (front)
379
+ const lo = 12, hi = 28;
380
+ const t = Math.max(0, Math.min(1, (r.sep - lo) / (hi - lo)));
381
+ const ease = t * t * (3 - 2 * t);
382
+ const sepFade = 0.18 + 0.82 * ease;
383
+ // Bias only kicks in around the crossings; wide rungs (where the
384
+ // strands sit symmetric and z ≈ 0 anyway) keep both letters at
385
+ // full opacity. Amplitude 0.37 lands the front letter near 0.55
386
+ // and the back letter at the 0.08 floor when |z| = 1.
387
+ const bias = z * (1 - ease) * 0.37;
388
+ return Math.max(0.08, Math.min(1, sepFade + bias));
389
+ }
390
+
391
  for (const r of rungs) {
 
392
  const [yA, yB] = rungLetterYs(r);
393
+ const topFade = letterFade(r, true);
394
+ const botFade = letterFade(r, false);
395
+ text(svg, r.x, yA, r.top, { mono: true, size: 10, weight: 600, fill: GREEN, opacity: topFade });
396
+ text(svg, r.x, yB, r.bot, { mono: true, size: 10, weight: 600, fill: GREEN, opacity: botFade });
397
  }
398
 
399
  // 5′ / 3′ end tags. Each label is placed *outside* the higher/lower
assets/styles/sandbox.css CHANGED
@@ -230,7 +230,16 @@
230
  min-height: 80px;
231
  flex: 1 0 auto;
232
  }
233
- #panel-sandbox .sb-seq-block.empty { color: #aaa; font-weight: 300; letter-spacing: normal; }
 
 
 
 
 
 
 
 
 
234
  #panel-sandbox .sb-seq-line { white-space: pre; }
235
  #panel-sandbox .sb-pos { color: #bbb; user-select: none; font-weight: 300; }
236
  #panel-sandbox .sb-seq-line.tail::after {
 
230
  min-height: 80px;
231
  flex: 1 0 auto;
232
  }
233
+ #panel-sandbox .sb-seq-block.empty {
234
+ color: #cfcfcf;
235
+ font-weight: 300;
236
+ letter-spacing: normal;
237
+ background: #fff;
238
+ text-align: center;
239
+ display: flex;
240
+ align-items: center;
241
+ justify-content: center;
242
+ }
243
  #panel-sandbox .sb-seq-line { white-space: pre; }
244
  #panel-sandbox .sb-pos { color: #bbb; user-select: none; font-weight: 300; }
245
  #panel-sandbox .sb-seq-line.tail::after {
demo.html CHANGED
@@ -3,7 +3,92 @@
3
  <head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Carbon · what the model learned</title>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600&display=swap">
@@ -1871,11 +1956,43 @@ print(f"log P(alt) - log P(ref) at pos 20: {delta:+.3f}")</code></pre></div>
1871
 
1872
  <div class="section-body">
1873
  <div class="demo" id="demo13">
1874
- <!-- TODO: drop in the real efficiency figure once it's exported. Placeholder
1875
- below holds the slot so the section reads cleanly at full layout. -->
1876
- <div style="padding:48px 24px;border:1px dashed #c7c2b3;background:#fafaf6;color:#888;font-family:'JetBrains Mono',monospace;font-size:11px;text-align:center;letter-spacing:1px">
1877
- EFFICIENCY FIGURE · COMING SOON<br>
1878
- <span style="font-size:10px;color:#aaa;text-transform:none;letter-spacing:0">throughput / memory vs Evo2 across context lengths</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1879
  </div>
1880
  </div>
1881
 
@@ -2045,6 +2162,7 @@ print(f"log P(alt) - log P(ref) at pos 20: {delta:+.3f}")</code></pre></div>
2045
  <script src="/assets/js/sections/architecture.js"></script>
2046
  <script src="/assets/js/sections/longcontext.js"></script>
2047
  <script src="/assets/js/sections/results.js"></script>
 
2048
  <script src="/assets/js/sections/sandbox.js"></script>
2049
  <script src="/assets/js/sections/umap.js"></script>
2050
  <script src="/assets/js/sections/tree.js"></script>
 
3
  <head>
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Carbon · an open-source autoregressive genomic foundation model</title>
7
+
8
+ <!-- ============================================================ -->
9
+ <!-- Discoverability: SEO + social previews + AI-agent metadata. -->
10
+ <!-- {{SITE_URL}} is substituted at request time by app.py with -->
11
+ <!-- the absolute base URL (scheme + host) the page was served -->
12
+ <!-- under, so og:image / og:url stay correct whether we're on -->
13
+ <!-- the HF Space, a preview deploy, or localhost. -->
14
+ <!-- ============================================================ -->
15
+ <meta name="description" content="Carbon is Hugging Face's open-source family of autoregressive genomic foundation models for DNA. Explore an interactive demo of what the 3B checkpoint learned: streaming continuation, variant effect prediction, ESMFold structure prediction, a UMAP of half a million gene embeddings, and the full training recipe.">
16
+ <meta name="keywords" content="Carbon, DNA, genomics, foundation model, Hugging Face, autoregressive, language model, bioinformatics, variant effect prediction, ESMFold, UMAP, gene embeddings, open source">
17
+ <meta name="author" content="Hugging Face Bio">
18
+ <meta name="theme-color" content="#f7f5ee">
19
+ <meta name="color-scheme" content="light">
20
+ <link rel="canonical" href="{{SITE_URL}}/">
21
+
22
+ <!-- Favicon. Modern browsers honour SVG; we keep the PNG as a -->
23
+ <!-- raster fallback for the few that don't (Safari < 14 etc.). -->
24
+ <link rel="icon" type="image/svg+xml" href="/img/logo.svg">
25
+ <link rel="icon" type="image/png" href="/img/logo.png">
26
+ <link rel="apple-touch-icon" href="/img/logo.png">
27
+
28
+ <!-- Open Graph (Facebook, LinkedIn, Slack, Discord, iMessage…). -->
29
+ <!-- og:image points at /img/logo.png, which is the wide Carbon -->
30
+ <!-- wordmark+helix lockup (1153x634, ~OG-shaped). Swap with a -->
31
+ <!-- proper 1200x630 screenshot of /social-banner once exported. -->
32
+ <meta property="og:type" content="website">
33
+ <meta property="og:site_name" content="Carbon">
34
+ <meta property="og:title" content="Carbon · an open-source autoregressive genomic foundation model">
35
+ <meta property="og:description" content="An interactive editorial demo of Carbon, Hugging Face's open-source DNA foundation model. Streaming continuation, variant scoring, protein folding, gene-embedding UMAP, and the full training recipe.">
36
+ <meta property="og:url" content="{{SITE_URL}}/">
37
+ <meta property="og:image" content="{{SITE_URL}}/img/logo.png">
38
+ <meta property="og:image:width" content="1153">
39
+ <meta property="og:image:height" content="634">
40
+ <meta property="og:image:alt" content="Carbon — the wordmark wrapped in a four-strand DNA helix.">
41
+ <meta property="og:locale" content="en_US">
42
+
43
+ <!-- Twitter / X card. summary_large_image renders the OG image -->
44
+ <!-- as a full-bleed preview tile. -->
45
+ <meta name="twitter:card" content="summary_large_image">
46
+ <meta name="twitter:site" content="@huggingface">
47
+ <meta name="twitter:creator" content="@huggingface">
48
+ <meta name="twitter:title" content="Carbon · an open-source autoregressive genomic foundation model">
49
+ <meta name="twitter:description" content="An interactive editorial demo of Carbon, Hugging Face's open-source DNA foundation model. Streaming continuation, variant scoring, protein folding, gene-embedding UMAP, and the full training recipe.">
50
+ <meta name="twitter:image" content="{{SITE_URL}}/img/logo.png">
51
+ <meta name="twitter:image:alt" content="Carbon — the wordmark wrapped in a four-strand DNA helix.">
52
+
53
+ <!-- JSON-LD structured data. Helps search engines and LLM- -->
54
+ <!-- powered answer engines (Perplexity, ChatGPT browsing, etc.) -->
55
+ <!-- understand what this page is: a tech article about an open- -->
56
+ <!-- source software model, with links back to its model card, -->
57
+ <!-- code, and dataset. -->
58
+ <script type="application/ld+json">
59
+ {
60
+ "@context": "https://schema.org",
61
+ "@graph": [
62
+ {
63
+ "@type": "TechArticle",
64
+ "@id": "{{SITE_URL}}/#article",
65
+ "headline": "Carbon · an open-source autoregressive genomic foundation model",
66
+ "description": "An interactive editorial walkthrough of Carbon, Hugging Face's open-source DNA foundation model: streaming continuation, variant effect prediction, ESMFold-based protein structure prediction, a UMAP of ~500k gene embeddings, and the full training recipe (tokenizer, loss, dataset, results).",
67
+ "url": "{{SITE_URL}}/",
68
+ "image": "{{SITE_URL}}/img/logo.png",
69
+ "inLanguage": "en",
70
+ "author": { "@type": "Organization", "name": "Hugging Face Bio", "url": "https://huggingface.co/HuggingFaceBio" },
71
+ "publisher": { "@type": "Organization", "name": "Hugging Face", "url": "https://huggingface.co" },
72
+ "about": {
73
+ "@type": "SoftwareApplication",
74
+ "name": "Carbon-3B",
75
+ "applicationCategory": "ScienceApplication",
76
+ "operatingSystem": "Any",
77
+ "url": "https://huggingface.co/HuggingFaceBio/Carbon-3B",
78
+ "description": "Autoregressive genomic foundation model. 3B parameters, 393,216 bp context, 6-mer tokenizer, trained on 1T tokens of DNA across the tree of life.",
79
+ "license": "https://huggingface.co/HuggingFaceBio/Carbon-3B",
80
+ "isAccessibleForFree": true
81
+ },
82
+ "isPartOf": {
83
+ "@type": "WebSite",
84
+ "name": "Carbon",
85
+ "url": "{{SITE_URL}}/"
86
+ }
87
+ }
88
+ ]
89
+ }
90
+ </script>
91
+
92
  <link rel="preconnect" href="https://fonts.googleapis.com">
93
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
94
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600&display=swap">
 
1956
 
1957
  <div class="section-body">
1958
  <div class="demo" id="demo13">
1959
+ <!-- Caption stack:
1960
+ - eyebrow (mono, green) : "what is this chart"
1961
+ - rule line : a thin neutral hairline that separates
1962
+ eyebrow from secondary meta, lifting
1963
+ the title above an undifferentiated
1964
+ string of bullet-separated notes
1965
+ - meta line (mono, grey) : units, hardware, axes
1966
+ The implementation detail (vLLM / Evo2 native runner) was previously
1967
+ crammed into the same line as the title; it now lives next to the
1968
+ legend at the bottom where the reader actually looks for "how was
1969
+ this measured" once they've parsed the curves. -->
1970
+ <div class="fig-caption" style="display:flex;align-items:baseline;gap:14px;flex-wrap:nowrap;margin-top:0;margin-bottom:6px;font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:1.2px;text-transform:uppercase;white-space:nowrap">
1971
+ <span style="color:#317f3f;font-weight:600">Fig · Inference throughput</span>
1972
+ <span aria-hidden="true" style="flex:1;min-width:24px;height:1px;background:#e5e5e5;align-self:center"></span>
1973
+ <span style="color:#1f1f1d">Output bp/s</span>
1974
+ <span style="color:#aaa">·</span>
1975
+ <span style="color:#888">Single H100</span>
1976
+ </div>
1977
+ <svg id="d13-throughput" preserveAspectRatio="xMinYMin meet" style="display:block;width:100%;background:#fff;border:1px solid #eee"></svg>
1978
+ <!-- Bigger sentence-case legend (.chart-legend variant from sequence.css)
1979
+ to make the 7-model key feel like a proper colour reference rather
1980
+ than a caption strip. The "Legend" prefix uses the same mono-uppercase
1981
+ editorial-label register as .seq-label / .sb-examples-label so it
1982
+ reads as a section gutter rather than as another item in the row. -->
1983
+ <div class="track-axis-label chart-legend" style="justify-content:flex-start">
1984
+ <span style="font-family:'JetBrains Mono',monospace;font-size:10px;color:#888;text-transform:uppercase;letter-spacing:1.5px;font-weight:500">Legend</span>
1985
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#1A7A40"></span>Carbon-8B</span>
1986
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#6DBF7E"></span>Carbon-3B</span>
1987
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#A8DCB4"></span>Carbon-500M</span>
1988
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#C9A06A"></span>Evo2 1B</span>
1989
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#8C7355"></span>Evo2 7B</span>
1990
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#5A4A38"></span>Evo2 20B</span>
1991
+ <span class="chart-legend__item"><span class="legend-swatch" style="background:#2A211A"></span>Evo2 40B</span>
1992
+ </div>
1993
+ <div style="margin-top:14px;padding-top:10px;border-top:1px solid #eee;font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:1px;text-transform:uppercase;color:#888;display:flex;justify-content:space-between;flex-wrap:wrap;gap:14px">
1994
+ <span>Source · <a href="https://huggingface.co/datasets/HuggingFaceBio/carbon-inference-evals" style="color:#1f1f1d;text-decoration:underline">carbon-inference-evals</a></span>
1995
+ <span style="color:#aaa">vLLM for Carbon · Evo2 native runner</span>
1996
  </div>
1997
  </div>
1998
 
 
2162
  <script src="/assets/js/sections/architecture.js"></script>
2163
  <script src="/assets/js/sections/longcontext.js"></script>
2164
  <script src="/assets/js/sections/results.js"></script>
2165
+ <script src="/assets/js/sections/efficiency.js"></script>
2166
  <script src="/assets/js/sections/sandbox.js"></script>
2167
  <script src="/assets/js/sections/umap.js"></script>
2168
  <script src="/assets/js/sections/tree.js"></script>
img/Group 2.eps ADDED
@@ -0,0 +1,971 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ %!PS-Adobe-3.0 EPSF-3.0
2
+ %APL_DSC_Encoding: UTF8
3
+ %APLProducer: (Version 26.2 (Build 25C56) Quartz PS Context)
4
+ %%Title: (Unknown)
5
+ %%Creator: (Unknown)
6
+ %%CreationDate: (Unknown)
7
+ %%For: (Unknown)
8
+ %%DocumentData: Clean7Bit
9
+ %%LanguageLevel: 2
10
+ %%Pages: 1
11
+ %%BoundingBox: 0 0 145 144
12
+ %%EndComments
13
+ %%BeginProlog
14
+ %%BeginFile: cg-pdf.ps
15
+ %%Copyright: Copyright 2000-2004 Apple Computer Incorporated.
16
+ %%Copyright: All Rights Reserved.
17
+ currentpacking true setpacking
18
+ /cg_md 141 dict def
19
+ cg_md begin
20
+ /L3? languagelevel 3 ge def
21
+ /bd{bind def}bind def
22
+ /ld{load def}bd
23
+ /xs{exch store}bd
24
+ /xd{exch def}bd
25
+ /cmmtx matrix def
26
+ mark
27
+ /sc/setcolor
28
+ /scs/setcolorspace
29
+ /dr/defineresource
30
+ /fr/findresource
31
+ /T/true
32
+ /F/false
33
+ /d/setdash
34
+ /w/setlinewidth
35
+ /J/setlinecap
36
+ /j/setlinejoin
37
+ /M/setmiterlimit
38
+ /i/setflat
39
+ /rc/rectclip
40
+ /rf/rectfill
41
+ /rs/rectstroke
42
+ /f/fill
43
+ /f*/eofill
44
+ /sf/selectfont
45
+ /s/show
46
+ %/as/ashow
47
+ /xS/xshow
48
+ /yS/yshow
49
+ /xyS/xyshow
50
+ /S/stroke
51
+ /m/moveto
52
+ /l/lineto
53
+ /c/curveto
54
+ /h/closepath
55
+ /n/newpath
56
+ /q/gsave
57
+ /Q/grestore
58
+ counttomark 2 idiv
59
+ %dup (number of ld's = )print == flush % *** how many
60
+ {ld}repeat pop
61
+ /SC{ % CSname
62
+ /ColorSpace fr scs
63
+ }bd
64
+ /sopr /setoverprint where{pop/setoverprint}{/pop}ifelse ld
65
+ /soprm /setoverprintmode where{pop/setoverprintmode}{/pop}ifelse ld
66
+ /cgmtx matrix def
67
+ /sdmtx{cgmtx currentmatrix pop}bd
68
+ /CM {cgmtx setmatrix}bd % pop the ctm: our gstate ctm on host is now identity
69
+ /cm {cmmtx astore CM concat}bd % reset the matrix and then concat
70
+ /W{clip newpath}bd
71
+ /W*{eoclip newpath}bd
72
+
73
+ statusdict begin product end dup (HP) anchorsearch{
74
+ pop pop pop % pop off the search results
75
+ true
76
+ }{
77
+ pop % previous search result
78
+ (hp) anchorsearch{
79
+ pop pop true
80
+ }{
81
+ pop false
82
+ }ifelse
83
+ }ifelse
84
+
85
+ { % HP is the product: we use this method of stroking because of a bug in their clone printers with certain T3 fonts
86
+ {
87
+ { % charCode Wx Wy
88
+ pop pop % charCode
89
+ (0)dup 0 4 -1 roll put
90
+ F charpath
91
+ }cshow
92
+ }
93
+ }{
94
+ {F charpath}
95
+ }ifelse
96
+ /cply exch bd
97
+ /cps {cply stroke}bd
98
+ /pgsave 0 def
99
+ /bp{/pgsave save store}bd
100
+ /ep{pgsave restore showpage}def % dont' bind
101
+ /re{4 2 roll m 1 index 0 rlineto 0 exch rlineto neg 0 rlineto h}bd
102
+
103
+ /scrdict 10 dict def
104
+ /scrmtx matrix def
105
+ /patarray 0 def
106
+ /createpat{patarray 3 1 roll put}bd
107
+ /makepat{
108
+ scrmtx astore pop
109
+ gsave
110
+ initgraphics
111
+ CM
112
+ patarray exch get
113
+ scrmtx
114
+ makepattern
115
+ grestore
116
+ setpattern
117
+ }bd
118
+
119
+ /cg_BeginEPSF{
120
+ userdict save/cg_b4_Inc_state exch put
121
+ userdict/cg_endepsf/cg_EndEPSF load put
122
+ count userdict/cg_op_count 3 -1 roll put
123
+ countdictstack dup array dictstack userdict/cg_dict_array 3 -1 roll put
124
+ 3 sub{end}repeat
125
+ /showpage {} def
126
+ 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin
127
+ 10 setmiterlimit [] 0 setdash newpath
128
+ false setstrokeadjust false setoverprint % don't use F
129
+ }bd
130
+ /cg_EndEPSF{
131
+ countdictstack 3 sub { end } repeat
132
+ cg_dict_array 3 1 index length 3 sub getinterval
133
+ {begin}forall
134
+ count userdict/cg_op_count get sub{pop}repeat
135
+ userdict/cg_b4_Inc_state get restore
136
+ F setpacking
137
+ }bd
138
+
139
+ /cg_biproc{currentfile/RunLengthDecode filter}bd
140
+ /cg_aiproc{currentfile/ASCII85Decode filter/RunLengthDecode filter}bd
141
+ /ImageDataSource 0 def
142
+ L3?{
143
+ /cg_mibiproc{pop pop/ImageDataSource{cg_biproc}def}bd
144
+ /cg_miaiproc{pop pop/ImageDataSource{cg_aiproc}def}bd
145
+ }{
146
+ /ImageBandMask 0 def
147
+ /ImageBandData 0 def
148
+ /cg_mibiproc{
149
+ string/ImageBandMask xs
150
+ string/ImageBandData xs
151
+ /ImageDataSource{[currentfile/RunLengthDecode filter dup ImageBandMask/readstring cvx
152
+ /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd
153
+ }bd
154
+ /cg_miaiproc{
155
+ string/ImageBandMask xs
156
+ string/ImageBandData xs
157
+ /ImageDataSource{[currentfile/ASCII85Decode filter/RunLengthDecode filter
158
+ dup ImageBandMask/readstring cvx
159
+ /pop cvx dup ImageBandData/readstring cvx/pop cvx]cvx bind}bd
160
+ }bd
161
+ }ifelse
162
+ /imsave 0 def
163
+ /BI{save/imsave xd mark}bd
164
+ /EI{imsave restore}bd
165
+ /ID{
166
+ counttomark 2 idiv
167
+ dup 2 add % leave room for imagetype and imagematrix
168
+ dict begin
169
+ {def} repeat
170
+ pop % remove mark
171
+ /ImageType 1 def
172
+ /ImageMatrix[Width 0 0 Height neg 0 Height]def
173
+ currentdict dup/ImageMask known{ImageMask}{F}ifelse exch
174
+ % currentdict on stack
175
+ L3?{
176
+ dup/MaskedImage known
177
+ {
178
+ pop
179
+ <<
180
+ /ImageType 3
181
+ /InterleaveType 2
182
+ /DataDict currentdict
183
+ /MaskDict
184
+ << /ImageType 1
185
+ /Width Width
186
+ /Height Height
187
+ /ImageMatrix ImageMatrix
188
+ /BitsPerComponent 1
189
+ /Decode [0 1]
190
+ currentdict/Interpolate known
191
+ {/Interpolate Interpolate}if
192
+ >>
193
+ >>
194
+ }if
195
+ }if
196
+ exch
197
+ {imagemask}{image}ifelse
198
+ end % pop imagedict from dict stack
199
+ }bd
200
+
201
+ /cguidfix{statusdict begin mark version end
202
+ {cvr}stopped{cleartomark 0}{exch pop}ifelse
203
+ 2012 lt{dup findfont dup length dict begin
204
+ {1 index/FID ne 2 index/UniqueID ne and
205
+ {def} {pop pop} ifelse}forall
206
+ currentdict end definefont pop
207
+ }{pop}ifelse
208
+ }bd
209
+ /t_array 0 def
210
+ /t_i 0 def
211
+ /t_c 1 string def
212
+ /x_proc{ % x y
213
+ exch t_array t_i get add exch moveto
214
+ /t_i t_i 1 add store
215
+ }bd
216
+ /y_proc{ % x y
217
+ t_array t_i get add moveto
218
+ /t_i t_i 1 add store
219
+ }bd
220
+ /xy_proc{
221
+ % x y
222
+ t_array t_i 2 copy 1 add get 3 1 roll get
223
+ 4 -1 roll add 3 1 roll add moveto
224
+ /t_i t_i 2 add store
225
+ }bd
226
+ /sop 0 def % don't bind sop
227
+ /cp_proc/x_proc ld % default moveto proc is for xwidths only
228
+ /base_charpath % string array
229
+ {
230
+ /t_array xs
231
+ /t_i 0 def
232
+ { % char
233
+ t_c 0 3 -1 roll put
234
+ currentpoint
235
+ t_c cply sop
236
+ cp_proc
237
+ }forall
238
+ /t_array 0 def
239
+ }bd
240
+ /sop/stroke ld % default sop is stroke. Done here so we don't bind in /base_charpath
241
+
242
+ % default sop is stroke
243
+ /nop{}def
244
+ /xsp/base_charpath ld
245
+ /ysp{/cp_proc/y_proc ld base_charpath/cp_proc/x_proc ld}bd
246
+ /xysp{/cp_proc/xy_proc ld base_charpath/cp_proc/x_proc ld}bd
247
+ /xmp{/sop/nop ld /cp_proc/x_proc ld base_charpath/sop/stroke ld}bd
248
+ /ymp{/sop/nop ld /cp_proc/y_proc ld base_charpath/sop/stroke ld}bd
249
+ /xymp{/sop/nop ld /cp_proc/xy_proc ld base_charpath/sop/stroke ld}bd
250
+ /refnt{ % newname encoding fontname
251
+ findfont dup length dict copy dup
252
+ /Encoding 4 -1 roll put
253
+ definefont pop
254
+ }bd
255
+ /renmfont{ % newname fontname
256
+ findfont dup length dict copy definefont pop
257
+ }bd
258
+
259
+ L3? dup dup{save exch}if
260
+
261
+ % languagelevel2 ONLY code goes here
262
+
263
+ /Range 0 def
264
+ /DataSource 0 def
265
+ /val 0 def
266
+ /nRange 0 def
267
+ /mulRange 0 def
268
+ /d0 0 def
269
+ /r0 0 def
270
+ /di 0 def
271
+ /ri 0 def
272
+ /a0 0 def
273
+ /a1 0 def
274
+ /r1 0 def
275
+ /r2 0 def
276
+ /dx 0 def
277
+ /Nsteps 0 def
278
+ /sh3tp 0 def
279
+ /ymax 0 def
280
+ /ymin 0 def
281
+ /xmax 0 def
282
+ /xmin 0 def
283
+
284
+ /setupFunEval % funDict -- % this calculates and sets up a function dict for evaulation.
285
+ {
286
+ begin
287
+ /nRange Range length 2 idiv store
288
+ /mulRange % precompute the range data needed to map a sample value from the table to a range value
289
+ % this data looks like [ range0mul range0min range1mul range1min ... rangeN-1mul rangeN-1min ]
290
+ [
291
+ 0 1 nRange 1 sub
292
+ { % index
293
+ 2 mul/nDim2 xd % 2*dimension# we are dealing with
294
+ Range nDim2 get % ymin
295
+ Range nDim2 1 add get % ymin ymax
296
+ 1 index sub % ymin (ymax-ymin)
297
+ % xmin = 0, xmax = 255 (2^bitspersample - 1)
298
+ 255 div % ymin (ymax-ymin)/(xmax - xmin)
299
+ exch % (ymax-ymin)/(xmax - xmin) ymin
300
+ }for
301
+ ]store
302
+ end
303
+ }bd
304
+
305
+ /FunEval % val1 fundict -> comp1 comp2 ... compN
306
+ {
307
+ begin
308
+ % the value passed in is the base index into the table
309
+ nRange mul /val xd % compute the actual index to the table
310
+ % since there are nRange entries per base index
311
+ 0 1 nRange 1 sub
312
+ {
313
+ dup 2 mul/nDim2 xd % dim
314
+ val % base value to use to do our lookup
315
+ add DataSource exch get % lookedupval
316
+ mulRange nDim2 get mul % lookedupval*(ymax-ymin)/(xmax-xmin)
317
+ mulRange nDim2 1 add get % lookedupval*(ymax-ymin)/(xmax-xmin) ymin
318
+ add % interpolated result
319
+ }for % comp1 comp2 ... compN
320
+ end
321
+ }bd
322
+
323
+ /max % a b -> max(a, b)
324
+ {
325
+ 2 copy lt
326
+ {exch pop}{pop}ifelse
327
+ }bd
328
+
329
+ /sh2
330
+ { % emulation of shading type 2. Assumes shading dictionary is top dictionary on the dict stack
331
+ /Coords load aload pop % x0 y0 x1 y1
332
+ 3 index 3 index translate % origin is now at beginning point of shading
333
+ % x0 y0 x1 y1
334
+ 3 -1 roll sub % x0 x1 y1-y0
335
+ 3 1 roll exch % y1-y0 x1 x0
336
+ sub % y1-y0 x1-x0
337
+ 2 copy
338
+ dup mul exch dup mul add sqrt % length of segment between two points
339
+ dup
340
+ scale
341
+ atan % atan (dy/dx)
342
+ %dup (rotation angle = )print ==
343
+ rotate % now line between 0,0 and 1,0 is the line perpendicular to which the axial lines are drawn
344
+
345
+ /Function load setupFunEval % may need to setup function dictionary by calling setupFunEval
346
+
347
+ % this is now specific to axial shadings. Compute the maximum bounds to fill
348
+ clippath {pathbbox}stopped {0 0 0 0}if newpath % x0 y0 x1 y1
349
+ /ymax xs
350
+ /xmax xs
351
+ /ymin xs
352
+ /xmin xs
353
+ currentdict/Extend known
354
+ {
355
+ /Extend load 0 get
356
+ {
357
+ 0/Function load FunEval sc % evaluate the function to get a color and set it
358
+ xmin ymin xmin abs ymax ymin sub rectfill
359
+ }if
360
+ }if
361
+ % paint the rects. The sampling frequency is that of our table
362
+ /Nsteps/Function load/Size get 0 get 1 sub store
363
+ /dx 1 Nsteps div store
364
+ gsave
365
+ /di ymax ymin sub store
366
+ /Function load
367
+ % loop Nsteps + 1 times, incrementing the index by 1 each time
368
+ 0 1 Nsteps
369
+ {
370
+ 1 index FunEval sc
371
+ 0 ymin dx di rectfill
372
+ dx 0 translate
373
+ }for
374
+ pop % pop our function
375
+ grestore % origin is back to start point
376
+ currentdict/Extend known
377
+ {
378
+ /Extend load 1 get
379
+ {
380
+ Nsteps/Function load FunEval sc % last element
381
+ 1 ymin xmax 1 sub abs ymax ymin sub rectfill
382
+ }if
383
+ }if
384
+ }bd
385
+
386
+ /shp % this paints our shape for shading type 3
387
+ { % x1 r1 x0 r0 -
388
+ 4 copy
389
+
390
+ % fill interior arc
391
+ dup 0 gt{
392
+ 0 exch a1 a0 arc
393
+ }{
394
+ pop 0 moveto
395
+ }ifelse
396
+
397
+ dup 0 gt{
398
+ 0 exch a0 a1 arcn
399
+ }{
400
+ pop 0 lineto
401
+ }ifelse
402
+
403
+ fill
404
+
405
+ % fill exterior arc
406
+ dup 0 gt{
407
+ 0 exch a0 a1 arc
408
+ }{
409
+ pop 0 moveto
410
+ }ifelse
411
+
412
+ dup 0 gt{
413
+ 0 exch a1 a0 arcn
414
+ }{
415
+ pop 0 lineto
416
+ }ifelse
417
+
418
+ fill
419
+ }bd
420
+
421
+ /calcmaxs
422
+ { % calculate maximum distance vector from origin to corner points
423
+ % of bbox
424
+ xmin dup mul ymin dup mul add sqrt % (xmin2 + ymin2)
425
+ xmax dup mul ymin dup mul add sqrt % (xmax2 + ymin2)
426
+ xmin dup mul ymax dup mul add sqrt % (xmin2 + ymax2)
427
+ xmax dup mul ymax dup mul add sqrt % (xmax2 + ymax2)
428
+ max max max % maximum value
429
+ }bd
430
+
431
+ /sh3
432
+ { % emulation of shading type 3. Assumes shading dictionary is top dictionary on the dict stack
433
+ /Coords load aload pop % x0 y0 r1 x1 y1 r2
434
+ 5 index 5 index translate % origin is now at first circle origin
435
+ 3 -1 roll 6 -1 roll sub % y0 r1 y1 r2 dx
436
+ 3 -1 roll 5 -1 roll sub % r1 r2 dx dy
437
+ 2 copy dup mul exch dup mul add sqrt
438
+ /dx xs % r1 r2 dx dy
439
+ 2 copy 0 ne exch 0 ne or
440
+ {
441
+ % r1 r2 dx dy
442
+ exch atan rotate % we are now rotated so dy is zero and positive values of dx move us as expected
443
+ }{
444
+ pop pop
445
+ }ifelse
446
+ % r1 r2
447
+ /r2 xs
448
+ /r1 xs
449
+ /Function load
450
+ dup/Size get 0 get 1 sub % this is the size of our table minus 1
451
+ /Nsteps xs % at some point we should optimize this better so NSteps is based on needed steps for the device
452
+ setupFunEval % may need to setup function dictionary by calling setupFunEval
453
+ % determine the case:
454
+ % case 0: circle1 inside circle2
455
+ % case 1: circle 2 inside circle 1
456
+ % case 2: r1 = r2
457
+ % case 3: r1 != r2
458
+ dx r2 add r1 lt{
459
+ % circle 2 inside of circle 1
460
+ 0
461
+ }{
462
+ dx r1 add r2 le
463
+ { % circle 1 inside of circle 2
464
+ 1
465
+ }{ % circles don't contain each other
466
+ r1 r2 eq
467
+ { % equal
468
+ 2
469
+ }{ % r1 != r2
470
+ 3
471
+ }ifelse
472
+ }ifelse
473
+ }ifelse
474
+ /sh3tp xs % sh3tp has the number of our different cases
475
+ clippath {pathbbox}stopped {0 0 0 0}if
476
+ newpath % x0 y0 x1 y1
477
+ /ymax xs
478
+ /xmax xs
479
+ /ymin xs
480
+ /xmin xs
481
+
482
+ % Arc angle atan( sqrt((dx*dx + dy*dy) - dr*dr), dr)
483
+ dx dup mul r2 r1 sub dup mul sub dup 0 gt
484
+ {
485
+ sqrt r2 r1 sub atan
486
+ /a0 exch 180 exch sub store
487
+ /a1 a0 neg store
488
+ }{
489
+ pop
490
+ /a0 0 store
491
+ /a1 360 store
492
+ }ifelse
493
+
494
+ currentdict/Extend known
495
+ {
496
+ /Extend load 0 get r1 0 gt and % no need to extend if the radius of the first end is 0
497
+ {
498
+ 0/Function load FunEval sc % evaluate the function to get a color and set it
499
+ % case 0: circle1 inside circle2
500
+ % case 1: circle 2 inside circle 1
501
+ % case 2: circles don't contain each other and r1 == r2
502
+ % case 3: circles don't contain each other and r1 != r2
503
+ {
504
+ { % case 0
505
+ dx 0 r1 360 0 arcn
506
+ xmin ymin moveto
507
+ xmax ymin lineto
508
+ xmax ymax lineto
509
+ xmin ymax lineto
510
+ xmin ymin lineto
511
+ eofill % for the bigger radius we fill everything except our circle
512
+ }
513
+ { % case 1
514
+ r1 0 gt{0 0 r1 0 360 arc fill}if
515
+ }
516
+ { % case 2
517
+ % r1 == r2, extend 0
518
+ % r3 = r, x3 = -(abs(minx) + r), x1 = 0
519
+
520
+ % x(i+1) r(i+1) x(i) r(i) shp
521
+ 0 r1 xmin abs r1 add neg r1 shp
522
+ }
523
+ { % case 3
524
+ % no containment, r1 != r2
525
+
526
+ r2 r1 gt{ % the endpoint we are drawing is that with a circle of zero radius
527
+ % x(i+1) r(i+1) x(i) r(i) shp
528
+ 0 r1
529
+ r1 neg r2 r1 sub div dx mul % this is point of beginning circle
530
+ 0 % point of ending circle
531
+ shp % takes x(i+1) r(i+1) x(i) r(i)
532
+ }{ % the first circle is the bigger of the two
533
+ % we find a circle on our line which is outside the bbox in the
534
+ % negative direction
535
+ % x(i+1) r(i+1) x(i) r(i) shp
536
+ 0 r1 calcmaxs % 0 r1 maxs
537
+ dup
538
+ % calculating xs: (-(maxs+r2)*x2)/(x2-(r1-r2))
539
+ r2 add dx mul dx r1 r2 sub sub div
540
+ neg % maxs xs'
541
+ exch 1 index % xs' maxs xs'
542
+ abs exch sub
543
+ shp
544
+ }ifelse
545
+ }
546
+ }sh3tp get exec % execute the extend at beginning proc for our shading type
547
+ }if
548
+ }if
549
+
550
+ % now do the shading
551
+ /d0 0 store
552
+ /r0 r1 store
553
+ /di dx Nsteps div store
554
+ /ri r2 r1 sub Nsteps div store
555
+ /Function load
556
+ 0 1 Nsteps
557
+ { % function t(i)
558
+ 1 index FunEval sc
559
+ d0 di add r0 ri add d0 r0 shp
560
+ {
561
+ % fill interior arc
562
+ d0 0 r0 a1 a0 arc
563
+ d0 di add 0 r0 ri add a0 a1 arcn
564
+ fill
565
+
566
+ % fill exterior arc
567
+ d0 0 r0 a0 a1 arc
568
+ d0 di add 0 r0 ri add a1 a0 arcn
569
+ fill
570
+ }pop
571
+
572
+ % advance to next
573
+ /d0 d0 di add store
574
+ /r0 r0 ri add store
575
+ }for
576
+ pop % pop our function dict
577
+
578
+ % handle Extend
579
+ currentdict/Extend known
580
+ {
581
+ /Extend load 1 get r2 0 gt and % no need to extend if the radius of the last end is 0
582
+ {
583
+ Nsteps/Function load FunEval sc % last element
584
+ % case 0: circle1 inside circle2
585
+ % case 1: circle 2 inside circle 1
586
+ % case 2: circles don't contain each other and r1 == r2
587
+ % case 3: circles don't contain each other and r1 != r2
588
+ {
589
+ {
590
+ dx 0 r2 0 360 arc fill
591
+ }
592
+ {
593
+ dx 0 r2 360 0 arcn
594
+ xmin ymin moveto
595
+ xmax ymin lineto
596
+ xmax ymax lineto
597
+ xmin ymax lineto
598
+ xmin ymin lineto
599
+ eofill % for the bigger radius we fill everything except our circle
600
+ }
601
+ { % r1 == r2, extend 1
602
+ % r3 = r, x3 = (abs(xmax) + r), x1 = dx
603
+ % x(i+1) r(i+1) x(i) r(i) shp
604
+ xmax abs r1 add r1 dx r1 shp
605
+ }
606
+ { % no containment, r1 != r2
607
+
608
+ r2 r1 gt{
609
+ % we find a circle on our line which is outside the bbox in the
610
+ % positive direction
611
+ % x(i+1) r(i+1) x(i) r(i) shp
612
+ calcmaxs dup % maxs maxs
613
+ % calculating xs: ((maxs+r1)*x2)/(x2-(r2-r1))
614
+ r1 add dx mul dx r2 r1 sub sub div % maxs xs
615
+ exch 1 index % xs maxs xs
616
+ exch sub
617
+ dx r2
618
+ shp
619
+ }{ % the endpoint we are drawing is that with a circle of zero radius
620
+ % x(i+1) r(i+1) x(i) r(i) shp
621
+ r1 neg r2 r1 sub div dx mul % this is point of ending circle
622
+ 0 % radius of ending circle
623
+ dx % point of starting circle
624
+ r2 % radius of starting circle
625
+ shp
626
+ }ifelse
627
+ }
628
+ }
629
+ sh3tp get exec % execute the extend at end proc for our shading type
630
+ }if
631
+ }if
632
+ }bd
633
+ /sh % emulation of shfill operator for type 2 and type 3 shadings based on type 0 functions
634
+ { % shadingDict --
635
+ begin
636
+ /ShadingType load dup dup 2 eq exch 3 eq or
637
+ { % shadingtype
638
+ gsave
639
+ newpath
640
+ /ColorSpace load scs
641
+ currentdict/BBox known
642
+ {
643
+ /BBox load aload pop % llx lly urx ury
644
+ 2 index sub % llx lly urx ury-lly
645
+ 3 index % llx lly urx ury-lly llx
646
+ 3 -1 roll exch sub
647
+ exch rectclip
648
+ }if
649
+ 2 eq
650
+ {sh2}{sh3}ifelse
651
+ grestore
652
+ }{
653
+ % shadingtype
654
+ pop
655
+ (DEBUG: shading type unimplemented\n)print flush
656
+ }ifelse
657
+ end
658
+ }bd
659
+
660
+ % end of language level 2 ONLY code
661
+
662
+ {restore}if not dup{save exch}if
663
+ % languagelevel3 ONLY code goes here
664
+ L3?{ % we do these loads conditionally or else they will fail on a level 2 printer
665
+ /sh/shfill ld
666
+ /csq/clipsave ld
667
+ /csQ/cliprestore ld
668
+ }if
669
+ {restore}if
670
+
671
+ %currentdict dup maxlength exch length sub (number of extra slots in md = )print == flush % *** how many entries are free
672
+ end
673
+ setpacking
674
+ % count 0 ne { pstack(***extras on stack during prolog execution***\n)print flush}if % *** BARK if anything is left on stack
675
+ %%EndFile
676
+ %%EndProlog
677
+ %%BeginSetup
678
+ %%EndSetup
679
+ %%Page: 1 1
680
+ %%PageBoundingBox: 0 0 145 144
681
+ %%BeginPageSetup
682
+ cg_md begin
683
+ bp
684
+ sdmtx
685
+ [ /CIEBasedABC 4 dict dup begin
686
+ /WhitePoint [ 0.9505 1.0000 1.0891 ] def
687
+ /DecodeABC [
688
+ { 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse
689
+ 1 index 1 index ge { exch pop } { pop } ifelse <
690
+ 0000000000000000000000000000000000000000000000000000000000000000
691
+ 0000000000000000000000000000000000000001010101010101010101010101
692
+ 0101010101010101010101010101010101010101010101020202020202020202
693
+ 0202020202020202020202020202020202030303030303030303030303030303
694
+ 0303030303030304040404040404040404040404040404040404050505050505
695
+ 0505050505050505050506060606060606060606060606060607070707070707
696
+ 0707070707070708080808080808080808080808090909090909090909090909
697
+ 0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c
698
+ 0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010
699
+ 1010101010111111111111111112121212121212121313131313131313141414
700
+ 1414141414151515151515151616161616161616171717171717171818181818
701
+ 18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d
702
+ 1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223
703
+ 2323232323242424242425252525252526262626262727272727282828282829
704
+ 292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f
705
+ 2f2f303030303131313131323232323333333333343434343535353535363636
706
+ 36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e
707
+ 3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646
708
+ 4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f
709
+ 4f50505051515151525252535353535454545555555656565657575758585859
710
+ 59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263
711
+ 63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e
712
+ 6e6e6f6f6f707070717171727273737374747475757576767677777878787979
713
+ 797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585
714
+ 86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292
715
+ 9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f
716
+ a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae
717
+ aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd
718
+ bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc
719
+ cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd
720
+ dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee
721
+ eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff
722
+ > dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling
723
+ cvi 3 index exch get 4 -1 roll 3 -1 roll get
724
+ dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind
725
+
726
+ { 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse
727
+ 1 index 1 index ge { exch pop } { pop } ifelse <
728
+ 0000000000000000000000000000000000000000000000000000000000000000
729
+ 0000000000000000000000000000000000000001010101010101010101010101
730
+ 0101010101010101010101010101010101010101010101020202020202020202
731
+ 0202020202020202020202020202020202030303030303030303030303030303
732
+ 0303030303030304040404040404040404040404040404040404050505050505
733
+ 0505050505050505050506060606060606060606060606060607070707070707
734
+ 0707070707070708080808080808080808080808090909090909090909090909
735
+ 0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c
736
+ 0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010
737
+ 1010101010111111111111111112121212121212121313131313131313141414
738
+ 1414141414151515151515151616161616161616171717171717171818181818
739
+ 18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d
740
+ 1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223
741
+ 2323232323242424242425252525252526262626262727272727282828282829
742
+ 292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f
743
+ 2f2f303030303131313131323232323333333333343434343535353535363636
744
+ 36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e
745
+ 3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646
746
+ 4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f
747
+ 4f50505051515151525252535353535454545555555656565657575758585859
748
+ 59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263
749
+ 63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e
750
+ 6e6e6f6f6f707070717171727273737374747475757576767677777878787979
751
+ 797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585
752
+ 86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292
753
+ 9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f
754
+ a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae
755
+ aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd
756
+ bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc
757
+ cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd
758
+ dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee
759
+ eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff
760
+ > dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling
761
+ cvi 3 index exch get 4 -1 roll 3 -1 roll get
762
+ dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind
763
+
764
+ { 1.0 0.0 3 -1 roll 1 index 1 index le { exch pop} { pop } ifelse
765
+ 1 index 1 index ge { exch pop } { pop } ifelse <
766
+ 0000000000000000000000000000000000000000000000000000000000000000
767
+ 0000000000000000000000000000000000000001010101010101010101010101
768
+ 0101010101010101010101010101010101010101010101020202020202020202
769
+ 0202020202020202020202020202020202030303030303030303030303030303
770
+ 0303030303030304040404040404040404040404040404040404050505050505
771
+ 0505050505050505050506060606060606060606060606060607070707070707
772
+ 0707070707070708080808080808080808080808090909090909090909090909
773
+ 0a0a0a0a0a0a0a0a0a0a0a0b0b0b0b0b0b0b0b0b0b0b0c0c0c0c0c0c0c0c0c0c
774
+ 0d0d0d0d0d0d0d0d0d0d0e0e0e0e0e0e0e0e0e0f0f0f0f0f0f0f0f0f10101010
775
+ 1010101010111111111111111112121212121212121313131313131313141414
776
+ 1414141414151515151515151616161616161616171717171717171818181818
777
+ 18181919191919191a1a1a1a1a1a1a1b1b1b1b1b1b1c1c1c1c1c1c1c1d1d1d1d
778
+ 1d1d1e1e1e1e1e1e1f1f1f1f1f1f202020202020212121212121222222222223
779
+ 2323232323242424242425252525252526262626262727272727282828282829
780
+ 292929292a2a2a2a2a2b2b2b2b2b2c2c2c2c2c2d2d2d2d2d2e2e2e2e2e2f2f2f
781
+ 2f2f303030303131313131323232323333333333343434343535353535363636
782
+ 36373737373838383839393939393a3a3a3a3b3b3b3b3c3c3c3c3d3d3d3d3e3e
783
+ 3e3e3f3f3f3f4040404041414141424242424343434444444445454545464646
784
+ 4647474748484848494949494a4a4a4b4b4b4b4c4c4c4d4d4d4d4e4e4e4f4f4f
785
+ 4f50505051515151525252535353535454545555555656565657575758585859
786
+ 59595a5a5a5a5b5b5b5c5c5c5d5d5d5e5e5e5f5f5f6060606061616162626263
787
+ 63636464646565656666666767676868686969696a6a6a6b6b6b6c6c6d6d6d6e
788
+ 6e6e6f6f6f707070717171727273737374747475757576767677777878787979
789
+ 797a7a7b7b7b7c7c7c7d7d7e7e7e7f7f7f808081818182828283838484848585
790
+ 86868687878888888989898a8a8b8b8b8c8c8d8d8d8e8e8f8f90909091919292
791
+ 9293939494949595969697979798989999999a9a9b9b9c9c9c9d9d9e9e9f9f9f
792
+ a0a0a1a1a2a2a3a3a3a4a4a5a5a6a6a6a7a7a8a8a9a9aaaaabababacacadadae
793
+ aeafafb0b0b0b1b1b2b2b3b3b4b4b5b5b6b6b6b7b7b8b8b9b9bababbbbbcbcbd
794
+ bdbebebebfbfc0c0c1c1c2c2c3c3c4c4c5c5c6c6c7c7c8c8c9c9cacacbcbcccc
795
+ cdcdcececfcfd0d0d1d1d2d2d3d3d4d4d5d5d6d6d7d7d8d8d9d9dadadbdcdcdd
796
+ dddededfdfe0e0e1e1e2e2e3e3e4e4e5e6e6e7e7e8e8e9e9eaeaebebecededee
797
+ eeefeff0f0f1f1f2f3f3f4f4f5f5f6f6f7f8f8f9f9fafafbfcfcfdfdfefeffff
798
+ > dup length 1 sub 3 -1 roll mul dup dup floor cvi exch ceiling
799
+ cvi 3 index exch get 4 -1 roll 3 -1 roll get
800
+ dup 3 1 roll sub 3 -1 roll dup floor cvi sub mul add 255 div } bind
801
+ ] def
802
+ /MatrixABC [ 0.4124 0.2126 0.0193 0.3576 0.7151 0.1192 0.1805 0.0722 0.9508 ] def
803
+ /RangeLMN [ 0.0 0.9505 0.0 1.0000 0.0 1.0891 ] def
804
+ end ] /Cs1 exch/ColorSpace dr pop
805
+ %%EndPageSetup
806
+ 0.60000002 i
807
+ /Cs1 SC
808
+ 0.19215687 0.50196081 0.24705882 sc
809
+ q
810
+ 107.81159 97.479164 m
811
+ 107.70937 97.318977 107.6055 97.16069 107.49998 97.004311 c
812
+ 105.73492 94.38842 102.64958 90.816887 99.963394 89.267845 c
813
+ 94.390419 86.056587 88.16684 85.510155 82.133011 85.425964 c
814
+ 80.360062 85.399292 78.461891 85.222542 76.881088 85.076981 c
815
+ 74.223763 84.832245 71.583275 84.33358 68.959625 83.580986 c
816
+ 68.066261 83.325096 67.04287 82.908684 65.889458 82.331726 c
817
+ 64.58416 81.678329 63.463833 80.832115 62.528469 79.793068 c
818
+ 62.503223 79.764771 62.49094 79.726929 62.495075 79.690193 c
819
+ 62.499214 79.65345 62.519321 79.62178 62.549747 79.60408 c
820
+ 84.089394 67.168159 l
821
+ 84.118233 67.151718 84.15358 67.150269 84.185539 67.164215 c
822
+ 84.217499 67.178162 84.24263 67.206009 84.253891 67.23996 c
823
+ 84.800957 68.883072 84.952927 70.5756 84.709808 72.317543 c
824
+ 84.701675 72.380081 84.667191 72.433487 84.615746 72.463181 c
825
+ 79.435493 75.455322 70.91024 80.378036 70.142578 80.821251 c
826
+ 74.395477 81.717239 l
827
+ 78.583549 79.292633 83.475731 76.463501 83.87587 76.229836 c
828
+ 83.894463 76.218201 83.918961 76.220802 83.936653 76.236275 c
829
+ 83.954346 76.251755 83.961258 76.276634 83.953796 76.298012 c
830
+ 83.269753 78.37262 82.458595 80.492157 81.52034 82.656616 c
831
+ 81.508797 82.682777 81.511681 82.714195 81.527977 82.739838 c
832
+ 81.544273 82.76548 81.571701 82.781769 81.600647 82.782982 c
833
+ 87.057648 82.97187 l
834
+ 87.083649 82.972557 87.106491 82.957031 87.115677 82.932411 c
835
+ 88.154175 80.357338 88.956558 78.015862 89.559402 75.191978 c
836
+ 90.097984 72.663963 90.122963 70.157173 89.634338 67.671593 c
837
+ 89.305534 65.995125 88.631523 64.334641 87.612282 62.690151 c
838
+ 85.797989 59.760822 82.732033 57.478695 79.625153 56.312176 c
839
+ 76.374931 55.091423 73.000679 54.354588 69.502396 54.101673 c
840
+ 67.25396 53.93853 63.718658 54.002148 60.815487 53.859646 c
841
+ 55.699306 53.60899 50.585567 53.009476 46.171291 49.772522 c
842
+ 46.141224 49.749836 46.123119 49.713654 46.123283 49.676563 c
843
+ 46.123444 49.639473 46.141846 49.606606 46.172085 49.589401 c
844
+ 66.34536 37.94236 l
845
+ 66.366119 37.930351 66.39344 37.938282 66.407135 37.960297 c
846
+ 66.439926 38.012844 66.45974 38.071552 66.466583 38.136429 c
847
+ 66.616646 39.562687 66.584175 41.035431 66.369186 42.554649 c
848
+ 66.354828 42.651142 66.300346 42.733353 66.220001 42.779762 c
849
+ 65.341606 43.283207 61.58448 45.45034 59.110184 46.878483 c
850
+ 57.155937 48.006458 55.080814 49.20525 53.480167 50.131138 c
851
+ 57.70182 50.979649 l
852
+ 58.31049 50.663971 61.808525 48.64835 65.242722 46.637821 c
853
+ 65.256119 46.63026 65.272957 46.631359 65.28643 46.640671 c
854
+ 65.299904 46.649982 65.307793 46.66597 65.306892 46.682171 c
855
+ 65.285988 46.915287 65.235031 47.131336 65.154022 47.330322 c
856
+ 64.360596 49.264248 63.895523 50.372593 63.758812 50.655357 c
857
+ 63.689651 50.798531 63.578194 50.973404 63.424431 51.179981 c
858
+ 63.407581 51.202202 63.405197 51.233398 63.418304 51.26017 c
859
+ 63.431408 51.286942 63.457664 51.304527 63.485802 51.305367 c
860
+ 69.062767 51.498455 l
861
+ 69.095558 51.498917 69.124481 51.479904 69.137321 51.449455 c
862
+ 70.08194 49.211174 70.769211 47.108231 71.199158 45.140621 c
863
+ 72.139458 40.838387 71.897247 35.775063 69.736961 31.646093 c
864
+ 69.65992 31.498837 67.861 28.374626 67.779045 28.229824 c
865
+ 63.466091 30.715939 l
866
+ 65.724426 34.866062 l
867
+ 65.747192 34.913773 65.73143 34.96954 65.68821 34.994186 c
868
+ 43.896503 47.57563 l
869
+ 43.849712 47.602848 43.788166 47.586426 43.75539 47.537979 c
870
+ 41.296982 43.515282 l
871
+ 37.014671 45.987675 l
872
+ 37.087574 46.118549 38.888317 49.232536 38.978039 49.373341 c
873
+ 39.177372 49.686165 39.418217 50.023487 39.700573 50.385311 c
874
+ 43.244904 54.930614 48.118938 57.211201 53.350811 58.298428 c
875
+ 55.762325 58.80024 58.08091 59.087009 60.306557 59.158741 c
876
+ 61.328564 59.192108 63.216022 59.234741 65.968933 59.286633 c
877
+ 67.805626 59.320854 69.851242 59.482624 72.105797 59.77195 c
878
+ 73.521057 59.954178 74.675316 60.175255 75.568558 60.435181 c
879
+ 78.122505 61.178383 80.95903 62.280609 82.667351 64.536514 c
880
+ 82.683975 64.558952 82.691216 64.586975 82.687256 64.613533 c
881
+ 82.683296 64.640099 82.66851 64.662659 82.646614 64.675552 c
882
+ 61.09182 77.120224 l
883
+ 61.072231 77.131241 61.048443 77.132599 61.02655 77.123932 c
884
+ 61.004662 77.115273 60.986801 77.097435 60.977558 77.075005 c
885
+ 60.333374 75.51709 60.208103 73.68737 60.376854 72.071091 c
886
+ 60.38942 71.948601 60.456219 71.843254 60.557571 71.786079 c
887
+ 62.952961 70.415016 70.361839 66.143448 74.123955 63.971394 c
888
+ 70.150085 62.926216 l
889
+ 66.804855 64.868179 62.681252 67.246956 61.243378 68.062553 c
890
+ 61.227962 68.072044 61.20771 68.069565 61.193394 68.056442 c
891
+ 61.179081 68.043312 61.17403 68.022583 61.180935 68.005287 c
892
+ 61.978542 65.792313 62.828018 63.77309 63.729362 61.947613 c
893
+ 63.740822 61.924011 63.738827 61.89497 63.724125 61.871479 c
894
+ 63.709427 61.847988 63.684269 61.833633 63.658173 61.833851 c
895
+ 61.785522 61.877308 59.955116 61.792473 58.166954 61.579342 c
896
+ 58.061222 61.566261 57.963032 61.623745 57.921261 61.723179 c
897
+ 57.349731 63.082924 56.801182 64.594856 56.275604 66.25898 c
898
+ 55.780033 67.82769 55.475639 69.46669 55.283581 70.90583 c
899
+ 54.659359 75.572617 56.044724 80.310135 59.354027 83.821716 c
900
+ 61.780403 86.395676 65.323822 88.060646 68.675797 88.932777 c
901
+ 70.46209 89.397148 71.866837 89.713844 72.890022 89.882866 c
902
+ 75.994705 90.393478 79.956833 90.665154 83.582916 90.771492 c
903
+ 84.893387 90.810387 86.144226 90.876427 87.335449 90.969612 c
904
+ 91.598228 91.303978 96.271645 92.578621 99.77639 95.344009 c
905
+ 99.788483 95.353035 99.795479 95.367683 99.794945 95.382866 c
906
+ 99.794418 95.398041 99.78643 95.411667 99.773766 95.418991 c
907
+ 79.223083 107.28393 l
908
+ 79.20314 107.29511 79.178452 107.29479 79.157288 107.28307 c
909
+ 79.136131 107.27135 79.121307 107.24979 79.117783 107.2256 c
910
+ 78.896484 105.77561 78.880066 104.30727 79.068535 102.82057 c
911
+ 79.086639 102.68067 79.164726 102.5612 79.28112 102.49532 c
912
+ 79.560493 102.33667 87.516136 97.750099 92.755722 94.735611 c
913
+ 88.659622 93.784828 l
914
+ 88.63942 93.796494 84.163239 96.384789 79.87014 98.871353 c
915
+ 79.856552 98.879875 79.838844 98.877953 79.825706 98.866531 c
916
+ 79.812576 98.85511 79.806763 98.836586 79.811134 98.820045 c
917
+ 79.970955 98.248619 80.193474 97.606583 80.478683 96.893944 c
918
+ 81.025894 95.521759 81.513702 94.38176 81.942108 93.47393 c
919
+ 81.96048 93.435539 81.957031 93.388542 81.933044 93.350243 c
920
+ 81.90905 93.311951 81.868057 93.288033 81.82518 93.287308 c
921
+ 80.025665 93.258095 78.262054 93.142632 76.534355 92.940926 c
922
+ 76.414925 92.927559 76.30468 92.991997 76.256981 93.10305 c
923
+ 74.592598 96.992493 73.533508 101.53908 73.830086 105.94624 c
924
+ 73.999916 108.48585 74.681496 110.94965 75.874825 113.33765 c
925
+ 75.951622 113.49133 76.890251 115.13376 76.971291 115.28681 c
926
+ 81.304047 112.78728 l
927
+ 80.60321 111.52448 80.220871 110.82555 80.157028 110.69051 c
928
+ 80.113869 110.59922 80.049133 110.46229 79.962822 110.27972 c
929
+ 79.941872 110.23676 79.955956 110.18616 79.995079 110.16381 c
930
+ 101.84601 97.548172 l
931
+ 101.889 97.523132 101.94555 97.53801 101.97594 97.582352 c
932
+ 102.13994 97.82048 102.26295 97.999077 102.34495 98.118134 c
933
+ 102.40427 98.204262 102.77982 98.829819 103.4716 99.994789 c
934
+ 107.81159 97.479164 l
935
+ h
936
+ W
937
+ 17 17 110 110 rc
938
+ 54.347878 147.30881 m
939
+ 146.8744 93.888588 l
940
+ 90.478394 -3.7921684 l
941
+ -2.0481343 49.628044 l
942
+ h
943
+ f
944
+ Q
945
+ 12 w
946
+ 0 0 0 sc
947
+ q
948
+ 117.96633 45.75 m
949
+ 72.5 19.5 l
950
+ 27.033667 45.75 l
951
+ 27.033667 98.25 l
952
+ 72.5 124.5 l
953
+ 117.96633 98.25 l
954
+ 117.96633 45.75 l
955
+ h
956
+ W*
957
+ 17 17 110 110 rc
958
+ -0.5 -0.86602539 -0.86602539 0.5 144.21634 91.216331 cm
959
+ 52.5 0 m
960
+ 97.966331 26.25 l
961
+ 97.966331 78.75 l
962
+ 52.5 105 l
963
+ 7.0336661 78.75 l
964
+ 7.0336661 26.25 l
965
+ 52.5 0 l
966
+ h
967
+ S
968
+ ep
969
+ end
970
+ %%Trailer
971
+ %%EOF
img/Group 2.pdf ADDED
Binary file (7.01 kB). View file
 
img/Group 2.png ADDED

Git LFS Details

  • SHA256: 4d9dfb9f9071e50012db4250ff739acf06376dc1a815cfd8c0839e866b8d9bb5
  • Pointer size: 130 Bytes
  • Size of remote file: 58.4 kB
img/Group 2.svg ADDED
img/logo-black-rectangle.svg ADDED
img/logo-black-square.svg ADDED
img/logo.svg CHANGED
llms.txt ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Carbon
2
+
3
+ > Carbon is Hugging Face's open-source family of autoregressive genomic foundation models for DNA. Three sizes (500M, 3B, and 8B parameters), a 393,216 bp context window, a 6-mer BPE tokenizer, and 1 trillion training tokens spanning the tree of life. Model weights, training code, and the data pipeline are all open source on the Hugging Face Hub.
4
+
5
+ This site is the interactive editorial walkthrough of what the 3B checkpoint learned. It is organised into four tabs:
6
+
7
+ - **Intro** — a short primer on what the model reads (the four bases of DNA, helices, genes, splicing, translation) and a guided tour of the rest of the page.
8
+ - **DNA Lab** — five live sections that hit the deployed 3B model: streaming continuation of an arbitrary DNA prefix, per-token likelihood scoring, in-silico variant effect prediction (VEP), ESMFold-based protein folding over Carbon-decoded ORFs, and a UMAP scatter of ~500,000 gene embeddings.
9
+ - **Carbon Recipe** — the training story: tokenizer design, the hybrid loss, the dataset mixture, the species tree learned from per-species mean embeddings, the long-context training schedule, and the headline results.
10
+ - **Sandbox** — a minimal prompt-and-stream UI for running Carbon on arbitrary DNA sequences without leaving the page.
11
+
12
+ ## Demo
13
+
14
+ - [Live interactive demo (this site)](/): Editorial scrollytell across Intro / DNA Lab / Carbon Recipe / Sandbox.
15
+ - [Standalone sandbox](/sandbox-only): The DNA continuation UI without the surrounding editorial.
16
+
17
+ ## Models
18
+
19
+ - [HuggingFaceBio/Carbon-3B](https://huggingface.co/HuggingFaceBio/Carbon-3B): The default 3B checkpoint used by every live interaction on this page.
20
+ - [HuggingFaceBio organisation page](https://huggingface.co/HuggingFaceBio): Full list of Carbon model sizes (500M, 3B, 8B) and related artefacts.
21
+
22
+ ## Code
23
+
24
+ - [github.com/huggingface/carbon](https://github.com/huggingface/carbon): Training and inference code.
25
+
26
+ ## Data
27
+
28
+ - [HuggingFaceBio/carbon-inference-evals](https://huggingface.co/datasets/HuggingFaceBio/carbon-inference-evals): The evaluation dataset behind the headline numbers shown in the Results section.
29
+
30
+ ## API
31
+
32
+ The demo's FastAPI backend exposes a small set of JSON endpoints that crawlers and agents may find useful. They are designed for the frontend but are not gated:
33
+
34
+ - `POST /generate` — streaming DNA continuation. Body: `{"prompt": "ACGT...", "max_tokens": 128, "temperature": 0.5, "top_p": 0.9}`. Returns Server-Sent Events.
35
+ - `POST /score` — per-token log-probabilities over a forced sequence. Body: `{"sequence": "ACGT...", "max_window": 24000}`.
36
+ - `POST /fold` — ESMFold-based protein structure prediction. Body: `{"sequence": "<AMINO_ACIDS>"}`. Returns PDB plus mean pLDDT.
37
+ - `GET /config` — the model identifier currently served.
38
+ - `GET /umap`, `GET /umap_labels`, `GET /umap_names`, `GET /highlights`, `GET /species_tree`, `GET /genes`, `GET /variants`, `GET /species` — static data payloads powering the visualisations.
robots.txt ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # robots.txt for the Carbon demo.
2
+ #
3
+ # Policy: explicitly welcome every crawler — including LLM-training and
4
+ # answer-engine bots — to read the page. The whole point of the demo is
5
+ # to make the model's behaviour and the surrounding write-up easy to
6
+ # discover and to cite. The only path we keep out of the index is the
7
+ # /social-banner utility page, which is a screenshot rig, not content.
8
+ #
9
+ # The Sitemap line below is rewritten with an absolute URL at request
10
+ # time by app.py (it has to be absolute per the sitemaps protocol).
11
+
12
+ User-agent: *
13
+ Allow: /
14
+ Disallow: /social-banner
15
+
16
+ # AI / LLM crawlers, called out by name so it's unambiguous that this
17
+ # site opts IN to training and to live answer-engine retrieval.
18
+ User-agent: GPTBot
19
+ Allow: /
20
+ Disallow: /social-banner
21
+
22
+ User-agent: ChatGPT-User
23
+ Allow: /
24
+ Disallow: /social-banner
25
+
26
+ User-agent: OAI-SearchBot
27
+ Allow: /
28
+ Disallow: /social-banner
29
+
30
+ User-agent: ClaudeBot
31
+ Allow: /
32
+ Disallow: /social-banner
33
+
34
+ User-agent: Claude-Web
35
+ Allow: /
36
+ Disallow: /social-banner
37
+
38
+ User-agent: anthropic-ai
39
+ Allow: /
40
+ Disallow: /social-banner
41
+
42
+ User-agent: PerplexityBot
43
+ Allow: /
44
+ Disallow: /social-banner
45
+
46
+ User-agent: Perplexity-User
47
+ Allow: /
48
+ Disallow: /social-banner
49
+
50
+ User-agent: Google-Extended
51
+ Allow: /
52
+ Disallow: /social-banner
53
+
54
+ User-agent: Applebot-Extended
55
+ Allow: /
56
+ Disallow: /social-banner
57
+
58
+ User-agent: CCBot
59
+ Allow: /
60
+ Disallow: /social-banner
61
+
62
+ User-agent: Bytespider
63
+ Allow: /
64
+ Disallow: /social-banner
65
+
66
+ User-agent: cohere-ai
67
+ Allow: /
68
+ Disallow: /social-banner
69
+
70
+ User-agent: Meta-ExternalAgent
71
+ Allow: /
72
+ Disallow: /social-banner
73
+
74
+ Sitemap: {{SITE_URL}}/sitemap.xml
sitemap.xml ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- {{SITE_URL}} is substituted with the absolute base URL at request -->
3
+ <!-- time by app.py so the sitemap stays valid wherever it's served. -->
4
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
5
+ <url>
6
+ <loc>{{SITE_URL}}/</loc>
7
+ <changefreq>weekly</changefreq>
8
+ <priority>1.0</priority>
9
+ </url>
10
+ <url>
11
+ <loc>{{SITE_URL}}/sandbox-only</loc>
12
+ <changefreq>monthly</changefreq>
13
+ <priority>0.4</priority>
14
+ </url>
15
+ </urlset>
social-banner.html CHANGED
@@ -4,6 +4,11 @@
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Carbon · social banner</title>
 
 
 
 
 
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600&display=swap">
@@ -22,16 +27,21 @@
22
  /* edges of the social-media canvas read clearly — handy when you're */
23
  /* about to crop a screenshot. */
24
  /* ------------------------------------------------------------------ */
25
- html, body { height: 100%; }
26
  body {
27
  background: #e8e5d6;
28
  display: flex;
29
  flex-direction: column;
30
  align-items: center;
31
- justify-content: center;
32
  gap: 28px;
33
- padding: 40px 24px;
34
- overflow: hidden;
 
 
 
 
 
35
  }
36
 
37
  /* The social-banner-stage IS the social-media canvas: a fixed width
@@ -165,6 +175,147 @@
165
  body { background: white; padding: 0; }
166
  .sb-switcher { display: none; }
167
  .social-banner-stage { transform: none !important; box-shadow: none; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  }
169
  </style>
170
  </head>
@@ -179,10 +330,14 @@
179
  <div class="banner-inner">
180
  <div class="banner-left">
181
 
182
- <!-- Identity strip — no logo card here, just the model-path
183
- breadcrumb so the banner reads as a Hugging Face model
184
- card identifier without the square thumbnail. -->
 
185
  <div class="banner-identity">
 
 
 
186
  <div class="banner-breadcrumb">
187
  <div class="banner-title">CARBON</div>
188
  <div class="banner-path">huggingfacebio/carbon-3b</div>
@@ -223,6 +378,42 @@
223
  <span class="sb-switcher__dim" id="sb-scale-readout">100%</span>
224
  </div>
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
  <!-- Helix animation. Same script as the main demo — it queries
227
  .carbon-banner + .cb-helix-canvas, both of which exist here. -->
228
  <script src="/assets/js/banner.js"></script>
@@ -243,12 +434,16 @@
243
  const stage = document.getElementById("sb-stage");
244
  const readout = document.getElementById("sb-scale-readout");
245
  const buttons = document.querySelectorAll(".sb-switcher__btn");
 
246
 
247
- // Vertical breathing room reserved for the format switcher
248
- // (height of the row + body padding + gap). Kept conservative so
249
- // the banner always has clear margin around it.
250
- const CHROME_V = 160;
251
  const CHROME_H = 80;
 
 
 
 
 
 
252
 
253
  function fitStage() {
254
  const w = parseFloat(getComputedStyle(stage).getPropertyValue("--sb-w"));
@@ -258,6 +453,21 @@
258
  const scale = Math.min(1, availW / w, availH / h);
259
  stage.style.setProperty("--sb-scale", scale.toFixed(4));
260
  readout.textContent = Math.round(scale * 100) + "%";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
  }
262
 
263
  function setFormat(btn) {
@@ -292,6 +502,29 @@
292
 
293
  fitStage();
294
  window.addEventListener("resize", fitStage);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  })();
296
  </script>
297
 
 
4
  <meta charset="utf-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Carbon · social banner</title>
7
+ <!-- Internal screenshot tool — keep it out of search results and AI -->
8
+ <!-- training crawls. The canonical page is demo.html (served at /). -->
9
+ <meta name="robots" content="noindex, nofollow">
10
+ <link rel="icon" type="image/svg+xml" href="/img/logo.svg">
11
+ <link rel="icon" type="image/png" href="/img/logo.png">
12
  <link rel="preconnect" href="https://fonts.googleapis.com">
13
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600;700;800&family=Inter:wght@300;400;500;600&display=swap">
 
27
  /* edges of the social-media canvas read clearly — handy when you're */
28
  /* about to crop a screenshot. */
29
  /* ------------------------------------------------------------------ */
30
+ html, body { min-height: 100%; }
31
  body {
32
  background: #e8e5d6;
33
  display: flex;
34
  flex-direction: column;
35
  align-items: center;
36
+ justify-content: flex-start;
37
  gap: 28px;
38
+ /* Top padding sized so the banner stage sits roughly where it used
39
+ to (centred-ish in a 1080p window) while leaving room for the
40
+ logo contact-sheet below without forcing a scrollbar on common
41
+ screens. Falls back to scroll when there's genuinely more
42
+ content than fits. */
43
+ padding: clamp(28px, 6vh, 80px) 24px 80px;
44
+ overflow-x: hidden;
45
  }
46
 
47
  /* The social-banner-stage IS the social-media canvas: a fixed width
 
175
  body { background: white; padding: 0; }
176
  .sb-switcher { display: none; }
177
  .social-banner-stage { transform: none !important; box-shadow: none; }
178
+ .sb-logos { page-break-before: always; }
179
+ }
180
+
181
+ /* ------------------------------------------------------------------ */
182
+ /* Logo showcase. */
183
+ /* Sits below the banner stage so the same page doubles as a brand */
184
+ /* contact-sheet: the square mark, the square lockup with wordmark, */
185
+ /* and the wide rectangular lockup, each painted at its native pixel */
186
+ /* size on a paper card. Screenshot one tile and you have the asset */
187
+ /* at the exact dimensions of the source SVG, ready to drop into a */
188
+ /* deck or a README without any re-export step. */
189
+ /* ------------------------------------------------------------------ */
190
+ .sb-section-label {
191
+ font-family: "JetBrains Mono", ui-monospace, monospace;
192
+ font-size: 11px;
193
+ letter-spacing: 0.18em;
194
+ text-transform: uppercase;
195
+ color: #6f6d65;
196
+ margin-top: 24px;
197
+ /* Hairline tick under the label, matching the section dividers used
198
+ on demo.html so the chrome reads as part of the same family. */
199
+ border-bottom: 1px solid #d6d3c4;
200
+ padding-bottom: 6px;
201
+ width: 100%;
202
+ max-width: 1100px;
203
+ display: flex;
204
+ justify-content: space-between;
205
+ align-items: baseline;
206
+ }
207
+ .sb-section-label__hint {
208
+ color: #b0ada0;
209
+ text-transform: none;
210
+ letter-spacing: 0.06em;
211
+ font-size: 10px;
212
+ }
213
+
214
+ .sb-logos {
215
+ display: flex;
216
+ flex-wrap: wrap;
217
+ align-items: flex-end;
218
+ justify-content: center;
219
+ gap: 24px;
220
+ /* Auto-scale row when the viewport is too narrow for both stages
221
+ side-by-side, mirroring the auto-fit behaviour the banner stage
222
+ already does for itself (see fitStage in the script below). The
223
+ JS sets --sb-logo-scale on this wrapper. */
224
+ transform: scale(var(--sb-logo-scale, 1));
225
+ transform-origin: center top;
226
+ }
227
+ .sb-logo-card {
228
+ background: #f7f5ee;
229
+ box-shadow:
230
+ 0 1px 0 #cfcdbf inset,
231
+ 0 14px 28px -18px rgba(31, 31, 29, 0.22),
232
+ 0 6px 14px -10px rgba(31, 31, 29, 0.14);
233
+ display: flex;
234
+ flex-direction: column;
235
+ flex-shrink: 0;
236
+ }
237
+ /* The .sb-logo-stage IS the export canvas: width × height pinned to the
238
+ SVG's native viewBox in pixels so a screenshot of the stage matches
239
+ the source 1:1. The inner <img> fills the stage. */
240
+ .sb-logo-stage {
241
+ --w: 230px;
242
+ --h: 230px;
243
+ width: var(--w);
244
+ height: var(--h);
245
+ box-shadow: inset 0 0 0 1px #cfcdbf;
246
+ display: flex;
247
+ align-items: center;
248
+ justify-content: center;
249
+ background: #f7f5ee;
250
+ }
251
+ .sb-logo-stage img {
252
+ width: 100%;
253
+ height: 100%;
254
+ display: block;
255
+ object-fit: contain;
256
+ }
257
+ /* Per-variant sizes, sourced from each SVG's viewBox so the stage
258
+ matches the asset 1:1 on screen. */
259
+ .sb-logo-stage--square { --w: 230px; --h: 230px; }
260
+ .sb-logo-stage--rectangle { --w: 487px; --h: 230px; }
261
+
262
+ .sb-logo-meta {
263
+ font-family: "JetBrains Mono", ui-monospace, monospace;
264
+ font-size: 10px;
265
+ letter-spacing: 0.12em;
266
+ text-transform: uppercase;
267
+ color: #6f6d65;
268
+ padding: 10px 12px 12px;
269
+ display: flex;
270
+ justify-content: space-between;
271
+ align-items: baseline;
272
+ gap: 12px;
273
+ border-top: 1px solid #cfcdbf;
274
+ background: #fbf9f2;
275
+ /* Constrain the row to the stage width so the long filename has
276
+ to truncate (with --name min-width:0) instead of pushing the
277
+ dim+copy chips off the right edge of the card. */
278
+ min-width: 0;
279
+ }
280
+ .sb-logo-meta__name {
281
+ color: #1f1f1d;
282
+ font-weight: 500;
283
+ /* Flex item with min-width:0 so the JetBrains Mono filename can
284
+ shrink and ellipsize instead of forcing the meta row wider than
285
+ its stage (most visible on the square tile, whose 230px width
286
+ is barely enough for the full "logo-black-square.svg"). */
287
+ min-width: 0;
288
+ flex: 1 1 auto;
289
+ overflow: hidden;
290
+ text-overflow: ellipsis;
291
+ white-space: nowrap;
292
+ }
293
+ /* Discreet "copy path" affordance so the SVG file name can be grabbed
294
+ without leaving the page. The button replaces itself with a "copied"
295
+ pill for ~1s on success. */
296
+ .sb-logo-meta__copy {
297
+ appearance: none;
298
+ border: 1px solid #cfcdbf;
299
+ background: #fff;
300
+ color: #6f6d65;
301
+ font-family: inherit;
302
+ font-size: 9px;
303
+ letter-spacing: 0.16em;
304
+ text-transform: uppercase;
305
+ padding: 3px 7px;
306
+ cursor: pointer;
307
+ transition: background 0.15s, border-color 0.15s, color 0.15s;
308
+ flex-shrink: 0;
309
+ }
310
+ .sb-logo-meta__copy:hover {
311
+ background: #1f1f1d;
312
+ border-color: #1f1f1d;
313
+ color: #f7f5ee;
314
+ }
315
+ .sb-logo-meta__copy.is-copied {
316
+ background: #317f3f;
317
+ border-color: #317f3f;
318
+ color: #f7f5ee;
319
  }
320
  </style>
321
  </head>
 
330
  <div class="banner-inner">
331
  <div class="banner-left">
332
 
333
+ <!-- Identity strip — square brand mark (img/logo.svg, the latest
334
+ black-hex stamp) sitting flush with the model-card breadcrumb,
335
+ same composition as the hero on demo.html. The SVG ships with
336
+ its own black frame so .logo-card stays chrome-free here too. -->
337
  <div class="banner-identity">
338
+ <a class="logo-card" href="#" aria-label="Carbon, go to top">
339
+ <img class="logo-img" src="/img/logo.svg" alt="" width="44" height="44">
340
+ </a>
341
  <div class="banner-breadcrumb">
342
  <div class="banner-title">CARBON</div>
343
  <div class="banner-path">huggingfacebio/carbon-3b</div>
 
378
  <span class="sb-switcher__dim" id="sb-scale-readout">100%</span>
379
  </div>
380
 
381
+ <!-- ------------------------------------------------------------------ -->
382
+ <!-- Logo contact-sheet. -->
383
+ <!-- Two tiles, each a 1:1 export stage for one of the SVG lockups -->
384
+ <!-- shipped in img/. Sized to match the source viewBox so screenshots -->
385
+ <!-- come out at exactly the right pixel dimensions. Order: square -->
386
+ <!-- lockup → wide rectangular lockup. -->
387
+ <!-- ------------------------------------------------------------------ -->
388
+ <div class="sb-section-label">
389
+ <span>logo · brand marks</span>
390
+ <span class="sb-section-label__hint">img/logo-black-*.svg · screenshot at 100% for 1:1 export</span>
391
+ </div>
392
+
393
+ <div class="sb-logos" id="sb-logos">
394
+
395
+ <figure class="sb-logo-card">
396
+ <div class="sb-logo-stage sb-logo-stage--square">
397
+ <img src="/img/logo-black-square.svg" alt="Carbon square lockup, symbol over wordmark">
398
+ </div>
399
+ <figcaption class="sb-logo-meta">
400
+ <span class="sb-logo-meta__name" title="logo-black-square.svg">logo-black-square.svg</span>
401
+ <button type="button" class="sb-logo-meta__copy" data-copy="/img/logo-black-square.svg">copy</button>
402
+ </figcaption>
403
+ </figure>
404
+
405
+ <figure class="sb-logo-card">
406
+ <div class="sb-logo-stage sb-logo-stage--rectangle">
407
+ <img src="/img/logo-black-rectangle.svg" alt="Carbon horizontal lockup, symbol next to wordmark">
408
+ </div>
409
+ <figcaption class="sb-logo-meta">
410
+ <span class="sb-logo-meta__name" title="logo-black-rectangle.svg">logo-black-rectangle.svg</span>
411
+ <button type="button" class="sb-logo-meta__copy" data-copy="/img/logo-black-rectangle.svg">copy</button>
412
+ </figcaption>
413
+ </figure>
414
+
415
+ </div>
416
+
417
  <!-- Helix animation. Same script as the main demo — it queries
418
  .carbon-banner + .cb-helix-canvas, both of which exist here. -->
419
  <script src="/assets/js/banner.js"></script>
 
434
  const stage = document.getElementById("sb-stage");
435
  const readout = document.getElementById("sb-scale-readout");
436
  const buttons = document.querySelectorAll(".sb-switcher__btn");
437
+ const logos = document.getElementById("sb-logos");
438
 
439
+ // Horizontal breathing room (body padding both sides).
 
 
 
440
  const CHROME_H = 80;
441
+ // Vertical breathing room reserved for the format switcher row +
442
+ // body padding + the section label above the logo contact-sheet.
443
+ // The fit-to-viewport cap aims at making the banner sit comfortably
444
+ // above the logos without forcing a scrollbar on a 1080p screen,
445
+ // while still letting tall windows render at native 100%.
446
+ const CHROME_V = 160;
447
 
448
  function fitStage() {
449
  const w = parseFloat(getComputedStyle(stage).getPropertyValue("--sb-w"));
 
453
  const scale = Math.min(1, availW / w, availH / h);
454
  stage.style.setProperty("--sb-scale", scale.toFixed(4));
455
  readout.textContent = Math.round(scale * 100) + "%";
456
+ fitLogos();
457
+ }
458
+
459
+ // Scale the logo contact-sheet down when the viewport is narrower
460
+ // than the row at 100%. The three tiles together are roughly
461
+ // 230 + 230 + 487 + (gaps) ≈ 1015px wide; on a 1024-ish window we
462
+ // want them to shrink to fit so they sit centred under the banner
463
+ // instead of overflowing the page horizontally.
464
+ function fitLogos() {
465
+ if (!logos) return;
466
+ logos.style.setProperty("--sb-logo-scale", "1");
467
+ const natural = logos.scrollWidth;
468
+ const avail = Math.max(200, window.innerWidth - CHROME_H);
469
+ const s = Math.min(1, avail / natural);
470
+ logos.style.setProperty("--sb-logo-scale", s.toFixed(4));
471
  }
472
 
473
  function setFormat(btn) {
 
502
 
503
  fitStage();
504
  window.addEventListener("resize", fitStage);
505
+
506
+ // Wire up the discreet "copy" buttons under each logo tile so the
507
+ // asset path can be grabbed in one click. Falls back gracefully on
508
+ // browsers / contexts where the async clipboard API is unavailable
509
+ // (e.g. http:// origins) by showing a "failed" pill briefly.
510
+ document.querySelectorAll(".sb-logo-meta__copy").forEach(btn => {
511
+ btn.addEventListener("click", async () => {
512
+ const value = btn.dataset.copy || "";
513
+ if (!value) return;
514
+ const original = btn.textContent;
515
+ try {
516
+ await navigator.clipboard.writeText(value);
517
+ btn.textContent = "copied";
518
+ btn.classList.add("is-copied");
519
+ } catch {
520
+ btn.textContent = "failed";
521
+ }
522
+ setTimeout(() => {
523
+ btn.textContent = original;
524
+ btn.classList.remove("is-copied");
525
+ }, 1100);
526
+ });
527
+ });
528
  })();
529
  </script>
530