imitation
← all crawls

Gallery | Luxury Villa Photos | Indo House

https://www.indohousestjohn.com/gallery

Explore stunning photos of Indo House, a Balinese-inspired luxury villa in St. John, USVI. View great room, guest suites, exterior, and aerial views.

indohousestjohn.com screenshot

Visuals

Colors

Primary
#0000ee
Accent
#cbaf7b
Background
#ffffff
Surface
#f9f7f4
Text Primary
#6d6d6d
Text Secondary
#030303

Typography

Aa
Display
Cormorant Garamond
56px / w700
Aa
Heading
Cormorant Garamond
31.2px / w700
Aa
Body
system-ui
16px / w400
Aa
Label
system-ui
14px / w600

Spacing

Xs
8px
Sm
10px
Md
16px
Lg
20px
Xl
24px

Radius

Sm
8px
Md
16px
Lg
20px
Pill
9999px

Shadows

Sm
Lg

Mode

Light mode
Background
Sample text on canvas
Bg#ffffff
Text#6d6d6d
Muted#030303

Motion

Levelsubtle
Duration200ms
Easingcubic-bezier(0.165, 0.84, 0.44, 1)

Stack

Frameworkwebflow
Iconscustom

Full Palette · 24 tokens

Brand
accent
#cbaf7b
accent-dark
#b89a68
primary
#0000ee
primary-hover
#0000cc
Surface
canvas
#ffffff
surface-elevated
#ffffff
surface-soft
#f9f7f4
surface-warm
#faf8f5
Text
body
#030303
ink
#6d6d6d
muted
#333333
muted-soft
rgba(3, 3, 3, 0.7)
muted-subtle
rgba(3, 3, 3, 0.6)
on-accent
#000000
on-primary
#ffffff
Hairlines & Borders
border-strong
rgba(3, 3, 3, 0.2)
hairline
rgba(3, 3, 3, 0.1)
Semantic
error
#cb2431
link
#0000ee
link-hover
#0000cc
success
#22863a
Other
body-strong
#222222
inset-border
#030303
label-warm
#b09a6f

Typography Roles · 11

body-md
Aa
16px / w400
body-sm
Aa
14.4px / w400
button
Aa
14.4px / w400
caption
Aa
13px / w400
display-lg
Aa
48.8px / w700
display-xl
Aa
56px / w700
label-md
Aa
14px / w600
label-warm
Aa
14px / w600
nav-link
Aa
16px / w600
title-md
Aa
31.2px / w700
title-sm
Aa
24px / w600

Components · 24

button-outline
backgroundColortransparent
padding12px 24px
rounded{rounded.DEFAULT}
textColor{colors.body}
typography{typography.button}
button-primary
backgroundColor{colors.accent}
padding14.4px 28.8px
rounded{rounded.DEFAULT}
textColor{colors.on-accent}
typography{typography.button}
button-primary-disabled
backgroundColor{colors.surface-soft}
rounded{rounded.DEFAULT}
textColor{colors.muted-soft}
typography{typography.button}
button-primary-hover
backgroundColor{colors.accent-dark}
rounded{rounded.DEFAULT}
textColor{colors.on-accent}
typography{typography.button}
button-secondary
backgroundColortransparent
padding14.4px 28.8px
rounded{rounded.DEFAULT}
textColor{colors.body}
typography{typography.button}
button-secondary-hover
backgroundColor{colors.surface-soft}
rounded{rounded.DEFAULT}
textColor{colors.body}
typography{typography.button}
footer
backgroundColor{colors.canvas}
padding{spacing.xl} {spacing.md}
textColor{colors.muted}
typography{typography.body-sm}
gallery-card
backgroundColor{colors.surface-elevated}
padding0
rounded{rounded.md}
textColor{colors.body}
gallery-card-image
backgroundColor{colors.surface-soft}
rounded{rounded.md}
textColor{colors.body}
gallery-grid
backgroundColortransparent
padding{spacing.md}
textColor{colors.body}
hero-band
backgroundColor{colors.canvas}
padding{spacing.section-lg} {spacing.md}
textColor{colors.body}
typography{typography.display-lg}
hero-cta-group
backgroundColortransparent
padding{spacing.lg} 0 0 0
textColor{colors.body}
hero-description
backgroundColortransparent
textColor{colors.muted-soft}
typography{typography.body-md}
hero-headline
backgroundColortransparent
textColor{colors.body}
typography{typography.display-lg}
label-text
backgroundColortransparent
textColor{colors.label-warm}
typography{typography.label-warm}
link-inline
backgroundColortransparent
textColor{colors.link}
typography{typography.body-md}
nav-dropdown-toggle
backgroundColortransparent
padding16px 40px 16px 16px
rounded{rounded.pill}
textColor{colors.body-strong}
typography{typography.nav-link}
nav-dropdown-toggle-active
backgroundColortransparent
rounded{rounded.pill}
textColor{colors.body}
typography{typography.nav-link}
nav-logo
backgroundColortransparent
height40px
textColor{colors.label-warm}
typography{typography.display-lg}
nav-tertiary-link
backgroundColortransparent
padding10px 18px
rounded{rounded.sm}
textColor{colors.body}
typography{typography.nav-link}
section-container
backgroundColortransparent
padding{spacing.section-lg} 0
textColor{colors.body}
text-input
backgroundColor{colors.canvas}
height48px
padding14px 16px
rounded{rounded.sm}
textColor{colors.body}
typography{typography.body-md}
text-input-focus
backgroundColor{colors.canvas}
rounded{rounded.sm}
textColor{colors.body}
typography{typography.body-md}
top-nav
backgroundColor{colors.canvas}
height80px
textColor{colors.body-strong}
typography{typography.nav-link}

