/* * Blueprint — technical drawing. * * Light-first: a near-achromatic drafting-paper field (whisper of cool at * hue 240, chroma ≤0.005 — the paper is calm gray; the BLUE lives in the ink * and the accent, never washed into the field) carrying pure-white cards, * with deep NAVY ink — the ink is navy, that is the signature. Hairline RULES are the organizing metaphor: * borders sit slightly more present than usual (ink at ~0.17 alpha) and * elevation stays minimal — surfaces separate by rule lines like a technical * drawing, not by shadow. One azure accent (hue ~232) owns primary, links, and * focus; the info status is pushed to violet (hue 285) so the two never read * as the same swatch. * * Dark mode is the iconic inversion: THE DARK MODE IS THE BLUEPRINT. A deep * drafting-blue field (low-chroma navy, hue 258 — unmistakably blue-leaning * but calm), near-white blue-tinted ink, cards stepping a full lightness step * above the field, and the azure accent turned luminous cyan with dark ink. * * Type is technical: Space Grotesk for headings (geometric, drafting-title), * Inter for body, JetBrains Mono for code. Dense/pro register — 0.9375rem * body, fixed rem sizes. Radius is a sharp 0.375rem; motion is precise * (120/220/320/450ms) with springs aliased to the standard eases. Tables get * tabular numerals — drafting tables demand aligned digits. * * Token contract matches lib-theme-caffe-florian/theme.css (Crema v1). */ /* * Fonts: consuming apps load Space Grotesk + Inter + JetBrains Mono at the top * of their entry CSS (where @import statements are allowed), via the Google * Fonts URL documented in this theme's README. Embedding the @import here — or * smuggling the URL in a comment for a build script to lift — breaks PostCSS's * ordering rules, so neither is done in this file. */ :root { --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-heading: "Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, sans-serif; --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; /* Tailwind utility families. Distinct names so a consuming app's * `@theme inline` can indirect to these (--font-heading/--font-sans collide * with Tailwind's own font-* namespace). Mirror --font-heading/--font-sans. */ --heading-family: "Space Grotesk", "Inter", -apple-system, BlinkMacSystemFont, sans-serif; --body-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; /* ── Colors ── cool drafting-paper field, pure-white cards, deep navy ink, * one azure accent. Rules do the separating; shadow stays out of it. */ --background: oklch(0.966 0.0035 240); --foreground: oklch(0.23 0.045 258); --card: oklch(1 0 0); --card-foreground: oklch(0.23 0.045 258); --popover: oklch(0.995 0.003 240); --popover-foreground: oklch(0.23 0.045 258); /* Primary — the azure of the drawing's live line (hue 232, L0.49), deep * enough to carry a near-white label at ~6:1. Spent on the primary action, * links, selection, and focus; nowhere else. */ --primary: oklch(0.49 0.13 232); --primary-foreground: oklch(0.98 0.008 232); --secondary: oklch(0.93 0.005 240); --secondary-foreground: oklch(0.29 0.04 258); --muted: oklch(0.93 0.0045 240); --muted-foreground: oklch(0.45 0.03 255); /* Accent — hover/selection tint: a pale azure wash with deep azure ink, * not a second competing fill. */ --accent: oklch(0.925 0.028 232); --accent-foreground: oklch(0.37 0.09 235); /* ── Status ── deep fills with light labels for red/violet, bright fills * with dark ink for green/amber. Info is pushed to VIOLET (hue 285) so it * can never be mistaken for the azure primary (hue 232). */ --destructive: oklch(0.54 0.21 27); --destructive-foreground: oklch(0.98 0.01 27); --success: oklch(0.52 0.13 155); --success-foreground: oklch(0.98 0.01 155); --warning: oklch(0.76 0.15 78); --warning-foreground: oklch(0.24 0.05 78); --info: oklch(0.5 0.13 285); --info-foreground: oklch(0.98 0.01 285); /* Hairline rules — the theme's organizing metaphor. Navy ink at a slightly * higher alpha than house-usual so every rule reads on the paper. */ --border: oklch(0.23 0.045 258 / 0.17); --input: oklch(0.23 0.045 258 / 0.2); --ring: oklch(0.49 0.13 232 / 0.6); /* Chart palette — azure lead, then spaced drafting-ink hues (violet, red, * amber, teal-green); hues ≥60° apart, adjacent lightness varied. */ --chart-1: oklch(0.55 0.13 235); --chart-2: oklch(0.55 0.14 300); --chart-3: oklch(0.62 0.17 25); --chart-4: oklch(0.75 0.14 85); --chart-5: oklch(0.66 0.11 165); --sidebar: oklch(0.945 0.004 240); --sidebar-foreground: oklch(0.23 0.045 258); --sidebar-primary: oklch(0.49 0.13 232); --sidebar-primary-foreground: oklch(0.98 0.008 232); --sidebar-accent: oklch(0.925 0.028 232); --sidebar-accent-foreground: oklch(0.37 0.09 235); --sidebar-border: oklch(0.23 0.045 258 / 0.13); --sidebar-ring: oklch(0.49 0.13 232 / 0.6); /* Syntax — muted-precise: navy-family base with disciplined accents. */ --syntax-keyword: oklch(0.44 0.12 285); --syntax-string: oklch(0.45 0.1 165); --syntax-number: oklch(0.48 0.11 60); --syntax-comment: oklch(0.55 0.02 250); --syntax-function: oklch(0.45 0.13 235); --syntax-type: oklch(0.45 0.09 200); /* ── Chat surfaces ── * Contract for lib-agent-chat-ui / lib-agent-dock-ui. User bubble is a * deep navy-ink panel with light text (the drawing's title block); * assistant bubble is a clean card with a hairline rule. */ --chat-user-bg: oklch(0.28 0.05 258); --chat-user-fg: oklch(0.97 0.006 240); --chat-assistant-bg: oklch(1 0 0); --chat-assistant-fg: oklch(0.23 0.045 258); --chat-assistant-border: oklch(0.23 0.045 258 / 0.17); /* Sharp drafting radius. */ --radius: 0.375rem; /* ── Motion ── precise, instrument-quick. Springs alias to the standard * eases — a drawing never bounces. */ --duration-fast: 120ms; --duration-base: 220ms; --duration-slow: 320ms; --duration-slower: 450ms; --duration-spring: 220ms; --ease-standard: cubic-bezier(0.2, 0, 0, 1); --ease-decelerate: cubic-bezier(0, 0, 0, 1); --ease-accelerate: cubic-bezier(0.3, 0, 1, 1); --ease-emphasized: cubic-bezier(0.2, 0, 0, 1); --ease-spring-gentle: var(--ease-standard); --ease-spring-snappy: var(--ease-decelerate); --ease-spring-bouncy: var(--ease-standard); /* ── Typography ── dense/pro register, fixed rem, full role ramp. */ --text-hero-size: 3rem; --text-hero-lh: 1.05; --text-display-size: 2.25rem; --text-display-lh: 1.1; --text-headline-size: 1.625rem; --text-headline-lh: 1.25; --text-title-size: 1.25rem; --text-title-lh: 1.35; --text-subtitle-size: 1.0625rem; --text-subtitle-lh: 1.45; --text-body-size: 0.9375rem; --text-body-lh: 1.5; --text-label-size: 0.8125rem; --text-label-lh: 1.125rem; --text-caption-size: 0.75rem; --text-caption-lh: 1.0625rem; /* ── Elevation ── minimal on purpose — rule lines do the separating. * Popovers and modals get just enough lift to read as floating. */ --elevation-0: none; --elevation-1: 0 1px 1px oklch(0.23 0.045 258 / 0.04); --elevation-2: 0 1px 2px oklch(0.23 0.045 258 / 0.06); --elevation-3: 0 2px 6px -1px oklch(0.23 0.045 258 / 0.08), 0 1px 2px oklch(0.23 0.045 258 / 0.05); --elevation-4: 0 8px 16px -4px oklch(0.23 0.045 258 / 0.1), 0 2px 4px -2px oklch(0.23 0.045 258 / 0.06); --elevation-5: 0 16px 32px -8px oklch(0.23 0.045 258 / 0.14); --spacing: 0.25rem; --border-width-thin: 0.5px; --border-width-base: 1px; --border-width-thick: 2px; --border-width-heavy: 4px; /* No glass — inert values so consuming apps referencing these get no-ops. */ --glass-blur: 0px; --glass-saturate: 100%; --glass-brightness: 1; --glass-contrast: 1; } /* * Dark mode — THE BLUEPRINT. Deep drafting-blue field (low-chroma navy, * hue 258 — blue-leaning but calm, never electric), near-white blue-tinted * ink, cards stepping a full lightness step above the field, and the accent * turned luminous cyan carrying dark ink. */ .dark { --background: oklch(0.21 0.035 258); --foreground: oklch(0.95 0.012 240); --card: oklch(0.26 0.035 258); --card-foreground: oklch(0.95 0.012 240); --popover: oklch(0.28 0.035 258); --popover-foreground: oklch(0.95 0.012 240); /* Primary — the luminous cyan line on the blueprint, dark navy ink on * top (bright-swatch/dark-ink pairing, ~9:1). */ --primary: oklch(0.78 0.12 220); --primary-foreground: oklch(0.2 0.04 230); --secondary: oklch(0.3 0.035 258); --secondary-foreground: oklch(0.9 0.012 240); --muted: oklch(0.3 0.035 258); --muted-foreground: oklch(0.72 0.02 245); --accent: oklch(0.34 0.06 230); --accent-foreground: oklch(0.85 0.09 215); --destructive: oklch(0.55 0.2 27); --destructive-foreground: oklch(0.98 0.01 27); --success: oklch(0.72 0.14 155); --success-foreground: oklch(0.18 0.04 155); --warning: oklch(0.78 0.15 80); --warning-foreground: oklch(0.22 0.05 80); --info: oklch(0.7 0.12 285); --info-foreground: oklch(0.17 0.04 285); /* Rules invert: light ink hairlines on the blueprint field. */ --border: oklch(0.95 0.012 240 / 0.15); --input: oklch(0.95 0.012 240 / 0.18); --ring: oklch(0.78 0.12 220 / 0.55); --chart-1: oklch(0.72 0.12 220); --chart-2: oklch(0.66 0.13 300); --chart-3: oklch(0.7 0.16 25); --chart-4: oklch(0.8 0.13 85); --chart-5: oklch(0.74 0.11 165); --sidebar: oklch(0.23 0.035 258); --sidebar-foreground: oklch(0.95 0.012 240); --sidebar-primary: oklch(0.78 0.12 220); --sidebar-primary-foreground: oklch(0.2 0.04 230); --sidebar-accent: oklch(0.34 0.06 230); --sidebar-accent-foreground: oklch(0.85 0.09 215); --sidebar-border: oklch(0.95 0.012 240 / 0.11); --sidebar-ring: oklch(0.78 0.12 220 / 0.55); --syntax-keyword: oklch(0.74 0.12 300); --syntax-string: oklch(0.76 0.11 165); --syntax-number: oklch(0.8 0.12 75); --syntax-comment: oklch(0.62 0.02 250); --syntax-function: oklch(0.76 0.11 220); --syntax-type: oklch(0.74 0.09 195); /* ── Chat surfaces (dark) ── */ --chat-user-bg: oklch(0.33 0.05 252); --chat-user-fg: oklch(0.96 0.01 240); --chat-assistant-bg: oklch(0.26 0.035 258); --chat-assistant-fg: oklch(0.95 0.012 240); --chat-assistant-border: oklch(0.95 0.012 240 / 0.15); --elevation-1: 0 1px 1px oklch(0 0 0 / 0.25); --elevation-2: 0 1px 2px oklch(0 0 0 / 0.3); --elevation-3: 0 2px 6px -1px oklch(0 0 0 / 0.35), 0 1px 2px oklch(0 0 0 / 0.2); --elevation-4: 0 8px 16px -4px oklch(0 0 0 / 0.4), 0 2px 4px -2px oklch(0 0 0 / 0.22); --elevation-5: 0 16px 32px -8px oklch(0 0 0 / 0.5); } /* * @layer base — Blueprint's precise, rule-lined drafting philosophy. * * No glass, no flourish. Geometric headings, hairline rules doing the * separating, tabular digits in tables, and the azure line reserved for * focus, selection, links, and the primary action. */ @layer base { body { min-height: 100vh; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; letter-spacing: -0.004em; font-family: var(--font-sans); font-size: var(--text-body-size); line-height: var(--text-body-lh); } /* Headings — Space Grotesk, geometric and technical. */ h1, h2, h3, h4, [data-slot="card-title"], [data-slot="dialog-title"], [data-slot="sheet-title"], [data-slot="alert-dialog-title"] { font-family: var(--font-heading); font-weight: 600; letter-spacing: -0.015em; color: var(--foreground); } code, kbd, samp, pre, [data-slot="code"], [data-slot="code-block"] { font-family: var(--font-mono); } /* Inline code — neutral ink chip, never accent-colored. */ :not(pre) > code { padding: 0.1em 0.35em; border-radius: calc(var(--radius) * 0.5); background: color-mix(in oklch, var(--foreground) 7%, transparent); color: var(--foreground); font-size: 0.9em; } /* Selection — the azure line. */ ::selection { background: color-mix(in oklch, var(--primary) 28%, transparent); color: var(--foreground); } /* Links — azure, underline-on-hover. */ a { color: color-mix(in oklch, var(--primary) 75%, var(--foreground)); text-decoration-color: color-mix(in oklch, var(--primary) 40%, transparent); text-underline-offset: 0.2em; transition: text-decoration-color var(--duration-fast) var(--ease-standard); } a:hover { text-decoration-color: var(--primary); } [data-slot="sidebar"] { background: var(--sidebar); border-right: var(--border-width-base) solid var(--sidebar-border); } /* Drafting tables demand aligned digits — tabular numerals on every * table, and a .num utility for any numeric cell/stat elsewhere. */ [data-slot="table"], .num { font-variant-numeric: tabular-nums; } } /* * Focus-visible — keyboard-first is a Blueprint signature. A crisp, * always-visible azure outline, offset (not inset). Placed outside * @layer base so it beats Tailwind's default ring utilities. */ [data-slot="button"]:focus-visible, [data-slot="input"]:focus-visible, [data-slot="textarea"]:focus-visible, [data-slot="select-trigger"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; box-shadow: none; } /* Buttons — quiet weight; opacity absorb on press, instrument-quick. */ [data-slot="button"] { font-weight: 500; letter-spacing: -0.004em; } /* Card titles — pinned to the subtitle role so the scale is the theme's * decision, not the card primitive's default. */ [data-slot="card-title"] { font-size: var(--text-subtitle-size); line-height: var(--text-subtitle-lh); } /* Touch targets — desktop keeps the dense drafting ladder; coarse pointers * get the 44px floor on every control. */ @media (pointer: coarse) { [data-slot="button"] { min-height: 2.75rem; min-width: 2.75rem; } [data-slot="input"], [data-slot="select-trigger"] { min-height: 2.75rem; } } [data-slot="button"]:hover:not(:disabled) { opacity: 0.9; } [data-slot="button"]:active:not(:disabled) { opacity: 0.82; transform: scale(0.99); } /* Inputs — clean card surface, hairline rule, azure focus as a flush * 1px ring plus border-color change. */ [data-slot="input"], [data-slot="textarea"], [data-slot="select-trigger"] { background: var(--card); border: var(--border-width-base) solid var(--input); border-radius: var(--radius); color: var(--foreground); transition: border-color var(--duration-fast) var(--ease-standard), box-shadow var(--duration-fast) var(--ease-standard); } [data-slot="input"]::placeholder, [data-slot="textarea"]::placeholder { color: var(--muted-foreground); opacity: 0.8; } [data-slot="input"]:hover:not(:disabled), [data-slot="textarea"]:hover:not(:disabled), [data-slot="select-trigger"]:hover:not(:disabled) { border-color: color-mix(in oklch, var(--foreground) 30%, transparent); } [data-slot="input"]:focus, [data-slot="textarea"]:focus, [data-slot="select-trigger"]:focus { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); outline: none; }