This document outlines the visual design system, token configuration, and component styling patterns used across the platform. It is designed to be reusable and applicable to sister sites (such as the Vietnam Wedding Guide blog) to ensure consistent, premium editorial presentation.
The palette mimics natural materials (paper, ink, terracotta) and uses custom HSL variables to support a cohesive theme switch between light and dark modes.
| Variable Name | Utility Class | Light Hex / Fallback | Dark Hex / Fallback | Usage |
|---|---|---|---|---|
paper |
bg-paper |
#F4F1E2 |
(Dynamic inverted) | Primary background canvas |
paper-alt |
bg-paper-alt |
#EAE6D6 |
(Dynamic inverted) | Card backgrounds, alternative rows |
ink |
text-ink |
#513229 |
#e2e8f0 (slate) |
Primary body copy, headers |
ink-secondary |
text-ink-secondary |
#786059 |
#94a3b8 |
Supporting text, metadata |
terracotta |
text-terracotta |
#C98E73 |
#C98E73 |
Accent highlights, buttons |
border-light |
border-border-light |
#DDDABF |
#475569 |
Subtle line dividers, borders |
For dynamic primary and highlight colors, configure tailwind variables mapping to rgb(var(--color-primary-50) / <alpha-value>) etc. in tailwind.config.mjs.
Typography defines the grid and reading order. Default browser styles are bypassed entirely.
siteConfig.fonts.families.heading). Used for h1 through h6.Inter, Outfits) with a font-feature-setting of "rlig" 1, "calt" 1.line-height: 1.7).scroll-margin-top: 2rem to prevent overlapping floating navbars during jump links.@tailwindcss/typography (.prose class) with a clean container width limit.Different viewport configurations dictate content density depending on the page type:
1000px (max-w-[1000px]) centered (mx-auto). This allows a grid layout (e.g., 2-column or 3-column) to breathe.720px (max-w-[720px]) centered. This is the optimal line length (60–75 characters per line) for long-form editorial reading.py-16 or py-24 on desktop) are used to isolate content sections, encouraging progressive disclosure.Headless components from Radix UI provide interactive behavior, styled cleanly with Tailwind utility classes.
Interactive elements must explicitly handle the following tailwind-state combinations:
- Focus: focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-terracotta
- Active / Select: data-[state=open]:bg-paper-alt (for dropdown menus/popovers) or selection background highlights.
- Hover: Subtle opacity transitions (transition-opacity hover:opacity-80 or color shifting).
Portal wrapper to avoid parent overflow: hidden constraints.shadow-lg).left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2).bg-black/50 backdrop-blur-sm).The motion system is calibrated to feel invisible and slow. Avoid springy, high-frequency, or bounce transitions.
tailwind.config.mjs tokens):animate-fade-in (Duration: 0.2s ease-in-out)animate-slide-up (Duration: 0.3s ease-out with a subtle 10px translate offset)animate-scale-in (Duration: 0.2s ease-out with scale from 95% to 100%)For custom features or overrides (such as KaTeX formatting or custom scrollbar overrides), stick to utility-aligned classes in global.css:
/* Custom utility override pattern */
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}