feat(eidos): default fonts -> variable woff2 + full variable-font API

Ship the base theme's default families (Instrument Sans / Lora / Azeret Mono --
identity unchanged) as self-hosted VARIABLE woff2 (SIL OFL, latin subset, wght
range, preload on primary), so the engine's variable path is exercised by the
default theme, not merely capable. The hand-written themes/fonts.css is retired
(@font-face is config-driven from typography.families[].faces); the static TTF
set under static/fonts/air is removed.

Also close the theming-API gaps so it supports ANY variable font, not just
wght+opsz:
- FontAxes is now a 4-letter-tag map. renderFontFace emits a descriptor per
  registered axis: wdth -> font-stretch: min% max%, slnt -> font-style: oblique
  (OpenType slnt negated to the CSS oblique sign), alongside wght/opsz.
- TypographyStyle.variationSettings -> --style-{name}-font-variation-settings,
  applied by the Text recipe (fallback normal), engaging non-standard axes
  (GRAD/MONO/custom) and fixed axis defaults.

Verified: variable faces load with weight ranges + mid-axis rendering; new axis
+ variation-settings emission covered by active-eidos-config.test.ts (99 pass);
npm run check src/ = 9-error baseline (0 new); no default-font regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
menubar-v4-safe
dev 3 months ago
parent e75f85becc
commit 7d4f95005d

@ -106,20 +106,34 @@ size = clamp(minRem, interceptRem + slope·100vw, maxRem)
load (the Fontaine / `next/font` approach). Metrics precomputed per font.
- **`unicode-range`** subsetting (latin / latin-ext split) → load only what's used.
- **`preload`** of the critical family (primary regular).
- **Type**: `FontFamily` += `axes?: { wght?: [min,max]; opsz?: [min,max] }` +
`sizeAdjust?` / metric overrides + `unicodeRanges?`. `source` already exists. ✅
- **Type**: `FontFamily` += `axes?` (variable axis ranges, keyed by 4-letter tag)
+ `fallback?` metric overrides + `unicodeRange?` per face + `preload?`. `source`
already exists. ✅
- **Optical sizing** ✅: `font-optical-sizing: auto` at `:root` when any family
declares `opsz`.
- **Variable weight axis** ✅: when a `face` omits `weight` and the family
declares `axes.wght`, the `@font-face` emits the range (`font-weight: 100 900`)
→ a single face covers the whole axis. (`render-css > renderFontFace`; test in
`active-eidos-config.test.ts`.)
> **§5 status**: the **engine** is wired — config-driven `@font-face`, anti-CLS
> fallback, `unicode-range`, and now `axes` consumption (weight range + optical
> sizing). Inert until a theme declares `axes` — like color's wide-gamut: ready,
> but not exercised by the current assets (static TTFs). **Pending on assets**:
> migrate to real variable woff2; `preload` (separate closure).
→ a single face covers the whole axis. (`render-css > renderFontFace`.)
- **Any variable axis** ✅ (2026-07-12): `FontAxes` is a 4-letter-tag map; the
engine emits an `@font-face` descriptor for each registered tag — `wdth` →
`font-stretch: min% max%`, `slnt` → `font-style: oblique …` (OpenType `slnt`
negated to the CSS `oblique` sign), alongside `wght`/`opsz`. NON-standard axes
(`GRAD`, `MONO`, custom …) have no descriptor — engage them (and fixed axis
defaults) via `TypographyStyle.variationSettings` → the emitted
`--style-{name}-font-variation-settings` token, applied by the Text recipe
(fallback `normal`, so it is a no-op until a style sets it). Tests in
`active-eidos-config.test.ts`.
> **§5 status** (2026-07-12): **SHIPPED**. The default theme's families
> (Instrument Sans / Lora / Azeret Mono — identity unchanged) now ship as
> **variable woff2** (self-hosted, SIL OFL, latin subset, `wght` range, `preload`
> on primary) — the engine's variable path is exercised by the default theme, not
> merely capable. The old hand-written `themes/fonts.css` is retired; `@font-face`
> is config-driven from `typography.families[].faces`. The API now supports **any**
> variable font: the four registered axes (`wght`/`wdth`/`slnt`/`opsz`) + arbitrary
> axes via `variationSettings`. **Still pending (optional)**: engine-side
> auto-computation of the anti-CLS metric overrides (today `fallback` values are
> precomputed / manual — the one remaining ergonomics gap).
## 6. Tracking · leading · features · measure · wrap (Phase 3)