design.md

Indo House Design System

Overview

Indo House presents a refined luxury hospitality experience rooted in Balinese-inspired design sensibilities, translated into a digital presence that feels both editorially spacious and warmly intimate. The visual system rests on a pristine {colors.canvas} white foundation, allowing the photography of sunlit interiors and sweeping coastal vistas to command full attention. Brand voltage concentrates deliberately in the warm gold {colors.accent} reserve buttons—a sophisticated, earthy alternative to conventional hospitality blues—that signals exclusivity without ostentation.

The typographic voice operates as a deliberate dual-tone conversation: {typography.display-lg} Cormorant Garamond headlines at 700 weight establish an old-world luxury cadence, their tight negative letter-spacing (-0.488px on the largest size) creating the dense, authoritative texture of premium print editorial. Beneath this, {typography.body-md} system-ui body copy at a restrained 400 weight and 1.6 line-height carries narrative content with quiet clarity, never competing with the serif's theatrical presence. This hierarchy—bold serif headers above light sans-serif body—is the single typographic move that defines the system's character.

Shape language favors soft confidence over geometric severity: the dominant {rounded.md} 16px radius on gallery cards creates approachable containers for imagery, while {rounded.DEFAULT} 12px on interactive elements balances friendliness with purpose. The system avoids sharp corners entirely; even the most functional surfaces carry some curvature. A subtle {extensions.shadows.card} elevation (0 6px 24px at 10% opacity) lifts gallery cards from the canvas just enough to suggest physicality without the heaviness of e-commerce product cards.

The gallery page specifically operates as a visual storytelling subsystem: a two-column layout places editorial copy left and an overlapping image collage right, creating depth through layering rather than decoration. The warm {colors.label-warm} gold used on navigational labels and the logo ties back to the CTA button, creating a cohesive brand accent thread that runs through interactive elements while leaving the photography uncolored by interface chrome.

