← 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; }