feat(db): roadmap_items gains 'considering' + 'in_beta' rename, --on-ink tokens
Migration 0006 (the spec said 0005 but that number was already taken by
polls_on_dispatches from the previous session): rebuilds the
roadmap_items CHECK to ('shipping','in_beta','exploring','considering')
and renames any existing 'beta' rows to 'in_beta' in-place. FKs from
roadmap_attributions are preserved across the DROP/RENAME by toggling
PRAGMA foreign_keys off around the rebuild — attribution count unchanged
after migrate (verified 4 rows survive on the demo DB).
Tokens (src/styles/tokens.css): adds --on-ink, --on-ink-body,
--on-ink-muted, --ink-divider. The bleached #fffcf7 cream replaces the
warm #e8e0d0 --ink-text wherever it sits on indigo. Legacy --ink-text /
--ink-muted stay in tokens.css for now — if any later commit references
them they remain defined; the migration of existing call sites is
covered here.
Migrated to the new tokens in this pass:
- src/components/MembershipCard.astro (members/:slug card)
- src/pages/events.astro (hero invitation card)
Both render with cleaner whites on indigo as a side effect.
Code updates for the new status enum:
- db.ts: RoadmapStatus = shipping | in_beta | exploring | considering
- admin/RoadmapTab.astro: Status select gains Considering + In beta;
grouped section iteration covers all four
- admin/index.astro: validation list updated
- scripts/seed-roadmap.js: 'In progress' markdown bucket → 'in_beta'
- pulse.astro: roadmapStatusDot + roadmapStatusBlurb temporarily widened
(full rewrite of that section lands in step 7)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cb2efa70f3
commit
9ae8422527
9 changed files with 100 additions and 45 deletions
40
migrations/0006_roadmap_considering.sql
Normal file
40
migrations/0006_roadmap_considering.sql
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
-- Roadmap status enum gains a fourth value `considering` for items that are
|
||||||
|
-- under discussion but not yet committed to. Same migration also renames
|
||||||
|
-- the existing `beta` value to `in_beta` so the canonical names line up
|
||||||
|
-- with the v4 spec (no second display label layer needed).
|
||||||
|
--
|
||||||
|
-- SQLite can't widen a CHECK constraint in place, so this is a full table
|
||||||
|
-- rebuild. roadmap_attributions has an ON DELETE CASCADE FK to
|
||||||
|
-- roadmap_items(id), so foreign keys are toggled off around the rebuild to
|
||||||
|
-- preserve attribution rows across the DROP/RENAME.
|
||||||
|
|
||||||
|
PRAGMA foreign_keys = OFF;
|
||||||
|
|
||||||
|
CREATE TABLE roadmap_items_new (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT NOT NULL DEFAULT '',
|
||||||
|
status TEXT NOT NULL DEFAULT 'exploring'
|
||||||
|
CHECK(status IN ('shipping','in_beta','exploring','considering')),
|
||||||
|
target TEXT,
|
||||||
|
display_order INTEGER NOT NULL DEFAULT 0,
|
||||||
|
shipped_at TEXT,
|
||||||
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||||
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO roadmap_items_new
|
||||||
|
(id, title, description, status, target, display_order, shipped_at, created_at, updated_at)
|
||||||
|
SELECT
|
||||||
|
id, title, description,
|
||||||
|
CASE status WHEN 'beta' THEN 'in_beta' ELSE status END,
|
||||||
|
target, display_order, shipped_at, created_at, updated_at
|
||||||
|
FROM roadmap_items;
|
||||||
|
|
||||||
|
DROP TABLE roadmap_items;
|
||||||
|
ALTER TABLE roadmap_items_new RENAME TO roadmap_items;
|
||||||
|
|
||||||
|
CREATE INDEX idx_roadmap_status ON roadmap_items(status, display_order);
|
||||||
|
CREATE INDEX idx_roadmap_shipped ON roadmap_items(shipped_at);
|
||||||
|
|
||||||
|
PRAGMA foreign_keys = ON;
|
||||||
|
|
@ -30,7 +30,7 @@ const md = readFileSync(mdPath, 'utf8');
|
||||||
// schema's three statuses. In-progress items are actively being built and
|
// schema's three statuses. In-progress items are actively being built and
|
||||||
// tested with pilots → beta. Next/Later are roadmap intent, not started → exploring.
|
// tested with pilots → beta. Next/Later are roadmap intent, not started → exploring.
|
||||||
const SECTION_STATUS = {
|
const SECTION_STATUS = {
|
||||||
'In progress': { status: 'beta', target: null },
|
'In progress': { status: 'in_beta', target: null },
|
||||||
'Next': { status: 'exploring', target: 'Next quarter' },
|
'Next': { status: 'exploring', target: 'Next quarter' },
|
||||||
'Later': { status: 'exploring', target: 'Later this year' },
|
'Later': { status: 'exploring', target: 'Later this year' },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ const tags = readFocusTags(member.focus_tags);
|
||||||
<style>
|
<style>
|
||||||
.m-card {
|
.m-card {
|
||||||
background: var(--ink);
|
background: var(--ink);
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -70,7 +70,7 @@ const tags = readFocusTags(member.focus_tags);
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: var(--ink-text);
|
background: var(--on-ink);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -89,7 +89,7 @@ const tags = readFocusTags(member.focus_tags);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--ink-muted);
|
color: var(--on-ink-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-name {
|
.m-name {
|
||||||
|
|
@ -99,7 +99,7 @@ const tags = readFocusTags(member.focus_tags);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
line-height: 1.15;
|
line-height: 1.15;
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
@ -116,12 +116,12 @@ const tags = readFocusTags(member.focus_tags);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--ink-muted);
|
color: var(--on-ink-muted);
|
||||||
}
|
}
|
||||||
.m-since-value {
|
.m-since-value {
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-body-sm);
|
font-size: var(--text-body-sm);
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-tags {
|
.m-tags {
|
||||||
|
|
@ -133,8 +133,8 @@ const tags = readFocusTags(member.focus_tags);
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
}
|
}
|
||||||
.m-tag {
|
.m-tag {
|
||||||
border: 0.5px solid rgba(232, 224, 208, 0.3);
|
border: 0.5px solid rgba(255, 252, 247, 0.3);
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
padding: 3px 8px;
|
padding: 3px 8px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,23 @@ interface Props {
|
||||||
|
|
||||||
const { items, editing, cabUsers } = Astro.props;
|
const { items, editing, cabUsers } = Astro.props;
|
||||||
|
|
||||||
const STATUS_LABEL = { shipping: 'Shipping', beta: 'Beta', exploring: 'Exploring' } as const;
|
const STATUS_LABEL = {
|
||||||
|
shipping: 'Shipping',
|
||||||
|
in_beta: 'In beta',
|
||||||
|
exploring: 'Exploring',
|
||||||
|
considering: 'Considering',
|
||||||
|
} as const;
|
||||||
|
|
||||||
const formAction = editing ? 'update_roadmap' : 'create_roadmap';
|
const formAction = editing ? 'update_roadmap' : 'create_roadmap';
|
||||||
const attributedSet = new Set((editing?.attributed ?? []).map(a => a.id));
|
const attributedSet = new Set((editing?.attributed ?? []).map(a => a.id));
|
||||||
|
|
||||||
// Group items by status for display
|
// Group items by status for display
|
||||||
type Status = 'shipping' | 'beta' | 'exploring';
|
type Status = 'shipping' | 'in_beta' | 'exploring' | 'considering';
|
||||||
const grouped: Record<Status, RoadmapItemWithAttribution[]> = {
|
const grouped: Record<Status, RoadmapItemWithAttribution[]> = {
|
||||||
shipping: items.filter(i => i.status === 'shipping' ).sort((a,b) => a.display_order - b.display_order),
|
shipping: items.filter(i => i.status === 'shipping' ).sort((a,b) => a.display_order - b.display_order),
|
||||||
beta: items.filter(i => i.status === 'beta' ).sort((a,b) => a.display_order - b.display_order),
|
in_beta: items.filter(i => i.status === 'in_beta' ).sort((a,b) => a.display_order - b.display_order),
|
||||||
exploring: items.filter(i => i.status === 'exploring').sort((a,b) => a.display_order - b.display_order),
|
exploring: items.filter(i => i.status === 'exploring' ).sort((a,b) => a.display_order - b.display_order),
|
||||||
|
considering: items.filter(i => i.status === 'considering').sort((a,b) => a.display_order - b.display_order),
|
||||||
};
|
};
|
||||||
---
|
---
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
|
|
@ -39,9 +45,10 @@ const grouped: Record<Status, RoadmapItemWithAttribution[]> = {
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="status" class="label-sm field-label">Status</label>
|
<label for="status" class="label-sm field-label">Status</label>
|
||||||
<select id="status" name="status" class="select body-md" required>
|
<select id="status" name="status" class="select body-md" required>
|
||||||
<option value="exploring" selected={editing?.status === 'exploring'}>Exploring</option>
|
<option value="considering" selected={editing?.status === 'considering'}>Considering</option>
|
||||||
<option value="beta" selected={editing?.status === 'beta'}>Beta</option>
|
<option value="exploring" selected={editing?.status === 'exploring'}>Exploring</option>
|
||||||
<option value="shipping" selected={editing?.status === 'shipping'}>Shipping</option>
|
<option value="in_beta" selected={editing?.status === 'in_beta'}>In beta</option>
|
||||||
|
<option value="shipping" selected={editing?.status === 'shipping'}>Shipping</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
|
|
@ -78,7 +85,7 @@ const grouped: Record<Status, RoadmapItemWithAttribution[]> = {
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ── List by status ────────────────────────────────────────── -->
|
<!-- ── List by status ────────────────────────────────────────── -->
|
||||||
{(['shipping','beta','exploring'] as const).map(status => (
|
{(['shipping','in_beta','exploring','considering'] as const).map(status => (
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<h2 class="label-sm section-heading">{STATUS_LABEL[status]} · {grouped[status].length}</h2>
|
<h2 class="label-sm section-heading">{STATUS_LABEL[status]} · {grouped[status].length}</h2>
|
||||||
{grouped[status].length === 0 ? (
|
{grouped[status].length === 0 ? (
|
||||||
|
|
|
||||||
|
|
@ -650,7 +650,7 @@ export function countPulseParticipants(pulseId: number): number {
|
||||||
|
|
||||||
// ── Roadmap items ────────────────────────────────────────────────
|
// ── Roadmap items ────────────────────────────────────────────────
|
||||||
|
|
||||||
export type RoadmapStatus = 'shipping' | 'beta' | 'exploring';
|
export type RoadmapStatus = 'shipping' | 'in_beta' | 'exploring' | 'considering';
|
||||||
|
|
||||||
export interface RoadmapItem {
|
export interface RoadmapItem {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ if (Astro.request.method === 'POST') {
|
||||||
const displayOrder = Number(data.get('display_order') ?? 0);
|
const displayOrder = Number(data.get('display_order') ?? 0);
|
||||||
const attributedIds = data.getAll('attributed_user_ids').map(v => Number(v)).filter(Boolean);
|
const attributedIds = data.getAll('attributed_user_ids').map(v => Number(v)).filter(Boolean);
|
||||||
|
|
||||||
if (!title || !['shipping','beta','exploring'].includes(status)) {
|
if (!title || !['shipping','in_beta','exploring','considering'].includes(status)) {
|
||||||
formError = 'Title and status are required.';
|
formError = 'Title and status are required.';
|
||||||
} else if (action === 'create_roadmap') {
|
} else if (action === 'create_roadmap') {
|
||||||
const id = createRoadmapItem({ title, description, status, target, display_order: displayOrder });
|
const id = createRoadmapItem({ title, description, status, target, display_order: displayOrder });
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,7 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
/* ── Hero ─────────────────────────────────────────────────────── */
|
/* ── Hero ─────────────────────────────────────────────────────── */
|
||||||
.hero {
|
.hero {
|
||||||
background: var(--ink);
|
background: var(--ink);
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
padding: 1.75rem;
|
padding: 1.75rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -232,7 +232,7 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: var(--ink-muted);
|
color: var(--on-ink-muted);
|
||||||
}
|
}
|
||||||
.hero-eyebrow {
|
.hero-eyebrow {
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
|
|
@ -255,7 +255,7 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
left: 100px;
|
left: 100px;
|
||||||
top: 0; bottom: 0;
|
top: 0; bottom: 0;
|
||||||
width: 0.5px;
|
width: 0.5px;
|
||||||
background: rgba(232, 224, 208, 0.2);
|
background: var(--ink-divider);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-date { display: flex; flex-direction: column; gap: 2px; }
|
.hero-date { display: flex; flex-direction: column; gap: 2px; }
|
||||||
|
|
@ -264,13 +264,13 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
}
|
}
|
||||||
.hero-day {
|
.hero-day {
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-size: 2.75rem;
|
font-size: 2.75rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-detail { padding-left: var(--space-5); }
|
.hero-detail { padding-left: var(--space-5); }
|
||||||
|
|
@ -279,22 +279,22 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
margin: 0 0 var(--space-3);
|
margin: 0 0 var(--space-3);
|
||||||
}
|
}
|
||||||
.hero-desc {
|
.hero-desc {
|
||||||
color: rgba(232, 224, 208, 0.85);
|
color: var(--on-ink-body);
|
||||||
margin: 0 0 var(--space-3);
|
margin: 0 0 var(--space-3);
|
||||||
max-width: 40rem;
|
max-width: 40rem;
|
||||||
}
|
}
|
||||||
.hero-meta {
|
.hero-meta {
|
||||||
color: var(--ink-muted);
|
color: var(--on-ink-muted);
|
||||||
font-size: var(--text-body-sm);
|
font-size: var(--text-body-sm);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-foot {
|
.hero-foot {
|
||||||
border-top: 0.5px solid rgba(232, 224, 208, 0.2);
|
border-top: 0.5px solid var(--ink-divider);
|
||||||
padding-top: var(--space-4);
|
padding-top: var(--space-4);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
@ -304,7 +304,7 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
}
|
}
|
||||||
.hero-foot-left { display: flex; align-items: center; gap: var(--space-4); }
|
.hero-foot-left { display: flex; align-items: center; gap: var(--space-4); }
|
||||||
.hero-foot-stat {
|
.hero-foot-stat {
|
||||||
color: var(--ink-muted);
|
color: var(--on-ink-muted);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
|
|
@ -313,7 +313,7 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
.hero-foot-right { display: flex; align-items: center; gap: var(--space-3); }
|
.hero-foot-right { display: flex; align-items: center; gap: var(--space-3); }
|
||||||
|
|
||||||
.hero-cta {
|
.hero-cta {
|
||||||
background: var(--ink-text);
|
background: var(--on-ink);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
border: none;
|
border: none;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
|
|
@ -329,20 +329,20 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
.hero-cta:hover { opacity: 0.85; }
|
.hero-cta:hover { opacity: 0.85; }
|
||||||
|
|
||||||
.hero-confirmed {
|
.hero-confirmed {
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-md);
|
font-size: var(--text-label-md);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
border: 0.5px solid rgba(232, 224, 208, 0.4);
|
border: 0.5px solid rgba(255, 252, 247, 0.4);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
}
|
}
|
||||||
.hero-change {
|
.hero-change {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--ink-muted);
|
color: var(--on-ink-muted);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
|
|
@ -359,7 +359,7 @@ const heroAudience = hero?.audience ?? 'Members only';
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
.hero-empty-line {
|
.hero-empty-line {
|
||||||
color: var(--ink-text);
|
color: var(--on-ink);
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
|
||||||
|
|
@ -98,19 +98,21 @@ const roadmapPreview = getAllRoadmapItems()
|
||||||
.sort((a, b) => (b.updated_at > a.updated_at ? 1 : -1))
|
.sort((a, b) => (b.updated_at > a.updated_at ? 1 : -1))
|
||||||
.slice(0, 3);
|
.slice(0, 3);
|
||||||
|
|
||||||
function roadmapStatusDot(status: 'shipping' | 'beta' | 'exploring'): string {
|
function roadmapStatusDot(status: 'shipping' | 'in_beta' | 'exploring' | 'considering'): string {
|
||||||
return ({
|
return ({
|
||||||
shipping: 'var(--pigment-copper)',
|
shipping: 'var(--pigment-copper)',
|
||||||
beta: 'var(--pigment-ochre)',
|
in_beta: 'var(--pigment-terracotta)',
|
||||||
exploring: 'var(--on-surface-muted)',
|
exploring: '#b4b2a9',
|
||||||
|
considering: '#d4d2c8',
|
||||||
})[status];
|
})[status];
|
||||||
}
|
}
|
||||||
function roadmapStatusBlurb(item: { status: 'shipping' | 'beta' | 'exploring'; target: string | null }): string {
|
function roadmapStatusBlurb(item: { status: 'shipping' | 'in_beta' | 'exploring' | 'considering'; target: string | null }): string {
|
||||||
const target = item.target ? ` · ${item.target}` : '';
|
const target = item.target ? ` · ${item.target}` : '';
|
||||||
switch (item.status) {
|
switch (item.status) {
|
||||||
case 'shipping': return `Shipping${target}`;
|
case 'shipping': return `Shipping${target}`;
|
||||||
case 'beta': return `In beta${target}`;
|
case 'in_beta': return `In beta${target}`;
|
||||||
case 'exploring': return `Exploring${target}`;
|
case 'exploring': return `Exploring${target}`;
|
||||||
|
case 'considering': return `Considering${target}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,14 @@
|
||||||
--surface-card: #ffffff;
|
--surface-card: #ffffff;
|
||||||
--surface-card-border: rgba(0, 0, 0, 0.08);
|
--surface-card-border: rgba(0, 0, 0, 0.08);
|
||||||
--ink: #2c3a52; /* deep indigo — membership card + event hero */
|
--ink: #2c3a52; /* deep indigo — membership card + event hero */
|
||||||
--ink-text: #e8e0d0; /* readable cream on --ink */
|
--ink-text: #e8e0d0; /* legacy warm cream — superseded by --on-ink */
|
||||||
--ink-muted: #b8a989; /* muted label tone on --ink */
|
--ink-muted: #b8a989; /* legacy tan — superseded by --on-ink-muted */
|
||||||
|
|
||||||
|
/* --- v4: bleached cream on indigo surfaces (replaces --ink-text) --- */
|
||||||
|
--on-ink: #fffcf7; /* primary text on --ink */
|
||||||
|
--on-ink-body: rgba(255, 252, 247, 0.85); /* body copy */
|
||||||
|
--on-ink-muted: rgba(255, 252, 247, 0.65); /* tracked labels */
|
||||||
|
--ink-divider: rgba(255, 252, 247, 0.18); /* 0.5px lines on --ink */
|
||||||
|
|
||||||
/* --- Semantic state mappings --- */
|
/* --- Semantic state mappings --- */
|
||||||
--color-success: var(--pigment-copper);
|
--color-success: var(--pigment-copper);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue