Files
archy/docker/justworks/public/assets/tokens.css
T
yaya 94899e69d3 feat: integrate Just Works app and native business setup
Preserve hosted website UX inside Archipelago, add isolated Business and owner-authorized native wallet setup, and include deployment handoff. Based on main with native signer import already accepted.
2026-10-08 19:39:38 +01:00

554 lines
21 KiB
CSS

/*
* Just Works design tokens — the single source of truth for color, type,
* space, radius, shadow, and motion. Everything else in the site (base.css,
* components.css, home.css, cms.css, public-page.css) and the /design viewer
* read from here. Change a value in this file and both the live site and the
* design system move together.
*
* Three tiers, in order:
* 1. Primitives --jw-<hue>-<step> raw palette, identical in every theme
* 2. Semantic --jw-bg, --jw-text-*, --jw-accent... theme-dependent roles
* 3. Component --jw-button-*, --jw-field-*... what components actually use
*
* Components must consume tier 3 (or tier 2), never tier 1 directly, so a
* theme swap reaches every surface.
*
* THEMING: light is the default; dark is declared twice on purpose, once for
* `prefers-color-scheme: dark` (system setting, works with JS disabled) and
* once for `[data-theme="dark"]` (explicit toggle). The two blocks must stay
* in sync — `npm run check` fails the build if they drift apart.
*/
/* ---------------------------------------------------------------------------
* 1. PRIMITIVES — the raw brand palette. Theme-independent.
* ------------------------------------------------------------------------ */
:root {
/* Mint — the primary brand hue. */
--jw-mint-50: #e8faf6;
--jw-mint-300: #55d6bd;
--jw-mint-400: #20c5a8;
--jw-mint-500: #12a98e;
--jw-mint-600: #08806b;
/* Sun — warmth, highlights, the "create" energy. */
--jw-sun-50: #fff8e3;
--jw-sun-300: #ffd463;
--jw-sun-400: #ffcc4d;
--jw-sun-600: #cd8f08;
/* Coral — alerts, destructive states, accent contrast. */
--jw-coral-50: #ffecec;
--jw-coral-300: #ff8585;
--jw-coral-500: #ed3c3c;
/* Blue — links, information, the Nostr/identity surfaces. */
--jw-blue-50: #eaf0ff;
--jw-blue-100: #cfdcff;
--jw-blue-300: #6f95ff;
--jw-blue-400: #2764ff;
/* Canonical white and black. Every white or black surface, fill, and piece
of text in the system resolves to one of these two — never to #fff or
#000 — so the whole site moves if they change. */
--jw-white: #fafafa;
--jw-black: #0a0a0a;
/* Neutral ramp between them. */
--jw-neutral-0: var(--jw-white);
--jw-neutral-100: #f2f4f3;
--jw-neutral-1000: var(--jw-black);
/* Ember — the accent. A vermilion red one step from Bitcoin orange:
provenance without impersonating the coin itself. */
--jw-ember-100: #ffe1d6;
--jw-ember-200: #ffb49a;
--jw-ember-300: #ff7a52;
--jw-ember-400: #f4511e;
--jw-ember-600: #b0300a;
/* Bitcoin orange. Payment rails only — never decorative. */
--jw-bitcoin: #f7931a;
}
/* ---------------------------------------------------------------------------
* 2. SEMANTIC — light theme (the default).
* ------------------------------------------------------------------------ */
:root {
color-scheme: light;
/* Ground and surfaces, back to front. */
--jw-bg: var(--jw-white);
--jw-bg-gradient: linear-gradient(180deg, var(--jw-white) 0%, #f4f5f4 46%, #eef0ef 78%, #e9ebea 100%);
--jw-surface: var(--jw-white);
--jw-surface-raised: var(--jw-white);
--jw-surface-sunken: var(--jw-neutral-100);
--jw-surface-veil: rgba(250, 250, 250, 0.78);
--jw-surface-glass: rgba(250, 250, 250, 0.86);
--jw-scrim: rgba(10, 10, 10, 0.42);
/* Text, strongest to faintest. */
--jw-text-primary: var(--jw-black);
--jw-text-strong: #1f2422;
--jw-text-body: #454545;
--jw-text-muted: #737373;
--jw-text-subtle: #8f9995;
--jw-text-inverse: var(--jw-white);
--jw-text-on-accent: var(--jw-black);
/* Lines and dividers. */
--jw-line: rgba(10, 10, 10, 0.1);
--jw-line-strong: rgba(10, 10, 10, 0.2);
--jw-line-faint: rgba(10, 10, 10, 0.06);
/* Accents. `accent` is the one the eye should follow. */
--jw-accent: var(--jw-ember-400);
--jw-accent-strong: var(--jw-ember-600);
--jw-accent-soft: var(--jw-ember-100);
--jw-accent-contrast: var(--jw-white);
--jw-accent-ring: rgba(244, 81, 30, 0.22);
--jw-highlight: var(--jw-sun-400);
--jw-highlight-soft: var(--jw-sun-50);
--jw-info: var(--jw-blue-400);
--jw-info-soft: var(--jw-blue-50);
/* Status. */
--jw-success: var(--jw-mint-600);
--jw-success-soft: var(--jw-mint-50);
--jw-warning: var(--jw-sun-600);
--jw-warning-soft: var(--jw-sun-50);
--jw-danger: var(--jw-coral-500);
--jw-danger-soft: var(--jw-coral-50);
/* Shadows carry the light theme's depth. */
--jw-shadow-color: rgba(0, 0, 0, 0.12);
--jw-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.06);
--jw-shadow-sm: 0 8px 22px rgba(0, 0, 0, 0.045);
--jw-shadow-md: 0 14px 34px rgba(0, 0, 0, 0.055);
--jw-shadow-lg: 0 18px 54px rgba(0, 0, 0, 0.08);
--jw-shadow-xl: 0 28px 80px rgba(0, 0, 0, 0.16);
--jw-shadow-accent: 0 14px 34px rgba(244, 81, 30, 0.16);
/* Ambient shadow behind the hero device: enough depth to lift a dark
object off either ground without reading as a glow. */
--jw-device-shadow:
0 4px 10px rgba(0, 0, 0, 0.18),
0 30px 60px rgba(0, 0, 0, 0.26);
/* The brand mark's conic sweep, so the logo follows the theme. */
--jw-mark-sweep: conic-gradient(from 200deg, #ffcc4d, #ff5d5d, #2764ff, #20c5a8, #ffcc4d);
--jw-mark-inset: var(--jw-white);
}
/* ---------------------------------------------------------------------------
* 2b. SEMANTIC — dark theme, applied by system preference.
*
* Keep every declaration below identical to the [data-theme="dark"] block.
* ------------------------------------------------------------------------ */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
color-scheme: dark;
--jw-bg: var(--jw-black);
--jw-bg-gradient: linear-gradient(180deg, var(--jw-black), var(--jw-black));
--jw-surface: rgba(255, 255, 255, 0.04);
--jw-surface-raised: rgba(255, 255, 255, 0.07);
--jw-surface-sunken: rgba(0, 0, 0, 0.28);
--jw-surface-veil: rgba(18, 18, 18, 0.72);
--jw-surface-glass: rgba(10, 10, 10, 0.82);
--jw-scrim: rgba(0, 0, 0, 0.66);
--jw-text-primary: var(--jw-white);
--jw-text-strong: rgba(250, 250, 250, 0.92);
--jw-text-body: rgba(250, 250, 250, 0.72);
--jw-text-muted: rgba(250, 250, 250, 0.56);
--jw-text-subtle: rgba(250, 250, 250, 0.44);
--jw-text-inverse: var(--jw-black);
--jw-text-on-accent: #052e27;
--jw-line: rgba(255, 255, 255, 0.12);
--jw-line-strong: rgba(255, 255, 255, 0.24);
--jw-line-faint: rgba(255, 255, 255, 0.07);
--jw-accent: var(--jw-ember-300);
--jw-accent-strong: var(--jw-ember-200);
--jw-accent-soft: rgba(244, 81, 30, 0.16);
--jw-accent-contrast: var(--jw-black);
--jw-accent-ring: rgba(255, 122, 82, 0.28);
--jw-highlight: var(--jw-sun-300);
--jw-highlight-soft: rgba(255, 204, 77, 0.14);
--jw-info: var(--jw-blue-300);
--jw-info-soft: rgba(39, 100, 255, 0.16);
--jw-success: var(--jw-mint-300);
--jw-success-soft: rgba(32, 197, 168, 0.14);
--jw-warning: var(--jw-sun-300);
--jw-warning-soft: rgba(255, 204, 77, 0.14);
--jw-danger: var(--jw-coral-300);
--jw-danger-soft: rgba(255, 93, 93, 0.16);
--jw-shadow-color: rgba(0, 0, 0, 0.6);
--jw-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
--jw-shadow-sm: 0 8px 22px rgba(0, 0, 0, 0.34);
--jw-shadow-md: 0 14px 34px rgba(0, 0, 0, 0.42);
--jw-shadow-lg: 0 18px 54px rgba(0, 0, 0, 0.5);
--jw-shadow-xl: 0 28px 80px rgba(0, 0, 0, 0.62);
--jw-shadow-accent: 0 14px 34px rgba(244, 81, 30, 0.22);
--jw-topbar-scrolled-bg: linear-gradient(180deg, rgba(10, 10, 10, 0.6), rgba(10, 10, 10, 0.3));
--jw-topbar-scrolled-border: rgba(255, 255, 255, 0.06);
--jw-topbar-scrolled-shadow: none;
--jw-button-primary-fill: var(--jw-white);
--jw-button-primary-text: var(--jw-black);
--jw-button-primary-fill-hover: #ececec;
--jw-button-secondary-fill: var(--jw-black);
--jw-button-secondary-fill-hover: #171717;
--jw-app-icon-bg: rgba(10, 10, 10, 0.72);
--jw-app-icon-rim-bright: rgba(255, 255, 255, 0.85);
--jw-app-icon-rim-fade: rgba(10, 10, 10, 0.04);
--jw-modal-bg: rgba(17, 17, 17, 0.78);
--jw-portal-depth: drop-shadow(0 0 5px rgba(250, 250, 250, 0.22));
--jw-device-shadow:
0 0 0 1px rgba(255, 255, 255, 0.07),
0 6px 14px rgba(0, 0, 0, 0.5),
0 34px 70px rgba(0, 0, 0, 0.6);
--jw-mark-sweep: conic-gradient(from 200deg, #ffd463, #ff8585, #6f95ff, #55d6bd, #ffd463);
--jw-mark-inset: var(--jw-black);
}
}
/* ---------------------------------------------------------------------------
* 2c. SEMANTIC — dark theme, applied by explicit toggle.
*
* Keep every declaration below identical to the prefers-color-scheme block.
* ------------------------------------------------------------------------ */
:root[data-theme="dark"] {
color-scheme: dark;
--jw-bg: var(--jw-black);
--jw-bg-gradient: linear-gradient(180deg, var(--jw-black), var(--jw-black));
--jw-surface: rgba(255, 255, 255, 0.04);
--jw-surface-raised: rgba(255, 255, 255, 0.07);
--jw-surface-sunken: rgba(0, 0, 0, 0.28);
--jw-surface-veil: rgba(18, 18, 18, 0.72);
--jw-surface-glass: rgba(10, 10, 10, 0.82);
--jw-scrim: rgba(0, 0, 0, 0.66);
--jw-text-primary: var(--jw-white);
--jw-text-strong: rgba(250, 250, 250, 0.92);
--jw-text-body: rgba(250, 250, 250, 0.72);
--jw-text-muted: rgba(250, 250, 250, 0.56);
--jw-text-subtle: rgba(250, 250, 250, 0.44);
--jw-text-inverse: var(--jw-black);
--jw-text-on-accent: #052e27;
--jw-line: rgba(255, 255, 255, 0.12);
--jw-line-strong: rgba(255, 255, 255, 0.24);
--jw-line-faint: rgba(255, 255, 255, 0.07);
--jw-accent: var(--jw-ember-300);
--jw-accent-strong: var(--jw-ember-200);
--jw-accent-soft: rgba(244, 81, 30, 0.16);
--jw-accent-contrast: var(--jw-black);
--jw-accent-ring: rgba(255, 122, 82, 0.28);
--jw-highlight: var(--jw-sun-300);
--jw-highlight-soft: rgba(255, 204, 77, 0.14);
--jw-info: var(--jw-blue-300);
--jw-info-soft: rgba(39, 100, 255, 0.16);
--jw-success: var(--jw-mint-300);
--jw-success-soft: rgba(32, 197, 168, 0.14);
--jw-warning: var(--jw-sun-300);
--jw-warning-soft: rgba(255, 204, 77, 0.14);
--jw-danger: var(--jw-coral-300);
--jw-danger-soft: rgba(255, 93, 93, 0.16);
--jw-shadow-color: rgba(0, 0, 0, 0.6);
--jw-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.4);
--jw-shadow-sm: 0 8px 22px rgba(0, 0, 0, 0.34);
--jw-shadow-md: 0 14px 34px rgba(0, 0, 0, 0.42);
--jw-shadow-lg: 0 18px 54px rgba(0, 0, 0, 0.5);
--jw-shadow-xl: 0 28px 80px rgba(0, 0, 0, 0.62);
--jw-shadow-accent: 0 14px 34px rgba(244, 81, 30, 0.22);
--jw-topbar-scrolled-bg: linear-gradient(180deg, rgba(10, 10, 10, 0.6), rgba(10, 10, 10, 0.3));
--jw-topbar-scrolled-border: rgba(255, 255, 255, 0.06);
--jw-topbar-scrolled-shadow: none;
--jw-button-primary-fill: var(--jw-white);
--jw-button-primary-text: var(--jw-black);
--jw-button-primary-fill-hover: #ececec;
--jw-button-secondary-fill: var(--jw-black);
--jw-button-secondary-fill-hover: #171717;
--jw-app-icon-bg: rgba(10, 10, 10, 0.72);
--jw-app-icon-rim-bright: rgba(255, 255, 255, 0.85);
--jw-app-icon-rim-fade: rgba(10, 10, 10, 0.04);
--jw-modal-bg: rgba(17, 17, 17, 0.78);
--jw-portal-depth: drop-shadow(0 0 5px rgba(250, 250, 250, 0.22));
--jw-device-shadow:
0 0 0 1px rgba(255, 255, 255, 0.07),
0 6px 14px rgba(0, 0, 0, 0.5),
0 34px 70px rgba(0, 0, 0, 0.6);
--jw-mark-sweep: conic-gradient(from 200deg, #ffd463, #ff8585, #6f95ff, #55d6bd, #ffd463);
--jw-mark-inset: var(--jw-black);
}
/* ---------------------------------------------------------------------------
* 3. TYPE, SPACE, SHAPE, MOTION — theme-independent.
* ------------------------------------------------------------------------ */
:root {
/* Geist carries the headings; Inter carries everything else. Swap this one
token to change every heading on the site and in /design. */
--jw-font-display: "Syne Variable", "Geist Variable", Inter, ui-sans-serif, system-ui, sans-serif;
--jw-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--jw-font-mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
/* Static steps for UI. */
--jw-text-2xs: 0.72rem;
--jw-text-xs: 0.78rem;
--jw-text-sm: 0.88rem;
--jw-text-base: 1rem;
--jw-text-lg: 1.125rem;
--jw-text-xl: 1.25rem;
--jw-text-2xl: 1.5rem;
--jw-text-3xl: 1.875rem;
/* Fluid steps for editorial headlines. The vw term dominates from phone to
desktop so poster type scales with the viewport rather than stepping. */
--jw-text-title: clamp(1.7rem, 3vw, 2.6rem);
--jw-text-headline: clamp(2.1rem, 4.6vw, 3.6rem);
--jw-text-display: clamp(2.45rem, 6.5vw, 5rem);
/* Syne hangs deep descenders; 0.96 clipped them. */
--jw-leading-tight: 1.06;
--jw-leading-snug: 1.12;
--jw-leading-normal: 1.45;
--jw-leading-relaxed: 1.6;
--jw-weight-normal: 450;
--jw-weight-medium: 560;
--jw-weight-semibold: 700;
--jw-weight-bold: 820;
--jw-weight-black: 900;
--jw-tracking-eyebrow: 0.09em;
--jw-tracking-tight: -0.01em;
/* Space scale — 4px base. */
--jw-space-1: 4px;
--jw-space-2: 8px;
--jw-space-3: 12px;
--jw-space-4: 16px;
--jw-space-5: 20px;
--jw-space-6: 24px;
--jw-space-8: 32px;
--jw-space-10: 40px;
--jw-space-12: 48px;
--jw-space-16: 64px;
--jw-space-20: 80px;
--jw-space-24: 96px;
--jw-section-gap: clamp(64px, 9vw, 128px);
--jw-radius-xs: 4px;
--jw-radius-sm: 6px;
--jw-radius-md: 8px;
--jw-radius-lg: 14px;
--jw-radius-xl: 22px;
--jw-radius-pill: 999px;
/* Fixed at 1220px through laptop widths, then grows with the window to a
1560px ceiling so large displays do not strand the content in gutters.
The outer min() keeps the side gutter on small screens. */
--jw-container: min(calc(100% - 32px), clamp(1220px, 82vw, 1560px));
--jw-container-narrow: min(calc(100% - 32px), 880px);
--jw-hitbox-min: 42px;
/* Motion. GSAP reads the durations/eases through motion.js so CSS
transitions and scripted tweens stay on the same curve. */
--jw-duration-fast: 120ms;
--jw-duration-base: 180ms;
--jw-duration-slow: 340ms;
--jw-duration-slower: 620ms;
--jw-ease-out: cubic-bezier(0.22, 1, 0.36, 1);
--jw-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--jw-ease-spring: cubic-bezier(0.2, 0.8, 0.2, 1);
--jw-z-base: 1;
--jw-z-sticky: 10;
--jw-z-overlay: 60;
--jw-z-modal: 70;
--jw-z-toast: 80;
}
/* ---------------------------------------------------------------------------
* 4. COMPONENT TOKENS
*
* What components.css actually reads. Every value resolves to a semantic
* token, so these follow the theme automatically and can be retargeted
* (e.g. point --jw-button-primary-bg at --jw-info) without touching CSS
* rules. This is the layer to tweak when a component needs to change.
* ------------------------------------------------------------------------ */
:root {
/* Buttons.
There are two: primary and secondary. Both are rimmed rather than
filled — a two-colour gradient painted onto the border only, with the
middle left transparent so whatever is behind shows through. Hierarchy
comes from which two colours the rim uses, not from a fill. */
--jw-button-height: var(--jw-hitbox-min);
--jw-button-radius: var(--jw-radius-md);
--jw-button-padding: 0 var(--jw-space-6);
--jw-button-weight: var(--jw-weight-bold);
/* Matched to the ring/app-icon rim the menu button wears. */
--jw-button-rim-width: 1px;
/* The rim is bright at the two diagonal corners and drops out entirely
across the middle, so the page shows through the gap. Same very light
grey in both themes. */
--jw-button-rim-bright: #e6e6e6;
--jw-button-rim-gap-start: 27%;
--jw-button-rim-gap-end: 73%;
/* Primary inverts the page: black on light, white on dark. */
--jw-button-primary-fill: var(--jw-black);
--jw-button-primary-text: var(--jw-white);
--jw-button-primary-fill-hover: #1c1c1c;
--jw-button-secondary-fill: var(--jw-white);
--jw-button-secondary-text: var(--jw-text-body);
--jw-button-secondary-fill-hover: var(--jw-neutral-100);
/* Ghost — a quiet inline action: no rim, no fill until hovered. */
--jw-button-ghost-text: var(--jw-text-muted);
--jw-button-ghost-text-hover: var(--jw-text-primary);
--jw-button-ghost-fill-hover: var(--jw-surface-veil);
/* Fields. */
--jw-field-height: 50px;
--jw-field-radius: var(--jw-radius-md);
--jw-field-bg: var(--jw-surface);
--jw-field-text: var(--jw-text-primary);
--jw-field-placeholder: var(--jw-text-subtle);
--jw-field-border: var(--jw-line);
--jw-field-border-focus: var(--jw-info);
--jw-field-ring: 0 0 0 4px var(--jw-accent-ring);
--jw-field-shadow: var(--jw-shadow-sm);
--jw-field-label: var(--jw-text-body);
--jw-field-sheen: var(--jw-line);
/* Cards and panels. */
--jw-card-bg: var(--jw-surface);
--jw-card-border: var(--jw-line);
--jw-card-radius: var(--jw-radius-md);
--jw-card-shadow: var(--jw-shadow-lg);
--jw-card-padding: var(--jw-space-5);
--jw-modal-padding: clamp(20px, 3vw, 30px);
/* Dialog glass: translucent over the scrim's blur, opaque enough to read. */
--jw-modal-bg: rgba(252, 252, 252, 0.94);
/* Depth under the brand mark: a soft contact shadow on light. */
--jw-portal-depth: drop-shadow(0 1px 1.5px rgba(10, 10, 10, 0.28));
/* Chips. */
--jw-chip-bg: var(--jw-surface-veil);
--jw-chip-text: var(--jw-text-strong);
--jw-chip-border: var(--jw-line);
--jw-chip-dot: var(--jw-accent);
/* Navigation chrome. */
--jw-topbar-height: 64px;
--jw-topbar-bg: var(--jw-surface-glass);
--jw-topbar-border: var(--jw-line);
/* Applied only once the page has scrolled past --jw-topbar-scroll-start. */
--jw-topbar-scrolled-bg: linear-gradient(180deg, rgba(250, 250, 250, 0.6), rgba(250, 250, 250, 0.3));
--jw-topbar-scrolled-border: rgba(10, 10, 10, 0.06);
--jw-topbar-scrolled-shadow: none;
--jw-topbar-blur: 8px;
/* Brand mark. */
--jw-mark-size: 30px;
--jw-mark-radius: var(--jw-radius-md);
--jw-mark-ring: 6px;
}
/* ---------------------------------------------------------------------------
* 5. LEGACY BRIDGE
*
* base.css, cms.css and public-page.css were written against these short
* names before the token layer existed. Mapping them here means the existing
* site inherits theming for free, and new work should reach for --jw-* names.
* ------------------------------------------------------------------------ */
:root {
--ink: var(--jw-text-primary);
--paper: var(--jw-bg);
--card: var(--jw-surface);
--muted: var(--jw-text-muted);
--line: var(--jw-line);
--mint: var(--jw-accent);
--green: var(--jw-accent-strong);
--sun: var(--jw-highlight);
--coral: var(--jw-danger);
--blue: var(--jw-info);
--shadow: var(--jw-shadow-color);
--soft-shadow: var(--jw-shadow-lg);
--radius: var(--jw-radius-md);
}
/* ---------------------------------------------------------------------------
* 6. APP ICON
*
* The mark in its container. Light theme: light ground, dark rim. Dark theme
* overrides these to the inverse in the theme blocks above.
* ------------------------------------------------------------------------ */
:root {
--jw-app-icon-size: 38px;
/* Roughly the iOS squircle ratio. */
--jw-app-icon-radius: 24%;
--jw-app-icon-bg: rgba(250, 250, 250, 0.72);
--jw-app-icon-blur: 10px;
--jw-app-icon-rim-width: 1px;
--jw-app-icon-rim-bright: rgba(10, 10, 10, 0.6);
--jw-app-icon-rim-fade: rgba(10, 10, 10, 0.04);
/* Circular icon actions (dialog close, help). */
--jw-ring-button-size: 44px;
}
/* ---------------------------------------------------------------------------
* 7. SELF-HOSTED FONTS
*
* The same files justworks.cash serves, so every surface here — dashboard,
* module pages, and the locally generated merchant site — renders the real
* Syne headings and Geist body instead of falling back to system fonts.
* Paths are relative to this stylesheet, so they work under any base path.
* ------------------------------------------------------------------------ */
@font-face {
font-family: "Syne Variable";
src: url("../fonts/syne-latin-wght-normal.woff2") format("woff2-variations");
font-weight: 400 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "Geist Variable";
src: url("../fonts/geist-latin-wght-normal.woff2") format("woff2-variations");
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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
font-family: "Geist Variable";
src: url("../fonts/geist-latin-ext-wght-normal.woff2") format("woff2-variations");
font-weight: 100 900;
font-style: normal;
font-display: swap;
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7, U+02CC, U+02CE-02D7, U+02DD, U+02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}