Color System

Three tiers, cascading. Two primitive scales (v-green, v-neutral) are the source of truth. Semantic tokens (--brand, --bg, --text…) reference primitives. Components only consume semantic tokens. Change a primitive, the whole system updates. All values in oklch(); no pure black, no pure white.

Tier 1 — Primitives

Raw scales, theme-stable. The same numbered stops exist whether the page is light or dark.

--v-green-50 … --v-green-950

50
100
200
300
400
500
600
700
800
900
950

--v-neutral-50 … --v-neutral-950

50
100
200
300
400
500
600
700
800
900
950

Hover any swatch for the oklch value. The ringed stop is the brand anchor — --v-green-500 = #9BC93C.

Tier 2 — Semantic

Brand

The hero. Each token maps to a stop in the v-green scale. Alpha tints (--brand-wash, --brand-glow) auto-derive from --brand via relative color syntax — change the brand once and washes, glows, and gradients all cascade.

--brand var(--v-green-500)oklch(0.79 0.17 124) · #9BC93C
--brand-bright var(--v-green-300)oklch(0.86 0.19 124) · highlight
--brand-dim var(--v-green-600)oklch(0.66 0.14 124) · hover step-down
--brand-deep var(--v-green-800)oklch(0.42 0.105 124) · pressed
--brand-wash oklch(from --brand l c h / 0.12)tinted surface

Surface

A warm, faintly green-tinted ramp from --v-neutral. Both themes use the same primitives — light mode flips which stops the semantic tokens point at.

--bg var(--v-neutral-900)page background
--bg-elevated var(--v-neutral-800)cards · nav
--surface color-mix(800 ↔ 700, 35%)inputs · chips
--surface-hover color-mix(800 ↔ 700, 70%)hover
--surface-active var(--v-neutral-700)active

Border

Three weights from the mid-range of --v-neutral. Most UI lives on --border-subtle; reserve --border-strong for inputs needing presence.

--border-subtlevar(--v-neutral-700)dividers · subtle outlines
--bordervar(--v-neutral-600)default border
--border-strongvar(--v-neutral-500)inputs · prominent

Text

No pure white. The light/dark pair shown next to each token is "dark theme value / light theme value" — both pull from --v-neutral. --text-on-brand is a very dark green-black used on green button fills.

--text v-neutral-100 / v-neutral-800body · headings
--text-secondary v-neutral-300 / v-neutral-600labels
--text-muted v-neutral-400 / v-neutral-500descriptions · captions
--text-disabled v-neutral-500 / v-neutral-400placeholders
--text-on-brand var(--v-neutral-900)on green

Status

For alerts and feedback. Currently one-offs (not yet scaled into --v-amber, --v-blue, --v-red primitives) — bring them into the scale architecture when a second use case appears.

--successoklch(0.78 0.16 145)
--infooklch(0.74 0.13 230)
--warningoklch(0.82 0.16 75)
--dangeroklch(0.66 0.20 25)

Typography

Montserrat covers everything — display, body, and labels — with weight and tracking doing the work. Eyebrow labels use heavy tracking and uppercase, in keeping with the section dividers throughout VRL surfaces. Every size is expressed in rem; lift or shrink the whole scale by changing the single --font-scale token.

Scale modifier

One token controls the size of every piece of text on the page. The default of 1.0625 bumps the 16px browser default to ~17px so body copy reads a touch larger.

/* tokens.css */
:root {
  --font-scale: 1.0625;  /* ≈ 17px root */
}
html {
  font-size: calc(100% * var(--font-scale));
}

Scale

FEATURED EVENTS

Eyebrow0.75rem · 600 · tracking 0.25em · uppercase

Display Large

Display Lclamp(2.5–4rem) · 800 · 1.05

Display Medium

Display Mclamp(2–3rem) · 700 · 1.1

Heading 1

H12rem · 700 · 1.2

Heading 2

H21.5rem · 700 · 1.25

Heading 3

H31.25rem · 600 · 1.3

Heading 4

H41.125rem · 600 · 1.4

Body Large — for intro paragraphs and short, important reading.