Key Characteristics:

  • Warm luxury palette anchored by {colors.accent} (#cbaf7b) gold CTAs against {colors.canvas} white
  • Dual-typeface system: {typography.display-lg} Cormorant Garamond serif headlines (700 weight) paired with {typography.body-md} system-ui body (400 weight)
  • Soft radius vocabulary dominated by {rounded.md} (16px) on cards and {rounded DEFAULT} (12px) on buttons
  • Generous {spacing.section-lg} (48px) vertical rhythm between major sections
  • Muted text hierarchy using {colors.muted-soft} (70% opacity black) for secondary content
  • Subtle {extensions.shadows.card} elevation on gallery cards without heavy layering
  • {typography.nav-link} navigation at 600 weight in {colors.body-strong} for clear wayfinding
  • {colors.link} traditional blue reserved for semantic links only, not brand expression

Colors

Brand & Accent

  • Primary ({colors.primary} — #0000ee): Standard link blue, used exclusively for inline hyperlinks and semantic link actions. Not a brand identity color.
  • Primary Hover ({colors.primary-hover} — #0000cc): Darkened blue state for link interactions.
  • Accent ({colors.accent} — #cbaf7b): Signature warm gold/beige serving as the sole brand color voltage. Applied to {component.button-primary} Reserve CTAs and the logo wordmark. Evokes sand, sunlit wood, and natural luxury materials.
  • Accent Dark ({colors.accent-dark} — #b89a68): Deepened gold for hover states on {component.button-primary-hover}, providing tactile feedback on the primary interactive surface.

Surface

  • Canvas ({colors.canvas} — #ffffff): Pure white foundational background across all page regions. No tints, gradients, or texture overlays—the canvas is intentionally neutral to let villa photography dominate.
  • Surface Soft ({colors.surface-soft} — #f9f7f4): Barely warmed off-white for subtle container differentiation when needed.
  • Surface Warm ({colors.surface-warm} — #faf8f5): Cream-adjacent tint for optional warmth in card backgrounds.
  • Surface Elevated ({colors.surface-elevated} — #ffffff): White elevated surfaces (cards, modals) that may cast shadows. Functionally identical to canvas but semantically distinct for layering.

Text

  • Ink ({colors.ink} — #6d6d6d): Medium-gray primary text color for body copy, navigation labels, and supporting content. Softer than pure black for reduced visual fatigue.
  • Body ({colors.body} — #030303): Near-black for maximum contrast text—headlines, primary CTAs, and critical UI labels requiring emphasis.
  • Body Strong ({colors.body-strong} — #222222): Dark charcoal for navigation links and elements needing more weight than {colors.ink} but less than absolute black.
  • Muted ({colors.muted} — #333333): Mid-gray for secondary information, captions, and de-emphasized metadata.
  • Muted Soft ({colors.muted-soft} — rgba(3, 3, 3, 0.7)): Black at 70% opacity—the workhorse for body paragraph text in {component.hero-description} and general content, providing softer reading than solid black.
  • Muted Subtle ({colors.muted-subtle} — rgba(3, 3, 3, 0.6)): Black at 60% opacity for tertiary text, placeholders, and truly subordinate information.
  • On Primary ({colors.on-primary} — #ffffff): White text for readability against {colors.primary} blue links or any dark background.
  • On Accent ({colors.on-accent} — #000000): Black text for strong contrast against {colors.accent} gold buttons.
  • Label Warm ({colors.label-warm} — #b09a6f): Muted gold used for the logo wordmark, section labels (h4), and decorative text accents that tie to the brand gold without full saturation.

Hairlines & Borders

  • Hairline ({colors.hairline} — rgba(3, 3, 3, 0.1)): 10% opacity black for subtle dividers, input borders, and outline buttons. Nearly invisible at a glance, present on close inspection.
  • Border Strong ({colors.border-strong} — rgba(3, 3, 3, 0.2)): 20% opacity black for focused states and borders needing more visibility.
  • Inset Border ({colors.inset-border} — #030303): Solid near-black used exclusively as an {extensions.shadows.inset} inner shadow (1px inset) for focus rings or pressed states.

Semantic

  • Link ({colors.link} — #0000ee): Traditional web blue for all inline hyperlinks. Distinguished from brand color to maintain semantic clarity.
  • Link Hover ({colors.link-hover} — #0000cc): Darkened blue on interaction.
  • Success ({colors.success} — #22863a): Green for confirmation states (form submissions, availability indicators).
  • Error ({colors.error} — #cb2431): Red for validation errors and alert states.

Typography

Font Family

The type system employs a carefully curated two-family pairing. Cormorant Garamond (served via Google Fonts with weights 300–700) functions as the exclusive display and headline typeface, bringing the elegant, slightly organic character of a modernized old-style serif. It conveys heritage, craftsmanship, and the tactile quality of printed luxury editorials. The fallback stack includes Georgia, serif for environments where the webfont fails to load.

System UI (system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif) handles all body copy, UI labels, navigation, buttons, and functional text. This native-first stack ensures crisp rendering at small sizes, optimal legibility for longer reading passages, and platform-appropriate feel (San Francisco on macOS, Segoe on Windows). No custom sans-serif is loaded—the system deliberately relies on OS-native fonts for body text to maintain performance and familiarity.

Hierarchy

| Token | Size | Weight | Line Height | Letter Spacing | Use | |---|---|---|---|---|---| | {typography.display-xl} | 56px | 700 | 1.05 | -0.56px | Hero-level page titles (largest context) | | {typography.display-lg} | 48.8px | 700 | 1.04 | -0.488px | Main page headlines (e.g., "Villa Gallery") | | {typography.title-md} | 31.2px | 700 | 1.04 | -0.312px | Section headings, sub-page titles | | {typography.title-sm} | 24px | 600 | 1.25 | -0.02em | Card titles, modal headers | | {typography.body-md} | 16px | 400 | 1.6 | 0 | Paragraph text, descriptions | | {typography.body-sm} | 14.4px | 400 | 1.5 | 0 | Button labels, compact body | | {typography.label-md} | 14px | 600 | 1.71 | 0 | Navigation links, UI labels | | {typography.label-warm} | 14px | 600 | 1.71 | 0 | Section labels, decorative labels in {colors.label-warm} | | {typography.button} | 14.4px | 400 | 1.38 | 0 | CTA button text | | {typography.nav-link} | 16px | 600 | 1.5 | 0 | Top navigation menu items | | {typography.caption} | 13px | 400 | 1.46 | 0 | Fine print, timestamps, metadata |

Principles

The typography system trusts size and family difference as its primary hierarchy signals rather than weight variation within a family. Cormorant Garamond at 700 weight is consistently bold—all headline levels share this weight—while the size differential (48.8px vs. 31.2px) establishes level distinction. Body text never exceeds 400 weight, creating a stark contrast between "voice" (headlines) and "content" (body) that feels editorial rather than utilitarian.

Negative letter-spacing on display sizes (-0.488px on {typography.display-lg}, proportional on others) tightens the serif characters for a denser, more luxurious feel—mimicking the tracking adjustments seen in high-end magazine spreads. This is applied consistently to all Cormorant instances 24px and above.

Color also carries hierarchical weight: {colors.body} near-black for headlines, {colors.muted-soft} (70% black) for paragraphs, and {colors.ink} medium-gray for supporting navigation. The {colors.label-warm} gold on h4 labels and the logo creates a separate decorative tier that brands without shouting.

Uppercase is avoided entirely—even the logo "INDOHOUSE" renders in spaced caps via styling rather than a capped font variant. Italics are reserved for future use (citations, foreign terms); the current page uses none.

Note on Font Substitutes

Cormorant Garamond is available freely from Google Fonts (https://fonts.googleapis.com/css?family=Cormorant+Garamond:300,400,500,600,700). For implementations unable to load Google Fonts, the fallback Georgia, serif provides acceptable (though less refined) rendering. The system-ui body stack requires no substitution—it maps natively to every modern operating system. If a more designed sans-serif is desired for body text in specific contexts, Inter (variable font) or Source Sans Pro would align with the geometric-neutral character of the current system font, though neither is currently loaded by the site.

CSS variable names to define if implementing a token system:

--font-display: 'Cormorant Garamond', Georgia, serif;
--font-body: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

Layout

Spacing System

  • Base unit: 4px (implicit), with practical tokens derived from observed values.
  • Tokens: {spacing.xxs} (6px — micro-adjustments, icon gaps), {spacing.xs} (8px — tight internal padding), {spacing.sm} (10px — compact element spacing), {spacing.md} (16px — standard component gap, default grid gutter), {spacing.lg} (20px — comfortable internal padding), {spacing.xl} (24px — section-internal separation), {spacing.xxl} (29px — observed specific spacing between hero text and CTAs), {spacing.section} (40px — vertical section padding), {spacing.section-lg} (48px — major section boundaries, article/container padding).
  • Section padding (vertical): {spacing.section-lg} (48px) — used on the {component.hero-band} article container and major content sections.
  • Card internal padding: Gallery cards ({component.gallery-card}) use 0 internal padding (edge-to-edge imagery); text-bearing cards would use {spacing.lg} (20px).
  • Gutters: {spacing.md} (16px) between grid columns in the two-column hero/gallery layout.

Grid & Container

  • Max content width: 1440px (observed on <article>, <section>, and <nav> containers).
  • Density choice: Editorial/luxury density—generous whitespace, large imagery, minimal information per viewport. This is not a marketplace or dashboard; breathability is the priority.
  • Desktop grid behavior: The hero and gallery section uses a 2-column asymmetric grid (text column ~40%, image column ~60%) with {spacing.md} gutters. The image column contains overlapping gallery cards positioned with negative margins or absolute positioning to create the layered collage effect.
  • Hero column splits: Left column holds the {component.hero-headline} ("Villa Gallery"), {component.hero-description} paragraph, and {component.hero-cta-group} (Reserve + Contact Us buttons). Right column holds the stacked/overlapping {component.gallery-card} elements showing villa photography.

Whitespace Philosophy

The system practices editorial airiness—whitespace is not empty space but an active design element that confers luxury. Horizontal margins are wide (container centered at 1440px max within larger viewports). Vertical rhythm is measured in 40–48px increments between major sections. Within the hero, {spacing.xxl} (29px) separates the description paragraph from the CTA group—a specific, non-standard value indicating intentional visual calibration rather than systematic rigidity.

Header Architecture

|-----------------------------------------------------------------------|
| INDOHOUSE        Explore v     Plan v              Instagram  [Reserve]|
| (label-warm)   (nav-link)   (nav-link)         (tertiary) (primary)  |
|-----------------------------------------------------------------------|
                    ^1440px max-width container^

The {component.top-nav} spans full viewport width with internal content constrained to 1440px. Logo sits flush left in {colors.label-warm}. Navigation dropdowns (Explore, Plan) follow with chevron indicators. Right side holds the Instagram {component.nav-tertiary-link} and the prominent {component.button-primary} Reserve CTA in {colors.accent} gold. Height approximately 80px based on 16px vertical padding on nav items plus content.

Hero Section

|------------------------------------------------------------|
|                                                            |
|  Villa Gallery                                             |  [Gallery Image 1 - tall]
|                            [Gallery Image 2 - overlapping] |
|  A visual journey through...                               |
|                                                            |
|  [Reserve]  [Contact us]          [Gallery Image 3 - wide] |
|                                                            |
|------------------------------------------------------------|
|                 ^ 1440px container, 48px vertical pad       |

Two-column layout: left column (text) and right column (image collage). The three gallery cards overlap each other, with the center/aerial image appearing to layer in front of the stair interior and room interior images. This creates perceived depth without shadows between the cards themselves—only the bottom-most card casts {extensions.shadows.card}.

Elevation & Depth

| Level | Treatment | Use | |---|---|---| | 0 (Flat) | No shadow, {colors.canvas} background | Base page surface, nav bar, footer | | 1 (Hairline) | {extensions.shadows.inset} — 1px inset near-black | Focus rings, pressed button states | | 2 (Soft lift) | {extensions.shadows.card} — 0 6px 24px at 10% opacity | Gallery cards, elevated containers | | 3 (Modal) | {extensions.shadows.lg} — 0 16px 48px at 12% opacity | Future modals, dropdown panels (not observed but anticipated) |

The elevation philosophy is restrained layering. Unlike e-commerce sites where every card floats aggressively, Indo House uses shadow sparingly—only the gallery image cards in the hero collage exhibit {extensions.shadows.card} elevation, and even then the shadow is soft (24px blur, low opacity) to avoid visual competition with photography. The overall tendency is toward flat or near-flat surfaces with depth created through overlapping positioning rather than shadow stacking.

Shadows are neutral/black-toned, not colored or cool-tinted. This maintains the warm, material honesty of the brand—shadows behave like real-world occlusion rather than graphic effects.

Decorative Depth

No gradient washes, pattern overlays, or atmospheric background treatments are present. Depth comes exclusively from: (1) the overlapping gallery card composition in the hero, (2) the single shadow layer on those cards, and (3) photographic content itself (the images provide all the visual complexity). The canvas remains pure {colors.canvas} white throughout.

Shapes

Border Radius Scale

| Token | Value | Use | |---|---|---| | {rounded.sm} | 8px | Small UI elements, tertiary nav links, potential input fields | | {rounded.DEFAULT} | 12px | Buttons (primary, secondary, outline), standard interactive elements | | {rounded.md} | 16px | Gallery cards, image containers, content cards (dominant radius) | | {rounded.lg} | 20px | Larger feature cards, hero image containers (less frequent) | | {rounded.xl} | 24px | Modal panels, large promotional surfaces (anticipated) | | {rounded.pill} / {rounded.full} | 9999px | Pill-shaped tags, avatar circles (not currently observed) |

The shape language is consistently soft—no sharp corners exist in the system. The 16px radius on gallery cards is the most frequently occurring (88 instances in extracted CSS), making it the signature curve of the brand. Buttons at 12px are slightly tighter, suggesting tactility without the playfulness of fully rounded pills.

Photography Geometry

Gallery images are displayed in portrait and landscape orientations within rounded rectangles ({rounded.md} 16px corners). The hero collage mixes aspect ratios: the stair-interior image appears roughly 3:4 portrait, the room-interior image is wider (perhaps 4:3 or 16:10), and the central aerial/satellite image is closer to square or slightly portrait. Images fill their containers edge-to-edge with no additional border, margin, or frame—pure photography within soft rounded vessels.

No circular crops, no diagonal treatments, no full-bleed edge-to-edge browser-width images were observed in this view. All imagery is contained within the card system.

Components

No hover states documented. Hover behavior is unreliable to extract from a single screenshot. State variants live as separate entries in the components: frontmatter (e.g. {component.button-primary-hover}, {component.text-input-focus}); add hover styling at implementation time per your stack's conventions.

Buttons

{component.button-primary} — The signature call-to-action using {colors.accent} gold background with {colors.on-accent} black text. Renders at {typography.button} (14.4px, weight 400) in a {rounded.DEFAULT} (12px) capsule with {padding} 14.4px horizontal × 28.8px vertical. Used for the "Reserve" action in both the navigation bar and hero CTA group. No box-shadow in default state; transitions on background-color per {extensions.motion.easing}. Hover state is {component.button-primary-hover} with darkened {colors.accent-dark}. Disabled state {component.button-primary-disabled} falls back to {colors.surface-soft} background with {colors.muted-soft} text.

{component.button-secondary} — Transparent-background button with {colors.body} text, intended for secondary actions. Shares dimensions and radius with primary. Observed implicitly in the system's structure; the "Contact us" button in the hero likely uses {component.button-outline} (below) or this variant depending on border treatment.

{component.button-outline} — Ghost/outlined button with transparent background, {colors.body} text, and a {colors.hairline} border (1px, 10% black). Same {typography.button} and {rounded.DEFAULT} as primary. Used for the "Contact us" CTA alongside the Reserve button, providing visual hierarchy without competing for attention. On hover, expect {colors.surface-soft} background fill (as {component.button-secondary-hover}).

{component.nav-tertiary-link} — Minimal text link styled as a subtle button: transparent background, {colors.body} text at {typography.nav-link} (16px, weight 600), {rounded.sm} (8px), padding 10px × 18px. Used for the "Instagram" link in the navigation bar—present but understated. Has a transparent border that may become visible on focus/hover.

Cards & Containers

{component.gallery-card} — The dominant visual component: a white ({colors.surface-elevated}) container with {rounded.md} (16px) radius holding villa photography. Casts {extensions.shadows.card} (0 6px 24px at 10% opacity) for soft elevation. Zero internal padding—imagery extends edge-to-edge. In the hero section, multiple gallery cards are positioned with negative margins or absolute positioning to create the layered collage effect. The central/aerial image card overlaps the others, suggesting z-index layering.

{component.section-container} — Vertical rhythm container applying {spacing.section-lg} (48px) top/bottom padding. Holds the hero content and would wrap subsequent gallery sections. Transparent background, inheriting {colors.canvas}.

{component.gallery-grid} — The two-column grid wrapper managing the text/image split. Uses {spacing.md} (16px) gutters between columns. Contains the left-rail editorial content and right-rail image collage.

{component.hero-band} — The full-width hero section background area. White ({colors.canvas}) background, {spacing.section-lg} vertical padding. Contains the {component.section-container} and establishes the initial scroll viewport.

Navigation

{component.top-nav} — Fixed or sticky top navigation bar spanning viewport width, approximately 80px tall. White ({colors.canvas}) background, no bottom border or shadow (flat against the page). Content constrained to 1440px max-width centered.

{component.nav-logo} — "INDOHOUSE" wordmark rendered in {typography.display-lg} Cormorant Garamond (though smaller than the 48.8px headline scale—likely scaled down via CSS or a dedicated logo lockup) in {colors.label-warm} gold. No background, transparent.

{component.nav-dropdown-toggle} — Interactive navigation items ("Explore", "Plan") with transparent background, {colors.body-strong} text at {typography.nav-link} (16px, weight 600). Includes right-padding (40px) for chevron indicator. {rounded.pill} radius suggests the hit area is capsule-shaped though visually rectangular. Active/open state is {component.nav-dropdown-toggle-active}.

Text & Input Components

{component.hero-headline} — The "Villa Gallery" h1 heading using {typography.display-lg} (48.8px, weight 700, -0.488px letter-spacing) in {colors.body} near-black. Cormorant Garamond. No background, inherits canvas.

{component.hero-description} — Supporting paragraph ("A visual journey through Indo House...") in {typography.body-md} (16px, weight 400, line-height 1.6) with {colors.muted-soft} text (70% black opacity). Sets the editorial tone before the CTAs.

{component.hero-cta-group} — Horizontal flex container holding the {component.button-primary} (Reserve) and {component.button-outline} (Contact us) with {spacing.lg} (20px) gap between them. Top margin of {spacing.xxl} (29px) separates it from the description paragraph.

{component.text-input} — Anticipated form input (not visible in screenshot but inferable from the "Reserve" flow): {colors.canvas} background, {colors.body} text, {rounded.sm} (8px) radius, 14px × 16px internal padding, 48px height. Border of {colors.hairline}. Focus state {component.text-input-focus} would strengthen border to {colors.border-strong} or apply {extensions.shadows.inset}.

{component.label-text} — Form field labels or section markers in {typography.label-warm} (14px, weight 600) using the {colors.label-warm} gold color. Creates visual connection to the brand accent without being interactive.

{component.footer} — Page footer (not in viewport but structurally expected): {colors.canvas} background, {colors.muted} gray text at {typography.body-sm}, {spacing.xl} (24px) vertical padding. Would contain legal links, contact info, and secondary navigation.

Do's and Don'ts

Do

  • Do use {colors.accent} (#cbaf7b) gold exclusively for the primary CTA button ({component.button-primary}) and logo/label accents—this is the sole brand color and should remain rare and precious.
  • Do set Cormorant Garamond headlines at weight 700 only—the system does not use lighter weights for display type; elegance comes from size and letter-spacing, not thin strokes.
  • Do apply {rounded.md} (16px) to all gallery/image cards—this is the dominant curve that defines the visual softness of the brand.
  • Do use {colors.muted-soft} (70% opaque black) for body paragraphs instead of solid {colors.body}—this reduces visual harshness during extended reading.
  • Do maintain {spacing.section-lg} (48px) minimum vertical padding between major sections—the airy feel depends on this rhythmic breathing room.
  • Do keep the canvas purely {colors.canvas} white with no gradient or texture overlays—let the photography provide all visual interest.
  • Do use {typography.nav-link} (16px, weight 600) for all navigation items—wayfinding text should be slightly bolder than body copy for scanability.
  • Do apply {extensions.shadows.card} only to floating gallery cards—avoid elevating other surfaces; flatness elsewhere reinforces the cards' special status.
  • Do pair {component.button-primary} (gold filled) with {component.button-outline} (transparent with hairline border) in CTA groups—the contrast guides users to the preferred action.
  • Do use negative letter-spacing on Cormorant text 24px and above (proportional to size)—this dense tracking is essential to the luxury editorial feel.

Don't

  • Don't use {colors.primary} blue (#0000ee) for anything except semantic hyperlinks—it's a standard link color, not a brand expression. Never make a blue button.
  • Don't round corners below {rounded.sm} (8px)—even the smallest interactive elements maintain softness; sharp corners contradict the luxury hospitality voice.
  • Don't introduce a third typeface beyond Cormorant Garamond and system-ui—the dual-face system is complete and intentional; adding a monospace or decorative face would fragment the voice.
  • Don't apply drop shadows to navigation, footers, or text blocks—only gallery cards elevate, and even they do so subtly.
  • Don't use font weights above 700 for any text—the system tops out at bold serif headlines; no extra-black or 900 weights exist in this palette.
  • Don't expand the spacing scale below {spacing.xxs} (6px) for layout purposes—finer granularity exists only for micro-adjustments inside components.
  • Don't place text directly over photography without a readable contrast layer—the system keeps text and imagery in separate columns.
  • Don't create "card stacks" with multiple shadows or borders—the layered gallery effect uses positioning (z-index, negative margins), not nested elevation.
  • Don't use uppercase for UI labels or buttons—all text is sentence case or title case; the logo's caps are a typographic treatment, not a system-wide convention.
  • Don't substitute {colors.label-warm} gold for {colors.accent} gold in buttons—the former is for labels/decoration, the latter for interactive surfaces; they serve different semantic roles despite similar hue.

Motion & Animation

Transition Tokens

--transition-interactive: border-color 0.2s, color 0.2s, background-color 0.2s cubic-bezier(0.165, 0.84, 0.44, 1), box-shadow 0.2s;
--transition-fade: opacity 0.3s;
--transition-general: all 0.3s;

The primary interactive transition uses a custom cubic-bezier (cubic-bezier(0.165, 0.84, 0.44, 1)) with a slight overshoot/ease-out character—this creates a snappy yet smooth response on button hovers, link interactions, and focus state changes. Duration is consistently 200ms (0.2s) for interactive elements, 300ms (0.3s) for opacity/fade transitions. The all 0.3s fallback suggests some elements use a simpler transition shorthand.

Keyframe Animations

  • spin — Detected in the CSS keyframes list, likely used for a loading indicator (not visible in the static screenshot but present in the stylesheet). Purpose: rotating loader animation during async operations (image loading, form submission).

Interaction Patterns

  • Button hover: Background color transitions from {colors.accent} to {colors.accent-dark} over 200ms with the custom ease curve. No transform (scale/translate) was detected—color change only.
  • Focus rings: Likely use the {extensions.shadows.inset} (1px inset near-black) treatment for keyboard focus indicators on buttons and inputs, providing accessibility without the heavy outlines of default browser styles.
  • Dropdown reveal: The Explore/Plan navigation dropdowns probably use opacity + transform (translateY) transitions on open/close, given the 300ms opacity transition token and common Webflow patterns.
  • Gallery card hover: While not explicitly extracted, the shadow elevation suggests possible hover-lift behavior (shadow deepening, subtle translateY) on gallery cards—this would align with the 200ms interactive timing.
  • Scroll-triggered animations: Not detected in CSS, but the editorial nature of the site suggests possible fade-up or parallax behaviors driven by JavaScript intersection observers rather than CSS keyframes.

No explicit motion tokens were found for complex orchestrations (staggered reveals, page transitions, spring physics). Recommended timing for any added motion: 200–300ms duration, ease-out curves, subtle opacity/transform changes only—never scale beyond 1.02 or translate beyond 4px.

Imagery Style

  • Photography-centric: The page is dominated by high-resolution villa photography—interior architecture, aerial/satellite views, and lifestyle shots showing the property in context.
  • Natural lighting: Images showcase sunlit interiors with warm wood tones (teak staircases, thatched ceilings) and lush tropical greenery, reinforcing the Balinese-inspired aesthetic.
  • Color treatment: Photography appears minimally processed—natural color balance with slight warmth matching the {colors.accent} gold palette. No heavy filters, duotones, or stylized grading.
  • Subject matter: Architectural details (staircases, ceiling textures, door frames), spatial compositions (great rooms, outdoor areas), and environmental context (aerial views showing the villa within tropical landscaping).
  • Composition variety: Mix of vertical/portrait orientation (stair interior) and horizontal/landscape (room interior, aerial), creating dynamic visual rhythm in the card collage.
  • Image role: Photography is the primary visual content, not supporting decoration. The UI exists to frame and contextualize the images, not compete with them.
  • No illustration or 3D: No rendered graphics, icons-as-art, or 3D elements were observed—pure photography carries all visual weight.
  • Full-bleed within cards: Images extend to the edges of their {rounded.md} containers with no borders, frames, or padding—maximum real estate for visual impact.
  • Overlapping composition: The gallery uses intentional layering (z-index stacking) where cards partially obscure one another, creating depth and a curated "scattered photo" aesthetic reminiscent of a designer's mood board.

Icon System

  • Library: Custom SVG icons (no external icon library detected in the framework analysis). The site loads Webflow's webflow-icons font-face for utility icons (dropdown chevrons, mobile menu hamburger).
  • Specific icons observed:
    • Chevron/down arrow (for "Explore ▼" and "Plan ▼" dropdown indicators)
    • Hamburger/menu icon (mobile navigation toggle, inferred from .uui-navbar02_menu-button)
    • Social icon placeholder for Instagram (likely a custom SVG or text-only link in this implementation)
  • Treatment: Icons appear to use currentColor inheritance, matching the text color of their parent element (dark for nav items, white for mobile menu toggle). Stroke-based rendering for chevrons.
  • Size: Dropdown chevrons are likely 10–12px (small, adjacent to 16px text). Mobile menu icon is 24px (per the extracted font-size on the menu button).
  • Alignment: Icons are inline with text, vertically centered via flexbox alignment. Chevrons sit to the right of their label text with left padding/margin separation.

Recommended Frontend Stack

- Framework:      Next.js 14+ (App Router) or Astro (for static/markdown-heavy content)
- Styling:        Tailwind CSS v4 (utility-first, excellent for design token mapping)
- Fonts:          Google Fonts: Cormorant Garamond (weights 300,400,500,600,700) + system-ui native stack
- Animation:      Framer Motion (for scroll-triggered reveals) or vanilla CSS (for hover states)
- Icons:          Lucide React (for chevrons, menu, social icons) + custom SVG for brand marks
- Component lib:  Radix UI Primitives (for accessible dropdowns, dialogs) + shadcn/ui patterns

Rationale: The site's clean component structure, CSS custom properties readiness, and Webflow origins map naturally to Tailwind's utility-first approach where design tokens become theme configuration. Framer Motion handles the scroll-triggered animation patterns common in editorial/luxury sites. Radix ensures the dropdown menus (Explore, Plan) meet accessibility standards without custom ARIA overhead.

Responsive Behavior

Breakpoints

| Name | Width | Key Changes | |---|---|---| | Mobile | < 768px | Single column layout, stacked hero (text above images), collapsed nav (hamburger menu), full-width gallery cards | | Tablet | 768px – 1024px | Two-column hero maintained but with reduced image sizes, condensed spacing | | Desktop | 1024px – 1440px | Full two-column layout, overlapping gallery collage, expanded nav | | Wide | > 1440px | Centered 1440px container with equal side margins, maximum layout realized |

Touch Targets

  • {component.button-primary}: 14.4px × 28.8px padding + text = approximately 120px × 48px total height—exceeds WCAG AAA 44×44px minimum comfortably.
  • {component.button-outline}: Similar dimensions to primary button—passes touch target guidelines.
  • {component.nav-dropdown-toggle}: 16px × (40px+16px) padding = approximately 72px × 52px—excellent touch target for dropdown triggers.
  • {component.nav-tertiary-link} (Instagram): 10px × 18px padding + text ≈ 100px × 40px—adequate for tertiary actions.

Collapsing Strategy

  • Navigation: At tablet/mobile breakpoints, the horizontal nav collapses to a hamburger menu icon ({component.nav-dropdown-toggle} mobile variant) that reveals a fullscreen or slide-down panel with vertical navigation links. The "Reserve" button likely moves inside this menu or becomes a sticky bottom-bar CTA.
  • Hero layout: The two-column grid ({component.gallery-grid}) stacks vertically on mobile—editorial text (headline, description, CTAs) appears first, followed by the gallery image stack. The overlapping collage effect may flatten to a simple vertical scroll of full-width images.
  • Gallery cards: Portrait-oriented images may resize to full viewport width on mobile, maintaining {rounded.md} corners. Landscape images constrain to container width with automatic height adjustment (aspect-ratio preserved).
  • Typography scaling: {typography.display-lg} (48.8px) likely steps down to 32–36px on mobile. {typography.body-md} (16px) may remain unchanged or reduce to 15px for smaller screens.
  • Spacing compression: Vertical section padding reduces from {spacing.section-lg} (48px) to {spacing.section} (40px) or {spacing.xl} (24px) on mobile to conserve viewport real estate.

Image Behavior

  • Hero illustrations (gallery cards): The three overlapping cards in the desktop hero collage will reflow on mobile. Most likely behavior: images stack vertically in DOM order, each at full container width (~100vw minus padding), maintaining {rounded.md} corners and {extensions.shadows.card}. The overlapping/layered effect is a desktop-specific luxury.
  • Aspect ratios: Images likely use object-fit: cover within their fixed-aspect-ratio containers, ensuring no distortion regardless of viewport. Portrait images may crop significantly on narrow mobile viewports if height-constrained.
  • Lazy loading: Given the photography-heavy nature, images below the fold should use loading="lazy" or Intersection Observer-based lazy loading to preserve initial paint performance.

Iteration Guide

  1. Initialize with tokens: Build the landing page using the exact YAML frontmatter values—every color, font-size, radius, and spacing value must reference a {section.token} path. Never hardcode #cbaf7b or 16px when {colors.accent} or {spacing.md} exists.

  2. Implement the type system first: Set up CSS custom properties for --font-display (Cormorant Garamond) and --font-body (system-ui). Verify the Google Fonts preload tag includes weights 300–700. Confirm the 700-weight headlines render with correct negative letter-spacing.

  3. Build the nav bar: Implement {component.top-nav} at 80px height with the logo in {colors.label-warm}, dropdown toggles with chevron icons, and the {component.button-primary} Reserve CTA in gold. Ensure the 1440px max-width container centers with auto margins.

  4. Construct the hero two-column grid: Create the {component.gallery-grid} with a 40/60 or 45/55 split. Left column gets the {typography.display-lg} headline, {typography.body-md} description in {colors.muted-soft}, and the CTA pair. Right column positions three {component.gallery-card} elements with overlapping placement (use negative margins or relative/absolute positioning).

  5. Apply the button system: Implement {component.button-primary} (gold filled), {component.button-outline} (transparent with hairline border), and {component.button-secondary} (transparent) as distinct variants. Add hover states using the 200ms cubic-bezier(0.165, 0.84, 0.44, 1) transition. Never style a button with {colors.primary} blue.

  6. Layer the gallery cards: Give each {component.gallery-card} {rounded.md} (16px) radius and {extensions.shadows.card} shadow. Position them so the center image overlaps the others. Ensure images use object-fit: cover and extend edge-to-edge within the radius.

  7. Responsive refactoring: At the <768px breakpoint, convert the two-column grid to single-column stack, collapse the nav to hamburger, and adjust {typography.display-lg} down to ~36px. Test that all touch targets remain ≥44×44px.

  8. Accessibility pass: Add aria-label to dropdown toggles, ensure focus-visible styles use {extensions.shadows.inset} or {colors.border-strong} outlines, and verify color contrast ratios (especially {colors.muted-soft} text on white, which should exceed 4.5:1 for body text).

  9. Run lint validation: Execute npx @google/design.md lint DESIGN.md after any edits. Watch for broken-ref (token paths that don't resolve), contrast-ratio (accessibility failures), and orphaned-tokens (defined but unused tokens).

  10. When in doubt about emphasis: Prefer larger type size before bolder weight (the system already uses 700 max), prefer {colors.accent} gold over any other color for CTAs, and prefer whitespace over decorative elements—the luxury is in the restraint.

Font Setup: Load Cormorant Garamond from Google Fonts:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@300;400;500;600;700&display=swap" rel="stylesheet">

Define CSS variables:

:root {
  --font-display: 'Cormorant Garamond', Georgia, serif;
  --font-body: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
}

Known Gaps

  • Hover state styling: Per the no-hover policy, exact hover background color shifts, shadow intensities, and transform values for buttons, links, and cards are not documented. Implementation teams should add these based on the transition tokens provided.
  • Loading/skeleton states: No loading skeletons, shimmer effects, or image placeholder patterns were detectable from the static screenshot. The photography-heavy page would benefit from skeleton screens or blur-up image loading.
  • Form validation states: Beyond {component.text-input-focus}, no error ({colors.error}), warning, or success ({colors.success}) input states were observable. These should be designed following the established radius and shadow patterns.
  • Dropdown panel styling: The "Explore" and "Plan" dropdown menus' open-state appearance (background, shadow, item list styling) is not visible in the screenshot. Assume white surface with {extensions.shadows.lg} elevation and {typography.nav-link} list items.
  • Mobile navigation panel: The hamburger menu's opened state (fullscreen overlay, slide-down panel, or off-canvas drawer) is inferred but not captured. Design decisions needed for mobile menu layout and animation.
  • Footer content and structure: The page footer falls below the viewport and was not captured. Its exact layout, link organization, and visual weight are undocumented.
  • Additional page templates: This spec covers only the Gallery page. Other templates (Home, Accommodations, Experience, Contact, Reservation flow) may introduce new components (date pickers, pricing tables, testimonial carousels, map embeds) not represented here.
  • Dark mode: The site appears to be light-mode only ({extensions.mode}: "light"). No dark mode token set or toggle mechanism was detected. If adding dark mode, invert canvas/ink relationships while preserving {colors.accent} gold.
  • Webflow-specific classes: Many CSS class names reference Webflow's utility namespace (.uui-navbar02_*, .w-dropdown-toggle, .w-nav). These indicate the site was built in Webflow; the design tokens abstract away from these implementation details, but developers recreating this outside Webflow should not attempt to replicate the class naming convention.
  • Exact gallery card positioning values: The pixel values or percentages used to create the overlapping card collage (negative margins, z-index values, translation offsets) are approximate based on visual inference. Fine-tuning the layering will require visual QA against the original design.