// page-service.jsx — single service page, rendered from SERVICE_DETAILS by ?slug= const SVCPAGECSS = ` .page .sv-intro{ max-width:1100px; margin:0 auto; padding:40px 56px 0; display:grid; grid-template-columns:1.6fr 1fr; gap:48px; align-items:start; } .page .sv-intro .body p{ font-size:19px; line-height:1.6; margin:0 0 22px; } .page .sv-intro .body p:last-child{ margin-bottom:0; } .page .sv-card{ background:var(--paper); border:1px solid var(--rule); border-radius:12px; padding:32px; position:sticky; top:80px; align-self:start; } .page .sv-card .row{ display:flex; justify-content:space-between; align-items:baseline; padding:16px 0; border-bottom:1px dashed var(--rule); gap:16px; } .page .sv-card .row:first-child{ padding-top:0; } .page .sv-card .row:last-child{ border-bottom:none; padding-bottom:0; } .page .sv-card .l{ font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--ink-soft); } .page .sv-card .v{ font-family:'Instrument Serif',serif; font-style:italic; font-size:24px; text-align:right; } .page .sv-card .v.price{ color:var(--terra); } .page .sv-card .btn{ width:100%; justify-content:center; margin-top:24px; } .page .sv-inc{ max-width:1100px; margin:0 auto; padding:96px 56px 0; } .page .sv-inc .grid{ display:grid; grid-template-columns:1fr 1fr; gap:24px; margin-top:40px; } .page .sv-inc .item{ background:var(--paper); border:1px solid var(--rule); border-radius:10px; padding:32px; position:relative; overflow:hidden; transition:transform .25s, box-shadow .25s, border-color .25s; cursor:default; } .page .sv-inc .item:hover{ transform:translateY(-5px) rotate(-.4deg); box-shadow:0 20px 48px -16px rgba(26,26,26,.18); border-color:var(--terra); } .page .sv-inc .item .n{ font-family:'JetBrains Mono',monospace; font-size:12px; color:var(--terra); letter-spacing:.1em; } .page .sv-inc .item h4{ font-family:'Instrument Serif',serif; font-style:italic; font-size:28px; margin:14px 0 10px; font-weight:400; } .page .sv-inc .item p{ margin:0; font-size:16px; line-height:1.5; color:var(--ink-soft); } .page .sv-inc .item .inc-doodle{ position:absolute; bottom:14px; right:18px; font-family:'Caveat',cursive; font-size:18px; color:var(--terra); opacity:0; transform:rotate(6deg) translateY(4px); transition:opacity .25s, transform .25s; pointer-events:none; } .page .sv-inc .item:hover .inc-doodle{ opacity:.7; transform:rotate(6deg) translateY(0); } .page .sv-steps{ background:var(--paper); margin-top:96px; padding:96px 56px; } .page .sv-steps .wrap{ max-width:1100px; margin:0 auto; } .page .sv-steps .grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:48px; margin-top:48px; } .page .sv-steps .step{ display:flex; flex-direction:column; align-items:center; text-align:center; } .page .sv-steps .step .sv-step-doodle{ width:80px; height:80px; color:var(--terra); margin-bottom:20px; opacity:.9; } .page .sv-steps .step .sv-step-doodle svg{ width:80px; height:80px; } .page .sv-steps .step .n{ font-family:'Instrument Serif',serif; font-style:italic; font-size:64px; color:var(--terra); line-height:1; } .page .sv-steps .step h4{ font-family:'Bricolage Grotesque',sans-serif; font-weight:500; font-size:22px; margin:16px 0 8px; } .page .sv-steps .step p{ margin:0; font-size:16px; line-height:1.5; color:var(--ink-soft); max-width:260px; } .page .sv-faq{ max-width:880px; margin:0 auto; padding:96px 56px 0; } .page .sv-faq details{ border-top:1px solid var(--rule); padding:8px 0; } .page .sv-faq details:last-child{ border-bottom:1px solid var(--rule); } .page .sv-faq summary{ list-style:none; cursor:pointer; display:flex; justify-content:space-between; align-items:center; gap:24px; padding:24px 0; } .page .sv-faq summary::-webkit-details-marker{ display:none; } .page .sv-faq summary .q{ font-family:'Instrument Serif',serif; font-style:italic; font-size:26px; } .page .sv-faq summary .ic{ font-family:'JetBrains Mono',monospace; font-size:22px; color:var(--terra); transition:transform .2s; } .page .sv-faq details[open] summary .ic{ transform:rotate(45deg); } .page .sv-faq .a{ font-size:17px; line-height:1.6; color:var(--ink-soft); padding:0 0 24px; max-width:680px; } .page .sv-other{ max-width:1280px; margin:96px auto 0; padding:64px 56px 0; border-top:1px solid var(--rule); } .page .sv-other .grid{ display:grid; grid-template-columns:1fr 1fr; gap:24px; margin-top:36px; } .page .sv-other a{ display:flex; flex-direction:column; gap:8px; padding:32px; border-radius:10px; background:var(--paper); text-decoration:none; color:inherit; transition:transform .25s; } .page .sv-other a:hover{ transform:translateY(-3px); } .page .sv-other a.next{ text-align:right; } .page .sv-other .dir{ font-family:'JetBrains Mono',monospace; font-size:10.5px; letter-spacing:.14em; text-transform:uppercase; color:var(--terra); } .page .sv-other .t{ font-family:'Instrument Serif',serif; font-style:italic; font-size:30px; } .page .sv-newtag{ display:inline-flex; align-items:center; gap:8px; font-family:'JetBrains Mono',monospace; font-size:11px; letter-spacing:.14em; text-transform:uppercase; color:var(--terra); border:1px solid var(--terra); border-radius:999px; padding:5px 12px; margin-left:16px; vertical-align:middle; } @media (max-width:900px){ .page .sv-intro{ grid-template-columns:1fr; gap:36px; padding:40px 24px 0; } .page .sv-card{ position:static; } .page .sv-inc{ padding:64px 24px 0; } .page .sv-inc .grid{ grid-template-columns:1fr; } .page .sv-steps{ padding:64px 24px; margin-top:64px; } .page .sv-steps .grid{ grid-template-columns:1fr; gap:36px; } .page .sv-faq{ padding:64px 24px 0; } .page .sv-faq summary .q{ font-size:22px; } .page .sv-other{ padding:48px 24px 0; margin-top:64px; } .page .sv-other .grid{ grid-template-columns:1fr; } .page .sv-other a.next{ text-align:left; } .page .sv-newtag{ display:flex; width:fit-content; margin:16px 0 0; } } `; function SvcNotFound(){ return ( Services · 404 No suchservice. I couldn’t find that one. Here’s everything I actually offer. ← All services ); } // ---- STEP SVG DOODLES ---- // Each returns an element. ViewBox 0 0 80 80, hand-drawn style. // Color inherits via currentColor. const STEP_SVGS = { notebook: () => ( ), screen: () => ( ), key: () => ( ), magnify: () => ( ), arrows: () => ( ), eye: () => ( ), diagram: () => ( ), phone: () => ( ), rocket: () => ( ), speech: () => ( ), palette: () => ( ), sparkle: () => ( ), checklist: () => ( ), funnel: () => ( ), hammer: () => ( ), wrench: () => ( ), calendar: () => ( ), switchon: () => ( ), chat: () => ( ), sliders: () => ( ), }; function StepDoodle({ icon }){ const fn = STEP_SVGS[icon]; if (!fn) return null; return ( {fn()} ); } function ServicePage(){ const params = new URLSearchParams(location.search); const slug = params.get('slug') || SERVICE_ORDER[0]; const s = SERVICE_DETAILS[slug]; const i = SERVICE_ORDER.indexOf(slug); React.useEffect(() => { if (!s){ document.title = 'Service not found — Maia Hariton'; return; } applySEO({ title: `${s.name} — Maia Hariton`, description: s.lede, type: 'website', }); applyJSONLD({ '@context':'https://schema.org', '@type':'Service', name: s.name, description: s.lede, category: s.cat, provider: { '@type':'Person', name:'Maia Hariton', url:'https://maiahariton.com' }, areaServed: 'Worldwide', offers: { '@type':'Offer', price: (s.from||'').replace(/[^0-9]/g,''), priceCurrency:'USD' }, }); }, [s]); if (!s) return ; const prev = SERVICE_DETAILS[SERVICE_ORDER[i-1]]; const next = SERVICE_DETAILS[SERVICE_ORDER[i+1]]; return ( Service · {s.n} · {s.cat} {s.name}{s.isNew && ✦ new} {s.lede} {s.intro.map((p,idx) => {p})} What’s included {s.includes.map((it,idx) => ( {String(idx+1).padStart(2,'0')} {it.t} {it.d} {['that\'s the one ✓','love this bit ↗','yes, really ✨','chef\'s kiss 🤌','non-negotiable ↑','worth it ✦','trust me on this','the good stuff ★'][idx % 8]} ))} How it works {s.steps.map((st,idx) => ( {idx+1} {st.t} {st.d} ))} Good to know {s.faqs.map((f,idx) => ( {f.q}+ {f.a} ))} More services {prev ? ( ← Previous{prev.name} ) : } {next ? ( Next →{next.name} ) : } 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. Book a call ↗ ); } ReactDOM.createRoot(document.getElementById('root')).render();
I couldn’t find that one. Here’s everything I actually offer.
{s.lede}
{p}
{it.d}
{st.d}
A 30-minute intro call, no pitch deck. We’ll figure out if we’re a fit and what it’ll take.