/* * Vermilion — poster chrome. * * A bold, identity-forward consumer theme. One hot vermilion red-orange is THE * brand, and it is carried by the CHROME — the primary action, hero panels, * the entire sidebar, selection — in big committed slabs, editorial-poster * style. Roughly 30–40% of a typical screen is drenched vermilion. The content * well stays out of the fight: warm paper with near-black warm ink, so the * poster color reads as identity, not noise. Massive condensed display type * (Anton) is the second half of the voice; the vermilion and the type do the * pointing together. * * Destructive is deliberately NOT a sibling of the brand: pulled to a deeper * crimson (hue ~15, L≈0.48, light label) so a destructive button and a primary * button never read as the same family. * * Dark mode is the poster at night: near-black warm charcoal with the same * vermilion glowing slightly brighter, carrying dark ink on top * (bright-swatch/dark-ink) — the chrome stays vermilion. * * Type: Anton (single weight 400 — condensed poster caps, it IS the voice) for * headings, Archivo for body, JetBrains Mono for code. Consumer register with * a tall display end of the ramp (hero 4rem — Anton is condensed, big sizes * stay narrow). Radius is a modest 0.5rem — poster edges, not toys. Motion is * snappy (120/240/360/500ms); springs alias to the standard eases. * * Token contract matches lib-theme-caffe-florian/theme.css (Crema v1). */ /* * Fonts: consuming apps load Anton + Archivo + 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: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-heading: "Anton", "Archivo", -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: "Anton", "Archivo", -apple-system, BlinkMacSystemFont, sans-serif; --body-family: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; /* ── Colors ── warm paper content well, near-black warm ink, and the hot * vermilion drenching the chrome. The paper carries a faint vermilion * tint (chroma 0.012, hue pulled toward the brand) so the brand reaches * the content well without gambling its legibility. */ --background: oklch(0.97 0.012 45); --foreground: oklch(0.21 0.012 40); --card: oklch(0.995 0.004 60); --card-foreground: oklch(0.21 0.012 40); --popover: oklch(0.99 0.005 60); --popover-foreground: oklch(0.21 0.012 40); /* Primary — the poster vermilion, deepened from the nominal 0.60 to L0.55 * so near-white ink clears the 4.5:1 floor with room to spare. This is the * same slab the sidebar is drenched in — one color, big commitments. */ --primary: oklch(0.55 0.21 30); --primary-foreground: oklch(0.985 0.006 40); --secondary: oklch(0.93 0.014 48); --secondary-foreground: oklch(0.3 0.014 40); --muted: oklch(0.93 0.014 48); --muted-foreground: oklch(0.45 0.014 40); /* Accent — a pale vermilion wash with deep vermilion ink: the hover / * selection tint that echoes the brand without adding a second fill. */ --accent: oklch(0.94 0.035 40); --accent-foreground: oklch(0.42 0.16 31); /* ── Status ── destructive must never look like the brand's sibling: * crimson hue ~15 AND visibly deeper (L0.48) with a light label, vs the * brighter orange-leaning primary (hue 30, L0.55). Success/warning carry * dark ink on bright swatches; warning sits at amber 70 — far from the * vermilion — so alerts never blend into the chrome. */ --destructive: oklch(0.48 0.19 15); --destructive-foreground: oklch(0.98 0.01 15); --success: oklch(0.62 0.14 150); --success-foreground: oklch(0.16 0.03 150); --warning: oklch(0.72 0.15 70); --warning-foreground: oklch(0.22 0.05 60); --info: oklch(0.52 0.13 250); --info-foreground: oklch(0.98 0.01 250); --border: oklch(0.21 0.012 40 / 0.12); --input: oklch(0.21 0.012 40 / 0.14); --ring: oklch(0.55 0.21 30 / 0.55); /* Chart palette — vermilion leads, then a spaced spectrum (blue / teal / * violet / gold), hues ≥60° apart, adjacent lightness varied. */ --chart-1: oklch(0.58 0.2 32); --chart-2: oklch(0.5 0.13 250); --chart-3: oklch(0.68 0.11 185); --chart-4: oklch(0.55 0.15 305); --chart-5: oklch(0.72 0.13 95); /* ── Sidebar ── DRENCHED. The whole rail is the poster slab: vermilion * field, near-white ink, white-alpha hairlines. The active item is a paper * chip punched out of the slab (deep vermilion ink on near-white). */ --sidebar: oklch(0.52 0.2 31); --sidebar-foreground: oklch(0.985 0.006 40); --sidebar-primary: oklch(0.985 0.008 60); --sidebar-primary-foreground: oklch(0.42 0.17 31); --sidebar-accent: oklch(0.46 0.185 31); --sidebar-accent-foreground: oklch(0.985 0.006 40); --sidebar-border: oklch(1 0 0 / 0.22); --sidebar-ring: oklch(0.985 0.008 60 / 0.6); /* Syntax — warm-ink base; the vermilion takes the function seat. */ --syntax-keyword: oklch(0.48 0.15 305); --syntax-string: oklch(0.5 0.12 150); --syntax-number: oklch(0.52 0.14 55); --syntax-comment: oklch(0.52 0.012 40); --syntax-function: oklch(0.5 0.18 30); --syntax-type: oklch(0.5 0.1 200); /* ── Chat surfaces ── * Contract for lib-chat-ui / lib-agent-ui / lib-agent-dock-ui. The user * bubble is a vermilion slab with near-white ink — the poster color owns * the human's voice; the assistant answers from clean paper. */ --chat-user-bg: oklch(0.55 0.21 30); --chat-user-fg: oklch(0.985 0.006 40); --chat-assistant-bg: oklch(0.995 0.004 60); --chat-assistant-fg: oklch(0.21 0.012 40); --chat-assistant-border: oklch(0.21 0.012 40 / 0.1); /* Poster edges, not toys. */ --radius: 0.5rem; /* ── Motion ── snappy poster energy. Springs alias to the standard eases — * the personality is speed and commitment, not bounce. */ --duration-fast: 120ms; --duration-base: 240ms; --duration-slow: 360ms; --duration-slower: 500ms; --duration-spring: 240ms; --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); /* One real spring — a bold consumer theme earns a snappy press. */ --ease-spring-snappy: cubic-bezier(0.2, 1.4, 0.3, 1); --ease-spring-bouncy: var(--ease-standard); /* ── Typography ── consumer register with a big condensed display end. * Anton is condensed, so the tall sizes stay narrow on screen; line * heights tighten hard at the poster end of the ramp. */ --text-hero-size: 4rem; --text-hero-lh: 1.02; --text-display-size: 3rem; --text-display-lh: 1.05; --text-headline-size: 2rem; --text-headline-lh: 1.12; --text-title-size: 1.375rem; --text-title-lh: 1.25; --text-subtitle-size: 1.125rem; --text-subtitle-lh: 1.4; --text-body-size: 1rem; --text-body-lh: 1.55; --text-label-size: 0.875rem; --text-label-lh: 1.25rem; --text-caption-size: 0.75rem; --text-caption-lh: 1.0625rem; /* ── Elevation ── low, warm-black shadows — print-flat until something * genuinely lifts. */ --elevation-0: none; --elevation-1: 0 1px 2px oklch(0.18 0.02 40 / 0.07); --elevation-2: 0 1px 3px oklch(0.18 0.02 40 / 0.09), 0 1px 2px oklch(0.18 0.02 40 / 0.05); --elevation-3: 0 4px 8px -2px oklch(0.18 0.02 40 / 0.1), 0 2px 4px -2px oklch(0.18 0.02 40 / 0.05); --elevation-4: 0 12px 24px -6px oklch(0.18 0.02 40 / 0.12), 0 4px 8px -4px oklch(0.18 0.02 40 / 0.06); --elevation-5: 0 20px 40px -8px oklch(0.18 0.02 40 / 0.18); --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 poster at night. Near-black warm charcoal (low chroma, hue * ~40, never blue-slate), cards stepping clearly lighter, and the vermilion * glowing slightly brighter with dark ink on top (bright-swatch/dark-ink). * The chrome stays vermilion — the sidebar does not go grey at night. */ .dark { --background: oklch(0.18 0.01 40); --foreground: oklch(0.95 0.008 55); --card: oklch(0.23 0.012 40); --card-foreground: oklch(0.95 0.008 55); --popover: oklch(0.25 0.012 40); --popover-foreground: oklch(0.95 0.008 55); --primary: oklch(0.64 0.2 33); --primary-foreground: oklch(0.13 0.018 35); --secondary: oklch(0.27 0.012 40); --secondary-foreground: oklch(0.92 0.01 55); --muted: oklch(0.27 0.012 40); --muted-foreground: oklch(0.73 0.014 50); --accent: oklch(0.32 0.075 33); --accent-foreground: oklch(0.89 0.08 40); --destructive: oklch(0.52 0.2 15); --destructive-foreground: oklch(0.98 0.01 15); --success: oklch(0.7 0.15 150); --success-foreground: oklch(0.16 0.03 150); --warning: oklch(0.76 0.15 70); --warning-foreground: oklch(0.22 0.05 60); --info: oklch(0.66 0.13 250); --info-foreground: oklch(0.15 0.03 250); --border: oklch(0.95 0.008 55 / 0.13); --input: oklch(0.95 0.008 55 / 0.15); --ring: oklch(0.64 0.2 33 / 0.55); --chart-1: oklch(0.66 0.19 33); --chart-2: oklch(0.62 0.13 250); --chart-3: oklch(0.74 0.11 185); --chart-4: oklch(0.66 0.15 305); --chart-5: oklch(0.8 0.13 95); /* Sidebar — still drenched, tuned a step deeper so near-white ink glows. */ --sidebar: oklch(0.48 0.185 30); --sidebar-foreground: oklch(0.985 0.006 40); --sidebar-primary: oklch(0.97 0.01 55); --sidebar-primary-foreground: oklch(0.4 0.165 31); --sidebar-accent: oklch(0.4 0.16 30); --sidebar-accent-foreground: oklch(0.985 0.006 40); --sidebar-border: oklch(1 0 0 / 0.2); --sidebar-ring: oklch(0.97 0.01 55 / 0.6); --syntax-keyword: oklch(0.72 0.13 305); --syntax-string: oklch(0.74 0.12 150); --syntax-number: oklch(0.78 0.13 60); --syntax-comment: oklch(0.62 0.012 45); --syntax-function: oklch(0.72 0.16 33); --syntax-type: oklch(0.72 0.1 200); /* ── Chat surfaces (dark) ── user bubble a step deeper than the glowing * primary so near-white ink stays comfortably legible. */ --chat-user-bg: oklch(0.5 0.19 30); --chat-user-fg: oklch(0.985 0.006 40); --chat-assistant-bg: oklch(0.23 0.012 40); --chat-assistant-fg: oklch(0.95 0.008 55); --chat-assistant-border: oklch(0.95 0.008 55 / 0.13); --elevation-1: 0 1px 2px oklch(0 0 0 / 0.3); --elevation-2: 0 1px 3px oklch(0 0 0 / 0.4), 0 1px 2px oklch(0 0 0 / 0.25); --elevation-3: 0 4px 8px -2px oklch(0 0 0 / 0.4), 0 2px 4px -2px oklch(0 0 0 / 0.25); --elevation-4: 0 12px 24px -6px oklch(0 0 0 / 0.45), 0 4px 8px -4px oklch(0 0 0 / 0.25); --elevation-5: 0 20px 40px -8px oklch(0 0 0 / 0.55); } /* * @layer base — Vermilion's poster philosophy. * * Condensed display type in committed sizes, warm paper for reading, and the * one hot color spent in slabs — chrome, primary, selection — never scattered. * Everything that isn't the poster stays quiet ink-on-paper. */ @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 — Anton, the single-weight poster voice. It ships at 400 only; * it is already black-condensed, so weight stays 400 and tracking opens a * hair (condensed faces need air, not squeeze). Case is the author's call — * the face carries the register without forced uppercase. */ 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: 400; text-transform: none; letter-spacing: 0.01em; /* inherit, not var(--foreground): identity themes put headings on * colored slabs (bg-primary heroes) — forcing the field ink there * breaks the slab's own foreground pairing. */ color: inherit; } code, kbd, samp, pre, [data-slot="code"], [data-slot="code-block"] { font-family: var(--font-mono); } /* Inline code — neutral ink chip, no brand color spent here. */ :not(pre) > code { padding: 0.1em 0.35em; border-radius: calc(var(--radius) * 0.5); background: color-mix(in oklch, var(--foreground) 6%, transparent); color: var(--foreground); font-size: 0.9em; } /* Selection — the poster color claims what you grab. */ ::selection { background: color-mix(in oklch, var(--primary) 30%, transparent); color: var(--foreground); } /* Links — vermilion, 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); } } /* * Focus-visible — the vermilion ring, offset (not inset), for keyboard users. * 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 — a touch of poster weight; opacity absorb on press, snappy. */ [data-slot="button"] { font-weight: 600; letter-spacing: 0; } /* Card titles — pinned to the subtitle role so the scale is the theme's * decision, not the card primitive's default. (Anton at title sizes inside a * card would shout; the subtitle size keeps the poster voice measured.) */ [data-slot="card-title"] { font-size: var(--text-subtitle-size); line-height: var(--text-subtitle-lh); } /* Touch targets — desktop keeps the crisp density 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 paper surface, hairline border, vermilion focus as a flush * ring. */ [data-slot="input"], [data-slot="textarea"], [data-slot="select-trigger"] { background: var(--card); border: var(--border-width-base) solid var(--border); 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) 22%, 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; }