Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .design-sync/NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.)
Expand Down
4 changes: 2 additions & 2 deletions .design-sync/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
31 changes: 24 additions & 7 deletions app/.designsync-fonts/monolisa.css
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
10 changes: 5 additions & 5 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@
<!-- Preconnect to API for faster first request -->
<link rel="preconnect" href="https://api.anyplot.ai" crossorigin>

<!-- Preload MonoLisa Basic Latin (most used, variable font = all weights) -->
<link rel="preload" href="https://storage.googleapis.com/anyplot-static/fonts/0-MonoLisa-normal.woff2" as="font" type="font/woff2" crossorigin>
<!-- Preload Basic Latin italic — the editorial script variant (`<em>` + ss02). Without this the font arrives too late under `font-display: optional` and the page renders with the upright fallback. -->
<link rel="preload" href="https://storage.googleapis.com/anyplot-static/fonts/1-MonoLisa-italic.woff2" as="font" type="font/woff2" crossorigin>
<!-- Preload MonoLisa Code Basic Latin (most used, variable font = all weights) -->
<link rel="preload" href="https://storage.googleapis.com/anyplot-static/fonts/v3/code/0-MonoLisaCode-normal.woff2" as="font" type="font/woff2" crossorigin>
<!-- Preload Basic Latin italic — the editorial script variant (`<em>` + ss01). The face is `font-display: swap`, so without the preload the hero tagline first paints in the upright fallback and then swaps to script. -->
<link rel="preload" href="https://storage.googleapis.com/anyplot-static/fonts/v3/code/1-MonoLisaCode-italic.woff2" as="font" type="font/woff2" crossorigin>
<!-- Preload Latin-1 Supplement for ä, ö, ü, ß etc. -->
<link rel="preload" href="https://storage.googleapis.com/anyplot-static/fonts/2-MonoLisa-normal.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="https://storage.googleapis.com/anyplot-static/fonts/v3/code/2-MonoLisaCode-normal.woff2" as="font" type="font/woff2" crossorigin>

<!-- JSON-LD Structured Data -->
<script type="application/ld+json">
Expand Down
2 changes: 1 addition & 1 deletion app/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Import design tokens (CSS custom properties for theming + dark mode)
import 'src/styles/tokens.css';
// Import web fonts - MonoLisa from GCS, Fraunces + Inter from Google Fonts
// Import web fonts - MonoLisa Code + Text from GCS (no Google Fonts)
import 'src/styles/fonts.css';

import React from 'react';
Expand Down
2 changes: 1 addition & 1 deletion app/src/sections/landing/HeroSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export function HeroSection({ potd = null }: HeroSectionProps) {
fontFamily: typography.serif,
fontWeight: 400,
fontStyle: 'italic',
fontFeatureSettings: '"ss02"',
fontFeatureSettings: '"ss01"',
whiteSpace: 'nowrap',
fontSize: '0.75em',
}}
Expand Down
Loading
Loading