@import '@fontsource/inter'; @import '@fontsource-variable/bricolage-grotesque'; @import '@fontsource-variable/outfit'; @import '@fontsource-variable/source-serif-4'; @import '@fontsource-variable/lora'; @import '@fontsource/courier-prime'; @import '@fontsource/dm-serif-display'; /* Libre Baskerville — a user-selectable editor font (font-family-dropdown.tsx), self-hosted so it keeps working offline after the Google-Fonts CDN removal. */ @import '@fontsource/libre-baskerville'; @font-face { font-family: 'Fenwick'; src: url('/Fenwick-Bold.woff2') format('woff2'); font-weight: bold; font-style: normal; font-display: swap; } /* ── Dialog system surfaces (brand-agnostic; spec: docs/redesign/dialogs) ── The dialog surface is intentionally NOT --background: it matches the elevated floating-toolbar / popover color so modals read as the top layer. */ :root { --np-dialog-surface: #ffffff; --np-dialog-line: rgba(28, 26, 21, 0.1); --np-scrim: rgba(28, 26, 21, 0.34); --np-dialog-shadow: 0 32px 90px rgba(28, 26, 21, 0.24), 0 2px 8px rgba(28, 26, 21, 0.1); /* Popover-tier elevation — lighter than the dialog shadow. Shared by popover/dropdown/select content for a consistent floating-surface feel. */ --np-popover-shadow: 0 8px 24px rgba(28, 26, 21, 0.12), 0 2px 6px rgba(28, 26, 21, 0.08); /* Brand accent tokens consumed by the dialog system (IconBadge gradient, DialogNote/DialogField brand tone). Defaulted here so they always resolve pre-hydration (before BrandingProvider sets data-brand) and for any unbranded root; the per-brand blocks below override them. Default = NovelPad. */ --np-gradient: linear-gradient(135deg, #22D3EE 0%, #D946EF 55%, #EC4899 100%); --np-gradient-soft: linear-gradient(135deg, rgba(34, 211, 238, .18) 0%, rgba(217, 70, 239, .18) 55%, rgba(236, 72, 153, .18) 100%); --np-brand-ink: #D946EF; --np-brand-soft: rgba(217, 70, 239, 0.13); } .dark { --np-dialog-surface: #1b2238; --np-dialog-line: rgba(255, 255, 255, 0.1); --np-scrim: rgba(6, 9, 20, 0.64); --np-dialog-shadow: 0 32px 90px rgba(0, 0, 0, 0.62), inset 0 0 0 1px rgba(255, 255, 255, 0.02); --np-popover-shadow: 0 10px 30px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(255, 255, 255, 0.02); } @layer base { :root { --background: 0 0% 100%; --foreground: 222.2 47.4% 11.2%; --muted: 210 40% 96.1%; --muted-foreground: 215.4 16.3% 46.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 47.4% 11.2%; --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --card: 0 0% 100%; --card-foreground: 222.2 47.4% 11.2%; --primary: 222.2 47.4% 11.2%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; --accent: 210 40% 96.1%; --accent-foreground: 222.2 47.4% 11.2%; --constructive: 142.1 70.6% 45.3%; --constructive-foreground: 210 40% 98%; --destructive: 0 100% 50%; --destructive-foreground: 210 40% 98%; --ring: 215 20.2% 65.1%; --highlight: 217 91% 60%; --radius: 0.5rem; /* Theme-aware radius scale. Values mirror the current Tailwind output so introducing themes does not change today's NovelPad appearance. */ --radius-sm: 0.25rem; --radius-xs: 0.1875rem; --radius-base: 0.25rem; --radius-md: 0.375rem; --radius-lg: 0.5rem; --radius-xl: 0.75rem; --radius-2xl: 1rem; --radius-compact: 0.5625rem; --radius-icon: 0.625rem; --radius-control: 0.6875rem; --radius-tile: 0.75rem; --radius-badge: 0.8125rem; --radius-panel: 0.875rem; --radius-dialog: 1.125rem; --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-serif: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-reading: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-mono: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --font-display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; --sidebar-background: 0 0% 98%; --sidebar-foreground: 240 5.3% 26.1%; --sidebar-primary: 240 5.9% 10%; --sidebar-primary-foreground: 0 0% 98%; --sidebar-accent: 240 4.8% 95.9%; --sidebar-accent-foreground: 240 5.9% 10%; --sidebar-border: 220 13% 91%; --sidebar-ring: 217.2 91.2% 59.8%; --app-header-background: hsl(var(--background)); --app-header-foreground: hsl(var(--foreground)); --app-header-border: hsl(var(--border)); --column: 210 40% 92.1%; --column-foreground: 222.2 47.4% 11.2%; --column-border: 210 40% 86.1%; /* Board-specific surfaces default to today's muted canvas and floating section stacks. Visual themes can override them independently without changing muted UI throughout the rest of the application. */ --board-background: var(--muted); --board-action-foreground: hsl(var(--foreground)); --board-column-gap: 1.5rem; --board-padding-inline: 1.5rem; --board-padding-block-start: 1.25rem; --board-padding-block-end: 0rem; --board-padding-block-end-stacked: 4rem; --board-header-background: hsl(var(--background)); --board-header-foreground: hsl(var(--foreground)); --board-header-muted-background: hsl(var(--muted) / 0.5); --board-header-muted-foreground: hsl(var(--muted-foreground)); --board-header-border: hsl(var(--column-border)); --board-header-border-width: 1px; --board-header-control-border: hsl(var(--border)); --board-footer-background: hsl(var(--muted)); --board-footer-foreground: hsl(var(--muted-foreground)); --board-footer-muted-foreground: hsl(var(--muted-foreground) / 0.7); --board-footer-hover-background: hsl(var(--accent)); --board-footer-border: hsl(var(--border)); --board-footer-border-width: 1px; --section-column-background: transparent; --section-column-radius: 0rem; /* Recessed board canvas (ink-0): darker than --background (chrome). */ --canvas: 0 0% 100%; } .dark { --background: 224 71% 4%; --foreground: 213 31% 91%; --muted: 223 47% 11%; --muted-foreground: 215.4 16.3% 56.9%; --accent: 216 34% 17%; --accent-foreground: 210 40% 98%; --popover: 224 71% 4%; --popover-foreground: 213 31% 91%; --border: 216 34% 17%; --input: 216 34% 17%; --card: 224 71% 4%; --card-foreground: 213 31% 91%; --primary: 210 40% 98%; --primary-foreground: 222.2 47.4% 1.2%; --secondary: 222.2 47.4% 11.2%; --secondary-foreground: 210 40% 98%; --constructive: 142.1 44.1% 37.1%; --constructive-foreground: 210 40% 98%; --destructive: 0 63% 42%; --destructive-foreground: 210 40% 98%; --ring: 216 34% 17%; --highlight: 217 91% 60%; --sidebar-background: 240 5.9% 10%; --sidebar-foreground: 240 4.8% 95.9%; --sidebar-primary: 224.3 76.3% 48%; --sidebar-primary-foreground: 0 0% 100%; --sidebar-accent: 240 3.7% 15.9%; --sidebar-accent-foreground: 240 4.8% 95.9%; --sidebar-border: 240 3.7% 15.9%; --sidebar-ring: 217.2 91.2% 59.8%; --column: 224 31% 22%; --column-foreground: 213 31% 91%; --column-border: 216 24% 30%; --canvas: 224 71% 3%; /* Raised card surface (lifts scene cards above the same-ink board in dark mode). Brand blocks override this with their own on-brand value. */ --card-raised: 226 39% 15.5%; } } :root[data-brand="helmdocs"] { --background: 0 0% 100%; --foreground: 20 14.3% 4.1%; --card: 0 0% 100%; --card-foreground: 20 14.3% 4.1%; --popover: 0 0% 100%; --popover-foreground: 20 14.3% 4.1%; --primary: 24.6 95% 53.1%; --primary-foreground: 60 9.1% 97.8%; --secondary: 60 4.8% 95.9%; --secondary-foreground: 24 9.8% 10%; --muted: 60 4.8% 95.9%; --muted-foreground: 25 5.3% 44.7%; --accent: 60 4.8% 95.9%; --accent-foreground: 24 9.8% 10%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 60 9.1% 97.8%; --border: 20 5.9% 90%; --input: 20 5.9% 90%; --ring: 24.6 95% 53.1%; --highlight: 24.6 95% 53.1%; --sidebar-background: 30 6% 97%; --sidebar-foreground: 20 14.3% 4.1%; --sidebar-primary: 24.6 95% 53.1%; --sidebar-primary-foreground: 60 9.1% 97.8%; --sidebar-accent: 60 4.8% 95.9%; --sidebar-accent-foreground: 24 9.8% 10%; --sidebar-border: 20 5.9% 90%; --sidebar-ring: 24.6 95% 53.1%; --column: 35 5% 92%; --column-foreground: 20 14.3% 4.1%; --column-border: 30 5% 85%; --canvas: 0 0% 100%; } .dark[data-brand="helmdocs"] { --background: 20 14.3% 4.1%; --foreground: 60 9.1% 97.8%; --card: 20 14.3% 4.1%; --card-foreground: 60 9.1% 97.8%; --popover: 20 14.3% 4.1%; --popover-foreground: 60 9.1% 97.8%; --primary: 20.5 90.2% 48.2%; --primary-foreground: 60 9.1% 97.8%; --secondary: 12 6.5% 15.1%; --secondary-foreground: 60 9.1% 97.8%; --muted: 12 6.5% 15.1%; --muted-foreground: 24 5.4% 63.9%; --accent: 12 6.5% 15.1%; --accent-foreground: 60 9.1% 97.8%; --destructive: 0 72.2% 50.6%; --destructive-foreground: 60 9.1% 97.8%; --border: 12 6.5% 15.1%; --input: 12 6.5% 15.1%; --ring: 20.5 90.2% 48.2%; --highlight: 20.5 90.2% 48.2%; --sidebar-background: 20 10% 7%; --sidebar-foreground: 60 9.1% 97.8%; --sidebar-primary: 20.5 90.2% 48.2%; --sidebar-primary-foreground: 60 9.1% 97.8%; --sidebar-accent: 12 6.5% 15.1%; --sidebar-accent-foreground: 60 9.1% 97.8%; --sidebar-border: 12 6.5% 15.1%; --sidebar-ring: 20.5 90.2% 48.2%; --column: 15 10% 14%; --column-foreground: 60 9.1% 97.8%; --column-border: 12 8% 22%; --canvas: 20 14.3% 3%; /* HelmDocs cards already lift: --card (L 4.1%) is darker than the muted board (L 15.1%), so the raised surface stays at --card — no NovelPad ink-navy. */ --card-raised: 20 14.3% 4.1%; /* Dialog surface: a neutral raised dark panel at the --secondary level, NOT the NovelPad ink-navy (#1b2238 from the .dark default). Keeps modals lifted off the near-black background while staying on-brand. */ --np-dialog-surface: hsl(12 6.5% 15.1%); --np-scrim: rgba(0, 0, 0, 0.64); } /* HelmDocs brand fonts (Outfit — geometric sans for body + headings; theme-agnostic). Outfit has no serif companion, so --font-serif (used by headings, e.g. the auth card title) also points at Outfit. Reading + mono stay on the system/Georgia stacks. Variable face registers as "Outfit Variable" — lead the stack with that or the self-hosted face never loads. */ :root[data-brand="helmdocs"], .dark[data-brand="helmdocs"] { --font-sans: "Outfit Variable", "Outfit", ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif; --font-serif: "Outfit Variable", "Outfit", ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif; --font-reading: Georgia, "Times New Roman", serif; --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace; --font-display: "Outfit Variable", "Outfit", ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif; /* HelmDocs brand sweep + accent: the orange ramp (mirrors --loader-gradient and --primary), replacing the NovelPad cyan→fuchsia gradient in shared dialog chrome (IconBadge, DialogNote/Field brand tone, step dots, etc.). */ --np-gradient: linear-gradient(135deg, hsl(24.6 95% 53.1%) 0%, hsl(20.5 90.2% 48.2%) 100%); --np-gradient-soft: linear-gradient(135deg, hsla(24.6, 95%, 53.1%, .18) 0%, hsla(20.5, 90.2%, 48.2%, .18) 100%); --np-brand-ink: hsl(24.6 95% 53.1%); --np-brand-soft: hsla(24.6, 95%, 53.1%, .14); } :root[data-brand="novelpad"] { --background: 37.5 50% 96.9%; --foreground: 42.9 14.3% 9.6%; --muted: 40 38.5% 92.4%; --muted-foreground: 32.7 6.9% 31.2%; --popover: 37.5 50% 96.9%; --popover-foreground: 42.9 14.3% 9.6%; --border: 40 34.3% 86.3%; --input: 40 34.3% 86.3%; /* Card is the raised ink: lighter than the paper --background (L 96.9%) so it lifts in light mode, mirroring dark mode where --card (L 12.9%) sits above --background (L 10.6%). A darker card here reads as a recessed panel. */ --card: 38 60% 99%; --card-foreground: 42.9 14.3% 9.6%; --primary: 42.9 14.3% 9.6%; --primary-foreground: 37.5 50% 96.9%; --secondary: 40 38.5% 92.4%; --secondary-foreground: 42.9 14.3% 9.6%; --accent: 40 38.5% 92.4%; --accent-foreground: 42.9 14.3% 9.6%; --constructive: 160.1 84.1% 39.4%; --constructive-foreground: 37.5 50% 96.9%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 37.5 50% 96.9%; --ring: 188.7 94.5% 42.7%; --highlight: 188.7 94.5% 42.7%; --sidebar-background: 40 48.4% 93.9%; --sidebar-foreground: 32.7 6.9% 31.2%; --sidebar-primary: 188.7 94.5% 42.7%; --sidebar-primary-foreground: 37.5 50% 96.9%; --sidebar-accent: 40 38.5% 92.4%; --sidebar-accent-foreground: 42.9 14.3% 9.6%; --sidebar-border: 40 34.3% 86.3%; --sidebar-ring: 188.7 94.5% 42.7%; --column: 40 38.5% 92.4%; --column-foreground: 42.9 14.3% 9.6%; --column-border: 40 34.3% 86.3%; /* Pro's status bar belongs to the board surface rather than reading as a separate bordered panel. */ --board-footer-background: hsl(var(--board-background)); --board-footer-border: transparent; --board-footer-border-width: 0px; --canvas: 37.5 50% 96.9%; } .dark[data-brand="novelpad"] { --background: 225 44.4% 10.6%; --foreground: 216 33.3% 97.1%; --muted: 226.2 39.4% 12.9%; --muted-foreground: 221.5 17.6% 71%; /* Menus/popovers sit at ink-3 (raised above the ink-2 cards), matching the prototype's scene/stack/board menus. */ --popover: 224.1 36.2% 18.4%; --popover-foreground: 216 33.3% 97.1%; --border: 224.1 36.2% 18.4%; --input: 223.9 32.8% 24.5%; --card: 226.2 39.4% 12.9%; --card-foreground: 216 33.3% 97.1%; --primary: 216 33.3% 97.1%; --primary-foreground: 225 44.4% 10.6%; --secondary: 224.1 36.2% 18.4%; --secondary-foreground: 216 33.3% 97.1%; --accent: 224.1 36.2% 18.4%; --accent-foreground: 216 33.3% 97.1%; --constructive: 160.1 84.1% 39.4%; --constructive-foreground: 216 33.3% 97.1%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 216 33.3% 97.1%; --ring: 187.9 85.7% 53.3%; --highlight: 187.9 85.7% 53.3%; /* Sidebar = ink-1 (chrome level), matching the toolbar; the board canvas (--canvas) is the darker ink-0 layer below it. */ --sidebar-background: 225 44.4% 10.6%; --sidebar-foreground: 225 21.7% 82%; --sidebar-primary: 187.9 85.7% 53.3%; --sidebar-primary-foreground: 225 44.4% 10.6%; --sidebar-accent: 224.1 36.2% 18.4%; --sidebar-accent-foreground: 216 33.3% 97.1%; --sidebar-border: 224.1 36.2% 18.4%; --sidebar-ring: 187.9 85.7% 53.3%; --column: 224.1 36.2% 18.4%; --column-foreground: 216 33.3% 97.1%; --column-border: 223.9 32.8% 24.5%; /* Recessed board canvas = ink-0 (#0B1020), darker than --background (ink-1). */ --canvas: 225.7 48.8% 8.4%; /* Raised card: ink-2 (--card, L 12.9%) lifted to L 15.5% so scene cards read above the same-ink board (--muted). */ --card-raised: 226.2 39.4% 15.5%; } /* NovelPad brand fonts, gradient, tag ramp, motion + focus atmosphere (theme-agnostic) */ :root[data-brand="novelpad"], .dark[data-brand="novelpad"] { --font-sans: "Bricolage Grotesque Variable", "Bricolage Grotesque", ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif; --font-serif: "Source Serif 4 Variable", "Source Serif 4", "Source Serif Pro", "Iowan Old Style", Georgia, serif; --font-reading: "Lora Variable", "Lora", "Iowan Old Style", Georgia, serif; --font-mono: "Courier Prime", "Courier New", ui-monospace, "SF Mono", Menlo, monospace; --font-display: "Fenwick", "DM Serif Display", "Source Serif 4 Variable", "Source Serif 4", Georgia, serif; --np-gradient: linear-gradient(135deg, #22D3EE 0%, #D946EF 55%, #EC4899 100%); --np-gradient-soft: linear-gradient(135deg, rgba(34, 211, 238, .18) 0%, rgba(217, 70, 239, .18) 55%, rgba(236, 72, 153, .18) 100%); --tag-cyan: #22D3EE; --tag-pink: #EC4899; --tag-plum: #7C3AED; --tag-amber: #F59E0B; --tag-sage: #5B8F6B; --tag-dusk: #64748B; --tag-coral: #FB7185; --ease: cubic-bezier(0.32, 0.72, 0, 1); --dur-fast: 150ms; --dur-base: 220ms; --dur-slow: 320ms; --np-focus-ring: 0 0 0 2px hsl(var(--background)), 0 0 0 4px #22D3EE; } /* ── NovelPad Classic ────────────────────────────────────────────────────── Visual theme for writers who prefer the previous NovelPad application. Source palette: ../novelpad/src/novelpad/ux/theme.ts. The app's structural layout stays current; semantic surfaces, accents, typography, and standard radii reproduce the Classic character in both color modes. */ :root[data-brand="novelpad"][data-novel-theme="novelpad-classic"] { --background: 60 11.1% 94.7%; /* #F3F3F0 */ --foreground: 247.1 11.4% 29.2%; /* #444253 */ --muted: 0 0% 93.3%; /* #EEEEEE */ --muted-foreground: 240 4% 34.7%; /* #55555C */ --popover: 0 0% 100%; --popover-foreground: 247.1 11.4% 29.2%; --border: 236.7 16.7% 78.8%; /* #C0C1D2 */ --input: 236.7 16.7% 78.8%; --card: 0 0% 100%; --card-foreground: 247.1 11.4% 29.2%; --card-raised: 0 0% 100%; --primary: 198.7 73.2% 49.8%; /* #22A2DC */ --primary-foreground: 253.3 20.9% 8.4%; --secondary: 334.1 74.7% 52%; /* #E02978 */ --secondary-foreground: 0 0% 100%; --accent: 236.7 16.7% 78.8%; --accent-foreground: 244.6 11.5% 22.2%; --constructive: 128.2 44.2% 44.3%; /* #3FA34D */ --constructive-foreground: 0 0% 100%; --destructive: 6.2 81.7% 62.7%; /* #EE6352 */ --destructive-foreground: 253.3 20.9% 8.4%; --ring: 198.7 73.2% 49.8%; --highlight: 198.7 73.2% 49.8%; /* Classic's navigation rail was dark in both modes. */ --sidebar-background: 244.6 11.5% 22.2%; --sidebar-foreground: 210 21.4% 94.5%; --sidebar-primary: 198.7 73.2% 49.8%; --sidebar-primary-foreground: 253.3 20.9% 8.4%; --sidebar-accent: 240 11.7% 15.1%; --sidebar-accent-foreground: 210 21.4% 94.5%; --sidebar-border: 244.6 11.5% 22.2%; --sidebar-ring: 198.7 73.2% 49.8%; --app-header-background: hsl(var(--sidebar-background)); --app-header-foreground: hsl(var(--sidebar-foreground)); --app-header-border: hsl(var(--sidebar-border)); --column: 0 0% 93.3%; --column-foreground: 240 8.1% 21.8%; --column-border: 236.7 16.7% 78.8%; --board-background: 240 11.7% 15.1%; /* #22222B */ --board-action-foreground: #EEF1F4; --canvas: 60 11.1% 94.7%; --np-dialog-surface: #FFFFFF; --np-dialog-line: rgba(68, 66, 83, 0.18); --np-scrim: rgba(19, 17, 26, 0.38); --np-dialog-shadow: 0 18px 48px rgba(34, 34, 43, 0.22), 0 2px 6px rgba(34, 34, 43, 0.10); --np-popover-shadow: 0 8px 20px rgba(34, 34, 43, 0.18); } .dark[data-brand="novelpad"][data-novel-theme="novelpad-classic"] { --background: 253.3 20.9% 8.4%; /* #13111A */ --foreground: 210 21.4% 94.5%; /* #EEF1F4 */ --muted: 244.6 11.5% 22.2%; /* #33323F */ --muted-foreground: 236.7 16.7% 78.8%; --popover: 244.6 11.5% 22.2%; --popover-foreground: 210 21.4% 94.5%; --border: 247.1 11.4% 29.2%; /* #444253 */ --input: 240 4% 34.7%; /* #55555C */ --card: 240 11.7% 15.1%; /* #22222B */ --card-foreground: 210 21.4% 94.5%; --card-raised: 240 11.7% 15.1%; --primary: 198.7 73.2% 49.8%; --primary-foreground: 253.3 20.9% 8.4%; --secondary: 334.1 74.7% 52%; --secondary-foreground: 0 0% 100%; --accent: 244.6 11.5% 22.2%; --accent-foreground: 210 21.4% 94.5%; --constructive: 128.2 44.2% 44.3%; --constructive-foreground: 253.3 20.9% 8.4%; --destructive: 6.2 81.7% 62.7%; --destructive-foreground: 253.3 20.9% 8.4%; --ring: 198.7 73.2% 49.8%; --highlight: 198.7 73.2% 49.8%; --sidebar-background: 244.6 11.5% 22.2%; --sidebar-foreground: 210 21.4% 94.5%; --sidebar-primary: 198.7 73.2% 49.8%; --sidebar-primary-foreground: 253.3 20.9% 8.4%; --sidebar-accent: 240 11.7% 15.1%; --sidebar-accent-foreground: 210 21.4% 94.5%; --sidebar-border: 240 11.7% 15.1%; --sidebar-ring: 198.7 73.2% 49.8%; --app-header-background: hsl(var(--sidebar-background)); --app-header-foreground: hsl(var(--sidebar-foreground)); --app-header-border: hsl(var(--sidebar-border)); --column: 240 8.1% 21.8%; /* #33333C */ --column-foreground: 0 0% 93.3%; --column-border: 240 4% 34.7%; --board-background: 240 11.7% 15.1%; /* #22222B */ --board-action-foreground: #EEF1F4; --canvas: 253.3 20.9% 8.4%; --np-dialog-surface: #22222B; --np-dialog-line: rgba(192, 193, 210, 0.18); --np-scrim: rgba(19, 17, 26, 0.68); --np-dialog-shadow: 0 24px 64px rgba(0, 0, 0, 0.56), inset 0 0 0 1px rgba(238, 241, 244, 0.025); --np-popover-shadow: 0 10px 26px rgba(0, 0, 0, 0.44); } :root[data-brand="novelpad"][data-novel-theme="novelpad-classic"], .dark[data-brand="novelpad"][data-novel-theme="novelpad-classic"] { /* Outfit is already self-hosted and is the closest available geometric sans to Classic's Montserrat without introducing a network-loaded font. */ --font-sans: "Outfit Variable", "Outfit", "Montserrat", "Roboto", "Helvetica", "Arial", sans-serif; --font-serif: "Outfit Variable", "Outfit", "Montserrat", "Roboto", "Helvetica", "Arial", sans-serif; --font-reading: "Libre Baskerville", Georgia, serif; --font-display: "Outfit Variable", "Outfit", "Montserrat", "Roboto", "Helvetica", "Arial", sans-serif; --np-gradient: linear-gradient(-45deg, #E02978 45%, #22A2DC 85%); --np-gradient-soft: linear-gradient(-45deg, rgba(224, 41, 120, 0.18) 45%, rgba(34, 162, 220, 0.18) 85%); --np-brand-ink: #22A2DC; --np-brand-soft: rgba(34, 162, 220, 0.14); --np-focus-ring: 0 0 0 2px hsl(var(--background)), 0 0 0 4px #22A2DC; --tag-cyan: #08B2E3; --tag-pink: #EE6352; --tag-plum: #B38CB4; --tag-amber: #E8AE68; --tag-sage: #3FA34D; --radius: 0.25rem; --radius-sm: 0.25rem; --radius-xs: 0.25rem; --radius-base: 0.25rem; --radius-md: 0.25rem; --radius-lg: 0.25rem; --radius-xl: 0.25rem; --radius-2xl: 0.25rem; --radius-compact: 0.25rem; --radius-icon: 0.25rem; --radius-control: 0.25rem; --radius-tile: 0.25rem; --radius-badge: 0.25rem; --radius-panel: 0.25rem; --radius-dialog: 0.25rem; /* Classic used one seven-pixel grid unit between stacks and around the board edges (../novelpad/src/novelpad/ux/theme.ts). */ --board-column-gap: 0.4375rem; --board-padding-inline: 0.4375rem; --board-padding-block-start: 0.4375rem; --board-padding-block-end: 0.4375rem; --board-padding-block-end-stacked: 0.4375rem; --board-header-background: hsl(var(--board-background)); --board-header-foreground: #EEF1F4; --board-header-muted-background: rgba(238, 241, 244, 0.08); --board-header-muted-foreground: #C0C1D2; --board-header-border: transparent; --board-header-border-width: 0px; --board-header-control-border: #444253; --board-footer-background: hsl(var(--board-background)); --board-footer-foreground: #EEF1F4; --board-footer-muted-foreground: #C0C1D2; --board-footer-hover-background: rgba(238, 241, 244, 0.08); --board-footer-border: transparent; --board-footer-border-width: 0px; --section-column-background: hsl(var(--column)); --section-column-radius: 0.25rem; } .btn-gradient { background: var(--np-gradient); color: #fff; } [data-slot="board-header"] [data-slot="board-type-chip"] { background-color: var(--board-header-muted-background); border-color: var(--board-header-control-border); color: var(--board-header-muted-foreground); } @layer base { * { @apply border-border; } body { @apply font-sans antialiased bg-background text-foreground; } } @layer base { * { @apply border-border; } body { @apply bg-background text-foreground; } } /* * --mention-ink: the link color for @-mention chips (and the active typeahead * highlight). On dark surfaces the bright brand --highlight reads well, but on * light surfaces the high-luminance accents (cyan/blue/orange) wash out — so we * deepen them per brand for legible contrast. Resolved against the originating * element, so it also feeds `::highlight(mention-active)` (mark.css). Kept out * of @layer base so these win over the layered theme blocks. */ :root { --mention-ink: var(--highlight); } :root:not(.dark) { --mention-ink: 217 78% 48%; } :root:not(.dark)[data-brand="helmdocs"] { --mention-ink: 24.6 88% 44%; } :root:not(.dark)[data-brand="novelpad"] { --mention-ink: 192 80% 30%; } :root:not(.dark)[data-brand="novelpad"][data-novel-theme="novelpad-classic"] { --mention-ink: 198.7 83% 34%; } /* * Loader + skeleton design tokens (see docs/features/loaders.md). These feed the * brand loader system in packages/app/src/components/common/loaders/: * --loader-gradient the brand sweep used by Spinner / Progress / skeleton stripe * --np-skel-track resting "bone" fill of a skeleton block * --np-skel-tint travelling highlight on the skeleton sweep * --np-skel-line skeleton card hairline (defaults to the theme border) * --np-skel-speed skeleton shimmer period (overridable inline per instance) * The handoffs are dark-tuned, so the light values raise contrast. Kept out of * @layer base so they win over the layered theme/brand blocks. NovelPad is the * default brand; helmdocs overrides keep the system on-brand if a *shared* * loader renders on a Helm surface (Helm skeletons themselves stay animate-pulse). */ :root { --loader-gradient: linear-gradient(135deg, #22d3ee 0%, #d946ef 55%, #ec4899 100%); --np-skel-track: rgba(20, 18, 15, 0.06); --np-skel-tint: rgba(34, 211, 238, 0.18); --np-skel-line: hsl(var(--border)); --np-skel-speed: 1400ms; } .dark { --np-skel-track: rgba(255, 255, 255, 0.07); --np-skel-tint: rgba(150, 228, 247, 0.17); } /* * Full-screen loading surface + inks (LoadingScreen / desktop boot splash). * Light = NovelPad paper (#FBF8F3 = the light --background) under a faint brand * glow; dark = the deep ink navy from the loader handoff. The desktop splash * (apps/desktop/src/renderer/src/splash.tsx) renders before this sheet is * guaranteed, so it mirrors these values inline — keep the two in sync. */ :root { --np-loading-surface: radial-gradient(120% 90% at 50% 42%, rgba(217, 70, 239, 0.10) 0%, rgba(34, 211, 238, 0.07) 32%, rgba(251, 248, 243, 0) 64%), #FBF8F3; --np-loading-ink: #1C1A15; --np-loading-muted: rgba(28, 26, 21, 0.60); --np-loading-subtitle: rgba(28, 26, 21, 0.45); --np-loading-line: rgba(28, 26, 21, 0.16); } .dark { --np-loading-surface: radial-gradient(120% 90% at 50% 42%, rgba(217, 70, 239, 0.10) 0%, rgba(34, 211, 238, 0.06) 32%, rgba(15, 21, 39, 0) 64%), #0B0F1A; --np-loading-ink: #F5F7FA; --np-loading-muted: rgba(245, 247, 250, 0.55); --np-loading-subtitle: rgba(245, 247, 250, 0.40); --np-loading-line: rgba(245, 247, 250, 0.16); } /* HelmDocs: plain theme surfaces, no NovelPad glow. */ :root[data-brand="helmdocs"] { --np-loading-surface: hsl(0 0% 100%); --np-loading-ink: hsl(20 14.3% 4.1%); } .dark[data-brand="helmdocs"] { --np-loading-surface: hsl(20 14.3% 4.1%); --np-loading-ink: hsl(60 9.1% 97.8%); } :root[data-brand="helmdocs"] { --loader-gradient: linear-gradient(135deg, hsl(24.6 95% 53.1%) 0%, hsl(20.5 90.2% 48.2%) 100%); --np-skel-tint: rgba(251, 146, 60, 0.16); /* Spinner (loader #4) conic sweep — retinted to the HelmDocs orange ramp so the shared Spinner / loaderToast reads on-brand instead of leaking the NovelPad cyan→plum→pink sweep. The stops map to spinner.css's conic slots (transparent → light 180deg → mid 280deg → deep 360deg). */ --np-spinner-from: rgba(251, 146, 60, 0); --np-spinner-cyan: #fb923c; --np-spinner-plum: #f97316; --np-spinner-pink: #ea580c; } .dark[data-brand="helmdocs"] { --np-skel-tint: rgba(251, 146, 60, 0.14); --np-spinner-from: rgba(251, 146, 60, 0); --np-spinner-cyan: #fb923c; --np-spinner-plum: #f97316; --np-spinner-pink: #ea580c; } :root[data-brand="novelpad"][data-novel-theme="novelpad-classic"] { --loader-gradient: linear-gradient(-45deg, #E02978 45%, #22A2DC 85%); --np-skel-track: rgba(68, 66, 83, 0.09); --np-skel-tint: rgba(34, 162, 220, 0.18); --np-loading-surface: #F3F3F0; --np-loading-ink: #444253; --np-loading-muted: rgba(68, 66, 83, 0.66); --np-loading-subtitle: rgba(68, 66, 83, 0.48); --np-loading-line: rgba(68, 66, 83, 0.20); } .dark[data-brand="novelpad"][data-novel-theme="novelpad-classic"] { --np-skel-track: rgba(238, 241, 244, 0.08); --np-skel-tint: rgba(34, 162, 220, 0.18); --np-loading-surface: #13111A; --np-loading-ink: #EEF1F4; --np-loading-muted: rgba(238, 241, 244, 0.60); --np-loading-subtitle: rgba(238, 241, 244, 0.44); --np-loading-line: rgba(238, 241, 244, 0.18); }