fix: align Den value section CTAs with hero styling (#902)

* docs: record Den value section CTA plan

* fix(landing): align Den value section CTAs with hero style

* fix(landing): neutralize remaining Den icon accents

* fix(landing): add premium gradient to Den badges

* fix(landing): add more breathing room to Den badge rail

* fix(landing): tighten Den badge medallions

* fix(landing): prevent Den badge clipping

* fix(landing): move Den capability rail higher

---------

Co-authored-by: jcllobet <jcllobet@users.noreply.github.com>
This commit is contained in:
Jan
2026-03-13 16:03:50 -07:00
committed by GitHub
parent 9502137dd4
commit af8068111e
12 changed files with 150 additions and 28 deletions

View File

@@ -0,0 +1,50 @@
# Den Value Section Carbon CTA Design
**Goal:** Bring the Den pricing/value section into visual parity with the Den hero CTA system by using OpenWork's black/carbon palette, rounded pill CTAs, and cleaner responsive spacing.
## Approved Scope
- Keep the existing pricing section structure and copy.
- Replace the bespoke CTA treatments in the value cards with the same rounded CTA language used in the hero.
- Remove the blue featured-card accent language from the Den worker card and use black/carbon gray instead.
- Add small responsive polish so the two cards read cleanly on desktop and stack cleanly on mobile.
- Follow through on the same carbon treatment for the `What you get` icon badges and the `4. Review & Merge` step badge.
## Layout
Desktop:
```text
+----------------------------------------------------------------+
| Pricing copy | [ Human repetitive work ] [ Den worker ]
| | neutral pill button carbon pill CTA|
| | gray accents carbon accents |
+----------------------------------------------------------------+
```
Mobile:
```text
+------------------------+
| Pricing copy |
| [ Human card ] |
| [ Den card ] |
| full-width pill CTAs |
| tighter spacing |
+------------------------+
```
## Visual Direction
- Primary CTA: reuse the shared `doc-button` style so the worker CTA matches the hero exactly.
- Secondary CTA: use a neutral white/carbon rounded pill treatment that sits naturally next to the primary CTA.
- Featured card: remove saturated blue fills, rings, and bullets. Replace them with carbon gradients, charcoal borders, and subtle shadow contrast.
- Capability badges: use soft gray badge fills with carbon icon strokes so the carousel no longer introduces a separate blue system.
- Workflow steps: keep step 1 blue as the intentional setup accent, but move step 4 to the same neutral carbon badge language.
- Responsive polish: prevent narrow text and CTA wrapping issues with slightly tighter gaps, full-width buttons, and card content that fills the available height without depending on desktop spacing.
## Verification
- Run the landing page locally and verify `/den` in desktop and mobile widths.
- Capture before/after screenshots of the value section for the PR.
- Use real-page verification rather than adding a new test harness for this styling-only landing change.

View File

@@ -0,0 +1,73 @@
# Den Value Section Carbon CTA Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Update the Den value section so its CTA and featured-card styling match the hero's black/carbon design language and stay readable on desktop and mobile.
**Architecture:** Keep the existing section/component structure intact and make the change entirely inside the landing package. Reuse the shared `doc-button` class for the worker CTA, keep the human CTA as a neutral pill, and tune only the value-section layout classes needed for responsive balance.
**Tech Stack:** Next.js, React, Tailwind utility classes, shared landing CSS in `packages/landing/app/globals.css`
---
### Task 1: Document the approved UI direction
**Files:**
- Create: `docs/plans/2026-03-13-den-value-section-carbon-design.md`
**Step 1:** Save the approved desktop/mobile layout and palette direction.
**Step 2:** Include the verification expectation for screenshots on `/den`.
**Step 3:** Commit with the implementation change once the section update is ready.
### Task 2: Update the Den value section styling
**Files:**
- Modify: `packages/landing/components/den-value-section.tsx`
**Step 1:** Reuse the shared `doc-button` class for the worker CTA.
**Step 2:** Replace the blue featured-card borders, backgrounds, rings, bullets, and badge accents with black/carbon gray treatments.
**Step 3:** Restyle the human CTA as a neutral rounded pill with border/shadow treatment compatible with the hero CTA system.
**Step 4:** Tighten spacing and width behavior so the two cards stack well on mobile and keep their CTAs visually aligned on desktop.
**Step 5:** Commit the UI change with a short imperative message.
### Task 2b: Neutralize remaining blue icon accents on Den
**Files:**
- Modify: `packages/landing/components/den-capability-carousel.tsx`
- Modify: `packages/landing/components/den-how-it-works.tsx`
**Step 1:** Replace the blue icon treatment in `What you get` with gray badge fills and carbon icon color.
**Step 2:** Keep step 1 blue in `How it works`, but move step 4 to a matching carbon/gray badge treatment.
**Step 3:** Refresh the PR screenshots so reviewers can verify the follow-up polish pass.
### Task 3: Verify the live page and collect artifacts
**Files:**
- Capture: `packages/landing/pr/2026-03-13-den-value-section-carbon-cta/*.png`
**Step 1:** Start the landing page locally.
**Step 2:** Open `/den` in a browser and inspect the value section at desktop and mobile widths.
**Step 3:** Capture before/after screenshots for both widths.
**Step 4:** Use the screenshots in the PR description alongside the problem statement and fix summary.
### Task 4: Open the pull request
**Files:**
- No code changes
**Step 1:** Push `code-factory/den-value-section-carbon-cta`.
**Step 2:** Open a PR against `dev`.
**Step 3:** Describe the bug, the styling changes, the responsive polish, and the screenshot evidence.

View File

@@ -19,6 +19,9 @@ const capabilityItems = [
{ label: "Persistent state", icon: Box },
];
const premiumBadgeClassName =
"relative flex h-8 w-8 shrink-0 items-center justify-center overflow-hidden rounded-full border border-white/80 bg-[radial-gradient(circle_at_28%_24%,rgba(255,255,255,0.96),rgba(255,255,255,0.52)_34%,transparent_35%),linear-gradient(180deg,#f6f8fb_0%,#e0e6ee_100%)] text-[#111827] shadow-[inset_0_1px_0_rgba(255,255,255,0.88),0_14px_26px_-20px_rgba(15,23,42,0.26)] ring-1 ring-[#d9e0e8]";
export function DenCapabilityCarousel() {
const reduceMotion = useReducedMotion();
const repeatedItems = [...capabilityItems, ...capabilityItems];
@@ -29,7 +32,7 @@ export function DenCapabilityCarousel() {
What you get
</div>
<div className="relative overflow-hidden">
<div className="relative overflow-hidden py-2">
<div className="pointer-events-none absolute inset-y-0 left-0 z-10 w-16 bg-gradient-to-r from-[#f6f9fc] via-[#f6f9fc]/90 to-transparent md:w-28" />
<div className="pointer-events-none absolute inset-y-0 right-0 z-10 w-16 bg-gradient-to-l from-[#f6f9fc] via-[#f6f9fc]/90 to-transparent md:w-28" />
<motion.div
@@ -49,8 +52,9 @@ export function DenCapabilityCarousel() {
key={`${item.label}-${index}`}
className="flex shrink-0 items-center gap-3 text-slate-700"
>
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-white/55 text-[#1b29ff] shadow-[0_10px_24px_-20px_rgba(15,23,42,0.4)] ring-1 ring-white/70 backdrop-blur-sm">
<Icon size={17} strokeWidth={2.2} />
<span className={premiumBadgeClassName}>
<span className="pointer-events-none absolute inset-[1px] rounded-full bg-[radial-gradient(circle_at_72%_76%,rgba(255,255,255,0.18),transparent_46%),repeating-linear-gradient(135deg,rgba(255,255,255,0.08)_0,rgba(255,255,255,0.08)_1px,transparent_1px,transparent_7px)] opacity-80" />
<Icon size={15} strokeWidth={2.2} className="relative z-10" />
</span>
<span className="text-[1rem] font-medium tracking-tight text-[#011627] md:text-[1.08rem]">
{item.label}

View File

@@ -25,7 +25,7 @@ const steps = [
title: "4. Review & Merge",
body: "The worker proposes changes via PRs or messaging platforms.",
icon: CheckCircle2,
accent: "bg-[#1b29ff]/10 text-[#1b29ff]",
accent: "bg-[linear-gradient(180deg,#eceff3,#dfe4ea)] text-[#111827] ring-1 ring-[#d7dde5]",
},
];

View File

@@ -1,6 +1,6 @@
"use client";
import { ArrowRight, CheckCircle2 } from "lucide-react";
import { CheckCircle2 } from "lucide-react";
type DenValueSectionProps = {
getStartedHref: string;
@@ -17,13 +17,13 @@ Best`;
const hireHumanHref = `mailto:ben@openwork.software?subject=${encodeURIComponent(hireHumanSubject)}&body=${encodeURIComponent(hireHumanBody)}`;
return (
<section className="landing-shell rounded-[2.1rem] bg-[radial-gradient(circle_at_top_right,rgba(27,41,255,0.08),transparent_28%),linear-gradient(180deg,rgba(255,255,255,0.94),rgba(248,250,252,0.98))] p-7 md:p-9">
<section className="landing-shell rounded-[2.1rem] bg-[radial-gradient(circle_at_top_right,rgba(15,23,42,0.08),transparent_30%),linear-gradient(180deg,rgba(255,255,255,0.94),rgba(244,246,248,0.98))] p-6 md:p-9">
<div className="grid gap-6 xl:grid-cols-[minmax(0,0.62fr)_minmax(0,1.38fr)] xl:items-start">
<div className="max-w-[28rem]">
<div className="mb-3 text-[11px] font-semibold uppercase tracking-[0.22em] text-gray-500">
Pricing
</div>
<p className="text-[2.35rem] font-medium leading-[1.02] tracking-tight text-[#011627] md:text-[2.8rem]">
<p className="text-[2.15rem] font-medium leading-[1.02] tracking-tight text-[#011627] md:text-[2.8rem]">
Replace repetitive work with a $50 worker.
</p>
<p className="mt-4 text-[16px] leading-7 text-[#5f6b7a]">
@@ -32,14 +32,14 @@ Best`;
</p>
</div>
<div className="rounded-[2rem] border border-[#dce2f4] bg-[rgba(255,255,255,0.94)] p-4 shadow-[0_24px_70px_-28px_rgba(15,23,42,0.18)] md:p-5">
<div className="grid gap-3 md:grid-cols-2 md:items-stretch">
<article className="flex h-full flex-col rounded-[1.5rem] border border-[#e2e8f0] bg-[linear-gradient(180deg,#ffffff,#f8fafc)] px-4 py-4 shadow-[0_10px_26px_-22px_rgba(15,23,42,0.22)] md:px-5">
<div className="rounded-[2rem] border border-[#d9dee5] bg-[rgba(255,255,255,0.94)] p-4 shadow-[0_24px_70px_-28px_rgba(15,23,42,0.16)] md:p-5">
<div className="grid gap-4 md:grid-cols-2 md:items-stretch">
<article className="flex h-full flex-col rounded-[1.6rem] border border-[#dbe1e8] bg-[linear-gradient(180deg,#ffffff,#f6f7f9)] px-4 py-4 shadow-[0_10px_26px_-22px_rgba(15,23,42,0.18)] md:px-5">
<div className="flex items-center justify-between gap-3">
<div className="whitespace-nowrap text-[11px] font-semibold uppercase tracking-[0.18em] text-[#64748b]">
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#64748b] sm:whitespace-nowrap">
Human repetitive work
</div>
<div className="invisible inline-flex items-center gap-1 rounded-full bg-white/80 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] ring-1 ring-transparent">
<div className="invisible hidden items-center gap-1 rounded-full bg-white/80 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] ring-1 ring-transparent md:inline-flex">
<CheckCircle2 size={12} strokeWidth={2.4} />
Recommended
</div>
@@ -63,9 +63,7 @@ Best`;
<div className="mt-auto pt-5">
<a
href={hireHumanHref}
target="_blank"
rel="noreferrer"
className="inline-flex min-h-10 w-full items-center justify-center rounded-xl border border-[#cbd5e1] bg-white px-4 py-2 text-center text-sm font-semibold text-[#334155] shadow-[0_1px_2px_rgba(17,24,39,0.06)] transition hover:bg-[#f8fafc]"
className="secondary-button w-full border border-[#d6dbe2] px-4 text-center text-sm font-semibold text-[#1f2937] shadow-[0_12px_24px_-22px_rgba(15,23,42,0.32)] transition hover:border-[#c8d0da] hover:bg-[#f5f6f8]"
>
Hire a human automator
</a>
@@ -75,12 +73,12 @@ Best`;
</div>
</article>
<article className="relative flex h-full flex-col rounded-[1.5rem] border border-[#c7d2fe] bg-[linear-gradient(180deg,rgba(245,247,255,0.98),rgba(237,242,255,0.98))] px-4 py-4 shadow-[0_18px_40px_-28px_rgba(27,41,255,0.28)] ring-1 ring-[#1b29ff]/10 md:px-5">
<article className="relative flex h-full flex-col rounded-[1.6rem] border border-[#c4cbd5] bg-[radial-gradient(circle_at_top,rgba(15,23,42,0.08),transparent_45%),linear-gradient(180deg,#fbfbfc,#eef1f4)] px-4 py-4 shadow-[0_20px_44px_-28px_rgba(15,23,42,0.28)] ring-1 ring-[#0f172a]/5 md:px-5">
<div className="flex items-center justify-between gap-3">
<div className="whitespace-nowrap text-[11px] font-semibold uppercase tracking-[0.18em] text-[#1b29ff]">
<div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-[#111827] sm:whitespace-nowrap">
Den worker
</div>
<div className="inline-flex items-center gap-1 rounded-full bg-white/80 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-[#1b29ff] ring-1 ring-[#1b29ff]/10">
<div className="inline-flex items-center gap-1 rounded-full bg-[#111827] px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] text-white shadow-[0_10px_24px_-18px_rgba(15,23,42,0.5)]">
<CheckCircle2 size={12} strokeWidth={2.4} />
Recommended
</div>
@@ -92,11 +90,11 @@ Best`;
</div>
<div className="mt-4 space-y-3 text-[12px] leading-6 text-[#42526a] md:text-[13px]">
<div className="flex items-start gap-2">
<span className="mt-[7px] h-1.5 w-1.5 shrink-0 rounded-full bg-[#1b29ff]" />
<span className="mt-[7px] h-1.5 w-1.5 shrink-0 rounded-full bg-[#111827]" />
<span>Handles repetitive work continuously instead of in bursts.</span>
</div>
<div className="flex items-start gap-2">
<span className="mt-[7px] h-1.5 w-1.5 shrink-0 rounded-full bg-[#1b29ff]" />
<span className="mt-[7px] h-1.5 w-1.5 shrink-0 rounded-full bg-[#111827]" />
<span>Keeps humans focused on approvals and exceptions.</span>
</div>
</div>
@@ -104,14 +102,11 @@ Best`;
<div className="mt-auto pt-5">
<a
href={props.getStartedHref}
target="_blank"
rel="noreferrer"
className="inline-flex min-h-10 w-full items-center justify-center gap-2 rounded-xl border border-[#1b29ff]/25 bg-[linear-gradient(135deg,#1b29ff_0%,#2639ff_58%,#1a2bd0_100%)] px-4 py-2 text-sm font-semibold text-white shadow-[0_12px_24px_rgba(27,41,255,0.2)] transition hover:-translate-y-px"
className="doc-button w-full px-4 text-sm font-semibold"
>
Start with one worker
<ArrowRight size={16} strokeWidth={2.3} />
Deploy your first worker
</a>
<p className="mt-2 text-center text-[11px] font-medium text-[#64748b]">
<p className="mt-2 text-center text-[11px] font-medium text-[#5f6b7a]">
Same setup. Lower cost.
</p>
</div>

View File

@@ -55,7 +55,7 @@ export function LandingDen(props: Props) {
<div className="mx-auto flex w-full max-w-6xl flex-col gap-14 px-6 pb-24 md:gap-20 md:px-8 md:pb-28">
<DenHero stars={props.stars} getStartedHref={props.getStartedHref} />
<DenCapabilityCarousel />
<section className="grid gap-5 md:grid-cols-3">
{useCaseCards.map(card => (
<article
@@ -81,7 +81,7 @@ export function LandingDen(props: Props) {
))}
</section>
<DenCapabilityCarousel />
<DenHowItWorks />

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 358 KiB