---
name: forge-soft
description: Premium expensive UI register. Warm neutrals, refined typography (Söhne / Inter Display / GT America), generous spacing, considered shadows, spring motion. The Linear/Apple/Vercel/Stripe high-end vibe done correctly. Contains ready-to-paste palettes, type stacks, shadow recipe, motion tokens, worked button + card. Use when the brief is "expensive, calm, refined." Mutex with `forge-minimalist` and `forge-brutalist`.
license: MIT
---

# forge-soft

You are designing in the premium-soft register. Default agent attempts at "polished" produce slightly washed-out cards with three identical greys and a "soft purple" gradient. Real premium-soft relies on perfect type, considered shadows, deliberate restraint, motion that rewards attention. This skill exists to do it right.

The mental model: this register **feels expensive**. Everything is slightly more refined than a normal SaaS dashboard - type tighter, colors warmer, shadows softer, motion springier, spacing more generous. The whole is calibrated to read as quality.

## Quick reference (the things you must never ship)

1. Pure white `#FFFFFF` background or pure black `#000000` foreground.
2. Default Inter at default tracking on every heading.
3. Any indigo-violet-pink gradient.
4. Drop shadow on text, on buttons, or on every card uniformly heavy.
5. Border radius > 24px on buttons (looks playful, not premium).
6. `transition-all` with default ease.
7. Stock photography of "person looking at laptop."
8. Section vertical padding under 5rem on a landing page.
9. More than three font weights on a single page.
10. More than three distinct hue families across the design.

## Hard rules

### Palette

**1. Warm-leaning neutrals over cool.** A near-white that tends toward `#F9F7F4` reads more expensive than pure `#FFFFFF`. A dark mode tending toward `#0F0E0D` reads more expensive than `#000000`.

**2. One brand accent. Used sparingly.** Premium does not mean colorful. Reserve accent for primary CTAs, active states, one or two intentional moments per page.

**3. Greys are warm.** Pure cool greys (`#808080`) read default; warm greys (`#A39C95`) read considered.

**4. No pure black, no pure white.** Both too harsh. `#0B0E13` for dark; `#FBFAF7` for light.

### Type stack (paste-ready)

```css
:root {
  /* contemporary premium */
  --font-display: "GT America", "Söhne", "Inter Display", "Inter", sans-serif;
  --font-body:    "Inter", system-ui, sans-serif;

  /* alt: editorial premium */
  --font-display: "Fraunces", "Tiempos Headline", "Iowan Old Style", serif;
  --font-body:    "Inter", sans-serif;
}
```

### Canonical palettes (paste-ready hex)

```
EDITORIAL WARM
  --bg:        #FBFAF7
  --bg-soft:   #F4F1EB
  --fg:        #1A1A1A
  --fg-dim:    #4A453E
  --fg-mute:   #948D85
  --accent:    #C8501E   /* terracotta */
  --border:    rgba(26, 26, 23, 0.10)

DARK REFINED
  --bg:        #0F0E0D
  --bg-soft:   #15140F
  --fg:        #F4F2EE
  --fg-dim:    #B8B2A8
  --fg-mute:   #6E6A60
  --accent:    #FF7A45
  --border:    rgba(244, 242, 238, 0.08)

COOL PREMIUM (Stripe-style)
  --bg:        #F8FAFB
  --fg:        #0F1419
  --fg-dim:    #4A5560
  --accent:    #4A6FA5   /* deep blue */
  --border:    rgba(15, 20, 25, 0.08)

CREAM HOSPITALITY
  --bg:        #F5F2EC
  --fg:        #1A1A1A
  --accent:    #3D5A4C   /* deep green */
  --border:    rgba(26, 26, 26, 0.12)
```

### Typography rules

**5. Display tracking is tight.** -0.02em to -0.04em at heading sizes. Default tracking looks cheap at scale.

```css
h1 { font-family: var(--font-display); font-size: clamp(3rem, 6vw, 6rem); font-weight: 500; letter-spacing: -0.03em; line-height: 1.02; }
h2 { font-size: clamp(2rem, 3.5vw, 3.5rem); font-weight: 500; letter-spacing: -0.025em; line-height: 1.08; }
h3 { font-size: 1.5rem; font-weight: 500; letter-spacing: -0.015em; }
```