@ -208,7 +208,7 @@ describe('ActiveEidos config', () => {
typography: {
families: {
primary: {
family: 'Inter'
family: 'Geist'
}
}
}
@ -245,14 +245,12 @@ describe('ActiveEidos config', () => {
// The patch overrides only `family`; fallbacks/source/faces deep-merge from the
// base (a real font swap would also override `faces` with its own files).
const mergedPrimary = cfg.primitives.typography?.families.primary
expect(mergedPrimary?.family).toBe('Inter')
expect(mergedPrimary?.family).toBe('Geist')
expect(mergedPrimary?.fallbacks).toEqual(['system-ui', 'sans-serif'])
expect(mergedPrimary?.source).toBe('local')
expect(mergedPrimary?.faces?.length).toBe(3)
expect(mergedPrimary?.faces?.length).toBe(1)
// Base constant not mutated.
expect(THEME_BASE_OPTIONS.primitives.typography?.families.primary.family).toBe(
'Instrument Sans'
)
expect(THEME_BASE_OPTIONS.primitives.typography?.families.primary.family).toBe('Instrument Sans')
expect(cfg.semantics.color.roles.primary).toEqual({
scale: 'blue',
slots: {
@ -441,10 +439,12 @@ describe('ActiveEidos config', () => {
const css = createThemeBaseEidos().renderStaticCss()
expect(css).toContain('@font-face')
expect(css).toContain("font-family: 'Instrument Sans';")
expect(css).toContain("src: url('/fonts/air/Lora-Bold.ttf') format('truetype');")
expect(css).toContain(
"src: url('/fonts/lora/lora-latin-wght-normal.woff2') format('woff2');"
)
expect(css).toContain('font-style: italic;')
// Lora is shared by `secondary` + `display` → its 8 faces emit once, not 16.
expect((css.match(/font-family: 'Lora';/g) ?? []).length).toBe(8)
// Lora is shared by `secondary` + `display` → its 2 faces emit once, not 4.
expect((css.match(/font-family: 'Lora';/g) ?? []).length).toBe(2)
})
it('emits variable-font output from family axes (weight range + optical sizing)', () => {
@ -467,6 +467,30 @@ describe('ActiveEidos config', () => {
expect(css).toContain('font-optical-sizing: auto')
})
it('emits width/slant axis descriptors + per-style font-variation-settings', () => {
const cfg = structuredClone(THEME_BASE_OPTIONS)
const t = cfg.primitives.typography!
// A variable font spanning wght + wdth + slnt, no explicit per-face style.
;(t.families as Record<string, unknown>).primary = {
...t.families.primary,
axes: { wght: [400, 700], wdth: [75, 125], slnt: [-10, 0] },
faces: [{ sources: [{ url: '/fonts/variable/Flex.woff2', format: 'woff2' }] }]
}
// A named style engaging a NON-standard axis (opsz/GRAD) via variationSettings.
;(t.styles as Record<string, unknown>).body = {
...t.styles!.body,
variationSettings: '"opsz" 40, "GRAD" 50'
}
const css = createEidos(cfg).renderStaticCss()
expect(css).toContain('font-weight: 400 700;')
// wdth → font-stretch percentage range
expect(css).toContain('font-stretch: 75% 125%;')
// slnt [-10,0] → oblique 0deg..10deg (CSS angle = -slnt, kept ascending)
expect(css).toContain('font-style: oblique 0deg 10deg;')
// variationSettings → per-style token (applied by the Text recipe)
expect(css).toContain('--style-body-font-variation-settings: "opsz" 40, "GRAD" 50;')
})
it('applyTypeScale returns a built scale (runtime type-scale builder)', () => {
const eidos = createThemeBaseEidos();
const result = eidos.applyTypeScale({ base: 16, ratio: 1.25 });

@ -26,6 +26,10 @@
* above). `measure` needs a block `as` (e.g. `p`) to take effect. */
text-wrap: var(--_text-wrap, wrap);
font-feature-settings: var(--_text-font-feature, normal);
/* Variable-font axes past wght/wdth/slnt (opsz, GRAD, custom …): a style sets
* `--style-{name}-font-variation-settings` from its config `variationSettings`;
* `normal` fallback keeps this a no-op until one does. */
font-variation-settings: var(--_text-variation, var(--style-body-font-variation-settings, normal));
max-inline-size: var(--_text-measure, none);
font-style: normal;
text-decoration: none;
@ -39,6 +43,7 @@
line-height: var(--_text-line-height, var(--style-prose-line-height));
letter-spacing: var(--_text-letter-spacing, var(--style-prose-letter-spacing));
color: var(--_text-color, var(--style-prose-color));
font-variation-settings: var(--_text-variation, var(--style-prose-font-variation-settings, normal));
}
[data-text][data-style='label'] {
@ -48,6 +53,7 @@
line-height: var(--_text-line-height, var(--style-label-line-height));
letter-spacing: var(--_text-letter-spacing, var(--style-label-letter-spacing));
color: var(--_text-color, var(--style-label-color));
font-variation-settings: var(--_text-variation, var(--style-label-font-variation-settings, normal));
}
[data-text][data-style='caption'] {
@ -57,6 +63,7 @@
line-height: var(--_text-line-height, var(--style-caption-line-height));
letter-spacing: var(--_text-letter-spacing, var(--style-caption-letter-spacing));
color: var(--_text-color, var(--style-caption-color));
font-variation-settings: var(--_text-variation, var(--style-caption-font-variation-settings, normal));
}
[data-text][data-italic] {

@ -13,114 +13,38 @@
@font-face {
font-family: 'Instrument Sans';
src: url('/fonts/air/InstrumentSans-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Instrument Sans';
src: url('/fonts/air/InstrumentSans-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Instrument Sans';
src: url('/fonts/air/InstrumentSans-SemiBold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Medium.ttf') format('truetype');
font-weight: 500;
src: url('/fonts/instrument-sans/instrument-sans-latin-wght-normal.woff2') format('woff2');
font-weight: 400 700;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-MediumItalic.ttf') format('truetype');
font-weight: 500;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-SemiBold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-SemiBoldItalic.ttf') format('truetype');
font-weight: 600;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Bold.ttf') format('truetype');
font-weight: 700;
src: url('/fonts/lora/lora-latin-wght-normal.woff2') format('woff2');
font-weight: 400 700;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-BoldItalic.ttf') format('truetype');
font-weight: 700;
src: url('/fonts/lora/lora-latin-wght-italic.woff2') format('woff2');
font-weight: 400 700;
font-style: italic;
font-display: swap;
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face {
font-family: 'Azeret Mono';
src: url('/fonts/air/AzeretMono-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Azeret Mono';
src: url('/fonts/air/AzeretMono-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Azeret Mono';
src: url('/fonts/air/AzeretMono-SemiBold.ttf') format('truetype');
font-weight: 600;
src: url('/fonts/azeret-mono/azeret-mono-latin-wght-normal.woff2') format('woff2');
font-weight: 100 900;
font-style: normal;
font-display: swap;
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
:root {
@ -1581,7 +1505,6 @@
--chronos-lane-height-md: var(--space-6);
--chronos-lane-height-lg: var(--space-7);
--chronos-timegrid-block-size: min(70vh, 40rem);
--chronos-focus-shadow: inset 0 0 0 var(--focus-ring-inner-width) var(--focus-ring-color), 0 0 0 var(--focus-ring-offset) var(--color-surface-default), 0 0 0 calc(var(--focus-ring-offset) + var(--focus-ring-width)) var(--focus-ring-color);
--chronos-disabled-opacity: var(--opacity-disabled);
--pagination-gap-xs: var(--space-0-5);
--pagination-gap-sm: var(--space-1);

@ -789,10 +789,20 @@ export interface FontFallback {
readonly lineGapOverride?: string;
}
/** Variable-font axis ranges. */
/**
* Variable-font axis ranges, keyed by 4-letter OpenType axis tag. The registered
* tags that map to a CSS `@font-face` descriptor are emitted by the engine:
* `wght` → `font-weight: min max` · `wdth` → `font-stretch: min% max%`
* `slnt` → `font-style: oblique …` · `opsz` → enables `font-optical-sizing: auto`
* Any other tag (custom axes — `GRAD`, `MONO`, `CASL`, `SOFT`, …) is accepted to
* document the font's range; engage it at runtime via a style's `variationSettings`.
*/
export interface FontAxes {
readonly wght?: readonly [number, number];
readonly wdth?: readonly [number, number];
readonly slnt?: readonly [number, number];
readonly opsz?: readonly [number, number];
readonly [tag: string]: readonly [number, number] | undefined;
}
export interface FontFamily {
@ -821,6 +831,14 @@ export interface TypographyStyle {
readonly lineHeight?: string;
readonly letterSpacing?: string;
readonly color?: string;
/**
* Raw `font-variation-settings` value for this style (e.g. `'"opsz" 40, "GRAD" 50'`).
* The single door to a variable font's NON-standard axes — anything past
* `wght`/`wdth`/`slnt` (which have their own descriptors) — plus fixed default
* positions. Emitted as `--style-{name}-font-variation-settings` and applied by
* the Text recipe (fallback `normal`, so it is a no-op unless a style sets it).
*/
readonly variationSettings?: string;
}
export interface TypographyPrimitiveSet {

@ -1,48 +1,67 @@
import type { TypographyPrimitiveSet } from '../config-types'
// Google Fonts "latin" subset range — the vendored variable woff2 are latin-only.
// Text outside this range falls back to the family's system fallback stack.
const LATIN_SUBSET =
'U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD'
export const STATIC_TYPOGRAPHY: TypographyPrimitiveSet = {
families: {
// @font-face is config-driven (Fase 2): the engine emits these from `faces`.
// These are the BASE THEME's fonts — a theme owns its families. TTF today;
// a theme can swap to woff2/variable + a metric-override `fallback` by editing
// this config only (no separate fonts.css). The font files live in /fonts/air.
// These are the BASE THEME's DEFAULT fonts — same identity as before
// (Instrument Sans / Lora / Azeret Mono), now shipped as VARIABLE woff2
// (self-hosted, SIL OFL) so the default theme exercises the engine's variable
// path: each face omits an explicit `weight`, so the engine emits the `wght`
// axis range (`font-weight: {min} {max}`) from `axes.wght`. Latin subset only
// (`unicodeRange`). A theme swaps all of this by editing THIS config — the
// files live in /fonts/{family}. (These families are `wght`-only; the engine's
// `opsz`/optical-sizing path stays available for any theme that brings it.)
primary: {
family: 'Instrument Sans',
fallbacks: ['system-ui', 'sans-serif'],
source: 'local',
axes: { wght: [400, 700] },
preload: true,
faces: [
{ sources: [{ url: '/fonts/air/InstrumentSans-Regular.ttf', format: 'truetype' }], weight: 400 },
{ sources: [{ url: '/fonts/air/InstrumentSans-Medium.ttf', format: 'truetype' }], weight: 500 },
{ sources: [{ url: '/fonts/air/InstrumentSans-SemiBold.ttf', format: 'truetype' }], weight: 600 }
{
sources: [
{ url: '/fonts/instrument-sans/instrument-sans-latin-wght-normal.woff2', format: 'woff2' }
],
unicodeRange: LATIN_SUBSET
}
]
},
secondary: {
family: 'Lora',
fallbacks: ['Georgia', 'Times New Roman', 'serif'],
source: 'local',
axes: { wght: [400, 700] },
faces: [
{ sources: [{ url: '/fonts/air/Lora-Regular.ttf', format: 'truetype' }], weight: 400 },
{ sources: [{ url: '/fonts/air/Lora-Italic.ttf', format: 'truetype' }], weight: 400, style: 'italic' },
{ sources: [{ url: '/fonts/air/Lora-Medium.ttf', format: 'truetype' }], weight: 500 },
{ sources: [{ url: '/fonts/air/Lora-MediumItalic.ttf', format: 'truetype' }], weight: 500, style: 'italic' },
{ sources: [{ url: '/fonts/air/Lora-SemiBold.ttf', format: 'truetype' }], weight: 600 },
{ sources: [{ url: '/fonts/air/Lora-SemiBoldItalic.ttf', format: 'truetype' }], weight: 600, style: 'italic' },
{ sources: [{ url: '/fonts/air/Lora-Bold.ttf', format: 'truetype' }], weight: 700 },
{ sources: [{ url: '/fonts/air/Lora-BoldItalic.ttf', format: 'truetype' }], weight: 700, style: 'italic' }
{
sources: [{ url: '/fonts/lora/lora-latin-wght-normal.woff2', format: 'woff2' }],
unicodeRange: LATIN_SUBSET
},
{
sources: [{ url: '/fonts/lora/lora-latin-wght-italic.woff2', format: 'woff2' }],
style: 'italic',
unicodeRange: LATIN_SUBSET
}
]
},
mono: {
family: 'Azeret Mono',
fallbacks: ['ui-monospace', 'monospace'],
source: 'local',
axes: { wght: [100, 900] },
faces: [
{ sources: [{ url: '/fonts/air/AzeretMono-Regular.ttf', format: 'truetype' }], weight: 400 },
{ sources: [{ url: '/fonts/air/AzeretMono-Medium.ttf', format: 'truetype' }], weight: 500 },
{ sources: [{ url: '/fonts/air/AzeretMono-SemiBold.ttf', format: 'truetype' }], weight: 600 }
{
sources: [{ url: '/fonts/azeret-mono/azeret-mono-latin-wght-normal.woff2', format: 'woff2' }],
unicodeRange: LATIN_SUBSET
}
]
},
display: {
// Shares the Lora font with `secondary`; faces are declared there and the
// Shares Lora with `secondary`; its faces are declared there and the
// generator dedupes by font name, so no @font-face is emitted twice.
family: 'Lora',
fallbacks: ['Georgia', 'Times New Roman', 'serif'],

@ -1375,6 +1375,12 @@ function appendTypographyStyleDeclarations(
cssVar(`style-${name}-color`, `var(--color-${style.color.replace(/\./g, '-')})`)
)
}
if (style.variationSettings) {
declarations.push(
cssVar(`style-${name}-font-variation-settings`, style.variationSettings)
)
}
}
}
@ -2603,14 +2609,24 @@ function renderFontFace(
// `wght` axis range, emit the range (`font-weight: 100 900`) so a single face spans the
// whole weight axis. (TYPOGRAPHY_ENGINE_RFC §5 — variable fonts)
const weight = face.weight ?? (axes?.wght ? `${axes.wght[0]} ${axes.wght[1]}` : 400)
// font-style: an explicit face `style` wins; otherwise a `slnt` axis emits an
// oblique RANGE. OpenType `slnt` is degrees with NEGATIVE = forward slant, while
// CSS `oblique` is POSITIVE = forward — so the angle is `-slnt`, and the [min,max]
// range maps to `oblique -max -min` (kept ascending). No slant axis → `normal`.
let fontStyle: string
if (face.style) fontStyle = face.style
else if (axes?.slnt) fontStyle = `oblique ${-axes.slnt[1]}deg ${-axes.slnt[0]}deg`
else fontStyle = 'normal'
const lines = [
'@font-face {',
`\tfont-family: '${family}';`,
`\tsrc: ${src};`,
`\tfont-weight: ${weight};`,
`\tfont-style: ${face.style ?? 'normal'};`,
`\tfont-display: ${face.display ?? defaultDisplay ?? 'swap'};`
`\tfont-style: ${fontStyle};`
]
// `wdth` axis → `font-stretch` percentage range (wdth axis values ARE percentages).
if (axes?.wdth) lines.push(`\tfont-stretch: ${axes.wdth[0]}% ${axes.wdth[1]}%;`)
lines.push(`\tfont-display: ${face.display ?? defaultDisplay ?? 'swap'};`)
if (face.unicodeRange) lines.push(`\tunicode-range: ${face.unicodeRange};`)
lines.push('}')
return lines.join('\n')

@ -1,111 +0,0 @@
@font-face {
font-family: 'Instrument Sans';
src: url('/fonts/air/InstrumentSans-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Instrument Sans';
src: url('/fonts/air/InstrumentSans-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Instrument Sans';
src: url('/fonts/air/InstrumentSans-SemiBold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Italic.ttf') format('truetype');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-MediumItalic.ttf') format('truetype');
font-weight: 500;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-SemiBold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-SemiBoldItalic.ttf') format('truetype');
font-weight: 600;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-Bold.ttf') format('truetype');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lora';
src: url('/fonts/air/Lora-BoldItalic.ttf') format('truetype');
font-weight: 700;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'Azeret Mono';
src: url('/fonts/air/AzeretMono-Regular.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Azeret Mono';
src: url('/fonts/air/AzeretMono-Medium.ttf') format('truetype');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Azeret Mono';
src: url('/fonts/air/AzeretMono-SemiBold.ttf') format('truetype');
font-weight: 600;
font-style: normal;
font-display: swap;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,93 @@
Copyright 2021 The Azeret Project Authors (https://github.com/displaay/azeret) AzeretMono-Italic[wght].ttf: Copyright 2021 The Azeret Project Authors (https://github.com/displaay/azeret)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

@ -0,0 +1,93 @@
Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans) InstrumentSans-Italic[wdth,wght].ttf: Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

@ -0,0 +1,93 @@
Copyright 2011 The Lora Project Authors (https://github.com/cyrealtype/Lora-Cyrillic), with Reserved Font Name "Lora". Lora-Italic[wght].ttf: Copyright 2011 The Lora Project Authors (https://github.com/cyrealtype/Lora-Cyrillic), with Reserved Font Name "Lora".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Loading…
Cancel
Save

Powered by TurnKey Linux.