/* ───────────────────────────────────────────────────────────────────────── * design-systems/meta/tokens.css * * Structured token bindings for "Design System Inspired by Meta (Store)". * Photography-first retail: pure white canvas, Optimistic VF typography, * Meta Blue (#0064E0) reserved for action, generous gallery whitespace, * pill-shaped CTAs, dual-shadow elevation. * * Brand-specific schema decisions (each one bends a schema convention to * match Meta's voice rather than the cross-brand default): * * 1. `--bg` is pure white (#FFFFFF), `--surface` is Warm Gray * (#F7F8FA — Dolly's --flat-card-bg), and `--surface-warm` is * independently bound to Linen (#F2F0E6) — the "warm off-white for * lifestyle-adjacent sections" called out in DESIGN.md §2. Three * genuinely different surface tiers ladder up: white for browsing, * warm gray for card differentiation, linen for the lifestyle / * Ray-Ban-adjacent moments. Aliasing `--surface-warm` to surface * would collapse a meaningful brand tier. * * 2. The foreground ramp binds four distinct tiers — Dark Charcoal * (#1C2B33) → Slate Gray (#5D6C7B) → Secondary Text (#65676B) → * CTA Disabled Text (#8595A4). DESIGN.md §2 names each one as a * shipped Dolly/FDS token with its own role (heading vs body vs * caption vs muted/disabled), so `--fg-2` and `--meta` are bound * independently rather than aliased to `--fg` / `--muted`. * * 3. `--accent` is Meta Blue (#0064E0), NOT Facebook Blue (#1877F2). * DESIGN.md §7 ("Don'ts") explicitly forbids Facebook Blue as a * primary CTA color — the corporate Meta Store layer overlays a * slightly deeper, more saturated blue on the FDS gray ramp. * `--accent-hover` and `--accent-active` are bound to the exact * Meta Blue Hover (#0143B5) and Pressed (#004BB9) hexes from * DESIGN.md §2 rather than computed via `color-mix()`, because * the Dolly hover/pressed pair is hand-tuned to land on different * hue points than a flat luminance darken. * * 4. Semantic colors bind to the Dolly-store palette: Success Green * (#31A24C), Warning Amber (#F7B928), Error Red (#E41E3F) — the * "badge" tier from DESIGN.md §2. Darker store-confirmation * variants (#007D1E, #C80A28) live in components, not the schema, * because they are state overrides on top of the shared semantic * slot rather than the slot itself. * * 5. `--font-display` and `--font-body` share the Optimistic VF * stack with the documented fallbacks (Montserrat, Helvetica, * Arial, Noto Sans). Inter is added as a humanist sans bridge for * hosts that have neither Optimistic nor Montserrat installed — * it matches Optimistic's geometric warmth more closely than the * Helvetica/Arial fallbacks alone. The variable font keeps weight * 300/400/500/700 all available; component CSS picks the weight, * not the face. * * 6. The type scale tracks DESIGN.md §3 verbatim: 12 / 14 / 16 / 18 * / 28 / 36 / 48 / 64. The 18px tier (`--text-lg`) is Meta's * primary body size — Body and Heading 3 BOTH live there per * DESIGN.md §3 — while `--text-base` (16px) is Body Compact * reserved for navigation and dense UI. Display tracking stays * neutral (`-0.01em`) because DESIGN.md §3 specifies negative * letter-spacing only at small sizes (`-0.14px` to `-0.16px` on * 14–16px UI text), not on display headlines. * * 7. Section rhythm is gallery-generous: 80 / 64 / 48 px desktop / * tablet / phone, mirroring the responsive padding ladder * DESIGN.md §8 prescribes ("Section padding: 80 → 64 → 48 → 32"). * The 32px floor folds into component-level overrides on the * smallest viewports rather than into the shared schema. * * 8. Radius scale: 8 / 20 / 24 / 100. DESIGN.md §5 explicitly * enumerates these four tiers — 8px inputs, 20px standard cards * (--card-corner-radius), 24px feature cards & ghost buttons, * 100px pill — and `--radius-pill` is bound to literal `100px` * (not the schema's 9999px sentinel) because the brand's pill * radius IS 100px and that value flows into actual padding / * stroke calculations on Meta-Blue CTAs. * * 9. `--elev-raised` reproduces DESIGN.md §6 Level 2 dual-shadow * pattern verbatim: a small sharp shadow (0 2px 4px rgba(0,0,0, * 0.1)) for direct-light contact + a large diffused shadow * (0 12px 28px rgba(0,0,0,0.2)) for ambient-light depth. * Reordering or dropping a layer breaks Meta's "physically * plausible depth" feel — the brand specifically uses two * shadows together, not one blurred soft shadow. * * 10. Container caps at 1440px per DESIGN.md §5 ("Max container * width: ~1440px"), wider than Vercel's 1200 because the store * surfaces full-bleed cinematic product photography that needs * the room. Gutters step 40 / 24 / 16 to preserve generous * breathing room around hero imagery on every breakpoint. * * Source contracts: * - Standard token names: design-systems/_schema/tokens.schema.ts * - A2 fallback parity: design-systems/_schema/defaults.css * - Lint enforcement: apps/daemon/src/lint-artifact.ts * * Optimistic VF is not embedded; the stack falls back through * Montserrat → Helvetica → Arial → Noto Sans so artifacts render * acceptably on hosts that haven't loaded the commissioned face. * ─────────────────────────────────────────────────────────────────── */ :root { /* ─── Surface (3 levels — schema slot) ───────────────────────────── * Binary plus a warm tier: pure white for browsing/information, * Warm Gray for flat card differentiation, Linen as the lifestyle- * adjacent warm off-white. DESIGN.md §1 calls out the binary * white/dark cadence; Linen lives between for Ray-Ban-flavored * sections where pure white feels too cold. Dark immersive * surfaces (#1C1E21 / #181A1B / #000000) are component-level * overrides, not surface tokens — they're product-context, not * canvas. */ --bg: #ffffff; /* White — primary canvas, nav, default cards */ --surface: #f7f8fa; /* Warm Gray — flat card, subtle differentiation */ --surface-warm: #f2f0e6; /* Linen — lifestyle-adjacent warm off-white */ /* ─── Foreground ramp (4 levels) ────────────────────────────────── * Dark Charcoal heading → Slate Gray body → Secondary Text caption * → CTA Disabled muted blue-gray. DESIGN.md §2 names each tier as * a shipped Dolly/FDS token with its own role, so the four-level * ramp resolves to four distinct values rather than aliasing. */ --fg: #1c2b33; /* Dark Charcoal — Dolly primary text, headings */ --fg-2: #5d6c7b; /* Slate Gray — Meta Store secondary text, body */ --muted: #65676b; /* Secondary Text — captions, labels, timestamps */ --meta: #8595a4; /* CTA Disabled — placeholder, muted blue-gray */ /* ─── Border (2 levels) ────────────────────────────────────────── * Standard divider for input/card edges, lighter inner divider for * Dolly section separators that should not visually compete. */ --border: #ced0d4; /* Divider — content separators, input borders */ --border-soft: #dee3e9; /* Divider Gray — lighter Dolly inner separator */ /* ─── Accent ───────────────────────────────────────────────────── * Meta Blue is the single action color. DESIGN.md §7 forbids * Facebook Blue (#1877F2) for primary CTAs — Meta Blue (#0064E0) * is the deeper, more saturated corporate-store variant. Hover * and active states are hand-tuned hexes from DESIGN.md §2, not * `color-mix()` derivations, because Dolly's interactive states * shift hue, not just luminance. */ --accent: #0064e0; /* Meta Blue — primary CTA, links, focus */ --accent-on: #ffffff; /* white label on Meta Blue */ --accent-hover: #0143b5; /* Meta Blue Hover — hand-tuned, not a darken */ --accent-active: #004bb9; /* Meta Blue Pressed — deepest interactive state */ /* ─── Semantic ─────────────────────────────────────────────────── * Dolly badge tier — bright enough to read on white surfaces. * Darker store-confirmation variants (#007D1E success, #C80A28 * error) are component-level state overrides, not slot bindings. */ --success: #31a24c; /* Success Green — badge, positive indicators */ --warn: #f7b928; /* Warning Amber — attention, caution badges */ --danger: #e41e3f; /* Error Red — critical badges, notifications */ /* ─── Typography ───────────────────────────────────────────────── * Optimistic VF is Meta's commissioned variable face; the documented * fallbacks (Montserrat → Helvetica → Arial → Noto Sans) ensure * artifacts read consistently on hosts without the licensed font. * Inter bridges between Optimistic and Helvetica when neither the * commissioned face nor Montserrat is loaded — it's the closest * humanist geometric sans available system-wide. Display and body * share one stack; weight (300/400/500/700) and size carry hierarchy. */ --font-display: "Optimistic VF", "Optimistic", Inter, Montserrat, Helvetica, Arial, "Noto Sans", sans-serif; --font-body: "Optimistic VF", "Optimistic", Inter, Montserrat, Helvetica, Arial, "Noto Sans", sans-serif; --font-mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Monaco, Consolas, monospace; /* Type scale — DESIGN.md §3 verbatim. The 18px tier (text-lg) is * Meta's primary body size (Body AND Heading 3 both live at 18/?); * 16px (text-base) is Body Compact for navigation and dense UI. * Display 1 lands at 64px on desktop; Display 2 at 48px; Heading 1 * at 36px; Heading 2 at 28px. */ --text-xs: 12px; /* Small — footer, legal, timestamps */ --text-sm: 14px; /* Caption — labels, button text, metadata */ --text-base: 16px; /* Body Compact — navigation, dense UI */ --text-lg: 18px; /* Body / Heading 3 — primary reading size */ --text-xl: 28px; /* Heading 2 — light-weight subheading */ --text-2xl: 36px; /* Heading 1 — major section heading */ --text-3xl: 48px; /* Display 2 — section heroes, product titles */ --text-4xl: 64px; /* Display 1 — hero headlines on desktop */ /* Body leading 1.5 (16px Body Compact ratio); tight leading 1.16 * (Display 1 ratio) for hero headlines. Display tracking stays * neutral (-0.01em) — DESIGN.md §3 reserves negative tracking for * small UI (-0.14px on Caption / Button), not for headlines. */ --leading-body: 1.5; --leading-tight: 1.16; --tracking-display: -0.01em; /* ─── Spacing ──────────────────────────────────────────────────── * 8px-base scale per DESIGN.md §5 ("Base unit: 8px"). The 1px / * 10px / 14px / 18px sub-tiers from DESIGN.md (hairlines, card * horizontal padding, caption rhythm, body vertical rhythm) are * inlined per-component because they are too fine to belong in * the shared schema. */ --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-5: 20px; --space-6: 24px; --space-8: 32px; --space-12: 48px; /* Section rhythm — DESIGN.md §8: "Section padding: 80 → 64 → 48 * → 32 as viewport narrows". We bind the documented desktop / * tablet / phone tiers; the 32px ultra-narrow floor falls into * component-level @media overrides, not the schema. */ --section-y-desktop: 80px; --section-y-tablet: 64px; --section-y-phone: 48px; /* ─── Radius ───────────────────────────────────────────────────── * DESIGN.md §5 enumerates 8 / 20 / 24 / 100 px. Pill is literal * 100px (not 9999px sentinel) because Meta's pill radius IS 100px * — DESIGN.md §4 buttons specify "Border radius: fully rounded * pill (100px)". For most components 100px and 9999px render * identically, but 100px flows correctly into outline / focus * geometry calculations in product. */ --radius-sm: 8px; /* Inputs, small UI, glimmer placeholders */ --radius-md: 20px; /* --card-corner-radius — standard cards */ --radius-lg: 24px; /* Feature cards, ghost buttons */ --radius-pill: 100px; /* Pill buttons, tags, badges (DESIGN.md §5) */ /* ─── Elevation ────────────────────────────────────────────────── * Three sanctioned levels. `--elev-raised` is DESIGN.md §6 Level 2 * dual-shadow pattern reproduced verbatim: small sharp shadow for * direct-light contact + large diffused shadow for ambient-light * depth. Together they create "physically plausible depth without * heavy visual weight" — never collapse to a single soft blur. * Most surface differentiation in Meta comes from background * color shifts (white → soft gray → dark), not shadow; cards in * dark sections SHOULD use --elev-flat per DESIGN.md §7 ("Don'ts"). */ --elev-flat: none; --elev-ring: 0 0 0 1px var(--border); --elev-raised: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1); /* ─── Focus ring ───────────────────────────────────────────────── * DESIGN.md §4 inputs: "Focus: border color shifts to accent blue, * 3px outer ring". DESIGN.md §4 buttons: "Focus: 3px ring in accent * color". The schema-default 3px alpha glow at the accent matches * Meta's documented behavior; the inner-element border-color shift * is component-level. */ --focus-ring: 0 0 0 3px color-mix(in oklab, var(--accent), transparent 70%); /* ─── Motion ───────────────────────────────────────────────────── * DESIGN.md §4 buttons: "Transition: background 200ms ease, * transform 150ms ease". Two durations, one easing curve. The * scale(1.1) hover and scale(0.9) press transforms from DESIGN.md * are component-level animation, not schema. */ --motion-fast: 150ms; --motion-base: 200ms; --ease-standard: cubic-bezier(0.2, 0, 0, 1); /* ─── Layout ───────────────────────────────────────────────────── * DESIGN.md §5: "Max container width: ~1440px, centered with auto * margins". Wider than Vercel/Mistral because Meta surfaces full- * bleed cinematic product photography that needs the room. Gutters * step 40 / 24 / 16 — DESIGN.md §5 names "Page horizontal padding: * 24-40px depending on breakpoint" and §8 collapses to 16px on * mobile to preserve gallery-style breathing room. */ --container-max: 1440px; --container-gutter-desktop: 40px; --container-gutter-tablet: 24px; --container-gutter-phone: 16px; }