**6. Body at 16-18px on the web.** Smaller reads tight; larger informal. Line-height 1.55-1.65.

**7. Two weights total: 400 and 500/600.** Bold reserved for one or two true emphasis points.

**8. Tabular figures for tables.** Old-style figures in prose where the typeface supports it.

### Spacing

**9. Vertical section padding: 6rem-10rem on landings.** Cramped section spacing is never premium.

**10. Container max-width: 1200-1280px for grids, 720px for prose.**

**11. Generous internal padding on cards: 2-3rem.**

### Shadows (the recipe)

**12. Subtle, warm-tinted, layered.**

```css
:root {
  --shadow-sm: 0 1px 2px rgba(20, 18, 16, 0.04);
  --shadow-md: 0 1px 2px rgba(20, 18, 16, 0.04),
               0 4px 12px rgba(20, 18, 16, 0.06);
  --shadow-lg: 0 1px 2px rgba(20, 18, 16, 0.04),
               0 12px 32px -8px rgba(20, 18, 16, 0.10),
               0 32px 64px -16px rgba(20, 18, 16, 0.08);
}
```

**13. One shadow recipe across the design.** Reusing the same shadow on every elevated element keeps the system coherent.

**14. No drop shadows on text or buttons.** Reserve elevation for cards and modals.

### Borders and radius

**15. Border radius: 8-12px for buttons, 12-20px for cards.** Above 24px starts feeling playful.

**16. Hairline borders 1px in low-contrast neutral.** `#E8E5E0` on warm bg. Present but not loud.

### Motion

**17. Spring or considered cubic-bezier easing.** Linear is wrong. Default ease-in-out reads as software.

```css
:root {
  --ease-out:    cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-inout:  cubic-bezier(0.4, 0, 0.2, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

.btn {
  transition: background 200ms var(--ease-out),
              transform 200ms var(--ease-out);
}
.btn:hover { transform: translateY(-1px); }
```

**18. Duration: 200-400ms component-level, 600-1000ms hero reveals.**

**19. Hover states subtle.** Scale 1.01, brightness 1.05. Never bounce on a button.

**20. Page transitions: cross-fade with slight Y-translate.**

### Imagery

**21. Photography editorially lit, off-center.** Stock-aesthetic centered subjects do not feel premium.

**22. Avoid Storyset/Undraw illustrations.** Custom or licensed.

**23. AI-generated faces only if you can guarantee no hand or eye artifacts.**

### Components

**24. Buttons:** solid accent or near-black, small radius (8-12px), subtle shadow or no shadow.

```tsx
// reference
<button className="bg-zinc-900 text-white px-6 py-3 rounded-lg text-sm font-medium
                   hover:bg-zinc-800 transition-colors duration-200">
  Get started
</button>
```

**25. Cards:** standard shadow recipe, 16-20px radius, 2-3rem internal padding.

```tsx
<div className="bg-white rounded-2xl p-8 shadow-md border border-zinc-100">
  <h3 className="text-2xl font-medium mb-2">Title</h3>
  <p className="text-zinc-600">Description.</p>
</div>
```

**26. Inputs:** soft border, generous padding, slight focus ring in accent color.

```tsx
<input className="w-full px-4 py-3 border border-zinc-200 rounded-lg
                  focus:border-zinc-900 focus:outline-none transition-colors" />
```

**27. Navigation:** simple, restrained. Type-led, no heavy bars.

## Common AI-output patterns to reject

| Pattern | Why it is not premium | Fix |
| --- | --- | --- |
| `bg-gradient-to-r from-pink-500 to-purple-500` on hero | $2999 SaaS gradient | One brand color OR near-black |
| `shadow-2xl` on every card | All-or-nothing | Standard recipe; one shadow scale |
| `rounded-full` on all buttons | Capsule = 2023 | `rounded-lg` (~10px) |
| `text-base font-bold` for hero | Too small + heavy | clamp + weight 500 + tight tracking |
| Three font sizes per section | Hierarchy collapses | 3 sizes total: display, body, label |
| `transition-all duration-300` | No intent | Name properties; 200ms for component |
| Stock photo of laptop user | Default | Real product, editorial photography, abstract gradient |
| 2rem section padding | Cramped | 6-10rem |
| Cool grey `text-gray-500` | Default | Warm `text-zinc-500` or `text-stone-500` |
| Indigo-violet gradient anywhere | AI fingerprint | Cut |

