Files
lib-theme-acid/theme.css
jules b25596c281 lib-theme-acid: initial import (bold/identity-forward set, 2026-07)
One of four divergent candidates for the bold consumer theme family
(committed saturated color at 30-60% surface coverage, strong display
type). Includes the post-diverge fixes: heading color:inherit so brand
slabs keep their foreground pairing, plus per-theme refinements.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 23:20:55 +10:00

427 lines
16 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Acid — chartreuse on black.
*
* Festival/Wrapped energy. The native identity is dark mode: a near-black
* green-cast field with electric acid chartreuse (oklch 0.87 0.21 128)
* carrying the type, the panels, and the fills. Black ink on acid is the
* signature pair (~13:1) — the primary button, the user bubble, the sidebar
* accents all run black-on-acid, never white-on-green.
*
* :root is the brand's paper mode — honest light mode on a committed
* chartreuse-washed paper (oklch 0.96 0.05 120; visibly acid, not cream)
* with near-black green ink and a DEEP green-black primary (0.3 0.09 130)
* whose labels are acid-bright. The saturated color carries 3060% of the
* surface in both modes; this is the opposite of a calm settings app.
*
* Status stays out of the brand's lane: destructive is hot red (hue 25,
* light label), warning is amber 85 pulled clearly apart from the
* chartreuse in both hue and chroma, success is pushed to TEAL (hue 175,
* dark ink) so no second green ever fights the brand, info is cool blue 240.
*
* Type: Archivo Black (single-weight display black, weight 400, tight
* -0.02em) for headings, Space Grotesk for body, JetBrains Mono for code.
* Radius is a chunky-sharp 0.75rem. Motion is punchy and fast
* (100/200/320/450ms) with one real snappy spring for affordances.
*
* Token contract matches lib-theme-caffe-florian/theme.css (Crema v1).
*/
/*
* Fonts: consuming apps load Archivo Black + Space Grotesk + 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: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-heading: "Archivo Black", "Space Grotesk", -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: "Archivo Black", "Space Grotesk", -apple-system, BlinkMacSystemFont, sans-serif;
--body-family: "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
/* ── Colors ── bright acid-tinted paper (committed chartreuse wash, not
* cream), near-white cards a step above it, near-black green ink, and a
* deep green-black primary carrying acid-bright labels. */
--background: oklch(0.96 0.05 120);
--foreground: oklch(0.18 0.02 130);
--card: oklch(0.985 0.02 120);
--card-foreground: oklch(0.18 0.02 130);
--popover: oklch(0.99 0.015 120);
--popover-foreground: oklch(0.18 0.02 130);
/* Primary — deep green-black fill with the acid chartreuse as its label:
* the paper-mode inversion of the dark-mode black-on-acid signature. */
--primary: oklch(0.3 0.09 130);
--primary-foreground: oklch(0.9 0.21 126);
--secondary: oklch(0.9 0.06 120);
--secondary-foreground: oklch(0.28 0.05 130);
--muted: oklch(0.915 0.045 120);
--muted-foreground: oklch(0.42 0.05 130);
/* Accent — an acid wash for hover/selection tints, with deep green ink. */
--accent: oklch(0.9 0.1 122);
--accent-foreground: oklch(0.3 0.09 130);
/* ── Status ── kept out of the chartreuse lane. Destructive = hot red
* (hue 25) with a light label; warning = amber 85, clearly apart from the
* brand in hue AND chroma; success = TEAL 175 with dark ink so no second
* green fights the chartreuse; info = cool blue 240. */
--destructive: oklch(0.54 0.21 25);
--destructive-foreground: oklch(0.98 0.01 25);
--success: oklch(0.72 0.13 175);
--success-foreground: oklch(0.16 0.03 175);
--warning: oklch(0.8 0.16 85);
--warning-foreground: oklch(0.22 0.05 85);
--info: oklch(0.54 0.15 240);
--info-foreground: oklch(0.98 0.01 240);
--border: oklch(0.18 0.02 130 / 0.14);
--input: oklch(0.18 0.02 130 / 0.16);
--ring: oklch(0.55 0.16 130 / 0.6);
/* Chart palette — acid-led: deep chartreuse first, then cool blue /
* magenta / teal / hot orange. Hues ≥60° apart, adjacent lightness varied. */
--chart-1: oklch(0.68 0.17 128);
--chart-2: oklch(0.55 0.15 240);
--chart-3: oklch(0.6 0.18 330);
--chart-4: oklch(0.7 0.12 190);
--chart-5: oklch(0.62 0.17 40);
/* Sidebar — a deeper acid-paper stripe: more committed chartreuse than
* the field, with the deep-green primary and acid washes on it. */
--sidebar: oklch(0.93 0.07 120);
--sidebar-foreground: oklch(0.18 0.02 130);
--sidebar-primary: oklch(0.3 0.09 130);
--sidebar-primary-foreground: oklch(0.9 0.21 126);
--sidebar-accent: oklch(0.88 0.11 122);
--sidebar-accent-foreground: oklch(0.3 0.09 130);
--sidebar-border: oklch(0.18 0.02 130 / 0.12);
--sidebar-ring: oklch(0.55 0.16 130 / 0.6);
/* Syntax — deep chartreuse keyword leads; the rest stays cool. */
--syntax-keyword: oklch(0.45 0.13 130);
--syntax-string: oklch(0.48 0.1 175);
--syntax-number: oklch(0.55 0.16 330);
--syntax-comment: oklch(0.52 0.03 130);
--syntax-function: oklch(0.48 0.14 240);
--syntax-type: oklch(0.5 0.13 40);
/* ── Chat surfaces ──
* Contract for lib-chat-ui / lib-agent-ui / lib-agent-dock-ui. In paper
* mode the user bubble is the deep green-black panel with light text;
* the assistant bubble is a clean card with a hairline border. */
--chat-user-bg: oklch(0.3 0.09 130);
--chat-user-fg: oklch(0.97 0.03 120);
--chat-assistant-bg: oklch(0.985 0.02 120);
--chat-assistant-fg: oklch(0.18 0.02 130);
--chat-assistant-border: oklch(0.18 0.02 130 / 0.14);
/* Chunky-sharp radius. */
--radius: 0.75rem;
/* ── Motion ── punchy and fast. One REAL snappy spring (actual overshoot)
* for affordances; gentle/bouncy alias to the standard ease so the
* personality stays a single sharp gesture, not a bounce-house. */
--duration-fast: 100ms;
--duration-base: 200ms;
--duration-slow: 320ms;
--duration-slower: 450ms;
--duration-spring: 380ms;
--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.3, 0, 0, 1);
--ease-spring-gentle: var(--ease-standard);
--ease-spring-snappy: cubic-bezier(0.2, 1.4, 0.3, 1);
--ease-spring-bouncy: var(--ease-standard);
/* ── Typography ── consumer register, fixed rem, full role ramp. */
--text-hero-size: 3.5rem;
--text-hero-lh: 1.02;
--text-display-size: 2.75rem;
--text-display-lh: 1.05;
--text-headline-size: 1.875rem;
--text-headline-lh: 1.15;
--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: 1rem;
/* ── Elevation ── crisp green-black shadows on the paper. */
--elevation-0: none;
--elevation-1: 0 1px 2px oklch(0.18 0.03 130 / 0.08);
--elevation-2: 0 1px 3px oklch(0.18 0.03 130 / 0.1), 0 1px 2px oklch(0.18 0.03 130 / 0.06);
--elevation-3: 0 4px 8px -2px oklch(0.18 0.03 130 / 0.1), 0 2px 4px -2px oklch(0.18 0.03 130 / 0.06);
--elevation-4: 0 12px 24px -6px oklch(0.18 0.03 130 / 0.13), 0 4px 8px -4px oklch(0.18 0.03 130 / 0.06);
--elevation-5: 0 20px 40px -8px oklch(0.18 0.03 130 / 0.2);
--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 native identity. Near-black green-cast field, cards
* stepping clearly lighter, and the full acid chartreuse as primary with
* BLACK ink on it (the signature pair, ~13:1). The acid carries the type
* accents, the panels, and the fills — a rave terminal with discipline.
*/
.dark {
--background: oklch(0.16 0.01 130);
--foreground: oklch(0.95 0.03 120);
--card: oklch(0.21 0.012 130);
--card-foreground: oklch(0.95 0.03 120);
--popover: oklch(0.23 0.014 130);
--popover-foreground: oklch(0.95 0.03 120);
/* Black-on-acid — the signature. */
--primary: oklch(0.87 0.21 128);
--primary-foreground: oklch(0.15 0.02 130);
--secondary: oklch(0.26 0.02 130);
--secondary-foreground: oklch(0.93 0.03 120);
--muted: oklch(0.25 0.015 130);
--muted-foreground: oklch(0.75 0.05 125);
/* Accent — a dark acid wash with acid-bright ink. */
--accent: oklch(0.28 0.06 128);
--accent-foreground: oklch(0.88 0.18 126);
--destructive: oklch(0.56 0.21 25);
--destructive-foreground: oklch(0.98 0.01 25);
--success: oklch(0.76 0.13 175);
--success-foreground: oklch(0.16 0.03 175);
--warning: oklch(0.82 0.16 85);
--warning-foreground: oklch(0.22 0.05 85);
--info: oklch(0.68 0.14 240);
--info-foreground: oklch(0.16 0.03 240);
--border: oklch(0.95 0.03 120 / 0.12);
--input: oklch(0.95 0.03 120 / 0.14);
--ring: oklch(0.87 0.21 128 / 0.6);
/* Chart palette — acid leads at full charge; cool spectrum follows. */
--chart-1: oklch(0.87 0.21 128);
--chart-2: oklch(0.68 0.14 240);
--chart-3: oklch(0.74 0.17 330);
--chart-4: oklch(0.8 0.12 190);
--chart-5: oklch(0.72 0.16 40);
/* Sidebar — a pure-black stripe with acid accents. */
--sidebar: oklch(0.13 0.008 130);
--sidebar-foreground: oklch(0.95 0.03 120);
--sidebar-primary: oklch(0.87 0.21 128);
--sidebar-primary-foreground: oklch(0.15 0.02 130);
--sidebar-accent: oklch(0.26 0.06 128);
--sidebar-accent-foreground: oklch(0.88 0.18 126);
--sidebar-border: oklch(0.95 0.03 120 / 0.09);
--sidebar-ring: oklch(0.87 0.21 128 / 0.6);
/* Syntax — rave terminal, disciplined: acid keyword against cool
* companions, nothing else allowed near the chartreuse lane. */
--syntax-keyword: oklch(0.85 0.2 128);
--syntax-string: oklch(0.78 0.11 175);
--syntax-number: oklch(0.76 0.16 330);
--syntax-comment: oklch(0.6 0.03 130);
--syntax-function: oklch(0.72 0.13 240);
--syntax-type: oklch(0.76 0.14 40);
/* ── Chat surfaces (dark) ──
* User bubble IS the signature: acid chartreuse with black ink. */
--chat-user-bg: oklch(0.87 0.21 128);
--chat-user-fg: oklch(0.15 0.02 130);
--chat-assistant-bg: oklch(0.21 0.012 130);
--chat-assistant-fg: oklch(0.95 0.03 120);
--chat-assistant-border: oklch(0.95 0.03 120 / 0.12);
/* ── Elevation (dark) ── pure-black shadows. */
--elevation-1: 0 1px 2px oklch(0 0 0 / 0.35);
--elevation-2: 0 1px 3px oklch(0 0 0 / 0.45), 0 1px 2px oklch(0 0 0 / 0.28);
--elevation-3: 0 4px 8px -2px oklch(0 0 0 / 0.45), 0 2px 4px -2px oklch(0 0 0 / 0.28);
--elevation-4: 0 12px 24px -6px oklch(0 0 0 / 0.5), 0 4px 8px -4px oklch(0 0 0 / 0.28);
--elevation-5: 0 20px 40px -8px oklch(0 0 0 / 0.6);
}
/*
* @layer base — Acid's festival philosophy, disciplined.
*
* Archivo Black headings hit like posters; Space Grotesk keeps the body
* legible; the chartreuse is committed (it carries panels and fills, not
* just a ring) but status meaning never borrows it. Selection is acid at
* 40% alpha — even highlighting text is on-brand.
*/
@layer base {
body {
min-height: 100vh;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
letter-spacing: -0.008em;
font-family: var(--font-sans);
font-size: var(--text-body-size);
line-height: var(--text-body-lh);
}
/* Headings — Archivo Black: single-weight display black. The face only
* ships 400, so the rule pins weight 400 and lets the blackness of the
* cut do the shouting; tracking pulled tight. */
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.02em;
/* 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 chip. */
: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 — acid at 40% alpha. */
::selection {
background: color-mix(in oklch, var(--primary) 40%, transparent);
color: var(--foreground);
}
/* Links — brand-inked, 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 acid 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; snappy spring press, festival-fast. */
[data-slot="button"] {
font-weight: 600;
letter-spacing: -0.008em;
transition:
opacity var(--duration-fast) var(--ease-standard),
transform var(--duration-spring) var(--ease-spring-snappy);
}
/* 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 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.92;
}
[data-slot="button"]:active:not(:disabled) {
opacity: 0.85;
transform: scale(0.97);
}
/* Inputs — card surface, hairline border, acid 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) 25%, 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;
}