// page-package.jsx — detail page for a single package. Reads ?p=oneweek|custom|brand const PkgCSS = ` .page .pk-hero{ padding:40px 56px 80px; display:grid; grid-template-columns:1.3fr 1fr; gap:80px; align-items:start; } .page .pk-hero .for{ font-family:'JetBrains Mono',monospace; font-size:12px; letter-spacing:.18em; text-transform:uppercase; color:var(--ink-soft); margin-bottom:18px; } .page .pk-hero h1{ font-family:'Instrument Serif',serif; font-style:italic; font-size:104px; line-height:.9; margin:0 0 24px; letter-spacing:-.02em; } .page .pk-hero .blurb{ font-size:19px; max-width:520px; margin:0 0 32px; } .page .pk-hero .price{ display:flex; align-items:baseline; gap:10px; margin-bottom:6px; } .page .pk-hero .price .from{ font-family:'Instrument Serif',serif; font-style:italic; font-size:22px; color:var(--terra); } .page .pk-hero .price .num{ font-family:'Bricolage Grotesque',sans-serif; font-weight:300; font-size:80px; line-height:1; letter-spacing:-.03em; } .page .pk-hero .when{ font-family:'JetBrains Mono',monospace; font-size:13px; letter-spacing:.04em; color:var(--ink-soft); } .page .pk-hero .cta-row{ display:flex; gap:14px; margin-top:36px; flex-wrap:wrap; } .page .pk-card{ background:var(--paper); border:1px solid var(--rule); border-radius:12px; padding:36px; position:relative; } .page .pk-card.dark{ background:var(--ink); color:var(--bg); } .page .pk-card .tape{ position:absolute; top:-14px; left:36px; width:96px; height:28px; background:rgba(251,191,36,.6); border:1px dashed rgba(26,26,26,.25); transform:rotate(-4deg); } .page .pk-card h3{ font-family:'Instrument Serif',serif; font-style:italic; font-size:30px; margin:6px 0 22px; } .page .pk-card ul{ list-style:none; padding:0; margin:0; display:grid; gap:14px; } .page .pk-card li{ display:flex; gap:12px; font-size:15px; line-height:1.45; align-items:flex-start; } .page .pk-card li::before{ content:'✻'; color:var(--terra); flex:none; } .page .pk-steps{ padding:100px 56px; background:var(--paper); } .page .pk-steps h2{ font-family:'Instrument Serif',serif; font-style:italic; font-size:64px; line-height:1; margin:14px 0 56px; } .page .pk-steps h2 em{ color:var(--terra); } .page .pk-steps .grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:24px; } .page .pk-step{ position:relative; } .page .pk-step .pk-doodle{ width:72px; height:72px; color:var(--terra); margin-bottom:16px; } .page .pk-step .pk-doodle svg{ width:72px; height:72px; } .page .pk-step .n{ font-family:'Instrument Serif',serif; font-style:italic; font-size:48px; color:var(--terra); line-height:1; } .page .pk-step h4{ font-family:'Instrument Serif',serif; font-style:italic; font-size:26px; margin:12px 0 8px; } .page .pk-step p{ font-size:14px; color:var(--ink-soft); margin:0; } .page .pk-incl{ padding:100px 56px; } .page .pk-incl .row{ display:grid; grid-template-columns:1fr 1.6fr; gap:64px; } .page .pk-incl h2{ font-family:'Instrument Serif',serif; font-style:italic; font-size:56px; line-height:1; margin:14px 0 0; } .page .pk-incl .tbl{ display:grid; gap:0; } .page .pk-incl .tr{ display:grid; grid-template-columns:1fr 80px; gap:24px; padding:20px 0; border-top:1px solid var(--rule); align-items:baseline; } .page .pk-incl .tr:last-child{ border-bottom:1px solid var(--rule); } .page .pk-incl .tr .t{ font-size:16px; } .page .pk-incl .tr .t span{ display:block; font-size:13px; color:var(--ink-soft); margin-top:3px; } .page .pk-incl .tr .yn{ text-align:right; font-family:'Instrument Serif',serif; font-style:italic; font-size:22px; } .page .pk-incl .tr .yn.yes{ color:var(--terra); } .page .pk-incl .tr .yn.no{ color:var(--ink-soft); opacity:.5; } .page .pk-faq{ padding:100px 56px; background:var(--paper); } .page .pk-faq h2{ font-family:'Instrument Serif',serif; font-style:italic; font-size:56px; margin:14px 0 40px; } .page .pk-faq h2 em{ color:var(--terra); } .page .pk-faq details{ border-top:1px solid var(--rule); padding:22px 0; max-width:820px; } .page .pk-faq details:last-child{ border-bottom:1px solid var(--rule); } .page .pk-faq summary{ cursor:pointer; list-style:none; display:flex; justify-content:space-between; gap:24px; align-items:baseline; } .page .pk-faq summary::-webkit-details-marker{ display:none; } .page .pk-faq summary .q{ font-family:'Instrument Serif',serif; font-style:italic; font-size:26px; } .page .pk-faq summary .ic{ font-family:'Instrument Serif',serif; font-style:italic; font-size:28px; color:var(--terra); transition:transform .25s; } .page .pk-faq details[open] summary .ic{ transform:rotate(45deg); } .page .pk-faq .a{ font-size:16px; color:var(--ink-soft); margin-top:14px; max-width:720px; } .page .pk-nav-other{ padding:80px 56px; display:grid; grid-template-columns:1fr 1fr; gap:24px; border-top:1px solid var(--rule); } .page .pk-nav-other a{ display:flex; flex-direction:column; gap:6px; padding:32px; border-radius:10px; background:var(--paper); border:1px solid var(--rule); text-decoration:none; color:inherit; transition:transform .25s; } .page .pk-nav-other a:hover{ transform:translateY(-3px); } .page .pk-nav-other .l{ font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.16em; text-transform:uppercase; color:var(--ink-soft); } .page .pk-nav-other .t{ font-family:'Instrument Serif',serif; font-style:italic; font-size:32px; } .page .pk-nav-other .t .px{ color:var(--terra); font-size:20px; margin-left:8px; } @media (max-width:980px){ .page .pk-hero, .page .pk-incl .row{ grid-template-columns:1fr; gap:40px; } .page .pk-steps .grid{ grid-template-columns:1fr 1fr; } .page .pk-nav-other{ grid-template-columns:1fr; } } `; const PACKAGES = { oneweek: { key:'oneweek', forwho:'For the speedy', name:'One-Week Site', price:'$1,800', when:'Live in 5 business days · Squarespace only', blurb:'A fast, fixed-scope Squarespace site for when you need to be online beautifully — and you needed it last week.', dark:false, features:[ 'Up to 5 pages, designed in-platform', 'Brand styling using your existing identity', 'Mobile-responsive, basic SEO setup', '1 round of revisions', '30 days of post-launch support', ], steps:[ { t:'Monday', d:'Kickoff call + you send content & assets.' }, { t:'Tue–Wed', d:'I design and build the whole thing in Squarespace.' }, { t:'Thursday', d:'You review, we do one round of tweaks.' }, { t:'Friday', d:'We launch. Loom walkthrough + you take the keys.' }, ], incl:[ { t:'Pages', s:'Up to 5', yn:'5', yes:true }, { t:'Custom design from scratch', s:'Uses your existing brand', yn:'No', yes:false }, { t:'Platform', s:'Squarespace only', yn:'Squarespace', yes:true }, { t:'Rounds of revisions', s:'', yn:'1', yes:true }, { t:'SEO setup', s:'Basic — titles, meta, sitemap', yn:'Basic', yes:true }, { t:'Post-launch support', s:'', yn:'30d', yes:true }, ], faq:[ { q:'Is one week really enough?', a:'Yes — if you have your content and brand ready on Monday. The speed comes from a tight, fixed scope: up to 5 pages, your existing identity, Squarespace. No custom illustration, no migrations, no surprises.' }, { q:'What do I need to have ready?', a:'Copy for each page, your logo and brand colors, any photography, and a clear idea of the pages you want. I send a short checklist when we book.' }, { q:'Can I add a shop?', a:'A simple one, sometimes — ask first. Anything beyond a handful of products is better suited to a Custom Build.' }, ], cta:'Book a week', }, custom: { key:'custom', forwho:'For the considered', name:'Custom Build', price:'$5,400', when:'5–7 weeks · any platform you like', blurb:'A site designed and built from scratch — no template feel — on whichever platform fits your team and content best.', dark:true, features:[ 'Sitemap, content plan, and proposal', 'Custom design, no template feel', 'Squarespace, Shopify, or WordPress', 'Full SEO setup & analytics', '2 rounds of revisions, Loom walkthrough', '60 days of post-launch care', ], steps:[ { t:'Week 1', d:'Discovery, sitemap, content plan, fixed proposal.' }, { t:'Week 2–3', d:'Design in the open — live in-platform, not static Figma.' }, { t:'Week 4–6', d:'Build, real content, animations, two revision rounds.' }, { t:'Week 7', d:'Launch, Loom walkthrough, written manual, handover.' }, ], incl:[ { t:'Pages', s:'Scoped to your needs', yn:'∞', yes:true }, { t:'Custom design from scratch', s:'No template feel', yn:'Yes', yes:true }, { t:'Platform', s:'Squarespace · Shopify · WordPress', yn:'Any', yes:true }, { t:'Rounds of revisions', s:'', yn:'2', yes:true }, { t:'SEO setup', s:'Full — technical, schema, analytics', yn:'Full', yes:true }, { t:'Post-launch care', s:'', yn:'60d', yes:true }, ], faq:[ { q:'Which platform will you recommend?', a:'Depends on what you sell and who maintains it. Lifestyle/service brands usually fit Squarespace; product-led businesses go Shopify; content-heavy or membership sites lean WordPress; motion-led studios love the platform. I’ll make the call with you in week one.' }, { q:'What does “design in the open” mean?', a:'Instead of static mockups, I design live in the platform you’re launching on. You can click around the actual site as it grows — far fewer “that’s not what I pictured” surprises.' }, { q:'Can this include a migration?', a:'Yes — moving from Wix, an old WordPress, or Squarespace→Shopify can be folded in. We’ll scope redirects and content migration in the proposal so no traffic is lost.' }, ], cta:'Start a project', }, brand: { key:'brand', forwho:'For the soup-to-nuts', name:'Brand & Site', price:'$9,500', when:'8–10 weeks · brand + custom build', blurb:'Identity and website together — logo, type, color, guidelines, and a custom-built site that wears the new brand perfectly.', dark:false, features:[ 'Logo, type system, and color palette', 'Brand guidelines you can hand to anyone', 'Custom-built site on the platform of your choice', 'Brand photography art-direction', '3 rounds of revisions, 90 days of care', ], steps:[ { t:'Week 1–2', d:'Brand discovery, moodboards, direction.' }, { t:'Week 3–4', d:'Logo, type, color, guidelines built and approved.' }, { t:'Week 5–8', d:'Custom site designed & built on your brand.' }, { t:'Week 9–10', d:'Photo art-direction, launch, full handover.' }, ], incl:[ { t:'Brand identity', s:'Logo, type, color, guidelines', yn:'Yes', yes:true }, { t:'Custom design from scratch', s:'Built on the new brand', yn:'Yes', yes:true }, { t:'Platform', s:'Your choice', yn:'Any', yes:true }, { t:'Rounds of revisions', s:'', yn:'3', yes:true }, { t:'Photography art-direction', s:'Moodboard + shot list', yn:'Yes', yes:true }, { t:'Post-launch care', s:'', yn:'90d', yes:true }, ], faq:[ { q:'Can you do just the brand, no site?', a:'I can — but the magic of this package is doing both together so the brand is designed knowing exactly how it’ll live online. If you only need identity, let’s talk scope.' }, { q:'Do you photograph too?', a:'I art-direct — moodboards, shot lists, and working with your photographer — rather than shoot myself. If you need a photographer I have a few I love to recommend.' }, { q:'What are the brand guidelines?', a:'A tidy document covering logo usage, type system, color, spacing, and tone — everything you’d hand to a future collaborator so the brand stays consistent without me.' }, ], cta:'Get the works', }, }; // Step doodles for the package timeline (phone, screen, magnify, rocket) const PK_STEP_ICONS = [ // 01 Monday — phone / kickoff call , // 02 Tue–Wed — browser screen / design + build , // 03 Thursday — magnifying glass / review , // 04 Friday — rocket / launch , ]; function PackagePage(){ const params = new URLSearchParams(window.location.search); const key = params.get('p') || 'custom'; const pk = PACKAGES[key] || PACKAGES.custom; const others = Object.values(PACKAGES).filter(p => p.key !== pk.key); return ( — {pk.forwho} {pk.name} {pk.blurb} from{pk.price} {pk.when} {pk.cta} → Compare all packages {!pk.dark && } What’s included {pk.features.map(f => {f})} How it runs From hello to launch. {pk.steps.map((s,i) => ( {PK_STEP_ICONS[i]} {String(i+1).padStart(2,'0')} {s.t} {s.d} ))} The detail Exactly what you get. {pk.incl.map((r,i) => ( {r.t}{r.s && {r.s}} {r.yn} ))} Good to know Questions, answered. {pk.faq.map((f,i) => ( {f.q}+ {f.a} ))} {others.map(o => ( — {o.forwho} {o.name}from {o.price} ))} Sound like your thing? A 30-minute intro call, no pitch deck. We’ll figure out if we’re a fit and what it’ll take. {pk.cta} → ); } ReactDOM.createRoot(document.getElementById('root')).render();
{pk.blurb}
{s.d}
A 30-minute intro call, no pitch deck. We’ll figure out if we’re a fit and what it’ll take.