Body L1.125rem · 400 · 1.6

Body — the default for paragraphs, descriptions, and most reading text on any surface.

Body1rem · 400 · 1.6

Body Small — UI text, secondary details, meta info, and dense card bodies.

Body S0.875rem · 400 · 1.55

Caption — Dec 22, 2025 6:45 PM

Caption0.75rem · 500 · 1.4

Weights

Six weights ship. Use 300 sparingly (only for very large display text), 400 for body, 500–600 for UI, 700–800 for headings.

Aa
300 · Light
Aa
400 · Regular
Aa
500 · Medium
Aa
600 · SemiBold
Aa
700 · Bold
Aa
800 · ExtraBold

Tracking

Headings tighten slightly; eyebrow labels open dramatically. Body stays neutral.

--tracking-tight-0.02emQuick brown fox
--tracking-normal0Quick brown fox
--tracking-wide0.04emQuick brown fox
--tracking-wider0.12emQUICK BROWN FOX
--tracking-widest0.25emQUICK BROWN FOX

Spacing · Radii · Shadows

A rem-based spacing scale, an 8-step radius ramp anchored by a generous pill, and a layered shadow set that includes the brand's signature glow.

Spacing

All spacing is rem-based, anchored to a 16px root. Use logical properties (padding-inline, margin-block) by default.

--space-3xs
0.125rem · 2px
--space-2xs
0.25rem · 4px
--space-xs
0.5rem · 8px
--space-sm
0.75rem · 12px
--space-md
1rem · 16px
--space-lg
1.5rem · 24px
--space-xl
2rem · 32px
--space-2xl
3rem · 48px
--space-3xl
4rem · 64px
--space-4xl
6rem · 96px

Border Radius

Most cards use --radius-lg. Pills are the signature shape on buttons, inputs, and chips. The squircle is a superellipse — square, but not square. Implemented as a mask-image, so wrap it if you need an outer shadow.

--radius-xs0.25rem
--radius-sm0.5rem
--radius-md0.75rem
--radius-lg1rem
--radius-xl1.5rem
--radius-2xl2rem
--radius-pill999px
--radius-circle50%
--squircle-maskmask-image

Shadows & Elevation

Layered shadows for depth, plus a brand glow that's used on primary buttons, the logo mark, and focus rings.

--shadow-xssubtle lift
--shadow-smcards · resting
--shadow-mdfloating
--shadow-lghover · popovers
--shadow-xlmodals
--shadow-glowbrand · default
--shadow-glow-lgbrand · hover

Aspect ratios

Two ratio tokens carry most of the imagery on VRL surfaces.

7 / 3
--thumb-ratio events · programs · cards
16 / 9
--video-ratio sermons · livestream · video thumbs

Buttons & Links

Pill-shaped, generous padding, and a glow on the primary. Secondary buttons start neutral and pick up brand color on hover.

Variants

.btn–primary · .btn–secondary · .btn–ghost · .btn–brand-soft · disabled

Sizes

.btn–sm (0.75rem · 0.5/0.875) · default (0.875rem · 0.6875/1.25) · .btn–lg (1rem · 0.875/1.75)

With icons

16px stroke icons · gap var(–space-xs)

Sparkle button Special

For high-stakes CTAs — "I'm New", "Sign Up", "Get Started". Animated gradient ring rotates around a pulsing brand glow. Respects prefers-reduced-motion.

.btn–sparkle · conic-gradient border + radial glow · @property animated angle

Contact pills

A subtler button shape used in the Contact band — full-width target, no fill, brand on hover.

Links

This is an inline brand-colored link within a paragraph of body text. Hover steps up to the brighter brand value.

Muted body text with a link still set in brand for clear affordance.

Cards & Surfaces

Cards anchor the entire VRL experience. They come in four flavors: action tiles, row links, featured event cards, and detail cards with image headers and footer actions.

Action tiles

Centered icon + label. Used for "Next Steps" style entry points.

Row links

Icon + label + chevron — used for long lists like "Other Links". Brand icon, neutral text, chevron picks up brand on hover.

Featured event cards

