Design System

Component & Class Reference

app-container

Main content wrapper. Adds responsive horizontal padding.

Live Demo

This div has .app-container — notice the horizontal padding

Usage

<div class="app-container">
  <!-- page content -->
</div>

Expands to: px-6 sm:px-20 xl:px-15

Utility Classes

Non-typography, non-color reusable CSS classes defined in tailwind.css.

.no-scrollbar

Hides the scrollbar on a scrollable element while keeping it scrollable. Works across WebKit and Firefox.

123456789101112
<div class="no-scrollbar overflow-x-auto">...</div>

.bg-curve-size

Responsive background-image sizing helper: no-repeat, switching to bg-cover at xl. Intended for the project's curve/texture background images (see assets/images) — pair it with a bg-[url(...)] utility. Per-breakpoint image swapping isn't wired up yet, so there's no live demo here.

<div class="bg-curve-size bg-[url(...)]">...</div>

Custom Tailwind Variants

Extended Tailwind variants defined in tailwind.css.

tap:

Targets touch devices only (@media (hover: none)). Use for touch-specific styles.

<div class="opacity-0 tap:opacity-100">Touch only</div>

children:

Applies styles to all descendants of the element (& *).

<div class="children:text-green">Every child text is green</div>

active-class:

Targets elements with the .active class (e.g. Vue Router active links).

<NuxtLink class="active-class:font-bold">Nav Link</NuxtLink>

exact-active:

Targets elements with the .router-link-exact-active class, or any element containing one.

<NuxtLink class="exact-active:underline">Nav Link</NuxtLink>

tight:

Targets landscape viewports under 800px height (phones in landscape).

<div class="py-20 tight:py-8">Section</div>

Typography System

Per the Two Moons responsiveness system, the root html font-size scales with viewport width (text-mobile sm:text-ipad-mini lg:text-ipad-pro xl:text-desktop 2xl:text-2xl), and every named class below is expressed in fixed rem sizes relative to that root — never in Tailwind's built-in text-sm/text-lg scale. Resize the window to see these scale proportionally.

Ginger — display

Font: ginger (custom display face). Main heading styles.

display-1

display-2

display-3

display-4

display-5

display-6

<h1 class="display-1">Hero Heading</h1>
<h2 class="display-3">Section Heading</h2>

Ginger — emphasis

Font: ginger (custom display face). Used for <strong> emphasis inside ginger-styled copy.

Plain ginger text with emphasized strong text inside it

<p class="font-ginger text-green-light">
  Plain text with <strong>emphasis</strong>
</p>

Gilda Display — accent

Font: Gilda Display (serif). Uppercase tracked label face for buttons, nav items and eyebrows. Each class bundles uppercase and tracking-accent (0.3em) — override locally where a call site deviates.

accent-1 — 14px fixed

accent-2 — 13px → 14px (sm)

accent-3 — 12px → 13px (sm)

<h1 class="accent-1">Discover</h1>
<button class="accent-2">Book now</button>
<a class="accent-3">Nav item</a>

Lato — body, button, message

Font: Lato (sans-serif). Default body font set on <body>.

text-16 — default body copy

text-button — button / label text

text-message — large message / quote text

<p class="text-16">Body copy</p>
<button class="text-button">Click me</button>
<p class="text-message">Large quote or message</p>

Colors

The project palette, defined as Tailwind theme colors. Body text defaults to green-dark, swapping to light in dark mode.

light #F9F9F8

black #000000

white #ffffff

green #5B604A

green-light #848B6F

green-dark #414141

<section class="bg-green text-light">
  <h2>Themed section</h2>
</section>

Dark

Add .dark to any container to flip it onto the dark theme: it applies bg-green-dark and text-light, so everything inside reads correctly with no per-element changes. It also activates the dark: variant on every descendant — use it to override individual utilities only when the theme flip isn't enough.

Live Demo

Dark section

This whole block just has .dark on its wrapper. The background and body text colour come along automatically — this paragraph wasn't given a text colour.

This one adds dark:text-green-light, so it only turns green-light while inside a .dark context.

Usage

<!-- Flip a whole section onto the dark theme -->
<section class="dark">
  <h2>Heading</h2>
  <p>Body text is light automatically.</p>

  <!-- Override a single element only in dark context -->
  <p class="dark:text-green-light">Muted line</p>
</section>

.dark expands to bg-green-dark text-light. The dark: variant matches &:where(.dark, .dark *) — the element itself when it has .dark, or any element nested inside one.

Breakpoints

Default Tailwind breakpoints, plus one project-specific addition. Each corresponds to a design artboard width — see CONTEXT.md.

PrefixMin width
(default)0px
sm:640px
lg:1024px
pro:1350px (84.375rem) — custom
xl:1280px
2xl:1536px

Reusable Vue Components

Components follow the shadcn philosophy: a single styled primitive whose look is driven by a variant prop, styles composed with cva (button-variants.ts) and merged with the cn() helper (app/lib/utils.ts).

AppButton

A polymorphic button primitive (renders as <button> by default, or anything via as / as-child). It carries the two button styles ported from the legacy ../swasti project. Colour comes from currentColor, so a button inherits its context — hover any of these.

PropTypeDefaultNotes
variant'line' | 'underline''line'Which ported style to render.
reversebooleanfalseunderline only — starts drawn, wipes out on hover.
asstring | Component'button'Element/component to render as.
as-childbooleanfalse Merge onto the single child instead of a wrapper (underline variant only).
classstringExtra classes, tailwind-merged over the variant.

variant="line"

Uppercase Gilda label + a hairline that scales on hover while the letter-spacing opens up.

<AppButton variant="line">Discover more</AppButton>

variant="underline"

A hairline underline that starts drawn and wipes out on hover. Pass :reverse="false" for the opposite: start hidden and wipe in from the right on hover.

<AppButton variant="underline">Read our story</AppButton>
<AppButton variant="underline" :reverse="false">Read our story</AppButton>

Polymorphic (as / as-child)

Render as a link. Use as for the line variant; either as or as-child for underline.

<AppButton :as="NuxtLink" to="/" variant="line">Home</AppButton>

<AppButton as-child variant="underline">
  <NuxtLink to="/">Home</NuxtLink>
</AppButton>

On a dark surface

Colour is inherited via bg-current / currentColor, so no dark-mode props are needed.

AppCalendar

A single composite wrapping the reka-ui Calendar primitives — no context file, no per-part wrappers, since Reka's CalendarRoot already provides state to every child. Prev/next page the months, keyboard arrows move the focused day, the selected day fills, today is underlined, and days outside the month dim.

July 2026
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
Event Date, July 2026
<script setup>
import { getLocalTimeZone, today } from '@internationalized/date'

const date = ref(today(getLocalTimeZone()))
</script>

<AppCalendar v-model="date" locale="en" />

AppContentBlock

Prismic bridge stack: AppRichText (renders a rich-text field through PrismicRichText, mapping heading/paragraph/label/hyperlink nodes) over AppNavList (a repeatable group of Link fields, each through the AppLink bridge). CTAs resolve reusable-CTA documents transparently since they flow through the same bridge.

Stay With Us

Nestled in the hills, Swasti offers a quiet escape. Learn more about our rooms.

<AppContentBlock
  :text="slice.primary.body"
  :links="slice.items"
  centered
/>

Contact us for the best offers