Skip to contentVibraUI
Palette

Folio theme

A warm linen ground with ink text and one iris accent — the paper look, for a dashboard that should read like a well-set report.

background
card
primary
chart-2
success
danger

Install

The file lands as app/vibra-folio.css. Import it after your globals and set data-preset="folio" on <html>, or on any wrapper.

npx shadcn@latest add @vibra/theme-folio

Needs the @vibra registry in your components.json — set it up once.

The stylesheet

app/vibra-folio.css
/* Folio — the warm paper look: a linen ground, ink text and one iris accent.
   The palette this site wore while the report typography was its default,
   kept whole now that the classic zinc ladder is what Vibra ships. */
[data-preset="folio"] {
  --radius: 0.625rem;

  /* Planes — hue 60–85 at chroma ≤0.012: warm, never yellow. */
  --background: oklch(0.962 0.008 80);
  --surface: oklch(0.978 0.006 82);
  --card: oklch(0.995 0.003 85);
  --popover: oklch(1 0 0);
  --muted: oklch(0.955 0.007 80);
  --secondary: oklch(0.945 0.008 80);
  --accent: oklch(0.945 0.008 80);

  /* Ink. --faint-foreground is for eyebrows, meta and axis titles at 11px/600
     and up — never body copy — and clears 4.5:1 on every plane above. */
  --foreground: oklch(0.22 0.018 55);
  --card-foreground: var(--foreground);
  --popover-foreground: var(--foreground);
  --muted-foreground: oklch(0.47 0.02 65);
  --faint-foreground: oklch(0.505 0.018 65);
  --secondary-foreground: var(--foreground);
  --accent-foreground: var(--foreground);

  /* The accent, and the aliases that carry it. */
  --brand: oklch(0.46 0.13 290);
  --brand-foreground: oklch(0.985 0.004 85);
  --brand-muted: oklch(0.93 0.035 290);
  --primary: var(--brand);
  --primary-foreground: var(--brand-foreground);
  --ring: var(--brand);

  /* Lines. --input is the field and unchecked-control boundary, so it carries
     WCAG 1.4.11's 3:1 against both the page and a card. */
  --border: oklch(0.885 0.012 78);
  --rule: oklch(0.78 0.015 72);
  --input: oklch(0.64 0.015 72);
  --chart-grid: oklch(0.9 0.008 80);

  /* Semantic tones on explicit opaque tints — a colour-mix of a hue-150 tone
     into a hue-60 card drifts the tint to hue ~73 and reads yellow. */
  --success: oklch(0.48 0.13 150);
  --success-foreground: oklch(0.99 0.003 85);
  --success-muted: oklch(0.94 0.045 150);
  --warning: oklch(0.5 0.1 75);
  --warning-foreground: oklch(0.99 0.003 85);
  --warning-muted: oklch(0.95 0.04 85);
  /* 0.52, not the 0.53 the spec names: at 0.53 the destructive text on its own
     10% tint over the page reads 4.45:1, just under the floor every other tone
     clears. One step darker buys the margin and changes nothing else. */
  --danger: oklch(0.52 0.21 25);
  --danger-foreground: oklch(0.99 0.003 85);
  --danger-muted: oklch(0.945 0.025 25);
  --info: oklch(0.5 0.13 250);
  --info-foreground: oklch(0.99 0.003 85);
  --info-muted: oklch(0.945 0.025 250);
  --destructive: var(--danger);

  /* Chart palette: iris, teal, plum, graphite, ochre, sage, brick, stone. The
     first four are hue-distinct and non-semantic; sage and brick sit at 6–7 so
     a third category never reads as a warning. */
  --chart-1: var(--brand);
  --chart-2: oklch(0.52 0.09 200);
  --chart-3: oklch(0.52 0.12 340);
  --chart-4: oklch(0.4 0.015 60);
  --chart-5: oklch(0.58 0.12 80);
  --chart-6: oklch(0.55 0.09 150);
  --chart-7: oklch(0.56 0.16 30);
  --chart-8: oklch(0.6 0.02 75);
  --chart-positive: var(--success);
  --chart-negative: var(--danger);
  --chart-neutral: var(--muted-foreground);
  --chart-axis: var(--muted-foreground);

  /* The sidebar sits one plane below the content it frames. */
  --sidebar: var(--background);
  --sidebar-foreground: var(--foreground);
  --sidebar-primary: var(--brand);
  --sidebar-primary-foreground: var(--brand-foreground);
  --sidebar-accent: oklch(0.925 0.01 80);
  --sidebar-accent-foreground: var(--foreground);
  --sidebar-border: var(--border);
  --sidebar-ring: var(--brand);

  /* Ink-tinted, never black: a neutral drop shadow on a warm ground reads grey. */
  --shadow-sheet: 0 1px 2px oklch(0.25 0.03 60 / 6%), 0 2px 6px -2px oklch(0.25 0.03 60 / 5%);
  --shadow-float: 0 8px 24px -8px oklch(0.25 0.03 60 / 22%), 0 1px 2px oklch(0.25 0.03 60 / 8%);
  --shadow-modal: 0 24px 48px -16px oklch(0.25 0.03 60 / 30%);
  --overlay: oklch(0.25 0.03 60 / 24%);
}

