diff --git a/.design-sync/NOTES.md b/.design-sync/NOTES.md
index 6086669bc01..94d1573dc52 100644
--- a/.design-sync/NOTES.md
+++ b/.design-sync/NOTES.md
@@ -17,15 +17,16 @@ This is an **app-shape** sync — the *source* is the `app/` website (`anyplot-w
## MonoLisa fonts (re-fetch on a fresh clone)
-MonoLisa is proprietary (© FaceType Foundry, CORS-locked GCS) and is **NOT in this public repo**. The variable ttf are fetched at sync time into `app/.designsync-fonts/` (the `.ttf`/`.woff2` binaries are gitignored; only the `@font-face` CSS there is committed) and shipped only to the private design project — never committed. `app/.designsync-fonts/monolisa.css` (the `@font-face`, committed) references them. On a fresh clone, re-fetch before building:
+MonoLisa is proprietary (© FaceType Foundry, CORS-locked GCS) and is **NOT in this public repo**. The variable ttf (v3: MonoLisa Code + MonoLisa Text, upright + italic) are fetched at sync time into `app/.designsync-fonts/` (the `.ttf`/`.woff2` binaries are gitignored; only the `@font-face` CSS there is committed) and shipped only to the private design project — never committed. `app/.designsync-fonts/monolisa.css` (the `@font-face`, committed) references them. On a fresh clone, re-fetch before building:
```sh
mkdir -p app/.designsync-fonts && cd app/.designsync-fonts
-curl -sSfo MonoLisaVariableNormal.ttf https://storage.googleapis.com/anyplot-static/fonts/MonoLisaVariableNormal.ttf
-curl -sSfo MonoLisaVariableItalic.ttf https://storage.googleapis.com/anyplot-static/fonts/MonoLisaVariableItalic.ttf
+for f in MonoLisaCodeUpright MonoLisaCodeItalic MonoLisaTextUpright MonoLisaTextItalic; do
+ curl -sSfo "$f.ttf" "https://storage.googleapis.com/anyplot-static/fonts/v3/desktop/$f.ttf"
+done
```
-The variable ttf cover the full glyph range (normal + italic, weights 100–900, the `ss02` script set intact). CORS is browser-only, so `curl` works even though browser fetches are restricted to `anyplot.ai`.
+The variable ttf cover the full glyph range (upright + italic, axes `wght` 1–1000 and `GRAD` −50…50, the `ss01` script set intact in the italics). CORS is browser-only, so `curl` works even though browser fetches are restricted to `anyplot.ai`.
## Known render warns
- None. (`[RENDER_THIN]` on Footer in an early pass was fixed by collapsing its preview to a single cell — its two variants differed only in a hidden link href.)
diff --git a/.design-sync/conventions.md b/.design-sync/conventions.md
index 92a38810c32..185710efb74 100644
--- a/.design-sync/conventions.md
+++ b/.design-sync/conventions.md
@@ -28,12 +28,12 @@ Style with the `var(--*)` tokens, not invented hex. The vocabulary (all defined
- **Surfaces** — warm off-white, *never* pure `#fff`: `--bg-page`, `--bg-surface`, `--bg-elevated`
- **Ink** (warm grayscale text) + hairlines: `--ink`, `--ink-soft`, `--ink-muted`, `--rule`
- **imprint palette — 8 categorical hues, reserved for PLOTS/charts, not UI chrome:** `--imprint-green` (`#009E73`, the brand), `--imprint-lavender`, `--imprint-blue`, `--imprint-ochre`, `--imprint-red`, `--imprint-cyan`, `--imprint-rose`, `--imprint-lime`; `--imprint-amber` = warning.
-- **Type stacks:** `--mono` ( = `--serif` = `--sans`, all MonoLisa); **code surface:** `--code-bg`, `--code-text`, `--code-border` (+ `--code-comment`/`-keyword`/`-string`/… syntax tokens)
+- **Type stacks:** `--mono` ( = `--serif` = `--sans`, all MonoLisa Code); `--text` (MonoLisa Text, proportional — experiments only, unused by default); **code surface:** `--code-bg`, `--code-text`, `--code-border` (+ `--code-comment`/`-keyword`/`-string`/… syntax tokens)
- **Layout:** `--gutter` (24px), `--max` (1240px — paper/reading width), `--max-catalog` (2200px — plot grids)
## Typography — one typeface, two voices
-**MonoLisa everywhere** — body, UI, nav, buttons, logo, headlines. There is no second font. The editorial accent is **italic**, which auto-triggers MonoLisa's `ss02` script set (enabled globally via `font-feature-settings: "ss02"` on `html`). So: upright = structure/prose/labels; `font-style: italic` = emphasis/taglines/title accents (renders as flowing script). Bold (700) only at display sizes.
+**MonoLisa Code everywhere** — body, UI, nav, buttons, logo, headlines. There is no second font in use (MonoLisa Text is registered but reserved for experiments). The editorial accent is **italic**, which auto-triggers MonoLisa's `ss01` script set (enabled globally via `font-feature-settings: "ss01"` on `html`; v3 tag — `ss02` was the v2 tag and now means "alt i r"). So: upright = structure/prose/labels; `font-style: italic` = emphasis/taglines/title accents (renders as flowing script). Bold (700) only at display sizes. Code surfaces (`pre`, `code`) add `dlig` for the coding ligatures.
## Color discipline (the core rule)
diff --git a/.gitignore b/.gitignore
index 5734dd533a7..711db4d6c35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -274,4 +274,5 @@ ds-bundle/
# proprietary brand font (MonoLisa, © FaceType Foundry) — fetched at sync time, never committed
# (the @font-face CSS at app/.designsync-fonts/monolisa.css IS committed)
app/.designsync-fonts/*.ttf
+app/.designsync-fonts/*.otf
app/.designsync-fonts/*.woff2
diff --git a/api/Dockerfile b/api/Dockerfile
index 21a7fc0c39b..432314186ee 100644
--- a/api/Dockerfile
+++ b/api/Dockerfile
@@ -103,7 +103,7 @@ COPY --chown=appuser:appuser api/ ./api/
COPY --chown=appuser:appuser core/ ./core/
# Fail the build if Pillow cannot shape text. Without it Pillow falls back to
-# its BASIC layout engine: the OG cards lose MonoLisa's italic `ss02` swashes
+# its BASIC layout engine: the OG cards lose MonoLisa's italic `ss01` swashes
# and all kerning, and nothing in the response signals it — the only symptom is
# an off-brand PNG (#10813). This runs in the RUNTIME stage on purpose: the
# check is only meaningful against the image that actually serves. In the
diff --git a/api/main.py b/api/main.py
index 23c4ab22e66..baa2f5c06c2 100644
--- a/api/main.py
+++ b/api/main.py
@@ -146,7 +146,7 @@ async def lifespan(app: FastAPI):
logger.info("Starting anyplot API...")
# Text shaping decides whether the OG cards carry MonoLisa's italic swashes
- # (`ss02`) and kerning at all — log it once so a degraded image is visible
+ # (`ss01`) and kerning at all — log it once so a degraded image is visible
# in Cloud Run logs instead of only in a pixel diff of the served PNG.
if has_text_shaping():
logger.info("Text shaping (libraqm): available")
diff --git a/app/.designsync-fonts/monolisa.css b/app/.designsync-fonts/monolisa.css
index ddb1b0ad029..dec028f2ddb 100644
--- a/app/.designsync-fonts/monolisa.css
+++ b/app/.designsync-fonts/monolisa.css
@@ -1,24 +1,41 @@
/*
- * MonoLisa (variable) — brand typeface for the anyplot design system.
+ * MonoLisa 3.000 (variable: wght + GRAD) — brand typeface for the anyplot
+ * design system. Two families: MonoLisa Code (monospaced, used everywhere)
+ * and MonoLisa Text (proportional sibling, registered for experiments).
* Proprietary, © FaceType Foundry. The .ttf binaries are fetched at sync time
* from the anyplot GCS bucket into this directory and gitignored (this CSS is
* committed); they are shipped only into the private claude.ai/design project,
* never committed to the (public) repo.
*
* Re-fetch (see .design-sync/NOTES.md):
- * curl -sSfo MonoLisaVariableNormal.ttf https://storage.googleapis.com/anyplot-static/fonts/MonoLisaVariableNormal.ttf
- * curl -sSfo MonoLisaVariableItalic.ttf https://storage.googleapis.com/anyplot-static/fonts/MonoLisaVariableItalic.ttf
+ * for f in MonoLisaCodeUpright MonoLisaCodeItalic MonoLisaTextUpright MonoLisaTextItalic; do
+ * curl -sSfo $f.ttf https://storage.googleapis.com/anyplot-static/fonts/v3/desktop/$f.ttf
+ * done
*/
@font-face {
- font-family: 'MonoLisa';
- src: url('./MonoLisaVariableNormal.ttf') format('truetype');
+ font-family: 'MonoLisa Code';
+ src: url('./MonoLisaCodeUpright.ttf') format('truetype');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
@font-face {
- font-family: 'MonoLisa';
- src: url('./MonoLisaVariableItalic.ttf') format('truetype');
+ font-family: 'MonoLisa Code';
+ src: url('./MonoLisaCodeItalic.ttf') format('truetype');
+ font-weight: 100 900;
+ font-style: italic;
+ font-display: swap;
+}
+@font-face {
+ font-family: 'MonoLisa Text';
+ src: url('./MonoLisaTextUpright.ttf') format('truetype');
+ font-weight: 100 900;
+ font-style: normal;
+ font-display: swap;
+}
+@font-face {
+ font-family: 'MonoLisa Text';
+ src: url('./MonoLisaTextItalic.ttf') format('truetype');
font-weight: 100 900;
font-style: italic;
font-display: swap;
diff --git a/app/index.html b/app/index.html
index de9537798f4..19bc98db9e5 100644
--- a/app/index.html
+++ b/app/index.html
@@ -73,12 +73,12 @@
-
-
-
-
+
+
+
+
-
+