/* * Grape — violet night-lounge. * * A committed, identity-forward theme: the surface itself is the brand. The * whole world is a deep luminous grape-violet FIELD (hue 300) — Skyrise's * violet ancestry taken to a full drench, with no glass and no iridescence. * There are no white cards anywhere: cards are clearly-lighter violet panels * lifted off the field, popovers a step above cards, the sidebar a deeper * violet stripe. Ink is near-white with a violet tint; hairlines are * white-alpha. The one action glows: a hot coral-pink primary (hue 20) with * dark ink on top, the single warm counterpoint in an otherwise violet room. * * Dark mode is later that night — the same lounge with the lights turned * down: the field deepens, the panels follow, and the coral burns slightly * brighter against it. The theme is violet in BOTH modes; .dark only changes * the hour. * * Status colors are tuned to read on violet panels: destructive stays a deep * crimson fill with a light label (a different lightness class from the * bright coral primary, so the two hue-20 swatches never read as siblings); * success is mint, warning amber, info cool cyan — all bright swatches with * dark ink. * * Type is a lounge voice: Instrument Serif (single weight 400) for headings, * Instrument Sans for body, Geist Mono for code. Consumer register — 1rem * body with a generous 1.6 line-height. Radius is a soft 1.125rem; motion is * languid-confident with a real gentle spring on the emphasized ease; shadows * are deep violet-black pools. * * Token contract matches lib-theme-caffe-florian/theme.css (Crema v1). */ /* * Fonts: consuming apps load Instrument Serif + Instrument Sans + Geist 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: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-heading: "Instrument Serif", Georgia, "Times New Roman", serif; --font-mono: "Geist 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: "Instrument Serif", Georgia, "Times New Roman", serif; --body-family: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; /* ── Colors ── the grape field. Background is a deep luminous violet; * cards are clearly-lighter violet panels (+0.06 L — the step must be * visible); ink is near-white with a violet tint. NOT white cards — the * whole world is violet. */ --background: oklch(0.38 0.13 300); --foreground: oklch(0.97 0.012 300); --card: oklch(0.44 0.12 300); --card-foreground: oklch(0.97 0.012 300); --popover: oklch(0.46 0.115 300); --popover-foreground: oklch(0.97 0.012 300); /* Primary — the hot coral-pink counterpoint. One warm glow against the * violet, carrying a deep wine-dark ink (bright-swatch/dark-ink pairing, * ~6.3:1) so the action reads at label sizes. */ --primary: oklch(0.7 0.19 20); --primary-foreground: oklch(0.2 0.06 20); --secondary: oklch(0.5 0.11 300); --secondary-foreground: oklch(0.97 0.012 300); /* Muted — a recessed violet wash sitting between field and card, so muted * chrome sinks rather than lifts. Muted ink is a pale lavender, verified * ≥4.5:1 on field, card, AND the muted wash itself. */ --muted: oklch(0.42 0.115 300); --muted-foreground: oklch(0.85 0.045 300); /* Accent — a lighter violet wash with near-white ink: hover/selection * lift inside the violet family, never a second warm fill. */ --accent: oklch(0.52 0.12 300); --accent-foreground: oklch(0.98 0.01 300); /* ── Status ── tuned to read on violet panels. All four are BRIGHT * swatches with dark ink: on a mid-lightness violet world, status-colored * text (badge chips render `text-destructive` on a 10% tint) can only * clear 4.5:1 if the status color itself is light. Destructive is a * luminous rose (hue 5) — separated from the coral primary (hue 20) by * hue and by a visibly higher lightness. */ --destructive: oklch(0.84 0.11 5); --destructive-foreground: oklch(0.2 0.04 5); --success: oklch(0.75 0.13 160); --success-foreground: oklch(0.2 0.05 160); --warning: oklch(0.8 0.13 85); --warning-foreground: oklch(0.22 0.05 85); --info: oklch(0.75 0.1 220); --info-foreground: oklch(0.2 0.04 220); /* White-alpha hairlines — the violet world separates with light, not * darkness. */ --border: oklch(1 0 0 / 0.16); --input: oklch(1 0 0 / 0.2); --ring: oklch(0.7 0.19 20 / 0.6); /* Chart palette — coral lead, then mint / amber / cyan / pale orchid: * spaced hues that all read on violet panels, adjacent-index lightness * varied. */ --chart-1: oklch(0.72 0.18 20); --chart-2: oklch(0.78 0.13 160); --chart-3: oklch(0.85 0.12 85); --chart-4: oklch(0.72 0.11 220); --chart-5: oklch(0.86 0.08 320); /* Sidebar — a deeper violet stripe against the field. */ --sidebar: oklch(0.33 0.12 300); --sidebar-foreground: oklch(0.97 0.012 300); --sidebar-primary: oklch(0.7 0.19 20); --sidebar-primary-foreground: oklch(0.2 0.06 20); --sidebar-accent: oklch(0.44 0.12 300); --sidebar-accent-foreground: oklch(0.98 0.01 300); --sidebar-border: oklch(1 0 0 / 0.12); --sidebar-ring: oklch(0.7 0.19 20 / 0.6); /* Syntax — bright, tuned to read on violet card panels. */ --syntax-keyword: oklch(0.82 0.12 350); --syntax-string: oklch(0.85 0.1 160); --syntax-number: oklch(0.87 0.1 85); --syntax-comment: oklch(0.76 0.04 300); --syntax-function: oklch(0.83 0.09 220); --syntax-type: oklch(0.88 0.06 300); /* ── Chat surfaces ── * Contract for lib-agent-chat-ui / lib-agent-dock-ui. User bubble is the * coral glow with dark ink (the user's turn IS the action); assistant * bubble is a violet card panel with a white-alpha hairline. */ --chat-user-bg: oklch(0.7 0.19 20); --chat-user-fg: oklch(0.2 0.06 20); --chat-assistant-bg: oklch(0.44 0.12 300); --chat-assistant-fg: oklch(0.97 0.012 300); --chat-assistant-border: oklch(1 0 0 / 0.16); /* Soft-lounge radius. */ --radius: 1.125rem; /* ── Motion ── languid-confident. Slower than a product theme on * purpose — the lounge doesn't rush — with a real gentle spring on the * emphasized ease and the spring family. */ --duration-fast: 160ms; --duration-base: 320ms; --duration-slow: 480ms; --duration-slower: 640ms; --duration-spring: 480ms; --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.34, 1.24, 0.54, 1); --ease-spring-gentle: cubic-bezier(0.38, 1.18, 0.58, 1); --ease-spring-snappy: cubic-bezier(0.3, 1.35, 0.5, 1); --ease-spring-bouncy: cubic-bezier(0.3, 1.55, 0.42, 1); /* ── Typography ── consumer register, fixed rem, full role ramp. */ --text-hero-size: 3.5rem; --text-hero-lh: 1.05; --text-display-size: 2.75rem; --text-display-lh: 1.1; --text-headline-size: 2rem; --text-headline-lh: 1.2; --text-title-size: 1.5rem; --text-title-lh: 1.3; --text-subtitle-size: 1.1875rem; --text-subtitle-lh: 1.45; --text-body-size: 1rem; --text-body-lh: 1.6; --text-label-size: 0.875rem; --text-label-lh: 1.25rem; --text-caption-size: 0.75rem; --text-caption-lh: 1.0625rem; /* ── Elevation ── deep violet-black pools; on a dark field the shadows * carry more alpha than a daylight theme's. */ --elevation-0: none; --elevation-1: 0 1px 2px oklch(0.12 0.06 300 / 0.3); --elevation-2: 0 2px 4px oklch(0.12 0.06 300 / 0.34), 0 1px 2px oklch(0.12 0.06 300 / 0.24); --elevation-3: 0 6px 12px -2px oklch(0.12 0.06 300 / 0.38), 0 2px 4px -2px oklch(0.12 0.06 300 / 0.26); --elevation-4: 0 14px 28px -6px oklch(0.1 0.05 300 / 0.44), 0 4px 10px -4px oklch(0.1 0.05 300 / 0.28); --elevation-5: 0 24px 48px -8px oklch(0.1 0.05 300 / 0.55); --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 — later that night. The field deepens toward violet-black, the * panels keep the same visible step above it, and the coral counterpoint * burns slightly brighter. The ladder keeps muted ABOVE popover * (bg 0.26 → card 0.32 → popover 0.34 → muted 0.36) so muted chrome still * reads as a lift on the darker field. */ .dark { --background: oklch(0.26 0.1 300); --foreground: oklch(0.97 0.012 300); --card: oklch(0.32 0.1 300); --card-foreground: oklch(0.97 0.012 300); --popover: oklch(0.34 0.1 300); --popover-foreground: oklch(0.97 0.012 300); --primary: oklch(0.73 0.19 20); --primary-foreground: oklch(0.2 0.06 20); --secondary: oklch(0.36 0.1 300); --secondary-foreground: oklch(0.97 0.012 300); --muted: oklch(0.36 0.1 300); --muted-foreground: oklch(0.83 0.05 300); --accent: oklch(0.4 0.11 300); --accent-foreground: oklch(0.98 0.01 300); --destructive: oklch(0.84 0.11 5); --destructive-foreground: oklch(0.2 0.04 5); --success: oklch(0.77 0.13 160); --success-foreground: oklch(0.2 0.05 160); --warning: oklch(0.82 0.13 85); --warning-foreground: oklch(0.22 0.05 85); --info: oklch(0.77 0.1 220); --info-foreground: oklch(0.2 0.04 220); --border: oklch(1 0 0 / 0.14); --input: oklch(1 0 0 / 0.18); --ring: oklch(0.73 0.19 20 / 0.6); --chart-1: oklch(0.74 0.18 20); --chart-2: oklch(0.8 0.13 160); --chart-3: oklch(0.87 0.12 85); --chart-4: oklch(0.74 0.11 220); --chart-5: oklch(0.88 0.08 320); --sidebar: oklch(0.22 0.09 300); --sidebar-foreground: oklch(0.97 0.012 300); --sidebar-primary: oklch(0.73 0.19 20); --sidebar-primary-foreground: oklch(0.2 0.06 20); --sidebar-accent: oklch(0.32 0.1 300); --sidebar-accent-foreground: oklch(0.98 0.01 300); --sidebar-border: oklch(1 0 0 / 0.1); --sidebar-ring: oklch(0.73 0.19 20 / 0.6); --syntax-keyword: oklch(0.84 0.12 350); --syntax-string: oklch(0.87 0.1 160); --syntax-number: oklch(0.89 0.1 85); --syntax-comment: oklch(0.74 0.04 300); --syntax-function: oklch(0.85 0.09 220); --syntax-type: oklch(0.9 0.06 300); /* ── Chat surfaces (dark) ── */ --chat-user-bg: oklch(0.73 0.19 20); --chat-user-fg: oklch(0.2 0.06 20); --chat-assistant-bg: oklch(0.32 0.1 300); --chat-assistant-fg: oklch(0.97 0.012 300); --chat-assistant-border: oklch(1 0 0 / 0.14); --elevation-1: 0 1px 2px oklch(0 0 0 / 0.35); --elevation-2: 0 2px 4px oklch(0 0 0 / 0.4), 0 1px 2px oklch(0 0 0 / 0.28); --elevation-3: 0 6px 12px -2px oklch(0 0 0 / 0.45), 0 2px 4px -2px oklch(0 0 0 / 0.3); --elevation-4: 0 14px 28px -6px oklch(0 0 0 / 0.5), 0 4px 10px -4px oklch(0 0 0 / 0.3); --elevation-5: 0 24px 48px -8px oklch(0 0 0 / 0.6); } /* * @layer base — Grape's night-lounge philosophy. * * One drenched violet field, panels lifted with light (white-alpha hairlines * and lighter violet), a serif voice for headings, and the coral glow spent * only on the action, the selection, and the focus ring. Nothing rushes. */ @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 — Instrument Serif, a single weight (400): the serif itself * is the emphasis, so no faux-bold. */ 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; 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 — a white-alpha tint chip with foreground ink, neutral * inside the violet world. */ :not(pre) > code { padding: 0.1em 0.35em; border-radius: calc(var(--radius) * 0.5); background: oklch(1 0 0 / 0.12); color: var(--foreground); font-size: 0.9em; } /* Selection — the coral glow. */ ::selection { background: color-mix(in oklch, var(--primary) 40%, transparent); color: var(--foreground); } /* Links — coral-warmed, underline-on-hover. */ a { color: color-mix(in oklch, var(--primary) 75%, var(--foreground)); text-decoration-color: color-mix(in oklch, var(--primary) 45%, 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 coral 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 — confident weight; opacity absorb on press with a languid ease. */ [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 lounge 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.92; } [data-slot="button"]:active:not(:disabled) { opacity: 0.84; transform: scale(0.99); } /* Inputs — card-violet panels, white-alpha hairline, coral 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: oklch(1 0 0 / 0.32); } [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; }