← back to Homesonspec
apps/web/src/app/globals.css
113 lines
@import "tailwindcss";
/* ============================================================================
HomesOnSpec design system — token layer
These @theme tokens are the single source of truth. The Claude Design bundle
in /design-system mirrors them 1:1 so the synced component library and the
live app never drift. Tailwind 4 exposes each token as a real CSS custom
property (e.g. --color-brand-700) AND generates utilities (bg-brand-700).
========================================================================== */
@theme {
/* Type — Fraunces (display serif) + Inter (body). next/font injects the
--font-fraunces / --font-inter vars in layout.tsx. */
--font-sans: var(--font-inter), ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
--font-display: var(--font-fraunces), ui-serif, Georgia, "Times New Roman", serif;
/* Brand — deep teal / pine. Anchors the HomesOnSpec wordmark and conveys
trust ("Verified from the source"). */
--color-brand-50: #f0f9f8;
--color-brand-100: #d9efec;
--color-brand-200: #b4deda;
--color-brand-300: #83c5c0;
--color-brand-400: #4fa5a1;
--color-brand-500: #2f8783;
--color-brand-600: #226b69;
--color-brand-700: #1e5654;
--color-brand-800: #1b4645;
--color-brand-900: #123231;
--color-brand-950: #081e1e;
/* Accent — honey / amber. CTAs, "move-in ready", highlights. Warm counter
to the cool brand teal (new-construction optimism). */
--color-accent-50: #fff9ed;
--color-accent-100: #fef0d0;
--color-accent-200: #fbdd9f;
--color-accent-300: #f8c464;
--color-accent-400: #f4a934;
--color-accent-500: #ed8f16;
--color-accent-600: #d1700f;
--color-accent-700: #ae5310;
--color-accent-800: #8d4114;
--color-accent-900: #743714;
/* Semantic status — construction status markers, reused by the map legend. */
--color-status-ready: #16a34a; /* move-in ready */
--color-status-uc: #f59e0b; /* under construction */
--color-status-plan: #3b82f6; /* planned */
--radius-lg: 0.75rem;
--radius-xl: 1rem;
--radius-2xl: 1.5rem;
--shadow-card: 0 1px 2px rgba(16, 50, 49, 0.05), 0 8px 24px -14px rgba(16, 50, 49, 0.20);
--shadow-lift: 0 2px 8px rgba(16, 50, 49, 0.07), 0 28px 56px -24px rgba(16, 50, 49, 0.34);
}
/* ---------------------------------------------------------------------------
Component classes — the reusable primitives. Each maps to a card in the
Claude Design bundle (/design-system/components/*). Kept as thin @apply
compositions so the token layer stays the source of truth.
------------------------------------------------------------------------- */
@layer components {
/* Tailwind 4's @apply only accepts real utilities, so each variant is
self-contained rather than composing a shared .btn class. */
.btn-primary {
@apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-2.5 text-sm font-semibold
transition focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2
bg-brand-700 text-white shadow-sm hover:bg-brand-800 focus-visible:ring-brand-300;
}
.btn-accent {
@apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-2.5 text-sm font-semibold
transition focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2
bg-accent-500 text-brand-950 shadow-sm hover:bg-accent-400 focus-visible:ring-accent-300;
}
.btn-ghost {
@apply inline-flex items-center justify-center gap-2 rounded-full px-5 py-2.5 text-sm font-semibold
transition focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2
bg-white text-brand-800 ring-1 ring-inset ring-brand-200 hover:bg-brand-50 focus-visible:ring-brand-300;
}
.badge-verified {
@apply inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium
bg-brand-50 text-brand-700 ring-1 ring-inset ring-brand-200;
}
.badge-ready {
@apply inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium
bg-accent-100 text-accent-800;
}
.badge-neutral {
@apply inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium
bg-neutral-100 text-neutral-600;
}
.card {
@apply rounded-2xl border border-neutral-200/70 bg-white shadow-[var(--shadow-card)];
}
.card-interactive {
@apply rounded-2xl border border-neutral-200/70 bg-white shadow-[var(--shadow-card)]
transition hover:-translate-y-0.5 hover:border-brand-300 hover:shadow-[var(--shadow-lift)];
}
.field {
@apply w-full rounded-xl border-0 bg-white px-4 py-3 text-neutral-900 shadow-sm
ring-1 ring-inset ring-neutral-200 focus:ring-2 focus:ring-brand-400;
}
.eyebrow {
@apply text-xs font-semibold uppercase tracking-[0.18em] text-brand-600;
}
}
/* Display headings pick up Fraunces with a tighter optical setting. */
.font-display { font-optical-sizing: auto; letter-spacing: -0.01em; }