Sage Hill Design System
Overview
Sage Hill's visual identity is that of a sanctuary — a counseling practice that treats design as part of the therapeutic encounter. The system rests on a stark duality: near-black olive {colors.canvas} backgrounds anchor the hero and key conversion moments, while warm cream {colors.surface-soft} and parchment {colors.surface-warm} tones carry content sections below. This isn't a high-contrast tech brand; it's an emotionally resonant practice where darkness signals safety and light signals clarity.
Brand voltage concentrates in two places: the forest-green {colors.primary} CTA buttons ({component.button-primary}) that appear against cream surfaces, and the pale sage {colors.accent-light} accent used sparingly for phone links and icon highlights. The primary green is nearly black in value — it recedes rather than shouts — while the accent-light green glows like new growth.
The single typography move that defines this system is the collision of serif display at extreme scale ({typography.display-xl} at 84px, weight 300) with monospace body copy ({typography.body-md} in Inconsolata). The serif headlines feel literary, vulnerable, almost whispered — they're set with aggressive letter-spacing compression ({letter-spacing: -3.5px}). The monospace body feels precise, clinical, grounding. This pairing says: "We hold space for your story (serif) and we have the tools to help you through it (mono)." UI elements fall to a neutral sans-serif, Helvetica Now, which handles navigation, buttons, and small interface text without emotional interference.
Shape language is aggressively organic. Every interactive element uses {rounded.xl} (48px) or {rounded.pill} (9999px) — there are no sharp corners on anything a user touches. Even form inputs use a 192px radius that renders as fully pill-shaped at typical widths. Slider arrows use a comically large 1440px radius. This is deliberate: the geometry of the site never cuts, never corners, never feels institutional.
Key Characteristics:
- Hero canvas is
{colors.canvas}(#111801) — an olive so dark it reads as black, carrying white serif type at 84px ({typography.display-xl}) - Primary action buttons use
{colors.primary}(#182e27) forest green with{colors.on-primary}pale sage text, at{rounded.xl}pill radius - Body copy throughout uses
Inconsolatamonospace ({typography.body-md}) at 16px weight 400 — no sans-serif body anywhere - Section surfaces alternate between
{colors.surface-soft}(warm cream) and{colors.surface-warm}(parchment), creating subtle banding without harsh divisions - All touch targets use
{rounded.xl}(48px) or larger; the system has no sharp-cornered interactive elements - Accent color
{colors.accent-light}(#e8f0ca) is reserved exclusively for phone contact links and icon treatments - Display type carries
-3.5pxletter-spacing, creating tightly-kerned elegant headlines - Glass/surface overlays use
{colors.surface-glass-dark}(16% opacity cream on dark) for subtle depth layering
Colors
Brand & Accent
- Primary (
{colors.primary}— #182e27): Deep forest green used for primary CTA buttons ({component.button-primary}), section headings on light backgrounds ({component.section-heading-light}), and strong text emphasis. Nearly black in value; reads as authoritative rather than vibrant. - Primary Active (
{colors.primary-active}— #122420): Darkened forest green for pressed/active states on{component.button-primary-active}. - Primary Hover (
{colors.primary-hover}— #1f3d33): Slightly lifted forest green for hover states where implemented. - Accent Light (
{colors.accent-light}— #e8f0ca): Pale sage green used as text color on{component.nav-phone-link}, icon fills for phone/contact affordances, and theon-primarytoken for text sitting atop dark green buttons. This is the only "bright" color in the palette.
Surface
- Canvas (
{colors.canvas}— #111801): Near-black olive serving as the hero background ({component.hero-band-dark}), footer surface ({component.footer-surface}), and any full-bleed dark band. This is the emotional anchor of the brand — it's not pure black, it's earth. - Surface Soft (
{colors.surface-soft}— #fcfaf5): Warm off-white/cream used for the top navigation bar ({component.top-nav}), card surfaces ({component.card-surface-cream}), and slider arrow backgrounds ({component.slider-arrow-button}). - Surface Warm (
{colors.surface-warm}— #f0eee9): Parchment tone used for alternating content section backgrounds ({component.content-section-light}) and some card variants ({component.card-surface-warm}). Slightly darker than surface-soft to create visual rhythm between bands. - Surface Elevated (
{colors.surface-elevated}— #d6d1c4): Muted tan used for subtle elevation differences where needed. - Glass Dark (
{colors.surface-glass-dark}— rgba(255, 253, 246, 0.16)): 16%-opacity cream overlaid on dark canvas for form inputs ({component.input-field-light}) and panel backgrounds ({component.glass-panel-dark}). Creates readable depth without breaking the dark atmosphere. - Glass Light (
{colors.surface-glass-light}— rgba(255, 255, 255, 0.24)): 24%-opacity white for subtle elevated panels on light surfaces ({component.glass-panel-light}).
Text / Ink
- Ink (
{colors.ink}— #182e27): Forest green identical to primary, used as the dominant text color on all light surfaces. Headings, body paragraphs, navigation labels. - Body (
{colors.body}— #000000): Pure black appearing in some text instances where maximum contrast is required. - Body Inverse (
{colors.body-inverse}— #fffdf6): Warm off-white (not pure white) used for body text on dark canvas backgrounds. Softer than{colors.on-canvas}. - On Primary (
{colors.on-primary}— #e8f0ca): Pale sage green, the legible foreground color on{colors.primary}backgrounds. Used in{component.button-primary}text and wherever primary-colored surfaces need readable overlay. - On Canvas (
{colors.on-canvas}— #ffffff): Pure white reserved for the hero headline ({component.hero-headline}) and highest-emphasis text on dark backgrounds. - On Dark (
{colors.on-dark}— #ffffff): Pure white for general dark-surface text usage. - Muted (
{colors.muted}— rgba(31, 25, 21, 0.48)): 48%-opacity near-black for secondary text on light surfaces — captions, metadata, placeholder text. - Muted Strong (
{colors.muted-strong}— rgba(31, 25, 21, 0.64)): 64%-opacity near-black for slightly more prominent secondary text.
Hairlines & Borders
- Hairline Subtle (
{colors.hairline-subtle}— rgba(31, 25, 21, 0.16)): Very faint border for form inputs on light backgrounds ({component.input-field-light}) and subtle dividers. - Hairline Medium (
{colors.hairline-medium}— rgba(31, 25, 21, 0.32)): Visible but gentle border for outlined elements on light surfaces, such as{component.slider-arrow-button}. - Border On Canvas (
{colors.border-on-canvas}— #ffffff): White border for inputs and outlines on dark canvas ({component.input-field-dark}). - Border On Surface (
{colors.border-on-surface}— #222222): Near-black border for elements on cream surfaces.
Semantic
- Link (
{colors.link}— #182e27): Standard inline link color matching ink/primary. - Link Accent (
{colors.link-accent}— #e8f0ca): Special link treatment for the phone number CTA in the nav — rendered in pale sage to draw attention.
Typography
Font Family
Sage Hill employs a three-font family architecture with strictly separated roles:
-
"Times New Roman", TimesNewroman, Times, Baskerville, Georgia, serif— The display/voice face. Used exclusively for headlines at large scale (84px). This stack includes proprietaryTimesNewroman(note: single-word variant) suggesting a Webflow-hosted custom build. This face carries all emotional weight in the system. It appears only in{typography.display-xl},{typography.display-lg}, and{typography.title-md}roles. -
Inconsolata, monospace— The clinical/copy face. Google Fonts hosted (confirmed via fontLinks). Used for ALL body copy, captions, labels, and any paragraph-level text. This choice is highly intentional for a therapy practice: monospace conveys precision, documentation, and lack of decorative interference. It makes the written word feel like a tool rather than an ornament. -
"Helvetica Now", sans-serif— The utility/UI face. Self-hosted via @font-face declarations with weights 200 (extra-light) and 400 (regular). Handles navigation links, button labels, small UI text, and any interface element that must be scannable and neutral. This is the "invisible" font — it does no emotional work.
A fourth face, Canela (proprietary, self-hosted at weights 100 normal/italic), appears in font-face declarations but was not detected in above-fold computed styles. It may serve deeper page sections or italic accent purposes.
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| {typography.display-xl} | 84px | 300 | 0.93 (-3.5px tracking) | -3.5px | Hero headline on dark canvas |
| {typography.display-lg} | 84px | 400 | 0.93 (-3.5px tracking) | -3.5px | Section headlines on light surfaces |
| {typography.title-md} | 42px | 400 | 1.2 | -1.5px | Sub-section titles, card headlines |
| {typography.heading-sm} | 20px | 400 | 1.4 | 0 | Small headings, card subtitles |
| {typography.body-md} | 16px | 400 | 1.375 | 0 | All body copy (monospace) |
| {typography.body-sm} | 14px | 400 | 1.45 | 0 | Small UI text, legal, footnotes |
| {typography.caption} | 13px | 400 | 1.38 | 0 | Labels, meta, bylines (monospace) |
| {typography.button} | 16px | 400 | 1.25 | 0 | Button labels, CTA text |
| {typography.nav-link} | 14px | 400 | 1.35 | 0 | Navigation menu items |
| {typography.mono-label} | 13px | 400 | 1.38 | 0 | Technical/form labels (monospace) |
Principles
The typography system's central tension — and its genius — is the weight inversion relative to convention. Display type sits at weight 300 (extra-light) even at 84px, while body copy sits at 400 (regular). Most systems bold their headlines and lighten their body; Sage Hill does the opposite. This means hierarchy is carried almost entirely by size differential (84px vs 16px = 5.25x scale) and family contrast (serif vs monospace), never by bolding. The result is headlines that feel whispered rather than announced — perfect for a practice dealing with vulnerability.
Letter-spacing is aggressively negative on display faces: -3.5px at 84px creates tightly-kerned elegant blocks of text that feel bespoke and editorial. This is not web-safe default behavior; it's a deliberate typesetting choice that gives the brand a print-magazine quality.
The monospace body face (Inconsolata) does something psychologically important: it depersonalizes the reading experience slightly. In a context where a visitor might feel exposed or emotional, monospace text feels like "documentation" rather than "conversation." It creates a micro-distance that can make difficult content easier to engage with.
Color also participates in hierarchy: {colors.on-canvas} (pure white) is reserved for the hero headline only; everything else on dark surfaces steps down to {colors.body-inverse} (warm white). On light surfaces, {colors.ink} (forest green) carries main text while {colors.muted} variants handle supporting information.
Note on Font Substitutes
The primary display face (Times New Roman stack) requires no substitution — it's universally available. For the proprietary Canela face (used in deeper pages), substitute Playfair Display (Google Fonts) at weight 300 for thin elegance, or Cormorant Garamond for a slightly more contemporary serif. For Helvetica Now, the closest open-source match is Inter (variable font, weights 200–400 available via Google Fonts) — note that Inter's 200 weight is slightly heavier than Helvetica Now's true extra-light, so consider dropping to 100 or 200 with a slight width adjustment. Inconsolata is already Google Fonts-hosted and needs no substitution.
CSS variable mapping for implementation:
--font-display: "Times New Roman", TimesNewroman, Times, Baskerville, Georgia, serif;
--font-body: "Inconsolata", monospace;
--font-ui: "Helvetica Now", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-proprietaty-substitute: "Playfair Display", "Cormorant Garamond", Georgia, serif;
Layout
Spacing System
- Base unit: 4px (inferred from xxs: 4px progression).
- Tokens:
{spacing.xxs}(4px — micro-gaps, icon internal spacing),{spacing.xs}(8px — tight component internal spacing),{spacing.sm}(10px — button vertical padding, compact gaps),{spacing.md}(12px — standard gaps),{spacing.base}(16px — card padding baseline, grid gap),{spacing.lg}(20px — medium component spacing),{spacing.xl}(24px — comfortable component spacing),{spacing.xxl}(30px — generous internal spacing),{spacing.section-sm}(40px — small section breaks),{spacing.section}(80px — major section vertical rhythm),{spacing.section-xl}(120px — hero-scale vertical breathing room). - Section padding (vertical):
{spacing.section-xl}(120px) on hero band ({component.hero-band-dark});{spacing.section}(80px) on content sections ({component.content-section-light}). - Card internal padding:
{spacing.xl}(24px) on both{component.card-surface-cream}and{component.card-surface-warm}. - Gutters: Content containers max at 1440px width with fluid horizontal margins; inner content likely constrained to ~1200px readable column.
Grid & Container
- Max content width: 1440px (explicit on
<nav>and<section>containers). - Editorial density: low-to-moderate — this is not a marketplace. Content breathes. The hero uses approximately 50-60% of viewport width for the headline column, leaving the rest for photographic presence.
- Grid behavior at desktop: Likely a 12-column implicit grid for content sections; hero appears to be a 2-column asymmetric layout (text left ~45%, image right ~55% or full-bleed photo underlay with text overlay).
- Hero column splits: Left-aligned headline block with sublabel beneath, positioned in lower-left quadrant of hero area (not centered).
Whitespace Philosophy
Sage Hill practices generous negative space as emotional container. The hero doesn't fill the frame — the headline sits low-left, surrounded by photographic negative space. Section padding of 80-120px vertically ensures no content feels cramped against band edges. Card padding of 24px gives internal breathing room. This is not "airy minimalist" whitespace (which can feel cold); it's holding-space whitespace — the kind that makes a visitor feel the page has room for them and their concerns. The system refuses density; even navigation items have 40-48px horizontal padding per item.
Header Architecture
[1440px max-width container, transparent/cream bg]
┌─────────────────────────────────────────────────────────────────┐
│ [Logo: 44px circle] [How We Help v] [About] [Careers] │
│ [Phone 📞] [Get Connected →] │
└─────────────────────────────────────────────────────────────────┘
↑ flush-left ← center/right cluster → ↑ flush-right
height: ~72px items spaced md-lg pill buttons
The navigation uses a floating bar aesthetic on the hero (appears to sit over the dark canvas/photograph with {colors.surface-soft} background and generous rounding on the overall container). Logo is a circular tree mark. Right side clusters utilities: dropdown toggle, static links, phone accent link, and the primary CTA button.
Hero Section
[FULL-VIEWPORT or NEAR-FULL, bg: canvas + photograph underlay]
┌──────────────────────────────────────────────────────────────┐
│ │
│ │
│ ┌──────────────────────────────┐ │
│ │ Helping you find │ ← display-xl, 84px, │
│ │ meaning in your struggle. │ white, -3.5px tracking │
│ │ │ │
│ │ Individual, Couples, & Group │ ← caption, 13px mono, │
│ │ Counseling in Nashville, TN │ body-inverse │
│ └──────────────────────────────┘ │
│ │
│ [Get Connected ↗] ← ghost pill button │
│ │
└──────────────────────────────────────────────────────────────┘
Hero uses a background photograph (portrait of a person, intimate framing, desaturated/warm-toned processing) overlaid with a solid {colors.canvas} tint or positioned behind a semi-transparent dark layer. The headline sits in the lower-left portion of the viewport. A floating ghost CTA button ({component.button-secondary-ghost}) appears in the lower area. The overall effect is cinematic and still.
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| 0 — Flat baseline | No shadow, direct surface color | Body backgrounds ({colors.surface-warm}), footer ({colors.footer-surface}) |
| 1 — Hairline outline | 1px border, {colors.hairline-subtle} or {colors.hairline-medium} | Form inputs ({component.input-field-light}, {component.input-field-dark}), slider arrows ({component.slider-arrow-button}) |
| 2 — Glass/overlay | Semi-transparent surface tokens | {component.glass-panel-dark} (on canvas), {component.glass-panel-light} (on cream) |
| 3 — Soft drop | {extensions.shadows.soft} — 0 6px 24px -3px rgba(0,0,0,0.1) | Elevated cards, modals, dropdowns |
| 4 — Button focus ring | Implicit (not explicitly extracted) | Focus states on interactive elements |
The depth philosophy here is layered warmth, not cool detachment. Shadows when present use neutral/black opacity rather than cool blue tints. The preferred elevation method for this brand is actually color blocking (alternating {colors.surface-soft} / {colors.surface-warm} bands) rather than drop shadows — shadows appear only on truly floated elements like dropdowns or modals. The glass panel approach (semi-transparent overlays) is used for form inputs within dark contexts, creating readable fields that don't break the atmospheric immersion of the canvas background.
Decorative Depth
The primary decorative depth element is full-bleed photography with canvas overlay in the hero section. Photographs appear to be processed with warm toning, slightly desaturated, and shot with shallow depth-of-field (intimate portraiture). The {colors.canvas} dark layer sits between the photograph and the text content, ensuring readability while allowing photographic texture to bleed through subtly. This is not a flat color block hero — it's a textured atmospheric hero.
Shapes
Border Radius Scale
| Token | Value | Use |
|---|---|---|
| {rounded.sm} | 8px | Light-mode form inputs ({component.input-field-light}), subtle panel corners |
| {rounded.DEFAULT} | 12px | General-purpose cards, content panels |
| {rounded.md} | 15px | Warm-surface card variant ({component.card-surface-warm}) |
| {rounded.lg} | 16px | Cream card surfaces ({component.card-surface-cream}) |
| {rounded.xl} | 48px | All primary buttons ({component.button-primary}), phone link ({component.nav-phone-link}), CTA pills |
| {rounded.pill} | 9999px | Ghost/outlined buttons ({component.button-secondary-ghost}), fully-rounded touch targets |
| {rounded.circle-pill} | 1440px | Slider navigation arrows ({component.slider-arrow-button}) — effectively circular at 52px size |
| {rounded.input-pill} | 192px | Dark-mode email input ({component.input-field-dark}) — renders as pill at typical widths |
Photography Geometry
Photography in the hero section is full-bleed, uncropped by corner radius — the image extends edge-to-edge beneath the canvas overlay. Portrait orientation or square crops appear favored based on the visible subject (person's face/shoulders). No rounded corners on photographs; images are allowed to be raw and uncontained. Aspect ratio appears to be approximately 4:5 or 1:1 (portrait/square), filling the hero area with the subject's gaze directed away from camera — contemplative, indirect eye line.
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-active},{component.text-input-focus}); add hover styling at implementation time per your stack's conventions.
Buttons & CTAs
{component.button-primary} — The principal call-to-action button, seen in the top navigation as "Get Connected." Background {colors.primary} (forest green), text {colors.on-primary} (pale sage), type {typography.button} (Helvetica Now 16px/400), heavily rounded at {rounded.xl} (48px creating full pill shape), padding 6px 32px. No box-shadow; relies on color contrast for prominence. Active state documented as {component.button-primary-active} with darkened background. This button converts the "safe space" promise into action.
{component.button-primary-active} — Pressed/active state for primary CTA. Background shifts to {colors.primary-active} (#122420) — a subtle deepening. Same text color and radius. Implement with transform: scale(0.98) or equivalent press feedback for tactile confirmation.
{component.nav-phone-link} — The phone number link in the navigation bar. Transparent background, text {colors.link-accent} (pale sage green #e8f0ca) making it visibly distinct from other nav items. Rounded {rounded.xl} (48px), padding 6px 32px 6px 6px — note the asymmetric padding leaving room for a phone icon on the left side. This is a "ghost button with accent color" pattern unique to contact affordances.
{component.button-secondary-ghost} — Outline/ghost-style button for secondary actions. Seen floating in the hero area as "Get Connected" with arrow. Transparent background, text {colors.on-canvas} (white) for dark-context usage, {rounded.pill} (fully rounded), padding 10px 28px. Variant {component.button-secondary-ghost-light} exists for light-surface contexts using {colors.ink} text instead.
{component.submit-button-icon} — Icon-only submit action adjacent to form inputs. Transparent background, white text color ({colors.on-canvas}), padding 9px 24px 9px 15px. Contains an arrow icon. No border-radius applied (or minimal).
Navigation
{component.top-nav} — The persistent header navigation. Background {colors.surface-soft} (warm cream), text {colors.border-on-surface} (near-black #222222) for readability, type {typography.nav-link} (Helvetica Now 14px), height approximately 72px. Contains logo mark left, navigation cluster center-right, CTA buttons far-right. The bar appears to float with potential subtle shadow or border separation from hero content beneath.
{component.nav-logo-container} — Circular logo mark (tree icon in a circle). Transparent background, size 44px diameter. Positioned flush-left in nav. The logo mark uses the brand's tree/nature symbol in a contained circle format.
{component.nav-dropdown-toggle} — "How We Help" dropdown trigger in navigation. Transparent background, text matches nav color, type {typography.nav-link}, padding 8px 40px 8px 16px (extra right-padding accommodates chevron indicator). Rounded {rounded.DEFAULT} (12px) giving subtle pill shape to the clickable area.
Surfaces & Sections
{component.hero-band-dark} — The full-width hero section. Background {colors.canvas} (near-black olive), text defaults to {colors.on-canvas} (white), type role {typography.display-xl} for headline content. Padding {spacing.section-xl} (120px) vertical with {spacing.base} (16px) horizontal. Contains photographic underlay and headline overlay. This is the emotional entry point to the brand.
{component.hero-headline} — The H1 headline "Helping you find meaning in your struggle." Transparent background inheriting parent, text {colors.on-canvas} (pure white — stronger than body-inverse for maximum headline punch), type {typography.display-xl} (Times New Roman 84px/300 with -3.5px tracking). This is the single most important typographic element on the entire site.
{component.hero-sublabel} — The descriptive line beneath the headline ("Individual, Couples, & Group Counseling in Nashville, TN"). Transparent background, text {colors.body-inverse} (warm white — intentionally softer than headline white), type {typography.caption} (Inconsolata 13px/400 monospace). The monospace choice for the location label reinforces the "clinical precision meets poetic voice" duality.
{component.content-section-light} — Standard content section band. Background {colors.surface-warm} (parchment #f0eee9), text {colors.ink} (forest green), padding {spacing.section} (80px) vertical. Used for about, services, team content below the hero. Creates warm, paper-like reading environment.
{component.section-heading-light} — Section title on light backgrounds. Transparent background, text {colors.ink}, type {typography.display-lg} (Times New Roman 84px/400 — note weight increases to 400 from hero's 300, as these headings compete less with photographic atmosphere). Carries same aggressive letter-spacing (-3.5px).
{component.footer-surface} — Page footer. Background {colors.canvas} returning to dark anchoring, text {colors.muted} (48% opacity dark), type {typography.body-sm}, padding {spacing.section} vertical. Brings the page to rest on the same ground it began with.
Cards & Panels
{component.card-surface-cream} — Content card on cream-tinted sections. Background {colors.surface-soft} (#fcfaf5), text {colors.ink}, rounded {rounded.lg} (16px), padding {spacing.xl} (24px). Used for service descriptions, team member previews, or testimonial blocks.
{component.card-surface-warm} — Content card on parchment sections. Background {colors.surface-warm} (#f0eee9), text {colors.ink}, rounded {rounded.md} (15px), padding {spacing.xl} (24px). Slightly different surface shade and radius creates subtle alternation when multiple cards appear together.
{component.glass-panel-dark} — Semi-transparent panel overlaid on dark canvas. Background {colors.surface-glass-dark} (16% opacity cream), text {colors.body-inverse} (warm white for readability over transparency), rounded {rounded.sm} (8px), padding {spacing.base} horizontally plus {spacing.lg} internally. Used for form containers or informational overlays within hero/footer dark zones.
{component.glass-panel-light} — Semi-transparent panel on light surfaces. Background {colors.surface-glass-light} (24% opacity white), text {colors.ink}, rounded {rounded.sm} (8px). Subtle lift without shadow commitment.
Inputs & Forms
{component.input-field-dark} — Email/text input on dark canvas background. Transparent background (lets canvas show through), text {colors.on-canvas} (white), border 1px solid {colors.border-on-canvas} (white hairline), rounded {rounded.input-pill} (192px — fully pill-shaped), padding 8px 12px 8px 16px. Font size 14px. This is likely the newsletter or contact form input in the hero or footer area. Focus state {component.input-field-dark-focus} maintains same properties with border-color change expected.
{component.input-field-light} — Email/text input on light/cream background. Background {colors.surface-glass-dark} (subtle cream tint, 16% opacity), text {colors.body-inverse} (warm white — note: this suggests the input may appear on a mid-tone surface or uses inverse treatment), border 1px solid {colors.hairline-subtle} (very faint), rounded {rounded.sm} (8px — notably sharper than dark-input, suggesting different context), padding 16px 50px 16px 16px (generous vertical padding, extra right padding for submit button). Focus state {component.input-field-light-focus} maintains properties.
{component.submit-button-icon} — Submit button paired with {component.input-field-light}. Transparent background, text/icon color {colors.on-canvas}, no visible radius, padding 9px 24px 9px 15px (asymmetric for icon positioning). Appears to sit inside or adjacent to the input field as an integrated submit control.
Navigation & Media Controls
{component.slider-arrow-button} — Carousel/testimonial slider navigation arrow. Background {colors.surface-soft} (cream), text/color {colors.canvas} (dark olive for arrow icon), border 1px solid {colors.hairline-medium} (visible but soft), rounded {rounded.circle-pill} (1440px — effectively circular), size 52px×52px. Large touch target with prominent circular presentation. Font-size 40px for the arrow character/glyph, weight 200 (extra-light). These controls feel friendly and substantial.
{component.logo-mark-circle} — The Sage Hill tree logo in its container. Transparent background, size 44px diameter (matching {component.nav-logo-container}). Circular crop of the brand mark.
{component.divider-line} — Horizontal rule/divider element. Height 1px, background inferred as {colors.hairline-subtle} or similar. Used for subtle content separation.
Do's and Don'ts
Do
- Do use
{typography.display-xl}(84px, weight 300, -3.5px tracking) for the hero headline and reserve{typography.display-lg}(weight 400) for section headings below — the weight increase compensates for reduced atmospheric support. - Do apply
{rounded.xl}(48px) or larger to every interactive element a user clicks or taps — buttons, links wrapped in hit areas, slider controls. Sharp corners on touch targets break the safe-container promise. - Do use
Inconsolatamonospace ({typography.body-md}) for all paragraph-level content, even though intuition might suggest a serif or sans-serif body face. The monospace choice is philosophically central to the brand voice. - Do alternate between
{colors.surface-soft}(cream) and{colors.surface-warm}(parchment) for consecutive content sections to create gentle visual rhythm without hard dividers. - Do place the hero headline in the lower-left quadrant of the viewport, not centered. The asymmetry combined with photographic presence feels more cinematic and intimate.
- Do use
{colors.accent-light}(#e8f0ca) sparingly — only for phone/contact affordances and text-on-primary situations. It loses impact if overused. - Do let
{colors.canvas}(#111801) anchor both the hero AND the footer, creating visual bookends that frame the lighter content between them. - Do maintain the 5.25x scale ratio between display (84px) and body (16px) type — this extreme contrast carries hierarchy without needing weight variation.
- Do process photography with warm toning and allow it to show through beneath a
{colors.canvas}tint layer rather than using flat color backgrounds. - Do use
{colors.body-inverse}(#fffdf6, warm white) for non-headline text on dark surfaces — reserve pure{colors.on-canvas}(#ffffff) only for the hero headline itself.
Don't
- Don't bold the display headlines — they are intentionally weight 300 (hero) or 400 (sections). Adding weight destroys the "whispered" quality that makes the brand feel therapeutic rather than promotional.
- Don't substitute
Helvetica NowforInconsolatain body copy contexts. The monospace face is a deliberate psychological choice, not a technical convenience. - Don't use
{colors.primary}(#182e27) as a text color on{colors.canvas}or dark surfaces — it's too close in value (both are very dark). Use{colors.on-canvas}(white) or{colors.body-inverse}(warm white) instead. - Don't add gradient backdrops, mesh gradients, or colorful abstract shapes to the hero or any section. The brand's depth comes from photography + solid color blocks, not digital decoration.
- Don't reduce the letter-spacing on display type below the specified
-3.5px— this tight kerning is a signature detail. Looser tracking would make the headlines feel generic. - Don't create sharp-cornered cards or panels. If you need a content container, use at least
{rounded.DEFAULT}(12px); prefer{rounded.lg}(16px) or{rounded.xl}(48px) for anything user-facing. - Don't place
{component.button-primary}(dark green CTA) on{colors.canvas}(dark background). It's designed for cream/light surfaces where the forest green provides clear contrast. On dark surfaces, use{component.button-secondary-ghost}instead. - Don't introduce a third font family beyond the established three (Display Serif / Mono Body / UI Sans). Even if Canela appears in font declarations, treat it as an optional enhancement, not a new voice.
- Don't pad sections thinner than
{spacing.section}(80px) vertically. Cramped vertical rhythm triggers anxiety — the opposite of what a counseling practice should convey. - Don't forget that
{colors.ink}and{colors.primary}share the same hex value (#182e27) — they're semantically distinct (text vs. background) even though they're visually identical.
Motion & Animation
Transition Tokens
--transition-base: all 0.2s ease;
--transition-spring: all 0.9s cubic-bezier(0.135, 0.9, 0.15, 1);
--transition-transform: transform 0.2s ease;
--transition-opacity: opacity 0.2s ease;
The extracted CSS reveals two distinct timing personalities: standard micro-interactions at 200ms (transform, opacity) for hover/focus states, and a signature spring transition at 900ms using a custom cubic-bezier cubic-bezier(0.135, 0.9, 0.15, 1) — this is an overshoot/ease-out curve that creates a gentle "settling" motion ideal for page loads, section reveals, or modal entrances. The 0.9s duration is unusually long for web transitions and signals a brand that prioritizes felt deliberateness over snappy responsiveness.
Keyframe Animations
The following keyframe names were detected in the stylesheet (likely from an animation library or Webflow's built-in set):
_spin_1nqjn_1— Rotational spin (loading states, icon animation)_wave_1nqjn_1— Wave oscillation (decorative or loading)_heartBeat_1nqjn_1— Pulse/heartbeat rhythm (possibly unused or for special moments)_flash_1nqjn_1— Opacity flash (attention calls)_bounce_1nqjn_1— Vertical bounce (entry animation)_rubberBand_1nqjn_1— Elastic stretch/squash (playful entry)_headShake_1nqjn_1— Horizontal shake (error/denial feedback)_tada_1nqjn_1— Scale+rotation celebration (success state)
Note: Many of these (heartbeat, tada, rubberBand) feel incongruous with the Sage Hill brand voice and may be library defaults rather than actively-used patterns. Recommend limiting production use to spin (preloader), fade/opacity, and subtle bounce only.
Interaction Patterns
- Preloader: A preloader component exists in the DOM (
div.preloader). Likely uses the_spin_or a custom fade-in animation during initial page load, consistent with the 0.9s spring timing. - Slider transitions: The sales preview section uses Webflow's slider component (
w-slider) with arrow controls ({component.slider-arrow-button}). Slides likely use the 0.9s spring transition for smooth, deliberate content changes. - Dropdown reveal: "How We Help" nav toggle (
{component.nav-dropdown-toggle}) probably uses the 0.2s transform/opacity transition for menu expansion. - Scroll-triggered fades: Given the editorial layout, sections likely fade/slide into view on scroll using the spring easing (0.9s) for a "revealing" rather than "snapping" feel.
- Button interactions: Primary and secondary buttons should respond to hover with 0.2s background-color transitions; active/pressed states may include subtle scale (0.98) with 0.2s transform transition.
- Focus rings: Form inputs on focus likely transition border-color over 0.2s, potentially accompanied by a subtle shadow lift.
Motion philosophy recommendation: Sage Hill's motion should feel organic and unhurried. The 0.9s spring is the signature timing — use it for any "entrance" animation (sections appearing, modals opening, photos fading in). Reserve 0.2s for "response" animations (hover, focus, dropdown). Avoid anything faster than 150ms (feels twitchy/anxious) or anything linear/ease-in (feels mechanical). All motion should feel like breathing.
Imagery Style
- Photography type: Intimate environmental portraiture — subjects shown from shoulders-up or chest-up, often in profile or three-quarter view, looking away from camera (contemplative gaze direction).
- Subject matter: Human faces, human hands near faces, natural textures (the visible image shows fingers near lips, suggesting vulnerability/thoughtfulness). Subjects appear to be real people (potential clients or counselors), not stock models.
- Color processing: Warm toning with slightly lifted blacks, desaturated but not black-and-white. Skin tones read naturally warm. Overall cast leans toward the brand's olive/cream palette (greens and warm neutrals).
- Depth of field: Shallow — subjects in sharp focus, backgrounds softly blurred (bokeh). Creates intimacy and isolates the subject emotionally.
- Composition: Asymmetric framing, subjects positioned off-center (rule-of-thirds or further). Negative space around subjects is meaningful, not accidental.
- Role in layout: Images are dominant in the hero (full-bleed underlay) and likely significant in subsequent sections (team portraits, office environments, detail shots of therapy spaces). They are not decorative accents — they carry equal or greater visual weight than text.
- Treatment on page: Photographs sit beneath semi-transparent
{colors.canvas}overlays in the hero, allowing texture to show while ensuring text readability. In content sections, images likely appear in frames or full-bleed without heavy filters. - Emotional register: Images should evoke stillness, interiority, and unguarded humanity. No smiling-at-camera stock joy; no clinical sterility; no dramatic high-contrast drama. The visual mood is "quiet moment of reflection."
Icon System
- Library: Custom SVG icons (no standard library detected in iconLibs). Icons appear to be custom-drawn or sourced to match brand geometry.
- Specific icons observed:
- Tree/circle mark (logo — organic tree shape within circle)
- Chevron down (dropdown indicator on "How We Help")
- Phone handset (phone link icon in navigation)
- Arrow up-right diagonal (external/action arrow on "Get Connected" ghost button)
- Arrow right (slider navigation control)
- Arrow diagonal-up-right (submit/send icon in form)
- Treatment: Icons use
currentColorfor fill/stroke, inheriting from parent text color. The phone icon specifically renders in{colors.link-accent}(pale sage). Slider arrow renders in{colors.canvas}(dark) on cream background. - Size: Navigation icons approximately 16–18px; slider arrow glyph at 40px (large, friendly); form submit arrow at ~16px.
- Alignment: Icons are center-aligned with adjacent text, with consistent internal padding (phone icon has 6px padding in its button). Line-height matches text for vertical centering.
- Stroke vs fill: Mix observed — logo mark appears filled, navigation chevron likely stroked, arrows likely filled or stroked depending on weight. Recommend consistent stroke-weight (1.5px–2px) for linear icons, filled for marks/logos.
Recommended Frontend Stack
- Framework: Next.js 14 (App Router) or Astro (static-first, ideal for brochure sites)
- Styling: Tailwind CSS v3.4+ (utility-first, matches extracted tailwindLikely flag)
- Fonts: Google Fonts: Inconsolata (400,700);
Self-host: Helvetica Now (200, 400 OTF from CDN);
System: "Times New Roman" stack for display (no host needed);
Optional: Playfair Display (Google Fonts) as Canela substitute
- Animation: Framer Motion (React) or GSAP (vanilla JS) for scroll-triggered reveals
using the 0.9s cubic-bezier(0.135, 0.9, 0.15, 1) spring
- Icons: Custom SVG components (inline React components or SVG sprite)
- Component lib: None (custom components) or Radix UI primitives for
accessible dropdown/slider foundations
- Build origin: Webflow (detected w-* classes suggest Webflow export/origin);
if continuing from Webflow, consider Webflow native or
migration to React/Next.js with tailwind
Responsive Behavior
Breakpoints
| Name | Width | Key Changes | |---|---|---| | Mobile | < 640px | Single-column hero (headline stacks above/below photo or photo hides), nav collapses to hamburger, slider arrows become swipe, form inputs go full-width, section padding reduces to 48px | | Tablet | 640px – 1024px | Two-column hero possible with smaller type (display scales down to 56–64px?), nav items may condense or hide in menu, card grids move to 2-column | | Desktop | 1024px – 1440px | Full layout as designed: 84px headlines, asymmetric hero, 1440px-max container, full nav visible | | Wide | > 1440px | Container centers with auto margins, hero may increase padding proportionally, type does not scale beyond 84px (maxes out) |
Note: Exact breakpoint values inferred from common patterns; the source HTML contains a media query at 1920px adjusting root font-size, indicating responsive typography via rem-scaling.
Touch Targets
{component.button-primary}: ~44px minimum height (padding 6px × 2 + 16px font ≈ 28px content + padding = ~40px; recommend ensuring 44px WCAG AAA compliance){component.nav-phone-link}: 48px radius zone ensures large circular hit area — passes easily{component.slider-arrow-button}: 52px × 52px explicit size — excellent touch target, exceeds 44px minimum{component.input-field-dark}/{component.input-field-light}: Padding 8px–16px vertical + 14px font = ~36–44px total; verify 44px on mobile{component.nav-dropdown-toggle}: 8px vertical padding + 14px font ≈ 30px — may need padding increase to 14–16px vertical for mobile touch compliance
Collapsing Strategy
- Navigation: At mobile breakpoint, the horizontal nav items (How We Help, About, Careers, phone, Get Connected) collapse into a hamburger menu (
w-nav-buttonclass detected in DOM). The menu button uses 24px font-size at weight 200 (thin) for the icon. - Hero layout: The asymmetric two-column hero (headline left, photo right/full-bleed) stacks vertically on mobile — headline moves above the photograph or the photograph becomes a background with headline overlaid centrally. The 84px display type should scale down (consider 48px–56px at mobile via clamp() or media query) to prevent 2-3 words per line.
- Slider/carousel:
{component.slider-arrow-button}(52px circle arrows) hide on mobile; touch/swipe gesture takes over for carousel navigation. - Form inputs:
{component.input-field-light}with integrated submit button likely stacks vertically on mobile (input full-width, submit button below or becomes a true submit bar). - Card grids: Multi-card layouts collapse from 3-column or 2-column to single-column stacking with
{spacing.lg}(24px) gaps between cards. - Section padding:
{spacing.section-xl}(120px) compresses to ~48–64px on mobile to avoid excessive scrolling within fold.
Image Behavior
- Hero photograph: On mobile, the full-bleed portrait likely crops to a tighter framing (face-focused) or shifts to a background-position that keeps the subject's face visible. Avoid scaling the photograph down to a small inset — maintain atmospheric dominance even at small sizes.
- Team/service imagery: If present below the hero, these likely move from side-by-side with text to stacked (image above, text below) on mobile, maintaining aspect ratio but reducing pixel dimensions proportionally.
- Logo mark: The 44px circle logo remains at 44px or reduces slightly to 36px on mobile — always visible, never hidden.
Iteration Guide
- Begin by implementing the color foundation first: Define all 25+ color tokens as CSS custom properties (or Tailwind config extend colors) exactly as specified in the frontmatter. The
{colors.canvas}/{colors.surface-soft}duality is the backbone — get these two right and everything else follows. - Establish the three-font system before writing any content: Import
Inconsolatafrom Google Fonts; self-hostHelvetica Now(or substitute Inter); rely on systemTimes New Romanfor display. Assign each to its CSS variable (--font-display,--font-body,--font-ui) and never deviate. - Build the hero section as your north star: Implement
{component.hero-band-dark}with the 84px{typography.display-xl}headline in white, the{typography.caption}sublabel in monospace beneath it, and the{component.button-secondary-ghost}CTA floating below. Get the letter-spacing (-3.5px) and line-height (0.93) exact — these numbers are the difference between "elegant" and "default browser." - Implement navigation second:
{component.top-nav}with the cream background, logo left, dropdown toggle, phone link in{colors.link-accent}, and{component.button-primary}(dark green pill) at the right edge. Ensure all touch targets meet 44px minimum. - Create component primitives before composing pages: Build
{component.button-primary},{component.button-primary-active},{component.card-surface-cream},{component.card-surface-warm},{component.input-field-dark},{component.input-field-light}, and{component.slider-arrow-button}as isolated, tested components. Each must accept props for backgroundColor, textColor, etc., mapped from the frontmatter tokens. - Apply the radius discipline relentlessly: Every clickable thing gets
{rounded.xl}(48px) or larger. Every content panel gets at least{rounded.DEFAULT}(12px). If you catch yourself typingrounded-noneorrounded-smon a button, stop. The safe-container shape language is non-negotiable. - Layer motion last: Add the 0.9s spring transition (
cubic-bezier(0.135, 0.9, 0.15, 1)) to section entrance animations. Add 0.2s ease to hover/focus states. Test that nothing feels faster than 200ms for responses or slower than 1s for entrances. - Test on dark and light surfaces: Many components exist in pairs (button on cream, button on canvas; input on dark, input on light). Verify each variant in situ. The
{colors.on-primary}token (pale sage on dark green) is particularly important to test for contrast. - Run accessibility audit: Verify the 84px white headline on
{colors.canvas}passes WCAG AA (it should at that size — large text has relaxed ratio requirements). Check{component.button-primary}(dark green text on dark green... wait:{colors.on-primary}is pale sage, which should pass on{colors.primary}). - Resist the urge to "improve": The monospace body copy, the extra-light headline weight, the 192px input radius, the 0.9s spring — these are all intentional brand choices that may look "wrong" compared to conventional SaaS patterns. Trust the specification. Sage Hill isn't a SaaS.
Font Setup for Implementation:
/* Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@400;700&display=swap');
/* CSS Variables */
:root {
--font-display: "Times New Roman", TimesNewroman, Times, Baskerville, Georgia, serif;
--font-body: "Inconsolata", monospace;
--font-ui: "Helvetica Now", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
/* If Canela is unavailable, uncomment below: */
/* --font-display-fallback: "Playfair Display", "Cormorant Garamond", Georgia, serif; */
}
For Helvetica Now, either:
(a) Host the OTF files from the detected CDN URLs in your /public/fonts/ directory and declare @font-face rules, or
(b) Substitute with Inter (variable font from Google Fonts, weights 200–400) accepting minor visual divergence.
Known Gaps
- Hover states: Not extractable from static screenshot. The spec documents Default and Active/Pressed only (
{component.button-primary-active},{component.input-field-focus}). Hover styling (background color shift, slight lift, border color change) should be designed at implementation time following the brand's "subtle, organic" motion philosophy. - Loading/skeleton states: No skeleton loaders, spinners (beyond the detected preloader), or empty-state designs were visible. Design loading states for forms, image lazy-loading, and async content using the
_spin_keyframe and{colors.accent-light}as the spinner color. - Form validation states: Only default and focus states captured for inputs. Error state (red border? message below?), success state (green checkmark?), and disabled state need design decisions. Recommend using
{colors.hairline-medium}red-tinted for error borders, keeping within the muted palette rather than introducing jarring semantic red. - Authenticated/dashboard flows: The screenshot captures the marketing landing page only. Client portal, scheduling dashboard, counselor admin views, or intake forms are unknown and likely follow a different (potentially more utilitarian) visual dialect.
- Mobile navigation reveal: The hamburger menu's expanded state (overlay? slide-down? full-screen?) was not visible. Design a mobile menu that maintains the cream/dark duality and uses the 0.9s spring for its entrance animation.
- Sub-brand palettes: If Sage Hill offers specialized programs (e.g., "Sage Hill for Teens," "Couples Intensive"), these may introduce accent color variations not captured here. The core palette should remain stable; extensions would add program-specific tokens.
- Canela font deployment: Detected in @font-face rules but not computed in above-fold styles. May be used on deeper pages (blog posts, long-form content) for italic accents or alternative headlines. Treat as optional enhancement;
Times New Romanserves all visible display needs. - Video/animation in hero: The class
w-background-videoon the hero container suggests video may play behind the canvas overlay (ambient, looped, muted). If video is used, it should share the same warm-portrait aesthetic as static photography. A static fallback image is required for performance/accessibility. - Exact slider/carousel design: The
sales-previewsection withw-sliderwas detected in DOM but not visible in the viewport screenshot. Its content (testimonials? pricing? therapist profiles?) and card design within the slider are unknown. Apply{component.card-surface-cream}or{component.card-surface-warm}as the slide template and{component.slider-arrow-button}for controls. - Footer content and structure: Footer surface token is defined (
{component.footer-surface}) but internal layout (columns? newsletter signup? social links? contact info block?) was not visible. Design footer as a dark ({{colors.canvas}}) band containing 2–4 columns of content using{typography.body-sm}for links and{colors.muted}for secondary text.