/* * Siena — drenched Mediterranean courtyard. A Sienese piazza at five in the * afternoon: the background is a real terracotta wall, not a tinted white; * cards are sun-bleached plaster panels resting ON that wall; the ink is a * deep warm olive-brown that never goes black. Warmth lives in the surface * itself — hierarchy is done by material (plaster on clay), not by shadow * theatrics or balloon corners. * * Palette rationale: burnt sienna carries the primary action (deep enough for * plaster-white labels at 6.9:1); worn-stone secondaries and an ochre warning * stay inside the courtyard's heat; one cool note — a Mediterranean blue — is * spent on accent and info so the warmth has something to push against. Dark * mode is the same courtyard at dusk: umber-brown surfaces (never blue-gray) * with the terracotta turned into glow. * * Token contract matches lib-theme-pristine/theme.css. */ /* * Fonts: consuming apps load Fraunces + Albert Sans + JetBrains Mono at the * top of their entry CSS via the Google Fonts URL documented in this theme's * README. No @import here — PostCSS ordering forbids it — and no URL smuggled * in comments for build scripts to lift. */ :root { --font-sans: "Albert Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --font-heading: "Fraunces", Georgia, serif; --font-mono: "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace; /* Tailwind utility families — distinct names so a consuming app's * `@theme inline` can indirect to these. Mirror --font-heading/--font-sans. */ --heading-family: "Fraunces", Georgia, serif; --body-family: "Albert Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; /* ── Colors ── terracotta field, plaster cards, olive-brown ink. * The background commits: L 0.84, chroma 0.055 at hue 55 — a painted * wall, not the pale cream band. */ --background: oklch(0.84 0.055 55); --foreground: oklch(0.24 0.03 60); --card: oklch(0.96 0.018 75); --card-foreground: oklch(0.24 0.03 60); --popover: oklch(0.97 0.015 75); --popover-foreground: oklch(0.24 0.03 60); /* Burnt sienna — deep enough to carry plaster-white labels (6.9:1). */ --primary: oklch(0.46 0.13 38); --primary-foreground: oklch(0.97 0.02 75); /* Worn stone — a step off the wall, still warm. */ --secondary: oklch(0.9 0.03 68); --secondary-foreground: oklch(0.28 0.035 55); --muted: oklch(0.89 0.035 65); --muted-foreground: oklch(0.38 0.045 55); /* The one cool note — washed Mediterranean blue. */ --accent: oklch(0.88 0.04 230); --accent-foreground: oklch(0.3 0.08 240); --destructive: oklch(0.48 0.18 28); --destructive-foreground: oklch(0.97 0.02 75); /* Olive success — courtyard green, dark olive ink on top. */ --success: oklch(0.62 0.11 130); --success-foreground: oklch(0.18 0.05 135); /* Ochre warning — sun pigment, umber ink label. */ --warning: oklch(0.76 0.13 80); --warning-foreground: oklch(0.24 0.06 80); /* Info shares the accent's Mediterranean blue, deepened for plaster text. */ --info: oklch(0.46 0.09 245); --info-foreground: oklch(0.97 0.02 75); /* Hairlines are ink washes — on a colored wall they need a little more * presence than they would on white. */ --border: oklch(0.24 0.03 60 / 0.2); --input: oklch(0.24 0.03 60 / 0.2); --ring: oklch(0.46 0.13 38 / 0.5); /* Chart palette — terracotta / olive / sea blue / ochre / plum. * Hues ≥60° apart, adjacent lightness varied. */ --chart-1: oklch(0.58 0.13 40); --chart-2: oklch(0.68 0.1 125); --chart-3: oklch(0.55 0.1 240); --chart-4: oklch(0.75 0.12 85); --chart-5: oklch(0.62 0.09 320); /* Sidebar — a deeper stripe of the same wall, in shadow. */ --sidebar: oklch(0.8 0.065 50); --sidebar-foreground: oklch(0.24 0.03 60); --sidebar-primary: oklch(0.46 0.13 38); --sidebar-primary-foreground: oklch(0.97 0.02 75); --sidebar-accent: oklch(0.86 0.05 55); --sidebar-accent-foreground: oklch(0.38 0.12 38); --sidebar-border: oklch(0.24 0.03 60 / 0.16); --sidebar-ring: oklch(0.46 0.13 38 / 0.5); --syntax-keyword: oklch(0.44 0.13 38); --syntax-string: oklch(0.46 0.09 135); --syntax-number: oklch(0.5 0.12 60); --syntax-comment: oklch(0.5 0.03 60); --syntax-function: oklch(0.44 0.1 245); --syntax-type: oklch(0.46 0.07 195); /* ── Chat surfaces ── * Contract for lib-chat-ui / lib-agent-ui / lib-agent-dock-ui. User * bubble is filled burnt sienna with plaster text; assistant bubble is * a plaster card with an ink hairline. */ --chat-user-bg: oklch(0.44 0.13 38); --chat-user-fg: oklch(0.97 0.02 75); --chat-assistant-bg: oklch(0.96 0.018 75); --chat-assistant-fg: oklch(0.24 0.03 60); --chat-assistant-border: oklch(0.24 0.03 60 / 0.16); /* Modest, honest corners — softness comes from color, not radius. */ --radius: 0.75rem; /* ── Motion ── settled and unhurried, still product-fast. */ --duration-fast: 130ms; --duration-base: 300ms; --duration-slow: 420ms; --duration-slower: 560ms; --duration-spring: 340ms; --ease-standard: cubic-bezier(0.25, 0.1, 0.25, 1); --ease-decelerate: cubic-bezier(0, 0, 0.2, 1); --ease-accelerate: cubic-bezier(0.4, 0, 1, 1); --ease-emphasized: cubic-bezier(0.3, 0, 0.15, 1); /* Calm theme — springs alias to standard easings rather than bounce. * Personality lives in the values, never in absence. */ --ease-spring-gentle: var(--ease-standard); --ease-spring-snappy: var(--ease-decelerate); --ease-spring-bouncy: var(--ease-emphasized); /* ── Typography ── product register: fixed rem sizes, full ramp. * Fraunces carries the display voice; Albert Sans does the work. */ --text-hero-size: 3.5rem; --text-hero-lh: 3.75rem; --text-display-size: 3rem; --text-display-lh: 3.25rem; --text-headline-size: 2rem; --text-headline-lh: 2.375rem; --text-title-size: 1.5rem; --text-title-lh: 1.875rem; --text-subtitle-size: 1.1875rem; --text-subtitle-lh: 1.75rem; --text-body-size: 1.0625rem; --text-body-lh: 1.625rem; --text-label-size: 0.9375rem; --text-label-lh: 1.25rem; --text-caption-size: 0.8125rem; --text-caption-lh: 1.125rem; /* ── Elevation ── warm umber shadows, low-key: things rest on the wall, * they don't float. Never pure black. */ --elevation-0: none; --elevation-1: 0 1px 2px oklch(0.24 0.03 60 / 0.1); --elevation-2: 0 1px 3px oklch(0.24 0.03 60 / 0.12), 0 1px 2px oklch(0.24 0.03 60 / 0.08); --elevation-3: 0 4px 10px -2px oklch(0.24 0.03 60 / 0.14), 0 2px 4px -2px oklch(0.24 0.03 60 / 0.08); --elevation-4: 0 12px 28px -6px oklch(0.24 0.03 60 / 0.18), 0 4px 10px -4px oklch(0.24 0.03 60 / 0.1); --elevation-5: 0 24px 48px -12px oklch(0.24 0.03 60 / 0.26); --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 — dusk in the same courtyard. Deep umber-brown surfaces (never * blue-gray); the terracotta becomes glow and takes dark umber labels, since * dark-ink-on-bright beats white-on-mid-tone. */ .dark { --background: oklch(0.22 0.02 55); --foreground: oklch(0.93 0.02 75); --card: oklch(0.28 0.022 55); --card-foreground: oklch(0.93 0.02 75); --popover: oklch(0.295 0.024 55); --popover-foreground: oklch(0.93 0.02 75); --primary: oklch(0.7 0.14 45); --primary-foreground: oklch(0.16 0.03 45); --secondary: oklch(0.31 0.025 55); --secondary-foreground: oklch(0.9 0.02 75); --muted: oklch(0.3 0.025 55); --muted-foreground: oklch(0.72 0.03 70); --accent: oklch(0.3 0.05 240); --accent-foreground: oklch(0.85 0.06 235); --destructive: oklch(0.64 0.19 30); --destructive-foreground: oklch(0.14 0.03 28); --success: oklch(0.7 0.12 130); --success-foreground: oklch(0.14 0.04 135); --warning: oklch(0.78 0.13 80); --warning-foreground: oklch(0.2 0.05 80); --info: oklch(0.7 0.1 240); --info-foreground: oklch(0.14 0.03 245); --border: oklch(0.93 0.02 75 / 0.12); --input: oklch(0.93 0.02 75 / 0.12); --ring: oklch(0.7 0.14 45 / 0.5); --chart-1: oklch(0.68 0.13 40); --chart-2: oklch(0.75 0.1 125); --chart-3: oklch(0.68 0.1 240); --chart-4: oklch(0.8 0.12 85); --chart-5: oklch(0.72 0.09 320); --sidebar: oklch(0.2 0.02 55); --sidebar-foreground: oklch(0.93 0.02 75); --sidebar-primary: oklch(0.7 0.14 45); --sidebar-primary-foreground: oklch(0.16 0.03 45); --sidebar-accent: oklch(0.32 0.04 45); --sidebar-accent-foreground: oklch(0.88 0.07 50); --sidebar-border: oklch(0.93 0.02 75 / 0.1); --sidebar-ring: oklch(0.7 0.14 45 / 0.5); --syntax-keyword: oklch(0.75 0.13 45); --syntax-string: oklch(0.76 0.11 135); --syntax-number: oklch(0.8 0.12 65); --syntax-comment: oklch(0.6 0.03 65); --syntax-function: oklch(0.74 0.1 240); --syntax-type: oklch(0.75 0.07 195); /* ── Chat surfaces (dark) ── */ --chat-user-bg: oklch(0.48 0.13 40); --chat-user-fg: oklch(0.97 0.02 75); --chat-assistant-bg: oklch(0.29 0.023 55); --chat-assistant-fg: oklch(0.93 0.02 75); --chat-assistant-border: oklch(0.93 0.02 75 / 0.12); /* Dusk shadows — deeper umber, never blue-black. */ --elevation-1: 0 1px 2px oklch(0.1 0.012 55 / 0.4); --elevation-2: 0 1px 3px oklch(0.1 0.012 55 / 0.45), 0 1px 2px oklch(0.1 0.012 55 / 0.3); --elevation-3: 0 4px 10px -2px oklch(0.1 0.012 55 / 0.45), 0 2px 4px -2px oklch(0.1 0.012 55 / 0.3); --elevation-4: 0 12px 28px -6px oklch(0.1 0.012 55 / 0.5), 0 4px 10px -4px oklch(0.1 0.012 55 / 0.3); --elevation-5: 0 24px 48px -12px oklch(0.1 0.012 55 / 0.6); } /* * @layer base — Siena's material philosophy. * * Plaster panels on a painted wall: cards get a hairline ink border and a * low warm shadow (they rest, they don't float). Fraunces carries headings; * everything else is quiet Albert Sans on olive-brown ink. */ @layer base { body { min-height: 100vh; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; letter-spacing: -0.011em; font-family: var(--font-sans); font-size: var(--text-body-size); line-height: var(--text-body-lh); } 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.01em; color: var(--foreground); } code, kbd, samp, pre, [data-slot="code"], [data-slot="code-block"] { font-family: var(--font-mono); } /* Inline code — neutral ink on a warm chip; sienna stays reserved for * actions, links and focus so the accent keeps pointing at one thing. */ :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 — sun-warmed sienna wash. */ ::selection { background: color-mix(in oklch, var(--primary) 24%, transparent); color: var(--foreground); } a { color: var(--primary); 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); } /* Plaster panels — hairline ink border + resting warm shadow. Border * AND shadow both stay light so surfaces read as material, not chrome. */ [data-slot="card"], [data-slot="popover-content"], [data-slot="dropdown-menu-content"], [data-slot="context-menu-content"], [data-slot="menubar-content"], [data-slot="hover-card-content"], [data-slot="select-content"], [data-slot="combobox-content"], [data-slot="command"], [data-slot="tooltip-content"], [data-slot="sheet-content"], [data-slot="dialog-content"], [data-slot="alert-dialog-content"], [data-slot="drawer-content"] { border: var(--border-width-base) solid var(--border); box-shadow: var(--elevation-2); } [data-slot="popover-content"], [data-slot="dropdown-menu-content"], [data-slot="context-menu-content"], [data-slot="menubar-content"], [data-slot="hover-card-content"], [data-slot="select-content"], [data-slot="combobox-content"], [data-slot="tooltip-content"] { box-shadow: var(--elevation-3); } [data-slot="sheet-content"], [data-slot="dialog-content"], [data-slot="alert-dialog-content"], [data-slot="drawer-content"] { box-shadow: var(--elevation-4); } [data-slot="button"] { font-weight: 500; } [data-slot="button"]:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; } [data-slot="sidebar"] { background: var(--sidebar); border-right: var(--border-width-base) solid var(--sidebar-border); } } /* * Unlayered control tuning — outside @layer base so it beats Tailwind's * utility defaults shipped with shadcn primitives. */ /* 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 its density; 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; } }