7/3 thumbnail with a floating date badge. Title below the image. Hover lifts and shadows.

Video cards

For sermons, talks, and any video content. 16/9 thumbnail with a play overlay and duration badge.

aspect-ratio: var(--video-ratio) · play icon centered · duration in bottom-left or top-right

Detail card

Image header (7/3) with tags bridging the seam between thumb and body, title, meta, body, and a split action footer. The workhorse pattern for programs, classes, and groups.

Recovery Adults

GriefShare

December 22, 2025 6:45 PM
Weekly: Mondays at 6:45 PM

GriefShare is a support group that provides a safe, welcoming place for people to understand the difficult emotions and process of grief. This 13-week group helps participants discover what to expect in the days ahead.

Forms & Inputs

Soft borders, gentle hover transitions, and a 4-px brand-tinted focus ring. The search pill is the signature input — paired with a circular brand-filled icon button.

Search pill

Used for browse/filter at the top of list views.

Standard fields

Selection controls

Components & Patterns

The page-level pieces — headers for internal pages, breadcrumbs, tags, dropdowns, dividers, and the brand lockup with its signature glow.

Page headers

Two patterns for the top of an internal page. The homepage gets its own treatment.

Simple · .page-title

A clean text-only header for most internal pages. Optional kicker, optional lede, optional actions on the right.

Connect

Life Groups

Small groups of people who meet weekly to do life together — share meals, ask hard questions, and pray for one another.

.page-title · responsive — actions wrap below title on narrow viewports

Hero · .page-hero

For weightier pages — campaigns, ministries, events. Image background with a brand-tinted overlay so text remains readable on any photo. Always treated as a dark surface regardless of page theme.

Heal · Grow · Belong

Recovery at Valley Real Life

A safe community where people walk through hard seasons together — grief, addiction, divorce, loss. You are not alone.

.page-hero · image + brand-tinted overlay + breadcrumb + kicker + title + lede + actions

Hero variants

Add modifiers for height and alignment.

Short

Page subsection

Centered

Featured campaign

.page-hero–short (220px min) · .page-hero–centered (text-align center) · also .page-hero–tall (420px min)

<header class="page-hero">
  <img src="..." alt="" />
  <div class="page-hero__content">
    <ol class="breadcrumb">…</ol>
    <p class="kicker">Eyebrow</p>
    <h1>Page Title</h1>
    <p class="lede">Optional subtitle…</p>
    <div class="page-hero__actions">…</div>
  </div>
</header>

Breadcrumbs Rock RMS compatible

Styled to the standard Rock <ol class="breadcrumb"> markup so it drops in without HTML changes. Three variants: chevron (default), slash, and enclosed pill.

Default — chevron separator

.breadcrumb–slash — classic Rock look

.breadcrumb–enclosed — pill container, for hero headers

<ol class="breadcrumb">
  <li><a href="...">Home</a></li>
  <li><a href="...">People</a></li>
  <li class="active" aria-current="page">Edit</li>
</ol>

Tags

Tiny pill labels — used inside cards and at the top of detail thumbnails. The default sits on a high-contrast surface (light pill on dark, dark pill on light) for legibility in both themes.

Recovery Adults Featured Optional Active Online Almost Full Closed

Date badge

Floats in the top-right corner of event thumbnails. Always tracked, uppercase, and pill-shaped.

Jun 7

Section divider

Centered, tracked uppercase label between two thin rules. Use to break long pages into clear sections.

Featured Events
Other Links
Contact Us

Dropdown / Share menu

Compact popover used for share actions and overflow menus.

Logo glow

The full lockup, presented on a soft brand wash with an outer glow. Reserved for hero placements and standalone screens like the offline page. Automatically swaps to a dark-text variant in light mode.

Valley Real Life Valley Real Life

Avatars

VR
JN
KM

Selection highlight

Native browser text selection is themed to the brand.

Try selecting this text — selection uses the brand green with our dark on-brand text color for readability.

Focus state

Visible focus is non-negotiable. Every interactive element gets a 2px brand outline at 2px offset, plus a 4-px tinted ring on inputs.