## Worked example: a hero (forge-soft register)

```tsx
export function PremiumHero() {
  return (
    <section className="bg-[#FBFAF7] px-6 lg:px-10 pt-32 pb-24">
      <div className="max-w-6xl mx-auto">
        <p className="font-mono text-xs tracking-widest text-zinc-500 uppercase mb-12">
          Built for engineering teams that ship every day
        </p>

        <h1 className="font-display text-[clamp(3rem,7vw,7rem)] font-medium leading-[0.96]
                       tracking-[-0.035em] text-zinc-900 max-w-[16ch] mb-10">
          Linear-grade tooling,
          <span className="text-zinc-500"> finally for backend.</span>
        </h1>

        <p className="text-xl text-zinc-600 leading-relaxed max-w-[36ch] mb-12">
          A modern issue tracker built around code, commits, and the rhythm of shipping.
          No process. No standups. Just the work.
        </p>

        <div className="flex flex-wrap gap-3">
          <a className="bg-zinc-900 text-white px-7 py-3.5 rounded-lg text-sm font-medium
                        shadow-[0_1px_2px_rgba(20,18,16,0.06)]
                        hover:bg-zinc-800 transition-colors duration-200">
            Start free trial →
          </a>
          <a className="border border-zinc-200 text-zinc-900 px-7 py-3.5 rounded-lg text-sm font-medium
                        hover:border-zinc-900 transition-colors duration-200">
            See demo
          </a>
        </div>
      </div>
    </section>
  );
}
```

What this does right: warm cream background not white (rule 1, 4); display weight 500 with -0.035em tracking (rule 5); 7rem max display via clamp (rule 5); two CTAs, primary solid near-black + secondary outlined (rule 24); type pair: display + sans + mono eyebrow, never four (rule 7); 8rem-equivalent top padding (rule 9); muted secondary text in zinc-500/600 (rule 6); no gradient anywhere; one accent moment via the highlighted second-line text-zinc-500.

## Workflow

When designing soft-premium:

1. **Pick palette and type stack BEFORE code.** Editorial sans + complementary serif, or two distinct sans weights.
2. **Define the shadow recipe once. Reuse everywhere.**
3. **Set the radius scale (8, 12, 16, 20px). Use within it.**
4. **Generous spacing from the start. Resist filling.**
5. **Subtle motion. Add one or two hover/scroll moments, not animations on everything.**
6. **One accent moment per view.** Primary CTA, highlighted figure.
7. **Step back. If it looks slightly more refined than the average SaaS, you are close.**

## Verification

Manual checklist:

- [ ] Background and foreground are warm-neutral, not pure white/black.
- [ ] One brand accent, used sparingly (<5% pixels).
- [ ] Type is a real display face, tracked tight for headlines.
- [ ] Section vertical spacing ≥6rem.
- [ ] Shadow recipe consistent across cards.
- [ ] No purple-pink-blue SaaS gradient.
- [ ] Hover/transition uses spring or considered cubic-bezier easing.
- [ ] Three or fewer font weights.

## When to skip this skill

- Brutalist or editorial-print register (use [`forge-brutalist`](../forge-brutalist/SKILL.md)).
- Minimalist register (use [`forge-minimalist`](../forge-minimalist/SKILL.md)).
- High-density dashboards where polish loses to information density.
- Consumer products that want warmth or whimsy.

## Related skills

- [`forge-frontend`](../forge-frontend/SKILL.md) - the base layer this stacks on.
- [`forge-frontend-nextjs`](../forge-frontend-nextjs/SKILL.md) - if Next.js is your stack.
- [`forge-imagegen-web`](../../imagegen/forge-imagegen-web/SKILL.md) - for the reference comps that match this register.
