# Pivot Sans

Pivot Sans is a permanent fork of
[Inclusive Sans](https://github.com/LivKing/Inclusive-Sans) 2.004, authored and
maintained by [Beacon Bay Technologies, Inc.](https://pivotsans.com). It
preserves the approachable upstream design while adding production-oriented
numeric, identifier, symbol, web-delivery, metadata, and QA improvements.

Current release: **Pivot Sans 1.200**

The original Inclusive Sans design is by Olivia King and remains credited to
the Inclusive Sans Project Authors. Pivot Sans is distributed under the SIL
Open Font License 1.1. See [`AUTHORS.txt`](AUTHORS.txt),
[`OFL.txt`](OFL.txt), [`FONTLOG.txt`](FONTLOG.txt), and
[`QA-NOTES.md`](QA-NOTES.md).

Project home: <https://pivotsans.com>

## What Pivot Sans adds

### A shared tabular money grid

The standard OpenType `tnum` feature covers ASCII digits and five currency
symbols:

```text
0 1 2 3 4 5 6 7 8 9  $ £ ¥ ₹ €
```

All 15 characters share one advance at a given weight, across upright and
italic. The slot deliberately includes the wider euro rather than creating a
locale-dependent exception:

| `wght` | Advance (font units) |
|---:|---:|
| 300 | 668 |
| 400 | 660 |
| 500 | 666 |
| 600 | 671 |
| 700 | 677 |

The 15 public `.tf` glyphs are composites that reference the original
outlines. One additional internal `.tf` wrapper preserves the specialized
heavy-dollar form selected by upstream `rvrn` before `tnum` runs. Default
figures and currencies remain proportional. Enable the shared grid with:

```css
font-variant-numeric: tabular-nums;
```

or:

```css
font-feature-settings: "tnum";
```

### Five encoded composite symbols

Pivot Sans adds Unicode-mapped composites built from existing design parts:

| Character | Unicode | Construction |
|---|---|---|
| ‰ | U+2030 PER MILLE SIGN | percent plus the unslashed degree circle |
| ≈ | U+2248 ALMOST EQUAL TO | paired tildes |
| ≠ | U+2260 NOT EQUAL TO | equals plus slash |
| ≤ | U+2264 LESS-THAN OR EQUAL TO | less-than plus bar |
| ≥ | U+2265 GREATER-THAN OR EQUAL TO | greater-than plus bar |

Their components follow the weight axis without duplicating upstream contour
data. The degree circle is used for the third per-mille counter because
Inclusive Sans’s full-size zero is intentionally slashed.

### A scoped, disambiguated lowercase l

The default-off `ss02` stylistic set adds a footed lowercase `l` for dense
identifiers such as `acct_Il1l-class`. Its foot follows Pivot Sans’s native
capital-I serif weight and the italic shear, while every alternate retains its
source glyph’s advance, kerning, mark anchors, and variation behavior.

Coverage includes:

```text
l ĺ ļ ľ ŀ ł ḷ ḻ
```

It also follows the upstream Marshallese `locl` substitution for `ļ`.
Defaults are untouched: ordinary prose continues to use the original
Inclusive Sans lowercase `l`. Apply the feature only to an identifier,
token, or code scope:

```css
.identifier {
  font-feature-settings: "ss02";
}
```

The implementation uses one weight-varying native-derived foot and nine
source-preserving composite alternates. When an authoritative source is
already composite, its native simple components are copied into the alternate
before the foot is appended; this avoids nested composites without redrawing
anything. Accents, strokes, locale forms, and metrics remain tied to their
authoritative source recipes.

### Locale-targeted web subsets

`dist/pivot-sans-subsets.css` declares disjoint `latin-core`, `latin-ext`, and
`vietnamese` WOFF2 slices for both styles. A typical Latin page fetches only
the core slice (about 34–36 KiB per style); extended Latin or Vietnamese
content causes the browser to fetch only the additional slice it needs.

The source whitelists live in `subsets/`. They are intentionally explicit,
auditable, and tested for disjointness and complete coverage of the full
Pivot Sans cmap.

### Static pins and specimen

The release includes custom instances at `wght` 450 and 550, upright and
italic, in both TTF and WOFF2. `dist/specimen.html` exercises the complete
axis, italics, `tnum`, `ss01`, `ss02`, the money grid, composite symbols,
locale slices, and custom pins.

### Metadata and clipping correctness

- Pivot Sans has an independent family identity and version.
- Beacon Bay Technologies, Inc. is recorded as fork author/manufacturer, with
  <https://pivotsans.com> as the project/vendor URL.
- Olivia King and the Inclusive Sans Project Authors retain original design
  credit and the original designer URL.
- Upright and italic variable fonts use distinct variation PostScript
  prefixes: `PivotSans` and `PivotSansItalic`.
- `OS/2.usWinAscent` is 1159 rather than the inherited 1150. The Bold styles
  reach y=1159, so the corrected value prevents clipping in software that uses
  Windows bounds. Other upstream vertical metrics are retained.

## Release files

The `dist/` directory contains:

| Files | Purpose |
|---|---|
| `PivotSans[wght].ttf/.woff2` | Upright variable font, `wght` 300–700 |
| `PivotSans-Italic[wght].ttf/.woff2` | Italic variable font, `wght` 300–700 |
| `static/PivotSans-*.ttf/.woff2` | Ten official 300/400/500/600/700 static styles |
| `pins/PivotSans-Wght{450,550}*.ttf/.woff2` | Four custom static instances |
| `subsets/PivotSans-*-{latin-core,latin-ext,vietnamese}[wght].woff2` | Six locale slices |
| `pivot-sans.css` | Full variable WOFF2 declarations |
| `pivot-sans-subsets.css` | Locale-sliced variable WOFF2 declarations |
| `specimen.html` | Interactive browser specimen and feature proof |
| `qa-visual.png` | Deterministic tabular-money and `ss02` visual proof |
| `SHA256SUMS` | Checksums for every font, CSS/HTML specimen, and QA image |

Variable fonts contain the 550 upstream glyphs, 15 public tabular alternates,
one internal heavy-dollar tabular wrapper, five encoded composites, one
shared `ss02` foot, and nine lowercase-l alternates: 581 glyphs total. Static
fonts are direct overlays on the official upstream static binaries. The
low/mid static styles contain 577 glyphs; the SemiBold/Bold styles retain the
three active upstream `rvrn` helpers plus the internal heavy-dollar wrapper
and contain 581. Each pruned 450/550 pin contains 577 glyphs.

### Desktop installation

Install one desktop set:

- the two variable TTFs;
- the ten official static TTFs; or
- only the custom pin TTFs you need.

Do not install overlapping sets simultaneously. Variable named instances and
matching static styles represent the same family positions and can conflict
in desktop font managers. WOFF2 files are web assets.

### Web use

For smallest locale-aware delivery, copy `dist/` with its directory structure
and include:

```html
<link rel="stylesheet" href="/fonts/pivot-sans/pivot-sans-subsets.css">
```

For a single full font per style, use `pivot-sans.css` instead. Both styles
cover the complete 300–700 weight range.

## Reproducible build

Python 3.10 or newer is recommended.

```sh
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python pipeline/measure.py
python pipeline/build.py
python -m pytest
```

The build:

1. verifies every authoritative input against `upstream/SHA256SUMS`;
2. overlays the variable and official static binaries, including the
   source-preserving `ss02` glyphs and layout metadata;
3. creates the 450/550 instances with fontTools’ variable instancer;
4. removes unreachable `rvrn` helpers from fixed pins;
5. creates six locale slices with `pyftsubset` and recalculates each slice’s
   horizontal-header extrema;
6. writes TTF and WOFF2 outputs with a fixed release timestamp; and
7. regenerates `dist/SHA256SUMS`.

Consecutive builds with the pinned dependencies are byte-for-byte identical.

To render the visual proof:

```sh
python -m pip install -r requirements-audit.txt
python pipeline/render_qa.py
```

To exercise the specimen in a real browser, verify selective slice fetching
and browser-native money alignment, and capture a full-page screenshot:

```sh
python -m playwright install chromium
python pipeline/audit_specimen.py
```

To create a normalized release ZIP without macOS metadata, caches, or
machine-specific timestamps:

```sh
python pipeline/package.py --output ../pivot-sans-1.200.zip
```

## QA

The pytest suite verifies:

- money-grid equality at every integer weight from 300 through 700;
- exact named-weight advances in TTF, WOFF2, official statics, and pins;
- exact `tnum` substitution of all ten digits and five currencies;
- default-off `ss02` shaping, metrics, kerning, mark anchors, localization,
  and interpolation for all lowercase-l forms;
- Unicode mapping, metrics, components, and shaping for all five new symbols;
- unchanged default shaping and semantic identity for every upstream glyph;
- preservation of `ss01`, all upstream GSUB behavior, and every source
  kerning/positioning record while narrowly cloning source behavior to
  `ss02`;
- direct static overlays against every official upstream static font;
- custom-pin equivalence to variable instancing at 450 and 550;
- disjoint whitelist coverage and per-slice cmap/feature behavior;
- family/style linking, authorship, URLs, versioning, names, and axes;
- TTF/WOFF2 table parity, source/release checksums, deterministic timestamps,
  and family clipping bounds.

For an independent release audit:

```sh
python -m pip install -r requirements-audit.txt
python -m ots 'dist/PivotSans[wght].ttf'
fontbakery check-universal --skip-network \
  'dist/PivotSans[wght].ttf' 'dist/PivotSans-Italic[wght].ttf'
fontbakery check-universal --skip-network dist/static/*.ttf
```

Run variable and static FontBakery sets separately. Combining overlapping
desktop sets creates expected duplicate-style diagnostics.

## Rebasing upstream

To rebase the permanent fork:

1. replace both variable fonts, all ten official static fonts, `OFL.txt`, and
   `README.txt` under `upstream/`;
2. update `upstream/SHA256SUMS`;
3. update the upstream version and release metadata in the pipeline;
4. run `python pipeline/measure.py`;
5. run the complete build, pytest, OpenType Sanitizer, and FontBakery workflow;
6. review `AUTHORS.txt` and `FONTLOG.txt` before assigning a new Pivot Sans
   version.

The build fails closed if the source manifest does not match.
