Theme Documentation

Tours is fully re-themeable. The visual system is built on Tailwind CSS whose color utilities are driven by CSS variables, declared in src/app/globals.css and wired into Tailwind in tailwind.config.ts. The default brand identity is blue, with an orange secondary. Because the palettes are variables, an admin can re-skin the storefront from Theme Options → Appearance without touching code or rebuilding.

How theming works

  1. globals.css declares the design tokens as CSS variables under :root (each color is a space-separated RGB triplet, e.g. 59 130 246).
  2. tailwind.config.ts maps each token to a Tailwind color using rgb(var(--token) / <alpha-value>), so utilities like bg-brand-600, text-heading, and border-line resolve to those variables and still honor opacity modifiers (bg-brand-600/30).
  3. The admin Theme Options → Appearance screen writes overrides scoped to the storefront wrapper class .site-theme, so the admin panel's own chrome is never affected by a customer's brand color.
TS
// tailwind.config.ts (excerpt)
colors: {
  brand:       { 500: "rgb(var(--brand-500) / <alpha-value>)", /* 50…950 */ },
  secondary:   { 500: "rgb(var(--secondary-500) / <alpha-value>)", /* 50…950 */ },
  surface:     "rgb(var(--surface) / <alpha-value>)",
  "surface-2": "rgb(var(--surface-2) / <alpha-value>)",
  heading:     "rgb(var(--heading) / <alpha-value>)",
  body:        "rgb(var(--body) / <alpha-value>)",
  line:        "rgb(var(--line) / <alpha-value>)",
  // `accent` and `ink` are STATIC hex scales (below) — not variable-driven.
}

Token groups

Group Tokens Role
Brand --brand-50--brand-950 Primary palette (blue). Buttons, links, active states, focus rings
Secondary --secondary-50--secondary-950 Secondary palette (orange). Highlights, accents, gradient stops
Ink ink-50ink-950 (static slate) Neutral scale for text, borders and surfaces
Accent accent-50accent-900 (static orange) Fixed accent scale defined directly in the config
Surfaces --surface, --surface-2 Page / panel backgrounds
Text --heading, --body, --txt-muted Headings, body copy, secondary/muted text
Lines --line Borders & dividers

brand and secondary (the re-themeable palettes) plus the semantic surface / surface-2 / heading / body / line tokens are variable-driven. accent and ink are static scales defined directly in tailwind.config.ts.

Brand scale — the real :root values (blue)

These are the exact default triplets from src/app/globals.css. The storefront overrides them within .site-theme when an admin picks a brand color.

CSS
:root {
  /* Brand palette (blue default). Storefront overrides these within .site-theme. */
  --brand-50:  239 246 255;
  --brand-100: 219 234 254;
  --brand-200: 191 219 254;
  --brand-300: 147 197 253;
  --brand-400: 96 165 250;
  --brand-500: 59 130 246;
  --brand-600: 37 99 235;
  --brand-700: 29 78 216;
  --brand-800: 30 64 175;
  --brand-900: 30 58 138;
  --brand-950: 23 37 84;
}

Secondary scale (orange) & semantic tokens

CSS
:root {
  /* Secondary palette (orange default). Overridable from Theme Options → Secondary Color. */
  --secondary-50:  255 247 237;
  --secondary-100: 255 237 213;
  --secondary-200: 254 215 170;
  --secondary-300: 253 186 116;
  --secondary-400: 251 146 60;
  --secondary-500: 249 115 22;
  --secondary-600: 234 88 12;
  --secondary-700: 194 65 12;
  --secondary-800: 154 52 18;
  --secondary-900: 124 45 18;
  --secondary-950: 67 20 7;

  /* Semantic neutral tokens (light defaults). Dark mode + theme colors override these. */
  --surface:   255 255 255;
  --surface-2: 248 250 252;
  --heading:   15 23 42;
  --body:      30 41 59;
  --txt-muted: 100 116 139;
  --line:      226 232 240;
}

Ink — the static neutral scale

ink-* is the neutral (slate) scale used for text, borders and surfaces throughout the app. It is fixed in tailwind.config.ts (not re-themeable), so neutrals stay consistent regardless of the chosen brand color.