.dark [data-preset="folio"],
[data-preset="folio"].dark,
[data-preset="folio"] .dark {
  --background: oklch(0.165 0.01 60);
  --surface: oklch(0.19 0.01 60);
  --card: oklch(0.225 0.011 62);
  --popover: oklch(0.27 0.011 62);
  --muted: oklch(0.26 0.011 62);
  --secondary: oklch(0.285 0.012 62);
  --accent: oklch(0.285 0.012 62);

  --foreground: oklch(0.95 0.008 80);
  --card-foreground: var(--foreground);
  --popover-foreground: var(--foreground);
  --muted-foreground: oklch(0.7 0.012 70);
  --faint-foreground: oklch(0.695 0.012 70);
  --secondary-foreground: var(--foreground);
  --accent-foreground: var(--foreground);

  --brand: oklch(0.78 0.11 290);
  --brand-foreground: oklch(0.18 0.02 290);
  --brand-muted: oklch(0.28 0.05 290);
  --primary: var(--brand);
  --primary-foreground: var(--brand-foreground);
  --ring: var(--brand);

  --border: oklch(0.315 0.012 62);
  --rule: oklch(0.4 0.014 65);
  --input: oklch(0.55 0.012 62);
  --chart-grid: oklch(0.335 0.012 62);

  --success: oklch(0.8 0.15 150);
  --success-foreground: oklch(0.16 0.03 150);
  --success-muted: oklch(0.3 0.04 150);
  --warning: oklch(0.84 0.14 85);
  --warning-foreground: oklch(0.16 0.03 85);
  --warning-muted: oklch(0.31 0.04 85);
  --danger: oklch(0.78 0.12 25);
  --danger-foreground: oklch(0.16 0.03 25);
  --danger-muted: oklch(0.31 0.035 25);
  --info: oklch(0.79 0.1 250);
  --info-foreground: oklch(0.16 0.03 250);
  --info-muted: oklch(0.3 0.04 250);
  --destructive: var(--danger);

  --chart-1: var(--brand);
  --chart-2: oklch(0.76 0.09 200);
  --chart-3: oklch(0.76 0.1 340);
  --chart-4: oklch(0.82 0.012 75);
  --chart-5: oklch(0.8 0.12 82);
  --chart-6: oklch(0.76 0.1 150);
  --chart-7: oklch(0.74 0.14 30);
  --chart-8: oklch(0.57 0.015 70);
  --chart-positive: var(--success);
  --chart-negative: var(--danger);
  --chart-neutral: var(--muted-foreground);
  --chart-axis: var(--muted-foreground);

  --sidebar: var(--background);
  --sidebar-foreground: var(--foreground);
  --sidebar-primary: var(--brand);
  --sidebar-primary-foreground: var(--brand-foreground);
  --sidebar-accent: oklch(0.245 0.012 62);
  --sidebar-accent-foreground: var(--foreground);
  --sidebar-border: var(--border);
  --sidebar-ring: var(--brand);

  /* A lamp-lit desk: a sheet is lifted by a top highlight rather than a drop. */
  --shadow-sheet: inset 0 1px 0 oklch(1 0 0 / 5%);
  --shadow-float: 0 12px 32px -8px oklch(0 0 0 / 60%), inset 0 1px 0 oklch(1 0 0 / 6%);
  --shadow-modal: 0 24px 64px -12px oklch(0 0 0 / 70%);
  --overlay: oklch(0 0 0 / 60%);
}