@import "tailwindcss"; @import "tw-animate-css"; @import "./timing-functions.css"; @custom-variant dark (&:is(.dark *)); /* Pull @unom/ui's compiled component classes (bg-neutral, rounded-card, p-padding-card, ring-accent, h-input-height, material…) into the Tailwind 4 scan so their utilities aren't purged. */ @source "../node_modules/@unom/ui/dist/**/*.{js,mjs}"; /* ── punktfunk brand · violet product chrome ──────────────────────────────── Two themes on one violet identity: LIGHT (lavender docs surface — the same palette the docs/Scalar reference uses: white bg, faint-violet cards/borders, #6c5bf3 brand) is the :root default; DARK (the violet-tinted app-icon chrome #141019 / #1c1530, #a79ff8 brand) is the `.dark` override. The live console pins `` so it stays dark by default — removing or toggling that class (e.g. Storybook's theme switch) yields light. The token set feeds BOTH @unom/ui's semantic contract (--brand/--primary/--accent/--neutral/ --main…) and the shadcn-style tokens the console's primitives + routes use (--background/--card/--muted…), mapped onto one palette so both render the same identity. Brand constants and the surface tokens that are pure indirections (--main, --neutral*, --error → other tokens) live in :root only — CSS resolves var() per-theme at use time, so .dark overrides just the raw values. */ :root { --radius: 0.625rem; /* Brand — the violet lens mark (from the punktfunk app icon). Theme-independent. */ --pf-brand: #6c5bf3; /* deep violet — primary on light */ --pf-brand-light: #a79ff8; /* light violet — primary on dark */ --pf-highlight: #d2c9fb; /* lens highlight */ /* Surfaces — light · lavender (white bg, faint-violet cards/borders). */ --background: #ffffff; --foreground: #1b1430; --card: #f6f2ff; --card-foreground: #1b1430; --popover: #ffffff; --popover-foreground: #1b1430; --muted: #f1ecfd; --muted-foreground: #6f6a86; --secondary: #ece6fb; --secondary-foreground: #1b1430; /* shadcn `accent` = subtle hover surface; also @unom/ui's card ring colour, so we tint it toward the brand violet (the same in both themes). */ --accent: var(--pf-brand); --accent-foreground: #ffffff; --border: #e4dcf7; --input: #e4dcf7; --ring: var(--pf-brand); /* Primary = the brand (buttons, active nav, default badges). */ --primary: var(--pf-brand); --primary-foreground: #ffffff; --success: oklch(0.6 0.14 160); --destructive: oklch(0.55 0.22 18); --destructive-foreground: #ffffff; /* ── @unom/ui semantic token contract (its components read these names). ── These are indirections — they follow the raw tokens above per-theme. */ --main: var(--foreground); --brand: var(--pf-brand); --brand-light: var(--pf-brand-light); --highlight: var(--pf-highlight); --neutral: var(--card); /* @unom card default surface (bg-neutral) */ --neutral-accent: var( --secondary ); /* accent / nested surface (bg-neutral-accent) */ --neutral-highlight: var(--border); --error: var(--destructive); --font-display: "Geist Variable", ui-sans-serif, system-ui, sans-serif; --font-sans: "Geist Variable", ui-sans-serif, system-ui, sans-serif; /* @unom/ui radius/spacing contract (pill buttons, rounded cards, tall inputs). */ --radius-card-min: var(--radius); } /* Dark · the violet-tinted app-icon chrome. Overrides only the raw values — the indirection tokens in :root resolve to these automatically. */ .dark { --background: #141019; --foreground: oklch(0.985 0 0); --card: #1c1530; --card-foreground: oklch(0.985 0 0); --popover: #1c1530; --popover-foreground: oklch(0.985 0 0); --muted: #1f1830; --muted-foreground: oklch(0.728 0.03 286); --secondary: #241c3d; --secondary-foreground: oklch(0.985 0 0); --border: #2a2148; --input: #2a2148; --ring: var(--pf-brand-light); /* Lighter violet reads better against the dark surface. */ --primary: var(--pf-brand-light); --primary-foreground: #141019; --success: oklch(0.7 0.15 160); --destructive: oklch(0.62 0.21 18); --destructive-foreground: oklch(0.985 0 0); } /* Map the palette to Tailwind colour/util tokens — both the shadcn vocabulary and @unom/ui's, resolved to one set of values. */ @theme inline { --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); --radius-button: 9999px; --radius-card: calc(var(--radius) * 2); --radius-main: calc(var(--radius) * 2); --spacing-input-height: 3rem; --spacing-padding-card: 1.25rem; --spacing-card: 1.5rem; --spacing-main: 15px; --font-sans: var(--font-sans); --font-display: var(--font-display); /* shadcn-style colour tokens. */ --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-success: var(--success); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); /* @unom/ui colour tokens. */ --color-main: var(--main); --color-brand: var(--brand); --color-brand-light: var(--brand-light); --color-neutral: var(--neutral); --color-neutral-accent: var(--neutral-accent); --color-neutral-highlight: var(--neutral-highlight); --color-highlight: var(--highlight); --color-error: var(--error); } /* Accordion / collapsible keyframes @unom/ui's interactive surfaces animate to. */ @theme { --animate-accordion-down: accordion-down 0.4s var(--ease-out-quart); --animate-accordion-up: accordion-up 0.4s var(--ease-out-quart); --animate-collapsible-down: collapsible-down 0.4s var(--ease-out-quart); --animate-collapsible-up: collapsible-up 0.4s var(--ease-out-quart); @keyframes accordion-down { from { height: 0; } to { height: var(--radix-accordion-content-height); } } @keyframes accordion-up { from { height: var(--radix-accordion-content-height); } to { height: 0; } } @keyframes collapsible-down { from { height: 0; opacity: 0; } to { height: var(--radix-collapsible-content-height); opacity: 1; } } @keyframes collapsible-up { from { height: var(--radix-collapsible-content-height); opacity: 1; } to { height: 0; opacity: 0; } } } @layer base { * { border-color: var(--border); } body { background-color: var(--background); color: var(--foreground); font-family: var(--font-sans); font-feature-settings: "rlig" 1, "calt" 1; } }