TS
// tailwind.config.ts (excerpt)
ink: {
  50:  "#f8fafc", 100: "#f1f5f9", 200: "#e2e8f0", 300: "#cbd5e1",
  400: "#94a3b8", 500: "#64748b", 600: "#475569", 700: "#334155",
  800: "#1e293b", 900: "#0f172a", 950: "#020617",
}

Use text-ink-* / border-ink-* / bg-ink-* for neutrals and bg-brand-* / text-brand-* / ring-brand-* for primary accents. Never hardcode a hex value in a component.

Light & dark mode

Dark mode is scoped to the storefront wrapper so the admin panel is unaffected: the dark overrides live under .site-theme.dark. Because every storefront surface is painted with the semantic utilities (bg-surface, text-heading, text-body, border-line, and the .site-theme remaps of bg-white / text-ink-* / border-ink-*), toggling the .dark class re-paints the whole storefront from these overrides — no per-component dark variants needed for neutrals.

CSS
/* Dark mode is scoped to the storefront wrapper (.site-theme.dark). */
.site-theme.dark {
  --surface:   17 24 39;
  --surface-2: 30 41 59;
  --heading:   248 250 252;
  --body:      203 213 225;
  --txt-muted: 148 163 184;
  --line:      51 65 85;
}

The admin panel has its own cohesive dark palette (a slate scheme under html:has(.admin-shell.dark) that remaps the light Tailwind utilities), kept separate from the storefront theme.

Re-theming from the admin panel

Admins change the look under Admin → Theme Options → Appearance:

  • Brand Color — overrides the --brand-* scale (default blue).
  • Secondary Color — overrides the --secondary-* scale (default orange).
  • Images — upload/format presets the ImageUpload server pipeline reads.

The chosen colors are injected as CSS-variable overrides on the .site-theme scope at runtime, so the catalog, tour pages, checkout and customer area all re-skin instantly. The admin UI keeps its own fixed brand-tinted chrome.

Changing the brand color in code

To change the default permanently, edit the --brand-* triplets in src/app/globals.css. Values are space-separated RGB channels (not hex), so Tailwind's <alpha-value> opacity modifiers keep working.

CSS
:root {
  /* The shipped default is blue (Tailwind blue-500 / 600 / 700). */
  --brand-500: 59 130 246;
  --brand-600: 37 99 235;
  --brand-700: 29 78 216;
}

After editing, every bg-brand-600, text-brand-700, ring-brand-500, etc. across the app reflects the new color — including derived tokens such as the glow shadow (0 10px 40px rgb(var(--brand-500) / 0.30)) and the brand-gradient background image.

Typography

Fonts are bound to CSS variables provided by next/font and mapped in tailwind.config.ts:

TS
fontFamily: {
  sans:    ["var(--font-inter)",   "system-ui", "sans-serif"], // body
  display: ["var(--font-raleway)", "system-ui", "sans-serif"], // headings
}
  • Body copy uses font-sans (Inter).
  • Headings (h1h6) use font-display (Raleway) via a base rule in globals.css:
CSS
h1, h2, h3, h4, h5, h6 {
  @apply font-display tracking-tight;
}

Helper classes & tokens

globals.css also ships reusable component/utility classes that lean on the brand tokens:

Class Purpose
.section / .section-title / .section-subtitle Consistent storefront section spacing & headings
.badge / .badge-vibrant Brand-tinted pills (bg-brand-50 text-brand-700)
.btn-vibrant Gradient-glow primary button (bg-brand-600 + brand ring)
.glass / .glass-dark Frosted-glass surfaces
.card-hover / .card-vibrant Lift-on-hover feature/pricing tiles
.text-gradient Brand → secondary gradient headline text
.scrollbar-thin / .thin-scroll Thin tinted scrollbars for panels & menus

The .text-gradient and .brand-gradient background blend the brand and secondary tokens:

CSS
.text-gradient {
  background-image: linear-gradient(120deg,
    rgb(var(--brand-700)) 0%,
    rgb(var(--brand-500)) 45%,
    rgb(var(--secondary-500)) 100%);
}

Custom keyframes/animations (shimmer for skeletons, plus fade/slide helpers) round out the system.


© CreativeCape Solutions · creative-cape.com · support@creative-cape.com