'use client' import type { CSSProperties, ReactNode } from 'react' import Link from 'next/link' import { X } from 'lucide-react' import { Button } from '@/components/ui/button' import { cn } from '@/lib/utils' import { START_CARDS, type StartCardName } from './startkort-assets' // The start card is a self-contained dark surface: like LedgerGraph it carries // its own palette in both themes, because the strata image bakes its ground // color into the pixels. Warm white type and a white primary pill sit on top. // Gradients here are image scrims inside a hero surface, not card chrome // (see DECISIONS.md 2026-08-13), and rounded-xl is the hero-surface allowance. const TITLE_COLOR = '#FAF8F1' const BODY_COLOR = 'rgba(247, 244, 236, 0.72)' const EYEBROW_COLOR = 'rgba(247, 244, 236, 0.52)' interface StartCardAction { label: string href?: string onClick?: () => void } interface StartCardProps { card: StartCardName /** 'side-right': image on the right half. 'bleed-left': full-bleed image, * text over a scrim on the left. 'center': full-bleed, centered text. */ layout: 'side-right' | 'bleed-left' | 'center' title: string body: string eyebrow?: string primary: StartCardAction secondary?: StartCardAction /** Floating channel badges over the right half (Underlag). */ floatIcons?: boolean /** Tighter type for narrow containers (the inbox preview pane). */ dense?: boolean onDismiss?: () => void dismissLabel?: string className?: string } function ActionButton({ action, kind }: { action: StartCardAction; kind: 'primary' | 'secondary' }) { const styles = kind === 'primary' ? 'bg-white text-[#1A1410] hover:bg-white/90 active:bg-white/90 focus-visible:ring-white/60 focus-visible:ring-offset-transparent' : 'border border-white/30 bg-transparent text-[#F7F4EC] hover:bg-white/10 active:bg-white/10 focus-visible:ring-white/60 focus-visible:ring-offset-transparent' if (action.href) { return ( ) } return ( ) } // Channel badges for the Underlag card, Wispr-style: translucent circles over // the image, one deliberately cropped by the card edge. Brand marks inline so // the card stays self-contained (Gmail's M, WhatsApp's glyph). const BADGE_STROKE = '#F4F1E8' function badgeSvg(paths: string) { return ( ) } const FLOAT_BADGES: Array<{ style: CSSProperties; icon: ReactNode }> = [ { style: { right: '34%', top: '8%', width: 38, height: 38 }, icon: badgeSvg( '', ), }, { style: { right: '6%', top: '14%', width: 46, height: 46 }, icon: ( ), }, { style: { right: '22%', top: '46%', width: 54, height: 54 }, icon: ( ), }, { style: { right: '5%', top: '64%', width: 42, height: 42 }, icon: badgeSvg( '', ), }, { style: { right: '26%', bottom: '-8%', width: 50, height: 50 }, icon: badgeSvg( '', ), }, ] export function StartCard({ card, layout, title, body, eyebrow, primary, secondary, floatIcons = false, dense = false, onDismiss, dismissLabel, className, }: StartCardProps) { const asset = START_CARDS[card] const g = asset.groundRgb const scrim = layout === 'center' ? `radial-gradient(ellipse 90% 130% at 50% 55%, rgba(${g}, 0.7) 0%, rgba(${g}, 0.36) 55%, rgba(${g}, 0.06) 100%)` : `linear-gradient(90deg, rgba(${g}, 0.92) 0%, rgba(${g}, 0.55) 45%, rgba(${g}, 0.08) 75%)` return (
{layout === 'side-right' ? (
{/* eslint-disable-next-line @next/next/no-img-element */}
) : ( <> {/* eslint-disable-next-line @next/next/no-img-element */}
)} {floatIcons && FLOAT_BADGES.map((badge, i) => ( ))} {onDismiss && ( )}
{eyebrow && (
{eyebrow}
)}

{title}

{body}

{secondary && }
) }