PageSourceSearch

https://arcbound.com/assets/WebsiteBrief-hU17nn_y.js

js arcbound.com collected 2026-10-09 22:59:02 UTC 108,615 bytes, 1,985 lines download raw bytes

1import{c as Xe,b as Ke,r as w,s as k,u as x,j as e,l as et}from"./index-DmBrIuMr.js";import{D as tt,a as st,b as ot,c as pe,d as at}from"./dropdown-menu-DOx7VjSH.js";import{E as Ge}from"./jspdf.es.min-QP5ynwro.js";import{B as F}from"./button-BVgaPNYd.js";import{D as nt,a as it,b as rt,c as lt,d as ct}from"./dialog-D3JEJsPU.js";import{A as dt}from"./arrow-right-D6kuqmE-.js";import{E as pt}from"./external-link-BDzjTqCP.js";import{C as Te}from"./circle-check-big-BuDXyV8n.js";import{G as Qe}from"./globe-DPgUrQ5O.js";import{F as We}from"./file-image-QXgjySDd.js";import{L as he}from"./loader-circle-BgFsXzCb.js";import{U as ht}from"./upload-CglqxmSA.js";import{A as mt}from"./arrow-left-CzyOJBz-.js";import{R as ut}from"./refresh-cw-CFMYbA4X.js";import{D as Le}from"./download-C5OTLHBb.js";import{C as gt}from"./chevron-down-BuzlTV0R.js";import{F as Ce}from"./file-text-BUtOihor.js";import{D as qe}from"./dna-PP0I9YbM.js";import{P as Ze}from"./palette-DM6ZdyWE.js";import{W as ft}from"./wand-sparkles-DCx-vvW5.js";import{C as Ve}from"./copy-M8CVK2vH.js";import{T as yt}from"./type-C50H1-S8.js";import{P as bt}from"./panels-top-left-mGRm0YVF.js";import{I as vt}from"./image-ChWzI2UK.js";import{S as _t}from"./sparkles-BrrgE7yr.js";import"./index-Bf1vIFkb.js";import"./Combination-B-vZEg9O.js";import"./index-DMAls7C9.js";import"./chevron-right-Bm11si2L.js";import"./check-Bd6GKLth.js";import"./circle-Bu3JpZwb.js";import"./index-BtoCHN1J.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const Ye=Xe("ClipboardCopy",[["rect",{width:"8",height:"4",x:"8",y:"2",rx:"1",ry:"1",key:"tgr4d6"}],["path",{d:"M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2",key:"4jdomd"}],["path",{d:"M16 4h2a2 2 0 0 1 2 2v4",key:"3hqy98"}],["path",{d:"M21 14H11",key:"1bme5i"}],["path",{d:"m15 10-4 4 4 4",key:"5dvupr"}]]);/**
7 * @license lucide-react v0.462.0 - ISC
8 *
9 * This source code is licensed under the ISC license.
10 * See the LICENSE file in the root directory of this source tree.
11 */const De=Xe("Code",[["polyline",{points:"16 18 22 12 16 6",key:"z7tu5w"}],["polyline",{points:"8 6 2 12 8 18",key:"1eg1df"}]]),Je=[{id:"native",name:"Arcbase Native",description:"Build directly in the OS, section by section",url:null,icon:"✨",native:!0},{id:"claude",name:"Claude",description:"Build with Claude AI — paste the brief and iterate",url:"https://claude.ai/new",icon:"🤖"},{id:"vercel",name:"Vercel / v0",description:"Launch on Vercel with v0.dev for rapid prototyping",url:"https://v0.dev",icon:"▲"},{id:"lovable",name:"Lovable",description:"Build with Lovable's AI-powered editor",url:"https://lovable.dev",icon:"💜"},{id:"other",name:"Other",description:"Manual build or another platform",url:null,icon:"🔧"}];function xt({clientId:y,clientName:se}){var fe;const H=Ke(),[Q,m]=w.useState(!1),[C,T]=w.useState({build_platform:"",html_code:"",figma_link:"",homepage_file_path:"",homepage_file_type:"",status:"draft",notes:""}),[oe,J]=w.useState(!1),[ae,me]=w.useState(!1),[Z,ne]=w.useState(null),[X,z]=w.useState(null);w.useEffect(()=>{ue()},[y]);const ue=async()=>{const{data:f}=await k.from("website_builds").select("*").eq("client_id",y).single();if(f){const u=f;if(ne(u.id),T({build_platform:u.build_platform||"",html_code:u.html_code||"",figma_link:u.figma_link||"",homepage_file_path:u.homepage_file_path||"",homepage_file_type:u.homepage_file_type||"",status:u.status||"draft",notes:u.notes||""}),u.homepage_file_path){const{data:D}=await k.storage.from("client-media").createSignedUrl(u.homepage_file_path,3600);D!=null&&D.signedUrl&&z(D.signedUrl)}}},ie=w.useCallback(async f=>{J(!0);try{if(Z)await k.from("website_builds").update({...f,updated_at:new Date().toISOString()}).eq("id",Z);else{const{data:u}=await k.from("website_builds").insert({client_id:y,...f}).select().single();u&&ne(u.id)}x.success("Build info saved")}catch{x.error("Failed to save")}finally{J(!1)}},[y,Z]),je=f=>{const u=Je.find(t=>t.id===f),D={...C,build_platform:f};if(T(D),u!=null&&u.native){ie(D),H(`/website-builder/${y}`);return}u!=null&&u.url&&window.open(u.url,"_blank","noopener,noreferrer"),m(!0)},Ae=async f=>{var t;const u=(t=f.target.files)==null?void 0:t[0];if(!u)return;if(!["image/png","image/jpeg","image/webp","application/pdf"].includes(u.type)){x.error("Please upload a PNG, JPEG, WebP, or PDF file");return}me(!0);try{const i=u.name.split(".").pop(),l=`${y}/homepage-build/homepage.${i}`;await k.storage.from("client-media").upload(l,u,{upsert:!0});const n={...C,homepage_file_path:l,homepage_file_type:u.type};T(n);const{data:r}=await k.storage.from("client-media").createSignedUrl(l,3600);r!=null&&r.signedUrl&&z(r.signedUrl),x.success("Homepage uploaded")}catch{x.error("Upload failed")}finally{me(!1)}},$e=()=>ie(C),ge=C.html_code||C.figma_link||C.homepage_file_path;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mt-8 rounded-xl border-2 border-dashed border-primary/30 bg-primary/5 p-6",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-4",children:[e.jsx("div",{className:"w-10 h-10 rounded-full bg-primary/10 flex items-center justify-center",children:e.jsx(dt,{className:"w-5 h-5 text-primary"})}),e.jsxs("div",{children:[e.jsx("h3",{className:"text-base font-semibold",children:"Ready to Build?"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Launch your website with the brief above, then come back to link your deliverables"})]})]}
11),e.jsx("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-3 mb-4",children:Je.map(f=>e.jsxs("button",{onClick:()=>je(f.id),className:`flex flex-col items-center gap-2 p-4 rounded-lg border text-center transition-all hover:border-primary hover:shadow-sm ${C.build_platform===f.id?"border-primary bg-primary/5 shadow-sm":"border-border bg-card"}`,children:[e.jsx("span",{className:"text-2xl",children:f.icon}),e.jsx("span",{className:"text-sm font-medium",children:f.name}),e.jsx("span",{className:"text-[10px] text-muted-foreground leading-tight",children:f.description}),f.url&&e.jsx(pt,{className:"w-3 h-3 text-muted-foreground"})]},f.id))}),ge&&e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground mb-3",children:[e.jsx(Te,{className:"w-3.5 h-3.5 text-green-600"}),"Build artifacts saved",e.jsx(F,{variant:"link",size:"sm",className:"h-auto p-0 text-xs",onClick:()=>m(!0),children:"View / Edit"})]}),!ge&&e.jsxs(F,{variant:"outline",size:"sm",onClick:()=>m(!0),className:"w-full",children:[e.jsx(De,{className:"w-4 h-4 mr-2"})," Paste HTML, Link Figma, or Upload Homepage"]})]}),e.jsx(nt,{open:Q,onOpenChange:m,children:e.jsxs(it,{className:"max-w-2xl max-h-[85vh] overflow-y-auto",children:[e.jsxs(rt,{children:[e.jsxs(lt,{children:["Website Build — ",se]}),e.jsx(ct,{children:"Paste your HTML code, link your Figma design, or upload the homepage screenshot."})]}),e.jsxs("div",{className:"space-y-6 mt-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm font-medium mb-2",children:[e.jsx(De,{className:"w-4 h-4"})," HTML Code"]}),e.jsx("textarea",{className:"w-full h-40 rounded-md border bg-muted/30 p-3 text-sm font-mono resize-y focus:outline-none focus:ring-2 focus:ring-ring",placeholder:"Paste your HTML code here...",value:C.html_code,onChange:f=>T({...C,html_code:f.target.value})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm font-medium mb-2",children:[e.jsx(Qe,{className:"w-4 h-4"})," Figma Design Link"]}),e.jsx("input",{type:"url",className:"w-full rounded-md border bg-muted/30 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",placeholder:"https://www.figma.com/file/...",value:C.figma_link,onChange:f=>T({...C,figma_link:f.target.value})})]}),e.jsxs("div",{children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm font-medium mb-2",children:[e.jsx(We,{className:"w-4 h-4"})," Upload Homepage (PDF, PNG, JPEG)"]}),X&&((fe=C.homepage_file_type)!=null&&fe.startsWith("image/"))?e.jsx("div",{className:"mb-3 rounded-lg border overflow-hidden",children:e.jsx("img",{src:X,alt:"Homepage preview",className:"w-full max-h-60 object-contain bg-muted/20"})}):X?e.jsxs("div",{className:"mb-3 p-3 rounded-lg border bg-muted/20 flex items-center gap-2",children:[e.jsx(We,{className:"w-5 h-5 text-muted-foreground"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:"PDF uploaded"}),e.jsx("a",{href:X,target:"_blank",rel:"noreferrer",className:"text-xs text-primary underline ml-auto",children:"View"})]}):null,e.jsxs("label",{className:"flex items-center justify-center gap-2 p-4 rounded-lg border-2 border-dashed border-border hover:border-primary/50 cursor-pointer transition-colors",children:[ae?e.jsx(he,{className:"w-4 h-4 animate-spin"}):e.jsx(ht,{className:"w-4 h-4 text-muted-foreground"}),e.jsx("span",{className:"text-sm text-muted-foreground",children:ae?"Uploading...":"Click to upload or replace"}),e.jsx("input",{type:"file",className:"hidden",accept:".pdf,.png,.jpg,.jpeg,.webp",onChange:Ae,disabled:ae})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-sm font-medium mb-2 block",children:"Notes"}),e.jsx("textarea",{className:"w-full h-20 rounded-md border bg-muted/30 p-3 text-sm resize-y focus:outline-none focus:ring-2 focus:ring-ring",placeholder:"Any notes about the build...",value:C.notes,onChange:f=>T({...C,notes:f.target.value})})]}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(F,{variant:"outline",onClick:()=>m(!1),children:"Cancel"}),e.jsxs(F,{onClick:$e,disabled:oe,children:[oe?e.jsx(he,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(Te,{className:"w-4 h-4 mr-1"}),"Save Build Info"]})]})]})]})})]})}
11const K=[{key:"voice-tone",title:"Brand Identity, Voice & Messaging",icon:yt},{key:"hero-concept",title:"⭐ Hero & Homepage Concept",icon:Qe},{key:"layout-components",title:"Layout & Component Guidelines",icon:bt},{key:"homepage-copy",title:"Homepage Copy (Exact Text)",icon:Ce},{key:"design-system",title:"Design System & Visual Foundation",icon:Ze},{key:"imagery-graphics",title:"Imagery, Graphics & Visual Content",icon:vt},{key:"design-references",title:"Design Inspirations & References",icon:_t},{key:"technical-spec",title:"Technical Implementation Specs",icon:De}];function wt({filePath:y,fileName:se}){const[H,Q]=w.useState(null);return w.useEffect(()=>{k.storage.from("client-media").createSignedUrl(y,3600).then(({data:m})=>{m!=null&&m.signedUrl&&Q(m.signedUrl)})},[y]),H?e.jsx("img",{src:H,alt:se,className:"aspect-square object-cover w-full"}):e.jsx("div",{className:"aspect-square bg-muted animate-pulse"})}function ts(){const{clientId:y}=et(),se=Ke(),[H,Q]=w.useState(!0),[m,C]=w.useState(null),[T,oe]=w.useState("voice-tone"),[J,ae]=w.useState([]),[me,Z]=w.useState(null);w.useState(!1);const[ne,X]=w.useState(!1),[z,ue]=w.useState({});w.useEffect(()=>{y&&ie()},[y]);const ie=async()=>{var t,i,l,n,r,c,d,g,v,S,$,_,O;Q(!0);try{const[j,P,G,R,U]=await Promise.all([k.from("clients").select("*").eq("id",y).single(),k.from("brand_dna").select("*").eq("client_id",y).single(),k.from("homepage_copy").select("*").eq("client_id",y).single(),k.from("client_sitemaps").select("*").eq("client_id",y).single(),k.from("client_media_requests").select("id").eq("client_id",y)]),W=j.data,A=((t=P.data)==null?void 0:t.profile_data)||{},ye=((i=G.data)==null?void 0:i.sections)||[],q=R.data,re=(U.data||[]).map(b=>b.id);if(re.length>0){const{data:b}=await k.from("client_media_uploads").select("*").in("media_request_id",re);ae(b||[])}const M=A.visualBrandKit||{},L=A.designParameters||{},be={};(((l=M.colorSystem)==null?void 0:l.palette)||L.colors||[]).forEach((b,N)=>{be[`color${N}`]={name:b.name||`Color ${N+1}`,hex:b.hex,role:b.role||b.usage||"accent"}});const V=M.typography||{},Ee=L.displayFont||L.headerFont||"",Y=L.bodyFont||"",Ie=Ee||((n=V.display)==null?void 0:n.fontFamily)||"Sans-serif",ve=Y||((r=V.body)==null?void 0:r.fontFamily)||"Sans-serif",Pe=L.displayFontSource||((c=V.display)==null?void 0:c.source)||"google",Oe=L.bodyFontSource||((d=V.body)==null?void 0:d.source)||"google",E=A.visualDirection||{},ee=E.moodKeywords||((g=E.moodAndAtmosphere)==null?void 0:g.split(",").map(b=>b.trim()))||A.brandPersonality||[],B=A.brandVoiceTone||{},_e=B.characteristics||B.voiceAttributes||[],xe=B.doSay||B.samplePhrases||[],s=B.dontSay||B.avoidPhrases||[],o=[];if(M.designInspirations){const b=M.designInspirations;b.tasteGamePicks&&b.tasteGamePicks.forEach(N=>o.push(N.label||N.chosenLabel||"")),b.websiteStylePicks&&b.websiteStylePicks.forEach(N=>o.push(N.url||N.label||"")),b.moodboardAssets&&b.moodboardAssets.forEach(N=>o.push(N.label||N.url||""))}E.aesthetic&&o.push(`Visual aesthetic: ${E.aesthetic}`),E.imageryStyle&&o.push(`Imagery style: ${E.imageryStyle}`);const a=[];q!=null&&q.sitemap_data&&(Array.isArray(q.sitemap_data)?q.sitemap_data:[]).forEach(N=>{var de;(de=N.data)!=null&&de.label&&a.push({label:N.data.label,href:`/${N.data.label.toLowerCase().replace(/\s+/g,"-")}`})});const p=((v=M.logoGuidelines)==null?void 0:v.approvedDirection)||L.logoDirection||"",te=L.logoUrls||[],le=A.narrativeIdentity||{},we=le.brandEssence||le.positioning||((S=A.purpose)==null?void 0:S.statement)||"",Se=E.aesthetic||(($=M.colorSystem)==null?void 0:$.story)||"",Ne=E.imageryStyle||E.photographyDirection||"",ke=E.layoutApproach||"Structured space with generous negative space. Built on a strong, clear grid.",ce={clientName:(W==null?void 0:W.name)||"Client",brandEssence:we,visualConcept:Se,colors:be,typography:{display:{name:Ie,usage:((_=V.display)==null?void 0:_.usage)||"Primary headlines (H1), large pull quotes"},body:{name:ve,usage:((O=V.body)==null?void 0:O.usage)||"All body copy, sub-headlines, UI text"}},mood:Array.isArray(ee)?ee:[ee],voiceTone:{characteristics:_e,doSay:xe,dontSay:s}
11,designReferences:o.filter(Boolean),imageryDirection:Ne,layoutPhilosophy:ke,navbar:a,homepageSections:ye,logoDirection:p,logoUrls:te,rawDna:A};C(ce),je(ce)}catch(j){console.error("Failed to load data:",j),x.error("Failed to load client data")}Q(!1)},je=t=>{var ve,Pe,Oe,E,ee,B,_e,xe;const i=Object.values(t.colors),l=i.map((s,o)=>`- ${s.name} (${s.hex}) — Role: ${s.role}`).join(`
12`),n=t.rawDna||{},r={},c=()=>{var ke,ce,b,N,de,Ue,Fe,Me,Be,He,ze;const s=[],o=n.visualBrandKit||{},a=n.designParameters||{},p=n.visualDirection||{};(ce=(ke=o.designInspirations)==null?void 0:ke.tasteGamePicks)!=null&&ce.length&&(s.push("## Taste Game Results (Client's Visual Preferences)"),s.push("These are REAL brand systems the client was shown side-by-side and CHOSE as aligned with their taste:"),o.designInspirations.tasteGamePicks.forEach(h=>{const I=[`**${h.label||h.chosenLabel||"Selected Brand"}**`];h.category&&I.push(`Category: ${h.category}`),h.description&&I.push(`Description: ${h.description}`),h.reason&&I.push(`Why chosen: ${h.reason}`),s.push(`- ${I.join(" | ")}`)}),s.push("")),(N=(b=o.designInspirations)==null?void 0:b.websiteStylePicks)!=null&&N.length&&(s.push("## Website Style Preferences"),s.push("Specific website styles the client identified as aspirational:"),o.designInspirations.websiteStylePicks.forEach(h=>{const I=[h.label||h.category||"Style"];h.url&&I.push(`→ Visit: ${h.url}`),h.notes&&I.push(`Client notes: "${h.notes}"`),h.screenshotUrl&&I.push(`Screenshot: ${h.screenshotUrl}`),s.push(`- ${I.join(" | ")}`)}),s.push("")),(Ue=(de=o.designInspirations)==null?void 0:de.moodboardAssets)!=null&&Ue.length&&(s.push("## Moodboard References"),s.push("Curated visual references assembled during brand exploration:"),o.designInspirations.moodboardAssets.forEach(h=>{const I=[h.label||h.url||"Reference"];h.source&&I.push(`Source: ${h.source}`),h.url&&I.push(`URL: ${h.url}`),s.push(`- ${I.join(" | ")}`)}),s.push("")),p.aesthetic&&s.push(`## Visual Aesthetic Direction
13${p.aesthetic}
14`),p.imageryStyle&&s.push(`## Imagery Style
15${p.imageryStyle}
16`),p.moodAndAtmosphere&&s.push(`## Mood & Atmosphere
17${p.moodAndAtmosphere}
18`),p.layoutApproach&&s.push(`## Layout Approach
19${p.layoutApproach}
20`);const te=a.logoPreferences||n.logoPreferences||{};(Fe=te.selectedTypes)!=null&&Fe.length&&s.push(`## Logo Type Preferences
21Client selected: ${te.selectedTypes.join(", ")}`),(Me=te.inspirations)!=null&&Me.length&&s.push(`Logo inspirations: ${te.inspirations.map(h=>h.name||h).join(", ")}
22`);const le=a.fontPreferences||n.fontPreferences||{};(Be=le.selectedStyles)!=null&&Be.length&&s.push(`## Typography Style Preferences
23Client gravitated toward: ${le.selectedStyles.join(", ")}
24`);const we=a.colorPreferences||n.colorPreferences||{};(He=we.selectedColors)!=null&&He.length&&s.push(`## Color Preferences from Discovery
25${we.selectedColors.map(h=>`${h.name||h.hex||h}: ${h.meaning||""}`).join(", ")}
26`);const Se=n.brandAdjectives||a.brandAdjectives||[];Se.length&&s.push(`## Brand Adjectives (Client-Selected)
27${Se.join(", ")}
28`);const Ne=((ze=t.rawDna)==null?void 0:ze.clientWebsite)||"";return Ne&&s.push(`## Client's Current Website
29${Ne}
30`),s},d=t.typography.display.name,g=t.typography.body.name,v=d!=="Sans-serif"&&d!=="Serif",S=g!=="Sans-serif"&&g!=="Serif";r["design-system"]=`# DESIGN SYSTEM & VISUAL FOUNDATION
31
32⚠️ CRITICAL — READ BEFORE DESIGNING ANYTHING ⚠️
33
34## Typography System — EXACT SPECIFICATIONS
35
36### DISPLAY / HEADLINE FONT: "${d}"
37${v?`- Google Fonts: https://fonts.google.com/specimen/${d.replace(/\s+/g,"+")}
38- Import: <link href="https://fonts.googleapis.com/css2?family=${d.replace(/\s+/g,"+")}:wght@400;500;600;700&display=swap" rel="stylesheet">`:"- This is a system/foundry font. Ensure it is properly loaded."}
39- CSS: font-family: '${d}', serif;
40- Usage: ${t.typography.display.usage}
41- THIS IS THE HEADER FONT. Use it for ALL H1, H2, and pull quotes. Do NOT substitute with a different font.
42
43### BODY / UI FONT: "${g}"
44${S?`- Google Fonts: https://fonts.google.com/specimen/${g.replace(/\s+/g,"+")}
45- Import: <link href="https://fonts.googleapis.com/css2?family=${g.replace(/\s+/g,"+")}:wght@300;400;500;600;700&display=swap" rel="stylesheet">`:"- This is a system/foundry font. Ensure it is properly loaded."}
46- CSS: font-family: '${g}', sans-serif;
47- Usage: ${t.typography.body.usage}
48
49### TYPOGRAPHIC HIERARCHY (Exact sizes)
50| Element | Font | Size (Desktop) | Size (Mobile) | Weight | Line-Height | Letter-Spacing |
51|---------|------|-----------------|---------------|--------|-------------|----------------|
52| H1 | ${d} | 56-72px | 36-44px | 600-700 | 1.1 | -0.02em |
53| H2 | ${d} | 36-48px | 28-32px | 600 | 1.2 | -0.01em |
54| H3 | ${d} | 24-32px | 20-24px | 500-600 | 1.3 | 0 |
55| Subtitle | ${g} | 20-24px | 18-20px | 400 | 1.4 | 0.01em |
56| Body | ${g} | 16-18px | 16px | 400 | 1.7 | 0 |
57| Small/Caption | ${g} | 13-14px | 13px | 400 | 1.5 | 0.02em |
58| Button | ${g}
58 | 15-16px | 15px | 500-600 | 1 | 0.05em |
59| Nav Link | ${g} | 15px | 15px | 500 | 1 | 0.03em |
60
61## Brand Concept
62Visual Concept: "${t.visualConcept}"
63Brand Essence: ${t.brandEssence}
64
65## Color Palette — EXACT HEX VALUES
66${l}
67
68COLOR APPLICATION RULES:
69• Primary color: hero backgrounds, CTA buttons, key accents
70• Secondary/Neutral: body text, section backgrounds, cards
71• Accent: hover states, highlights, small decorative elements
72• NEVER use pure black (#000000) — use the darkest brand color or a warm/cool near-black
73• Accent colors max 15% of any composition
74• All interactive elements (buttons, links, hover states) MUST use the primary accent
75• Backgrounds should alternate between white and the lightest brand neutral
76
77## Mood & Atmosphere Keywords
78${t.mood.join(", ")}
79These keywords should be FELT in every design decision — spacing, image selection, animation speed, and color balance.
80
81${t.logoDirection?`## Logo Direction
82${t.logoDirection}`:""}
83${t.logoUrls.length>0?`
84## Logo Assets (Use these exact files)
85${t.logoUrls.map(s=>`- ${s}`).join(`
86`)}`:""}`,r["layout-components"]=`# LAYOUT & COMPONENT GUIDELINES
87
88## HTML Structure Contract (Arcbound theme)
89This site MUST be built inside our Arcbound WordPress theme shell. The visual
90design is yours — but the markup must follow this pattern so each block can be
91lifted into a shortcode partial:
92
93\`\`\`
94#main
95  header.masthead > .inner-masthead (logo + .main-menu nav)
96  #main-content
97    section.section-padding.home-banner       > .content-width
98    section.section-padding.home-about        > .content-width
99    section.section-padding.home-services     > .content-width
100    section.section-padding.home-{slug}       > .content-width
101  footer.site-footer.section-padding          > .content-width
102\`\`\`
103
104- One \`<section class="section-padding {slug}">\` per homepage block.
105- Every section wraps content in \`<div class="content-width">\`.
106- Use CSS variables \`--color-1/2/3\`, \`--xl/lg/md/sm\`, \`--heading-font\`,
107  \`--default-font\` (see Technical Implementation Specs for full contract).
108- Buttons use \`class="button"\`. Scroll reveals use \`fade-from-left|right|bottom\`.
109
110## Layout Philosophy
111"${t.layoutPhilosophy}"
112
113## CRITICAL VISUAL RULE
114Every section of the website MUST contain at least ONE visual element beyond text:
115- Hero: Full-bleed image, video background, or animated graphic
116- About/Story sections: Portrait photo, brand photography, or illustrated timeline
117- Services/Offerings: Icon grid, illustrated cards, or process diagram
118- Testimonials: Client photos, logo wall, or trust badges
119- Stats/Impact: Animated counters with infographic styling, charts, or data visualization
120- CTA sections: Background imagery or decorative brand patterns
121
122DO NOT create text-only sections. Every section needs visual weight.
123
124## Grid System
125- 12-column grid, gutters: 24-32px
126- Max content width: 1200px text-heavy, 1440px full layouts
127- Asymmetric layouts encouraged — offset images, staggered grids
128- Minimum 64px vertical section padding (96-128px preferred)
129
130## Navigation Bar
131- Fixed/sticky, height 80-96px
132- Logo left, nav right-aligned
133- Nav items: ${t.navbar.map(s=>s.label).join(", ")||"TBD from sitemap"}
134- Mobile: hamburger → full-screen overlay with brand-colored background
135- Font: ${g}, 15px, weight 500, letter-spacing 0.03em
136
137## Component Specifications
138
139### Hero Section
140- Full viewport height (100vh) or minimum 80vh
141- Large impactful imagery or video background
142- Headline: ${d}, 56-72px, positioned with dramatic negative space
143- CTA button: Solid fill primary color, 16px vertical / 40px horizontal padding, bold
144- Consider: parallax scroll, subtle animation on load, or gradient overlay
145
146### Section Dividers
147- Use alternating background colors (white ↔ lightest brand neutral)
148- Thin accent-colored line, or brand pattern strip between sections
149- Decorative elements: geometric shapes, thin rules, or brand motifs
150
151### Cards/Modules
152- Clean with subtle border OR soft shadow (not both)
153- Border-radius: 4-8px
154- Internal padding: 32-48px
155- Each card should have an icon, illustration, or image — never just text
156
157### Buttons
158PRIMARY: Solid fill primary accent, 4px radius, hover: darken 10%
159SECONDARY: Outlined with primary color border, transparent bg
160GHOST: Text-only with underline on hover
161Font: ${g}, 15-16px, weight 600, letter-spacing 0.05em
162
163## Responsive Breakpoints
164640px (mobile) | 768px (tablet) | 1024px (desktop) | 1280px (large)
165- Headlines reduce 35-40% on mobile
166- Stack all multi-column layouts to single column
167- Touch targets minimum 44x44px`,r["imagery-graphics"]=`# IMAGERY, GRAPHICS & VISUAL CONTENT DIRECTION
168
169## CRITICAL RULE: No Section Without Visuals
170Every single section of the homepage MUST include at least one of:
171□ Photography (hero, team, process, behind-the-scenes)
172□ Custom illustration or icon set
173□ Diagram, flowchart, or infographic
174□ Data visualization (charts, animated counters)
175□ Decorative brand graphics (patterns, geometric shapes, gradients)
176□ Video or animated element
177
178## Photography Style
179${t.imageryDirection||"Professional, authentic, editorial quality. Documentary or photojournalistic style — never stock."}
180
181PHOTO SPECIFICATIONS:
182- Style: Candid, editorial, cinematic — NOT posed stock photography
183- Color treatment: Warm or cool-toned to match brand palette, slight desaturation for sophistication
184- Composition: Rule of thirds, strong leading lines, shallow depth of field
185- Subjects: Real people in authentic moments, workspaces, details, textures
186- ⛔ AVOID: Generic stock photos, posed corporate headshots, cheesy handshakes, busy cluttered backgrounds
187
188## Section-by-Section Visual Assignments
189${t.homepageSections.map((s,o)=>{const a=s.heading.toLowerCase();let p="";return a.includes("hero")?p="→ VISUAL: Full-bleed cinematic hero image OR video background. Overlay with brand gradient (60-70% opacity). Bold headline with dramatic scale contrast.":a.includes("about")||a.includes("story")||a.includes("who")?p="→ VISUAL: Side-by-side layout with editorial portrait or brand photography. Consider a timeline graphic or illustrated origin story.":a.includes("service")||a.includes("offer")||a.includes("what")||a.includes("how")?p="→ VISUAL: Icon cards with custom illustrations (not generic). OR a process flow diagram showing steps. Each offering needs its own visual icon.":a.includes("testimonial")||a.includes("client")||a.includes("result")||a.includes("impact")?p="→ VISUAL: Client photos, company logos, or trust badges. Animated stat counters. Consider a quote card with portrait + decorative quotation mark.":a.includes("cta")||a.includes("contact")||a.includes("start")||a.includes("next")?p="→ VISUAL: Full-width background image with color overlay, or brand pattern/gradient. Large bold CTA button with ample padding.":a.includes("feature")||a.includes("benefit")||a.includes("why")?p="→ VISUAL: Feature grid with icons/illustrations per item. OR a comparison infographic. Consider before/after or side-by-side visual.":a.includes("process")||a.includes("approach")||a.includes("method")?p="→ VISUAL: Numbered step diagram, flowchart, or illustrated process timeline. Horizontal on desktop, vertical on mobile.":a.includes("faq")||a.includes("question")?p="→ VISUAL: Accordion with brand-colored expand icons. Decorative illustration or geometric pattern in sidebar.":p="→ VISUAL: Include relevant imagery, illustration, or infographic. Never leave this section as text-only.",`### Section ${o+1}: "${s.heading}"
190${p}`}).join(`
191
192`)}
193
194## Iconography System
195- Style: ${t.mood.includes("bold")||t.mood.includes("modern")?"Solid fill with rounded corners":"Outline style, 1.5-2px stroke weight"}
196- Color: Primary brand accent for active, muted neutral for inactive
197- Size: 24-32px for inline UI, 48-64px for feature highlights, 80px+ for section heroes
198- Consistency: All icons from the same set/style — do not mix outline and fill
199
200## Diagrams & Infographics
201- Clean, 2D flat design (no 3D, no skeuomorphism)
202- Use ONLY brand color palette
203- Typography: ${g} for all labels and data
204- Generous whitespace between data points
205- Animate on scroll into view where possible
206
207## Decorative Elements
208- Subtle geometric patterns using brand colors at 5-10% opacity
209- Thin accent lines as section dividers
210- Abstract shapes (circles, arcs) as background decorations
211- These should enhance, never compete with content`;const $=t.homepageSections.map((s,o)=>{const a=s.heading.toLowerCase();let p="🖼️ This section MUST include a visual element — image, icon, illustration, or diagram. See Imagery section for specifics.";return a.includes("hero")?p="🖼️ HERO IMAGE REQUIRED: Full-bleed cinematic image or video background behind this text. Use gradient overlay for text readability.":a.includes("service")||a.includes("offer")?p="🖼️ ICONS/ILLUSTRATIONS REQUIRED: Each service/offering needs its own visual icon or illustration card.":(a.includes("testimonial")||a.includes("result"))&&(p="🖼️ SOCIAL PROOF VISUALS: Include client photos, company logos, or stat counters alongside this text."),`---
212
213## SECTION ${o+1}: ${s.heading}
214
215${p}
216
217${s.copy}
218
219${s.notes?`ADMIN NOTES: ${s.notes}`:""}`}).join(`
220
221`);r["homepage-copy"]=`# HOMEPAGE COPY — EXACT TEXT TO USE
222
223⚠️ USE THIS COPY VERBATIM. Do not rewrite, summarize, or improvise. This is approved client copy.
224
225## Navigation Bar
226Logo: "${t.clientName}" — use the provided logo asset, not text
227Nav Items: ${t.navbar.map(s=>`"${s.label}"`).join(" | ")||"TBD"}
228CTA Button: Use the primary CTA from the hero section
229
230## IMPORTANT: Every Section Needs Visuals
231Do NOT render any section as text-only. Each section below should be paired with imagery, icons, diagrams, or decorative elements as specified in the Imagery & Graphics section.
232
233${$||"No homepage copy generated yet. Generate it from the Homepage Copy step first."}
234
235## Footer
236- Brand logo (not just text name)
237- Navigation links repeated in columns
238- Contact info, social media icons
239- Newsletter signup (if applicable)
240- Legal: © ${new Date().getFullYear()} ${t.clientName}. All rights reserved.
241- Footer should have subtle brand pattern or accent color background`;const _=n.narrativeIdentity||{},O=n.purpose||{},j=n.coreOfferings||{},P=n.targetDemographic||{},G=n.differentiators||n.competitivePosition||{},R=n.keyMessages||n.messagingPillars||{},U=n.brandPersonality||[],W=[_.positioning?`POSITIONING: ${_.positioning}`:"",_.brandEssence?`BRAND ESSENCE: ${_.brandEssence}`:"",_.tagline?`TAGLINE: "${_.tagline}"`:"",_.elevatorPitch?`ELEVATOR PITCH: ${_.elevatorPitch}`:"",_.originStory?`ORIGIN STORY: ${_.originStory}
241`:""].filter(Boolean).join(`
242
243`),A=[O.statement?`PURPOSE: ${O.statement}`:"",O.vision?`VISION: ${O.vision}`:"",O.mission?`MISSION: ${O.mission}`:""].filter(Boolean).join(`
244`),ye=typeof j=="object"&&!Array.isArray(j)?Object.entries(j).map(([s,o])=>typeof o=="string"?`- ${s}: ${o}`:typeof o=="object"&&o?`- ${o.name||s}: ${o.description||JSON.stringify(o)}`:"").filter(Boolean).join(`
245`):Array.isArray(j)?j.map(s=>`- ${s.name||s.title||s}: ${s.description||""}`).join(`
246`):String(j),q=typeof P=="object"?Object.entries(P).map(([s,o])=>{const a=s.replace(/([A-Z])/g," $1").replace(/^./,p=>p.toUpperCase());return typeof o=="string"?`${a}: ${o}`:Array.isArray(o)?`${a}: ${o.join(", ")}`:typeof o=="object"&&o?`${a}: ${JSON.stringify(o)}`:""}).filter(Boolean).join(`
247`):String(P),re=typeof G=="object"?Object.entries(G).map(([s,o])=>{const a=s.replace(/([A-Z])/g," $1").replace(/^./,p=>p.toUpperCase());return typeof o=="string"?`- ${a}: ${o}`:Array.isArray(o)?`- ${a}: ${o.join(", ")}`:""}).filter(Boolean).join(`
248`):String(G),M=typeof R=="object"?Array.isArray(R)?R.map((s,o)=>`${o+1}. ${typeof s=="string"?s:s.headline||s.message||JSON.stringify(s)}`).join(`
249`):Object.entries(R).map(([s,o])=>`- ${s.replace(/([A-Z])/g," $1").replace(/^./,p=>p.toUpperCase())}: ${typeof o=="string"?o:JSON.stringify(o)}`).join(`
250`):String(R);r["voice-tone"]=`# BRAND IDENTITY, VOICE & MESSAGING
251## READ THIS SECTION FIRST — It establishes who ${t.clientName} is, what they do, and how they communicate.
252
253## Who Is ${t.clientName}?
254${t.brandEssence||"See narrative identity below."}
255
256${W?`## Narrative Identity
257${W}`:""}
258
259${A?`## Purpose, Vision & Mission
260${A}`:""}
261
262${U.length>0?`## Brand Personality
263${Array.isArray(U)?U.join(", "):U}`:""}
264
265${ye?`## Core Offerings
266${ye}`:""}
267
268${q?`## Target Audience
269${q}`:""}
270
271${re?`## Differentiators & Competitive Position
272${re}`:""}
273
274${M?`## Key Messages & Messaging Pillars
275${M}`:""}
276
277## Voice Characteristics
278${t.voiceTone.characteristics.join(", ")||"Authoritative, Precise, Clear"}
279
280The brand voice should permeate every headline, subhead, body paragraph, button label, and micro-copy on the site.
281
282## DO Say (Use These Phrases/Patterns):
283${t.voiceTone.doSay.map(s=>`• "${s}"`).join(`
284`)||"• [From brand strategy messaging pillars]"}
285
286## DON'T Say (Avoid These):
287${t.voiceTone.dontSay.map(s=>`• ${s}`).join(`
288`)||"• Generic marketing clichés"}
289
290## Writing Style Rules
291- Clear, direct sentences with varied rhythm
292- Active voice predominantly
293- 2-4 sentences per paragraph for web
294- Strategic questions to engage
295- Every CTA: action-oriented, specific, no urgency tactics`;const L=c();r["design-references"]=`# DESIGN INSPIRATIONS & VISUAL REFERENCES
296
297⚠️ THIS SECTION IS CRITICAL. Study these references deeply before designing.
298These are not generic suggestions — they come directly from the client's brand discovery sessions, taste exercises, and strategic conversations.
299
300${L.length>0?L.join(`
301`):"No specific references captured yet."}
302
303${t.designReferences.length>0?`## Additional References
304${t.designReferences.map((s,o)=>`${o+1}. ${s}`).join(`
305`)}`:""}
306
307## How to Use These References
3081. **Visit every linked website** and study: layout structure, typography scale, whitespace usage, image treatment, color application, animation/motion, and overall feeling
3092. **Identify the common threads** across all references — what visual patterns keep repeating? That's the client's natural taste
3103. **Synthesize, don't copy** — extract the feeling, sophistication level, and design approach, then apply with this client's unique brand palette & typography
3114. **Match the energy level** — if references are calm/refined, don't add flashy animations; if they're bold/dynamic, don't make it too quiet
312
313## Design Principles (Derived from Client Taste)
3141. **${t.mood[0]||"Sophisticated"} over generic** — Every design choice must reinforce the brand personality
3152. **Visual richness** — Every section needs imagery, graphics, or visual elements. NO text-only sections
3163. **Typography as art** — Headlines using ${d} should be a key design element with dramatic scale
3174. **Intentional whitespace** — Breathing room signals quality and confidence
3185. **Brand-aligned imagery** — Every photo, icon, and graphic should feel like it belongs to this specific brand
319
320## Anti-References (AVOID AT ALL COSTS)
321❌ Generic template sites with stock photography
322❌ Coaching/consulting sites with aggressive countdown timers
323❌ Dense text walls with no visual hierarchy or imagery
324❌ Corporate templates that feel institutional or cold
325❌ Overly busy designs with competing visual elements
326❌ Sites that use system fonts or mismatched typography`;const be=((ve=i[0])==null?void 0:ve.hex)||"#111111",Re=((Pe=i[1])==null?void 0:Pe.hex)||((Oe=i[0])==null?void 0:Oe.hex)||"#333333",V=((E=i[2])==null?void 0:E.hex)||((ee=i[1])==null?void 0:ee.hex)||((B=i[0])==null?void 0:B.hex)||"#cccccc",Ee=i.map((s,o)=>`  /* --color-${o+1}: ${s.hex}  (${s.name} — ${s.role}) */`).join(`
327`);r["technical-spec"]=`# TECHNICAL IMPLEMENTATION SPECIFICATIONS
328
329⚠️ CRITICAL: The output HTML MUST follow the **Arcbound WordPress theme** structure.
330The visual design is up to you — but the markup, class names, and CSS variable
331names below are NON-NEGOTIABLE so the result drops cleanly into our WordPress
332theme as shortcode partials.
333
334---
335
336## 1. Page Skeleton (mirror header.php → main → footer)
337
338\`\`\`html
339<!doctype html>
340<html lang="en">
341<head>
342  <meta charset="UTF-8" />
343  <meta name="viewport" content="width=device-width, initial-scale=1" />
344  <title>${t.clientName}</title>
345  <link rel="preconnect" href="https://fonts.googleapis.com">
346  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
347  <link href="https://fonts.googleapis.com/css2?family=${d.replace(/\s+/g,"+")}:wght@400;500;600;700&family=${g.replace(/\s+/g,"+")}:wght@300;400;500;600;700&display=swap" rel="stylesheet">
348  <!-- inline <style> block goes here (see section 3) -->
349</head>
350<body>
351  <div id="main">
352    <a class="skip-menu" href="#main-content">Skip to Main Content</a>
353
354    <header class="masthead">
355      <div class="inner-masthead">
356        <a class="logo-container" href="/"><img src="LOGO_URL" width="400" height="64" alt="${t.clientName} logo"></a>
357        <div class="menu-container">
358          <label for="mobile-input">☰</label>
359          <input type="checkbox" id="mobile-input">
360          <nav>
361            <ul class="main-menu">
362              ${(t.navbar.length?t.navbar:[{label:"Home",href:"/"}]).map(s=>`<li><a href="${s.href}">${s.label}</a></li>`).join(`
363              `)}
364            </ul>
365          </nav>
366        </div>
367      </div>
368    </header>
369
370    <div id="main-content">
371
372      <!-- Each homepage block = its own <section>.
373           One section per shortcode partial (home-banner, home-services, etc.) -->
374
375      <section class="section-padding home-banner">
376        <div class="content-width">
377          <!-- hero content -->
378        </div>
379      </section>
380
381      <!-- ...additional <section class="section-padding xxx"> blocks... -->
382
383    </div><!-- /#main-content -->
384
385    <footer class="site-footer section-padding">
386      <div class="content-width">
387        <!-- footer content -->
388      </div>
389    </footer>
390  </div><!-- /#main -->
391</body>
392</html>
393\`\`\`
394
395---
396
397## 2. Section / Shortcode Naming Convention
398
399Every homepage block becomes one \`<section class="section-padding {slug}">\`
400where {slug} matches an Arcbound shortcode partial. Use these slugs (one per
401section) so the markup can be split into \`template-parts/sections/home/{slug}.php\`:
402
403- \`home-banner\`      → hero
404- \`home-about\`       → about / story
405- \`home-services\`    → offerings / services
406- \`home-mission\`     → purpose / mission
407- \`home-results\`     → stats / impact
408- \`home-team\`        → team
409- \`home-testimonials\`→ testimonials / social proof
410- \`home-awards\`      → press / awards
411- \`home-news\`        → blog / news
412- \`home-social\`      → social feed
413- \`home-cta\`         → call-to-action
414- \`home-contact\`     → contact form
415
416Inside every section: \`<div class="content-width">…</div>\` is required.
417
418---
419
420## 3. CSS Variables (Arcbound contract — use these EXACT names)
421
422\`\`\`css
423:root{
424  /* site colors — positional, not name-based */
425  --color-1: ${be};
426  --color-2: ${Re};
427  --color-3: ${V};
428${Ee}
429
430  /* font sizes */
431  --xl: 55px;
432  --lg: 40px;
433  --md: 30px;
434  --sm: 20px;
435  --default: 16px;
436
437  /* font families */
438  --heading-font: "${d}", serif;
439  --default-font: "${g}", sans-serif;
440  --accent-font: "${g}", sans-serif;
441}
442@media(max-width: 1000px){
443  :root{ --xl: 40px; --lg: 30px; --md: 20px; --sm: 18px; }
444}
445@media(max-width: 750px){
446  :root{ --xl: 35px; --lg: 25px; --md: 20px; --sm: 18px; }
447}
448
449/* Theme defaults — DO NOT rename these classes */
450html, body{ scroll-behavior: smooth; font-size: var(--default); }
451body{ margin:0; -webkit-font-smoothing: antialiased; }
452*{ box-sizing: border-box; }
453img, svg{ max-width: 100%; height: auto; }
454a{ text-decoration: none; color: var(--color-2); }
455
456h1, h2, h3, h4, h5, h6{ font-family: var(--heading-font); line-height: 1.25em; }
457body, p, ul, ol, li{ font-family: var(--default-font); line-height: 1.25em; }
458h1{ font-size: var(--xl); }
459h2{ font-size: var(--lg); }
460h3{ font-size: var(--md); }
461h4{ font-size: var(--sm); }
462
463#main{ overflow-x: hidden; }
464.section-padding{ padding: min(150px, max(5%, 50px)) 0; }
465.content-width{ width: 1230px; max-width: 100%; padding: 0 15px; margin: 0 auto; }
466.has-text-align-right{ text-align: right; }
467.has-text-align-center, .aligncenter{ text-align: center; }
468
469.absolute-cover{ position: absolute; left: 0; top: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; }
470
471/* Buttons */
472.button,
473.button-container a{
474  background: var(--color-1); color: white; font-size: 16px;
475  padding: 10px 40px; font-weight: bold; border-radius: 5px;
476  transition: background .25s; display: inline-block;
477}
478.button:hover,
479.button-container a:hover{ background: var(--color-2); }
480
481/* Masthead — keep these class names */
482.inner-masthead{ display: flex; justify-content: space-between; align-items: center; position: relative; padding: 0 25px; }
483.inner-masthead .logo-container{ width: 300px; }
484.inner-masthead .main-menu{ display: flex; align-items: center; padding: 0; margin: 0; list-style: none; }
485.inner-masthead .main-menu > li > a{ padding: 30px 15px; display: inline-block; }
486.menu-container label, .menu-container #mobile-input{ display: none; }
487@media(max-width: 1000px){
488  .menu-container label{ display: block; font-size: 25px; cursor: pointer; }
489  .menu-container nav{ position: absolute; left: 0; top: 100%; width: 100%; background: #222; height: 0; overflow: hidden; }
490  .menu-container input:checked + nav{ height: auto; padding: 15px 0; }
491  .inner-masthead .main-menu{ flex-direction: column; align-items: flex-start; }
492  .inner-masthead .main-menu > li a{ color: #ddd; padding: 15px; }
493}
494
495/* Animations (theme contract) */
496.fade-from-left{ opacity: 0; transform: translateX(-25px); transition: opacity 1s, transform 1s; }
497.fade-from-left.active{ opacity: 1; transform: translateX(0); }
498.fade-from-right{ opacity: 0; transform: translateX(25px); transition: opacity 1s, transform 1s; }
499.fade-from-right.active{ opacity: 1; transform: translateX(0); }
500.fade-from-bottom{ opacity: 0; transform: translateY(25px); transition: opacity 1s, transform 1s; }
501.fade-from-bottom.active{ opacity: 1; transform: translateY(0); }
502@media(max-width: 750px){
503  .fade-from-left, .fade-from-right, .fade-from-bottom{ opacity: 1; transform: none; }
504}
505\`\`\`
506
507Add any extra section-specific CSS *scoped* to that section's slug
508(e.g. \`.home-services .card{…}\`). Never rename \`--color-1/2/3\`,
509\`--xl/lg/md/sm\`, \`--heading-font\`, \`--default-font\`,
510\`.section-padding\`, \`.content-width\`, \`.button\`, \`.masthead\`,
511or \`.absolute-cover\` — those are the theme contract.
512
513---
514
515## 4. Animations
516- Add \`fade-from-left | fade-from-right | fade-from-bottom\` to any element
517  that should reveal on scroll. A small IntersectionObserver script adds
518  \`.active\` when the element enters the viewport.
519- Stat counters: animate 0 → final value over 1.5s.
520
521\`\`\`html
522<script>
523  const io = new IntersectionObserver((entries) => {
524    entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('active'); });
525  }, { threshold: 0.15 });
526  document.querySelectorAll('.fade-from-left,.fade-from-right,.fade-from-bottom')
527    .forEach(el => io.observe(el));
528<\/script>
529\`\`\`
530
531---
532
533## 5. Responsive Breakpoints (theme-aligned)
534\`750px\` · \`1000px\` · \`1230px\` (max content width).
535
536## 6. Accessibility
537- Single \`<h1>\` per page (inside \`.home-banner\`).
538- Keep the \`<a class="skip-menu">\` link.
539- All images get meaningful \`alt\`. Decorative imagery → \`alt=""\`.
540- Color contrast ≥ 4.5:1.
541
542## 7. SEO
543- \`<title>\` ≤ 60 chars with primary keyword.
544- \`<meta name="description">\` ≤ 160 chars.
545- Lazy-load below-fold images (see section 10).
546- JSON-LD Organization block in \`<head>\`.
547
548---
549
550## 8. Interior Page Shortcodes
551
552Every NON-homepage page is composed from these interior shortcode partials.
553Use the exact \`<section class="…">\` wrappers below so each block maps 1:1 to
554\`template-parts/sections/internal/{slug}.php\`.
555
556### \`[internal_banner]\` — page header strip
557\`\`\`html
558<section class="internal-banner">
559  <div class="content-width"><h1>{Page Title}</h1></div>
560</section>
561\`\`\`
562Used on archive, search, 404 and the top of every interior page.
563
564### \`[internal_content]\` — long-form / rich text body
565\`\`\`html
566<section class="internal-content section-padding">
567  <div class="content-width">
568    <!-- prose: h2/h3, paragraphs, lists, blockquotes, inline images -->
569  </div>
570</section>
571\`\`\`
572
573### \`[internal_services]\` — feature / offerings grid
574\`\`\`html
575<section class="internal-services section-padding">
576  <div class="content-width">
577    <h2>{Section Heading}</h2>
578    <div class="service-grid">
579      <article class="service-card"><h3>…</h3><p>…</p></article>
580    </div>
581  </div>
582</section>
583\`\`\`
584
585### \`[internal_fullwidth]\` — edge-to-edge image / video / quote band
586\`\`\`html
587<section class="internal-fullwidth">
588  <!-- NO .content-width — this block bleeds to viewport edges -->
589  <img class="absolute-cover" src="…" alt="…">
590  <div class="overlay"><h2>…</h2></div>
591</section>
592\`\`\`
593
594### \`[internal_cta]\` — closing call-to-action band
595\`\`\`html
596<section class="internal-cta section-padding">
597  <div class="content-width has-text-align-center">
598    <h2>{CTA Headline}</h2>
599    <p>{Supporting line}</p>
600    <div class="button-container"><a href="…">{Button Label}</a></div>
601  </div>
602</section>
603\`\`\`
604
605Typical interior stack: \`internal_banner\` → \`internal_content\` →
606(optional \`internal_services\` or \`internal_fullwidth\`) → \`internal_cta\`.
607
608---
609
610## 9. Scoped Section Styles
611
612Every section's extra CSS must be **scoped to its own class** so partials
613stay portable. In WordPress this is wrapped in an \`apply_{slug}_styles\`
614function hooked to \`wp_footer\`; in the generated HTML, emit a matching
615\`<style>\` block immediately AFTER the section — never let one section's CSS
616leak into another.
617
618\`\`\`html
619<section class="home-services">…</section>
620<style>
621  .home-services{ background: var(--color-3); }
622  .home-services .card{ padding: 32px; }
623  @media(max-width: 750px){ .home-services .card{ padding: 20px; } }
624</style>
625\`\`\`
626
627---
628
629## 10. Lazy-loading Convention (theme-changes.php contract)
630
631For below-fold media, use the theme's data-attribute lazy loader — NOT
632\`loading="lazy"\`:
633
634- \`<img data-url="/path/image.jpg" alt="…">\`              → swaps to \`src\` on intersect
635- \`<iframe data-url="https://…">\`                         → same, for embeds
636- \`<div data-bg-img="/path/image.jpg" class="hero"></div>\` → sets \`background-image\`
637- Add \`class="lazyload"\` to any extra element you want the observer to watch.
638
639Include this script once at the bottom of \`<body>\` (mirrors theme-changes.php):
640
641\`\`\`html
642<script>
643  window.addEventListener("load", () => {
644    const items = document.querySelectorAll('img[data-url], iframe[data-url], .lazyload[data-url], [data-bg-img]');
645    const io = new IntersectionObserver((entries, obs) => {
646      entries.forEach(e => {
647        if (!e.isIntersecting) return;
648        const el = e.target;
649        if (el.hasAttribute('data-url'))         { el.setAttribute('src', el.getAttribute('data-url')); el.removeAttribute('data-url'); }
650        else if (el.hasAttribute('data-bg-img')) { el.style.backgroundImage = "url('" + el.getAttribute('data-bg-img') + "')"; el.removeAttribute('data-bg-img'); }
651        obs.unobserve(el);
652      });
653    }, { rootMargin: '150px 0px', threshold: 0.01 });
654    items.forEach(i => io.observe(i));
655  });
656<\/script>
657\`\`\`
658
659---
660
661## 11. Blog / Archive / Search / Single / 404 Templates
662
663Class names below are hard-coded in \`blog-styles.php\` and must not be renamed.
664
665### Blog index, Category archive, Search results
666\`\`\`html
667<section class="internal-banner"><div class="content-width"><h1>Blog</h1></div></section>
668
669<section class="section-padding">
670  <div class="content-width">
671    <div class="posts-container has-blogs">
672      <div class="indiv-post">
673        <a href="/post-slug" class="img-container">
674          <img src="/featured.jpg" alt="">
675          <!-- if no thumb: <span class="empty-thumb-container"></span> -->
676        </a>
677        <div class="post-info">
678          <p class="date">
679            <span class="day">07</span>
680            <span class="y-m-container">
681              <span class="year">2026</span>
682              <span class="month">June</span>
683            </span>
684          </p>
685          <h2 class="title">{Post Title}</h2>
686          <p>{Excerpt}</p>
687          <a class="button" href="/post-slug">Read More</a>
688        </div>
689      </div>
690      <!-- repeat .indiv-post -->
691    </div>
692
693    <div class="nav-links">
694      <a class="prev page-numbers" href="#"><span>&lt;</span></a>
695      <span class="page-numbers current">1</span>
696      <a class="page-numbers" href="#">2</a>
697      <a class="next page-numbers" href="#"><span>&gt;</span></a>
698    </div>
699  </div>
700</section>
701\`\`\`
702Grid: 3 cols desktop → 2 cols @ 900px → 1 col @ 700px.
703Empty state uses \`<div class="posts-container no-blogs">\`.
704Search page banner: \`[internal_banner title="You searched for: {term}"]\` and
705prepend \`<h2>The following is a list of results for your search term:</h2>\`
706inside the section before \`.posts-container\`.
707
708### Single post
709\`\`\`html
710<section class="section-padding single-post">
711  <div class="content-width">
712    <h1>{Post Title}</h1>
713    <div class="author-date"><strong>{Author}</strong> | {Date}</div>
714    <div class="img-container"><img src="/featured.jpg" alt=""></div>
715    <div class="blog-content">
716      <!-- the_content() output -->
717    </div>
718  </div>
719</section>
720\`\`\`
721Scoped CSS (single-blog-styles.php):
722\`.single-post .blog-content{ width:750px; max-width:100%; margin:0 auto; }\`
723\`.single-post h1{ text-align:center; margin:0; }\`
724\`.single-post .img-container{ width:1000px; max-width:100%; margin:1em auto; text-align:center; }\`
725\`.single-post .author-date{ text-align:center; }\`
726
727### 404
728\`\`\`html
729<section class="internal-banner"><div class="content-width"><h1>
729That's a 404</h1></div></section>
730<section class="section-padding">
731  <div class="content-width" style="text-align: center;">
732    The URL you entered doesn't exist on our site. Perhaps try navigating from
733    <a href="/">our homepage</a>?
734  </div>
735</section>
736\`\`\`
737
738---
739
740## 12. Footer Markup (footer.php contract)
741
742\`\`\`html
743<footer class="site-footer section-padding">
744  <div class="content-width">
745    <!-- columns: logo, nav, contact/social, newsletter -->
746  </div>
747</footer>
748<!-- footer.php then closes #main-content and #main -->
749\`\`\`
750
751---
752
753## 13. Theme Class Whitelist (DO NOT rename)
754
755\`#main\` · \`#main-content\` · \`.masthead\` · \`.inner-masthead\` ·
756\`.logo-container\` · \`.menu-container\` · \`.main-menu\` · \`.sub-menu\` ·
757\`.skip-menu\` · \`.section-padding\` · \`.content-width\` · \`.absolute-cover\` ·
758\`.button\` · \`.button-container\` · \`.has-text-align-center\` ·
759\`.has-text-align-right\` · \`.aligncenter\` ·
760\`.fade-from-left\` · \`.fade-from-right\` · \`.fade-from-bottom\` ·
761\`.internal-banner\` · \`.internal-content\` · \`.internal-services\` ·
762\`.internal-fullwidth\` · \`.internal-cta\` ·
763\`.posts-container\` · \`.has-blogs\` · \`.no-blogs\` · \`.indiv-post\` ·
764\`.img-container\` · \`.empty-thumb-container\` · \`.post-info\` · \`.date\` ·
765\`.day\` · \`.month\` · \`.year\` · \`.y-m-container\` · \`.title\` ·
766\`.nav-links\` · \`.page-numbers\` · \`.current\` · \`.prev\` · \`.next\` ·
767\`.single-post\` · \`.blog-content\` · \`.author-date\` · \`.site-footer\`.
768
769Any new visual treatment must be ADDITIVE — new modifier classes scoped
770under the section slug, never edits to the names above.
771
772---
773
774## 14. Section Scaffold Templates (drop-in PHP partials)
775
776Every \`<section>\` in this brief maps 1:1 to a WordPress shortcode partial in
777\`template-parts/sections/home/{slug}.php\` (or \`internal/{slug}.php\`). The
778generated HTML must mirror the EXACT scaffold below so we can lift each
779\`<section>…</section>\` block straight into its partial. The \`shortcode_atts\`
780array enumerates the dynamic props the section accepts; the
781\`apply_{slug}_styles\` wp_footer hook is where that section's CSS lives.
782
783> Rule: emit one \`<section class="{slug}">\` PER scaffold below. Put that
784> section's CSS in a single \`<style>\` block that follows the section (it will
785> become the body of \`apply_{slug}_styles\` in WordPress). Do NOT merge two
786> sections into one partial.
787
788### \`internal-banner.php\` — top of every interior page
789\`\`\`php
790<?php $atts = shortcode_atts(array(
791  'title' => '',
792), $atts); ?>
793
794<style type="text/css"></style>
795
796<section class="internal-banner section-padding">
797  <h1><?= $atts['title']; ?></h1>
798</section>
799\`\`\`
800
801### \`home-services.php\`
802\`\`\`php
803<?php $atts = shortcode_atts(array(
804  '' => '',
805), $atts); ?>
806
807<section class="home-services">
808</section>
809
810<?php if(!function_exists('apply_home_services_styles')){
811  function apply_home_services_styles(){ ?>
812    <style>/* .home-services { … } */</style>
813  <?php }
814  add_action('wp_footer', 'apply_home_services_styles');
815} ?>
816\`\`\`
817
818### \`home-mission.php\`
819\`\`\`php
820<section class="home-mission"></section>
821<?php if(!function_exists('apply_home_mission_styles')){
822  function apply_home_mission_styles(){ ?><style>/* .home-mission { … } */</style><?php }
823  add_action('wp_footer', 'apply_home_mission_styles');
824} ?>
825\`\`\`
826
827### \`home-results.php\`
828\`\`\`php
829<section class="home-results"></section>
830<?php if(!function_exists('apply_home_results_styles')){
831  function apply_home_results_styles(){ ?><style>/* .home-results { … } */</style><?php }
832  add_action('wp_footer', 'apply_home_results_styles');
833} ?>
834\`\`\`
835
836### \`home-team.php\`
837\`\`\`php
838<section class="home-team"></section>
839<?php if(!function_exists('apply_home_team_styles')){
840  function apply_home_team_styles(){ ?><style>/* .home-team { … } */</style><?php }
841  add_action('wp_footer', 'apply_home_team_styles');
842} ?>
843\`\`\`
844
845### \`home-testimonials.php\`
846\`\`\`php
847<section class="home-testimonials"></section>
848<?php if(!function_exists('apply_home_testimonials_styles')){
849  function apply_home_testimonials_styles(){ ?><style>/* .home-testimonials { … } */</style><?php }
850  add_action('wp_footer', 'apply_home_testimonials_styles');
851} ?>
852\`\`\`
853
854### \`home-portfolio.php\`
855\`\`\`php
856<section class="home-portfolio"></section>
857<?php if(!function_exists('apply_home_portfolio_styles')){
858  function apply_home_portfolio_styles(){ ?><style>/* .home-portfolio { … } */</style><?php }
859  add_action('wp_footer', 'apply_home_portfolio_styles');
860} ?>
861\`\`\`
862
863### \`home-news.php\`
864\`\`\`php
865<section class="home-news"></section>
866<?php if(!function_exists('apply_home_news_styles')){
867  function apply_home_news_styles(){ ?><style>/* .home-news { … } */</style><?php }
868  add_action('wp_footer', 'apply_home_news_styles');
869} ?>
870\`\`\`
871
872### \`home-social.php\`
873\`\`\`php
874<section class="home-social"></section>
875<?php if(!function_exists('apply_home_social_styles')){
876  function apply_home_social_styles(){ ?><style>/* .home-social { … } */</style><?php }
877  add_action('wp_footer', 'apply_home_social_styles');
878} ?>
879\`\`\`
880
881### \`home-cta.php\`
882\`\`\`php
883<section class="home-cta"></section>
884<?php if(!function_exists('apply_home_cta_styles')){
885  function apply_home_cta_styles(){ ?><style>/* .home-cta { … } */</style><?php }
886  add_action('wp_footer', 'apply_home_cta_styles');
887} ?>
888\`\`\`
889
890### \`home-banner.php\` — homepage hero (note: uses inline \`<style>\`, NOT wp_footer)
891\`\`\`php
892<?php $atts = shortcode_atts(array(
893  '' => '',
894), $atts); ?>
895
896<style>
897/* .home-banner { … }  — banner styles live INLINE because the hero is the
898   first thing painted; it must not wait for wp_footer to inject CSS. */
899</style>
900
901<section class="home-banner section-padding">
902  <div class="content-width">
903    <!-- single <h1> for the entire page lives here -->
904  </div>
905</section>
906\`\`\`
907
908### \`home-about.php\`
909\`\`\`php
910<?php $atts = shortcode_atts(array(
911  '' => '',
912), $atts); ?>
913
914<section class="home-about"></section>
915
916<?php if(!function_exists('apply_home_about_styles')){
917  function apply_home_about_styles(){ ?><style>/* .home-about { … } */</style><?php }
918  add_action('wp_footer', 'apply_home_about_styles');
919} ?>
920\`\`\`
921
922### \`home-awards.php\`
923\`\`\`php
924<?php $atts = shortcode_atts(array(
925  '' => '',
926), $atts); ?>
927
928<section class="home-awards"></section>
929
930<?php if(!function_exists('apply_home_awards_styles')){
931  function apply_home_awards_styles(){ ?><style>/* .home-awards { … } */</style><?php }
932  add_action('wp_footer', 'apply_home_awards_styles');
933} ?>
934\`\`\`
935
936### \`home-contact.php\`
937\`\`\`php
938<?php $atts = shortcode_atts(array(
939  '' => '',
940), $atts); ?>
941
942<section class="home-contact"></section>
943
944<?php if(!function_exists('apply_home_contact_styles')){
945  function apply_home_contact_styles(){ ?><style>/* .home-contact { … } */</style><?php }
946  add_action('wp_footer', 'apply_home_contact_styles');
947} ?>
948\`\`\`
949
950> All other home-* sections (any new one you introduce) follow the SAME pattern:
951> \`shortcode_atts\` → \`<section class="{slug}">\` → \`apply_{slug}_styles\`
952> hooked to \`wp_footer\`. Only \`home-banner\` uses an inline \`<style>\` block
953> because the hero must render without waiting for the footer.
954
955---
956
957## 16. Shortcode Registry — \`inc/shortcodes.php\`
958
959Every section partial in §14 MUST be registered as a WordPress shortcode in
960\`inc/shortcodes.php\` so it can be dropped into the page editor as
961\`[home_banner]\`, \`[home_services]\`, etc. Use this exact pattern — one
962function per partial, name matches the slug with underscores:
963
964\`\`\`php
965<?php
966/****** HOME SHORTCODES *******/
967function home_banner($atts, $content=null){
968  ob_start();
969  include(locate_template('template-parts/sections/home/home-banner.php'));
970  return ob_get_clean();
971}
972add_shortcode('home_banner', 'home_banner');
973
974function home_services($atts, $content=null){
975  ob_start();
976  include(locate_template('template-parts/sections/home/home-services.php'));
977  return ob_get_clean();
978}
979add_shortcode('home_services', 'home_services');
980
981// ...repeat for: home_about, home_team, home_cta, home_results,
982// home_testimonials, home_social, home_news, home_contact, home_mission,
983// home_awards, home_portfolio
984
985/****** INTERNAL SHORTCODES *******/
986function internal_banner($atts, $content=null){
987  ob_start();
988  include(locate_template('template-parts/sections/internal/internal-banner.php'));
989  return ob_get_clean();
990}
991add_shortcode('internal_banner', 'internal_banner');
992
993// ...repeat for: internal_content, internal_services, internal_fullwidth,
994// internal_cta
995\`\`\`
996
997> Rule: if you create a new \`{slug}.php\` partial, you MUST add a matching
998> shortcode function + \`add_shortcode()\` call in this file. Missing
999> registrations = broken page editor.
1000
1001---
1002
1003## 17. WordPress Template Files (theme root)
1004
1005These templates live at the THEME ROOT (not in \`template-parts/\`) and are
1006required for WordPress to render non-homepage routes. Generate them exactly
1007as shown — only the styling layer (\`single-blog-styles.php\`,
1008\`blog-styles.php\`) is brand-customizable.
1009
1010### \`page.php\` — generic page wrapper (uses Gutenberg / shortcode content)
1011\`\`\`php
1012<?php
1013/**
1014 * The template for displaying all standard pages
1015 */
1016
1017get_header();
1018
1019/* Start the Loop */
1020while ( have_posts() ) :
1021  the_post();
1022  the_content();
1023endwhile;
1024
1025get_footer();
1026\`\`\`
1027
1028### \`single.php\` — single blog post layout
1029\`\`\`php
1030<?php
1031/**
1032 * The template for displaying all single posts
1033 */
1034
1035function add_single_blog_styles(){
1036  include(locate_template('single-blog-styles.php'));
1037}
1038add_action('wp_head', 'add_single_blog_styles');
1039
1040get_header();
1041?>
1042
1043<?php while ( have_posts() ) : the_post(); ?>
1044  <section class="section-padding single-post">
1045    <div class="content-width">
1046      <h1><?= get_the_title(); ?></h1>
1047      <div class="author-date">
1048        <strong><?= get_the_author(); ?></strong> | <?= get_the_date(); ?>
1049      </div>
1050
1051      <?php if(has_post_thumbnail()){ ?>
1052        <div class="img-container">
1053          <img src="<?= get_the_post_thumbnail_url(); ?>">
1054        </div>
1055      <?php } ?>
1056
1057      <div class="blog-content">
1058        <?php the_content(); ?>
1059      </div>
1060    </div>
1061  </section>
1062<?php endwhile; ?>
1063
1064<?php get_footer(); ?>
1065\`\`\`
1066
1067### \`single-blog-styles.php\` — scoped styles for \`single.php\`
1068\`\`\`php
1069<style type="text/css">
1070  .single-post .blog-content { width: 750px; max-width: 100%; margin: 0 auto; }
1071  .single-post h1 { text-align: center; margin: 0; }
1072  .single-post .img-container { width: 1000px; max-width: 100%; margin: 1em auto; text-align: center; }
1073  .single-post .img-container img { display: block; margin: 0 auto; }
1074  .single-post .author-date { text-align: center; }
1075</style>
1076\`\`\`
1077
1078### \`search.php\` — search results page (reuses \`[internal_banner]\` + \`blog-styles.php\`)
1079\`\`\`php
1080<?php
1081/**
1082 * The template for displaying search results pages
1083 */
1084
1085function add_blog_styles(){
1086  include(locate_template('blog-styles.php'));
1087}
1088add_action('wp_head', 'add_blog_styles');
1089
1090get_header();
1091$term = get_search_query();
1092$banner = '[internal_banner title="You searched for: '. $term . '"]';
1093?>
1094
1095<?= apply_shortcodes($banner); ?>
1096
1097<section class="section-padding">
1098  <div class="content-width">
1099    <h2>The following is a list of results for your search term:</h2>
1100
1101    <?php if ( have_posts() ) { ?>
1102      <div class="posts-container has-blogs">
1103        <?php while ( have_posts() ) { the_post(); ?>
1104          <div class="indiv-post">
1105            <a href="<?= get_the_permalink(); ?>" class="img-container">
1106              <?php if(has_post_thumbnail()){ ?>
1107                <img src="<?= get_the_post_thumbnail_url(); ?>">
1108              <?php } else { ?>
1109                <span class="empty-thumb-container"></span>
1110              <?php } ?>
1111            </a>
1112            <div class="post-info">
1113              <p class="date">
1114                <span class="day"><?= get_the_date('d'); ?></span>
1115                <span class="y-m-container">
1116                  <span class="year"><?= get_the_date('Y'); ?></span>
1117                  <span class="month"><?= get_the_date('F'); ?></span>
1118                </span>
1119              </p>
1120              <h2 class="title"><?= get_the_title(); ?></h2>
1121              <p><?= get_the_excerpt(); ?></p>
1122              <a class="button" href="<?= get_the_permalink(); ?>">Read More</a>
1123            </div>
1124          </div>
1125        <?php } ?>
1126      </div>
1127
1128      <div class="nav-links">
1129        <?php echo paginate_links(array(
1130          'prev_text' => '<span>&lt;</span>',
1131          'next_text' => '<span>&gt;</span>',
1132        )); ?>
1133      </div>
1134    <?php } else { ?>
1135      <div class="posts-container no-blogs">
1136        There are no posts with that category name.
1137        <a style="width:100%;" href="/">Return to our homepage.</a>
1138      </div>
1139    <?php } ?>
1140  </div>
1141</section>
1142
1143<?php get_footer(); ?>
1144\`\`\`
1145
1146> Rule: \`search.php\` and any archive/index template ALWAYS load styles via
1147> a brand-specific \`blog-styles.php\` partial hooked into \`wp_head\` — never
1148> inline. Classes used (\`posts-container\`, \`indiv-post\`, \`img-container\`,
1149> \`post-info\`, \`date\`, \`day\`, \`y-m-container\`, \`year\`, \`month\`,
1150> \`title\`, \`nav-links\`, \`no-blogs\`, \`has-blogs\`, \`empty-thumb-container\`)
1151> are part of the theme class whitelist in §13 and MUST NOT be renamed.
1152
1153---
1154
1155## 18. Theme Header — \`style.css\`
1156
1157WordPress requires the theme's \`style.css\` to start with a metadata
1158docblock. Visual styles do NOT live here — they live in
1159\`theme-style.css\` (loaded via \`functions.php\` \`wp_enqueue_style\`).
1160
1161\`\`\`css
1162/*
1163Theme Name: {Client} Custom
1164Theme URI: https://{client-domain}/
1165Author: Arcbound Team
1166Description: Custom theme generated from the Arcbound brand kit.
1167Requires PHP: 5.6+
1168Version: 1.0
1169*/
1170
1171/* STYLES FOR THEME CAN BE FOUND IN THEME-STYLE.CSS */
1172\`\`\`
1173
1174> Do not put real CSS in \`style.css\` — only the WordPress theme header. All
1175> compiled styles ship from \`theme-style.css\` so cache-busting and
1176> conditional loading can be controlled from \`functions.php\`.
1177
1178---
1179
1180## 15. Section-by-Section Build Workflow (MANDATORY)
1181
1182⚠️ DO NOT generate the entire homepage in one pass. The builder MUST work
1183section-by-section, using full reasoning capacity on each section before
1184moving on. This brief is the blueprint; each section is its own contained
1185deliverable.
1186
1187For EACH section listed in §2 (\`home-banner\` → \`home-contact\`), execute
1188this 7-step loop in order before starting the next section:
1189
1190**Step 1 — Read brief context**
1191Re-read: Brand DNA (voice/tone, messaging pillars, audience), Design
1192References, this section's copy from "Homepage Copy", and any uploaded
1193visual references for this section.
1194
1195**Step 2 — Decide the section's job**
1196State in one sentence: what this section must communicate, what scroll
1197moment it owns, and what the user should feel/do leaving it.
1198
1199**Step 3 — Choose the layout pattern**
1200Pick a specific layout (split hero, asymmetric grid, full-bleed image with
1201overlay, marquee, etc.) justified by the design references — not generic
1202"3-column card grid" defaults. Sketch the grid in a comment.
1203
1204**Step 4 — Write the markup**
1205Emit the section using its §14 scaffold:
1206\`<section class="{slug}">…</section>\`. Include real copy from the
1207Homepage Copy spec, real image URLs (or labeled placeholders matching the
1208brief's image direction), \`data-url\`/\`data-bg-img\` for below-fold media,
1209and \`fade-from-*\` classes on reveal elements. Single \`<h1>\` only in
1210\`home-banner\`; \`<h2>\` for every other section's primary heading.
1211
1212**Step 5 — Write the scoped CSS**
1213Immediately after the section, emit one \`<style>\` block where EVERY
1214selector starts with \`.{slug}\` (this becomes \`apply_{slug}_styles\` in
1215PHP). Use \`var(--color-1/2/3)\`, \`var(--xl/lg/md/sm)\`, \`var(--heading-font)\`,
1216\`var(--default-font)\`. Include the 1000px and 750px breakpoint overrides.
1217
1218**Step 6 — Self-QA the section**
1219Confirm: (a) markup uses only whitelisted theme classes + new modifiers
1220scoped under \`.{slug}\`; (b) all CSS is scoped to \`.{slug}\`; (c) copy
1221matches the Homepage Copy spec verbatim — no paraphrasing; (d) imagery
1222direction matches design references; (e) no \`loading="lazy"\` (use
1223\`data-url\`); (f) contrast ≥ 4.5:1 against background; (g) reveals use
1224\`fade-from-*\` not custom animation names.
1225
1226**Step 7 — Commit the section, then move on**
1227Output the finished \`<section>\` + scoped \`<style>\` as a self-contained
1228block. Do not touch a previously-completed section while building a new
1229one — its styles are already isolated by §9.
1230
1231After ALL home-* sections are complete, assemble the page skeleton from §1,
1232drop the sections into \`#main-content\` in the order listed in §2, append
1233the footer (§12) and the lazy-load + IntersectionObserver scripts (§4, §10).
1234Run a final pass to confirm zero cross-section CSS leakage and that every
1235section maps cleanly to a \`template-parts/sections/home/{slug}.php\` partial
1236using the §14 scaffolds.
1237
1238For interior pages, repeat the same 7-step loop using the
1239\`internal-banner\` / \`internal-content\` / \`internal-services\` /
1240\`internal-fullwidth\` / \`internal-cta\` scaffolds from §8 and §14.
1241
1242---
1243
1244## 19. \`functions.php\` Contract (theme bootstrap)
1245
1246Every generated WordPress theme MUST ship a \`functions.php\` that mirrors
1247the Arcbound boilerplate exactly. This is what wires \`theme-styles.php\`
1248into \`wp_head\`, registers the shortcode registry from §16, and strips
1249WordPress default cruft (emojis, block-library CSS) that fights the brand.
1250
1251\`\`\`php
1252<?php
1253// 1. Load theme styles partial into <head>
1254function add_theme_styles(){
1255  include(locate_template('theme-styles.php'));
1256}
1257add_action( 'wp_head', 'add_theme_styles' );
1258
1259// 2. Register all section shortcodes (see §16)
1260include(locate_template('shortcodes.php'));
1261
1262// 3. Kill WordPress emoji scripts (perf + visual cleanliness)
1263function disable_emojis() {
1264  remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
1265  remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
1266  remove_action( 'wp_print_styles', 'print_emoji_styles' );
1267  remove_action( 'admin_print_styles', 'print_emoji_styles' );
1268  remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
1269  remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
1270  remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
1271  add_filter( 'tiny_mce_plugins', 'disable_emojis_tinymce' );
1272  add_filter( 'wp_resource_hints', 'disable_emojis_remove_dns_prefetch', 10, 2 );
1273}
1274add_action( 'init', 'disable_emojis' );
1275
1276function disable_emojis_tinymce( $plugins ) {
1277  return is_array( $plugins ) ? array_diff( $plugins, array( 'wpemoji' ) ) : array();
1278}
1279function disable_emojis_remove_dns_prefetch( $urls, $relation_type ) {
1280  if ( 'dns-prefetch' == $relation_type ) {
1281    $emoji_svg_url = apply_filters( 'emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/' );
1282    $urls = array_diff( $urls, array( $emoji_svg_url ) );
1283  }
1284  return $urls;
1285}
1286
1287// 4. Drop Gutenberg block-library + WooCommerce block CSS (we ship our own)
1288function smartwp_remove_wp_block_library_css(){
1289  wp_dequeue_style( 'wp-block-library' );
1290  wp_dequeue_style( 'wp-block-library-theme' );
1291  wp_dequeue_style( 'wc-blocks-style' );
1292}
1293add_action( 'wp_enqueue_scripts', 'smartwp_remove_wp_block_library_css', 100 );
1294
1295// 5. Theme support
1296add_action( 'after_setup_theme', 'add_theming_support' );
1297function add_theming_support(){
1298  add_theme_support( 'automatic-feed-links' );
1299  add_theme_support( 'title-tag' );
1300  add_theme_support( 'post-formats', array( 'aside','image','video','quote','link' ) );
1301  add_theme_support( 'post-thumbnails' );
1302  add_theme_support( 'html5', array( 'search-form','comment-form','comment-list','gallery','caption','script','style' ) );
1303  register_nav_menus( array( 'main-menu' => 'Main Menu', 'footer-menu' => 'Footer Menu' ) );
1304}
1305\`\`\`
1306
1307> Rules: \`functions.php\` NEVER contains markup or visual CSS. It only
1308> wires hooks. Any new section partial added in §14 MUST also be registered
1309>
1309 as a shortcode in \`shortcodes.php\` (§16) — \`functions.php\` includes
1310> that file once.
1311
1312---
1313
1314## 20. \`theme-styles.php\` Contract (global base styles partial)
1315
1316\`theme-styles.php\` is the partial \`functions.php\` injects into
1317\`wp_head\`. It contains ONLY global base styles: CSS variables, reset,
1318typography, navbar, footer, and the utility classes from §13. Section
1319styles NEVER live here — they live in their own scoped \`apply_{slug}_styles\`
1320block (§9 / §14).
1321
1322\`\`\`php
1323<style type="text/css">
1324  :root{
1325    --color-1: {hex};  /* primary */
1326    --color-2: {hex};  /* secondary */
1327    --color-3: {hex};  /* accent */
1328    --color-4: {hex};  /* neutral */
1329    --heading-font: '{display}', serif;
1330    --default-font: '{body}', sans-serif;
1331    --xl: clamp(56px, 6vw, 88px);
1332    --lg: clamp(36px, 4vw, 56px);
1333    --md: clamp(22px, 2.5vw, 32px);
1334    --sm: 16px;
1335  }
1336  /* reset, body, masthead, inner-masthead, main-menu, mobile menu,
1337     .section-padding, .content-width, .absolute-cover, .button,
1338     .site-footer, fade-from-* keyframes — see §13 whitelist */
1339</style>
1340\`\`\`
1341
1342> Rule: the AI builder writes one \`theme-styles.php\` per brand, populated
1343> from the Visual Brand Kit. It MUST NOT contain any \`.home-*\` or
1344> \`.internal-*\` selectors.
1345
1346---
1347
1348## 21. \`header.php\` Contract (WordPress)
1349
1350\`header.php\` is the only template that emits the opening \`<html>\`,
1351\`<head>\`, and the masthead. It MUST follow this exact contract — the
1352class names are whitelisted (§13) and the WordPress hooks are required.
1353
1354\`\`\`php
1355<?php /** The header. */ ?>
1356<!doctype html>
1357<html <?php language_attributes(); ?>>
1358<head>
1359  <meta charset="<?php bloginfo( 'charset' ); ?>" />
1360  <meta name="viewport" content="width=device-width, initial-scale=1" />
1361  <?php wp_head(); ?>
1362</head>
1363<body <?php body_class(); ?>>
1364<?php wp_body_open(); ?>
1365<div id="main">
1366  <a class="skip-menu" href="#main-content">Skip to Main Content</a>
1367  <header class="masthead">
1368    <div class="inner-masthead">
1369      <a class="logo-container" href="<?= get_home_url(); ?>/">
1370        <img src="<?= wp_get_attachment_url(LOGO_ATTACHMENT_ID); ?>" width="400" height="64" alt="logo for <?php bloginfo('name'); ?>">
1371      </a>
1372      <div class="menu-container">
1373        <label for="mobile-input">☰</label>
1374        <input type="checkbox" id="mobile-input">
1375        <nav>
1376          <?php wp_nav_menu(array('menu' => 'Main Menu', 'menu_class' => 'main-menu')); ?>
1377        </nav>
1378      </div>
1379    </div>
1380  </header>
1381  <div id="main-content">
1382\`\`\`
1383
1384> Rules: never hard-code the logo \`<img src>\` — always
1385> \`wp_get_attachment_url()\`. \`wp_head()\`, \`wp_body_open()\`, and the
1386> matching \`wp_footer()\` in \`footer.php\` are non-negotiable. The
1387> mobile menu uses the CSS checkbox-toggle pattern in §13 — no JS.
1388
1389---
1390
1391## 22. \`index.php\` / \`archive.php\` / \`404.php\` Contracts
1392
1393These three WordPress templates share the \`blog-styles.php\` partial
1394(§11) and the \`[internal_banner]\` shortcode (§8) so brand styling stays
1395centralised. Builder must emit all three verbatim, varying only the
1396banner title source.
1397
1398### \`index.php\` — blog index (post archive fallback)
1399\`\`\`php
1400<?php
1401function add_blog_styles(){ include(locate_template('blog-styles.php')); }
1402add_action('wp_head', 'add_blog_styles');
1403get_header();
1404$banner = '[internal_banner title="Blog"]';
1405?>
1406<?= apply_shortcodes($banner); ?>
1407<section class="section-padding">
1408  <div class="content-width">
1409    <?php if ( have_posts() ) { ?>
1410      <div class="posts-container has-blogs">
1411        <?php while ( have_posts() ) { the_post(); ?>
1412          <div class="indiv-post">
1413            <a href="<?= get_the_permalink(); ?>" class="img-container">
1414              <?php if(has_post_thumbnail()){ ?>
1415                <img src="<?= get_the_post_thumbnail_url(); ?>">
1416              <?php }else{ ?>
1417                <span class="empty-thumb-container"></span>
1418              <?php } ?>
1419            </a>
1420            <div class="post-info">
1421              <p class="date">
1422                <span class="day"><?= get_the_date('d'); ?></span>
1423                <span class="y-m-container">
1424                  <span class="year"><?= get_the_date('Y'); ?></span>
1425                  <span class="month"><?= get_the_date('F'); ?></span>
1426                </span>
1427              </p>
1428              <h2 class="title"><?= get_the_title(); ?></h2>
1429              <p><?= get_the_excerpt(); ?></p>
1430              <a class="button" href="<?= get_the_permalink(); ?>">Read More</a>
1431            </div>
1432          </div>
1433        <?php } ?>
1434      </div>
1435      <div class="nav-links">
1436        <?php echo paginate_links(array('prev_text'=>'<span>&lt;</span>','next_text'=>'<span>&gt;</span>')); ?>
1437      </div>
1438    <?php } else { ?>
1439      <div class="posts-container has-blogs">no content</div>
1440    <?php } ?>
1441  </div>
1442</section>
1443<?php get_footer(); ?>
1444\`\`\`
1445
1446### \`archive.php\` — taxonomy / category archives
1447Identical loop to \`index.php\` except the banner title pulls from the
1448queried term and the empty state copy changes:
1449\`\`\`php
1450<?php
1451function add_blog_styles(){ include(locate_template('blog-styles.php')); }
1452add_action('wp_head', 'add_blog_styles');
1453get_header();
1454$term = get_queried_object();
1455$banner = '[internal_banner title="'. $term->name .'"]';
1456?>
1457<?= apply_shortcodes($banner); ?>
1458<!-- …same loop as index.php… -->
1459<!-- Empty-state variant: -->
1460<div class="posts-container no-blogs">
1461  There are no posts with that category name.
1462  <a style="width:100%;" href="/">Return to our homepage.</a>
1463</div>
1464\`\`\`
1465
1466### \`404.php\` — not found
1467\`\`\`php
1468<?php get_header(); ?>
1469<?= apply_shortcodes('[internal_banner title="That\\'s a 404"]'); ?>
1470<section class="section-padding">
1471  <div class="content-width" style="text-align: center;">
1472    The URL you entered doesn't exist on our site. Perhaps try navigating from <a href="/">our homepage</a>?
1473  </div>
1474</section>
1475<?php get_footer(); ?>
1476\`\`\`
1477
1478> Rules: (a) \`index.php\` and \`archive.php\` ALWAYS load
1479> \`blog-styles.php\` via the \`add_blog_styles\` hook — never inline. (b)
1480> The banner is ALWAYS \`[internal_banner]\` so it inherits the brand's
1481> interior-banner styling. (c) Loop markup (\`posts-container\`,
1482> \`indiv-post\`, \`img-container\`, \`empty-thumb-container\`, \`post-info\`,
1483> \`date\`/\`day\`/\`y-m-container\`/\`year\`/\`month\`, \`title\`,
1484> \`nav-links\`) is part of the §13 whitelist and MUST NOT be renamed —
1485> \`blog-styles.php\` selectors depend on these exact class names.
1486
1487---
1488
1489## 23. Arcbound Theme File Structure (CANONICAL — WordPress-ready)
1490
1491Every generated build MUST map 1:1 to this file tree so it can be dropped
1492into the Arcbound WordPress boilerplate without restructuring. Do NOT
1493invent alternative folder layouts.
1494
1495\`\`\`
1496{theme-root}/
1497├── style.css                           (§18 — registration only, no real CSS)
1498├── functions.php                       (§19 — bootstrap, enqueues, shortcode + hook wiring)
1499├── theme-styles.php                    (§20 — global :root vars, reset, nav, footer, utilities)
1500├── header.php                          (§21 — <html>, <head>, <body>, .masthead, mobile nav)
1501├── footer.php                          (§12 — closes #main-content/#main, wp_footer)
1502├── page.php                            (§17 — generic page wrapper, the_content())
1503├── single.php                          (§17 — single post; loads single-blog-styles.php)
1504├── single-blog-styles.php              (§17 — scoped post styles)
1505├── index.php                           (§22 — blog index, loads blog-styles.php)
1506├── archive.php                         (§22 — taxonomy archive, loads blog-styles.php)
1507├── search.php                          (§17 — reuses [internal_banner] + blog-styles.php)
1508├── 404.php                             (§22 — uses [internal_banner])
1509├── blog-styles.php                     (§11 — shared archive/search loop styles)
1510├── includes/
1511│   ├── shortcodes.php                  (§16 — home_* + internal_* registry)
1512│   └── theme-changes.php               (§10 — wp_footer: IntersectionObserver lazy load + scroll-in animations)
1513└── template-parts/
1514    └── sections/
1515        ├── home/
1516        │   ├── home-banner.php         (§14 — inline <style>, NOT wp_footer)
1517        │   ├── home-services.php
1518        │   ├── home-about.php
1519        │   ├── home-team.php
1520        │   ├── home-cta.php
1521        │   ├── home-results.php
1522        │   ├── home-testimonials.php
1523        │   ├── home-social.php
1524        │   ├── home-news.php
1525        │   ├── home-contact.php
1526        │   ├── home-mission.php
1527        │   ├── home-awards.php
1528        │   └── home-portfolio.php
1529        └── internal/
1530            ├── internal-banner.php
1531            ├── internal-content.php
1532            ├── internal-fullwidth.php
1533            ├── internal-cta.php
1534            ├── internal-contact.php
1535            └── internal-services.php
1536\`\`\`
1537
1538> Generation contract: when the AI emits the build payload it MUST return a
1539> map keyed by these exact relative paths. Any partial that does not have a
1540> matching shortcode registration in \`includes/shortcodes.php\` is a build
1541> failure — re-run the §15 workflow for that section.
1542
1543---
1544
1545## 24. \`includes/theme-changes.php\` Contract (lazy load + scroll animations)
1546
1547Single source of truth for the two runtime behaviours referenced in §4 and
1548§10. Output ONLY via the \`wp_footer\` hook — never inline in templates.
1549
1550\`\`\`php
1551<?php
1552add_action('wp_footer', 'arcbound_footer_scripts');
1553function arcbound_footer_scripts() { ?>
1554<script>
1555// 1. Lazy load: swap data-url -> src as elements enter viewport
1556(function () {
1557  var imgs = document.querySelectorAll('img[data-url]');
1558  if (!('IntersectionObserver' in window)) {
1559    imgs.forEach(function (i) { i.src = i.getAttribute('data-url'); });
1560    return;
1561  }
1562  var io = new IntersectionObserver(function (entries, obs) {
1563    entries.forEach(function (e) {
1564      if (!e.isIntersecting) return;
1565      var el = e.target;
1566      el.src = el.getAttribute('data-url');
1567      el.removeAttribute('data-url');
1568      obs.unobserve(el);
1569    });
1570  }, { rootMargin: '200px 0px' });
1571  imgs.forEach(function (i) { io.observe(i); });
1572})();
1573
1574// 2. Scroll-in animations: activate .fade-from-* once visible (disabled <=750px)
1575window.addEventListener('load', function () {
1576  if (window.innerWidth <= 750) return;
1577  var els = document.querySelectorAll('.fade-from-left, .fade-from-right, .fade-from-bottom');
1578  var io = new IntersectionObserver(function (entries, obs) {
1579    entries.forEach(function (e) {
1580      if (!e.isIntersecting) return;
1581      e.target.classList.add('is-visible');
1582      obs.unobserve(e.target);
1583    });
1584  }, { threshold: 0.15 });
1585  els.forEach(function (el) { io.observe(el); });
1586});
1587<\/script>
1588<?php }
1589\`\`\`
1590
1591> Rules: (a) Every \`<img>\` in every section partial MUST use \`data-url\`
1592> instead of \`src\` (except the LCP image inside \`home-banner.php\`, which
1593> stays as \`src\` for performance). (b) The \`.fade-from-*\` classes
1594> declared in §13 are inert until the observer adds \`.is-visible\` —
1595> \`theme-styles.php\` MUST define both the resting and \`.is-visible\` state.
1596> (c) Do not enqueue any other lazy-load plugin; \`functions.php\` (§19)
1597> explicitly disables native WP lazy loading and \`wp_calculate_image_srcset\`.
1598
1599---
1600
1601## 25. \`functions.php\` — Required Disables (additive to §19)
1602
1603The Arcbound boilerplate intentionally disables WordPress features that
1604conflict with the custom lazy loader and scoped section styles. Include
1605ALL of the following in \`functions.php\`:
1606
1607\`\`\`php
1608// Disable native lazy loading (custom IntersectionObserver used instead — §24)
1609add_filter('wp_lazy_loading_enabled', '__return_false');
1610
1611// Disable responsive srcset (custom data-url swap handles delivery)
1612add_filter('wp_calculate_image_srcset_meta', '__return_null');
1613add_filter('wp_calculate_image_srcset', '__return_false');
1614
1615// Strip emoji scripts/styles (see §19 disable_emojis)
1616remove_action('wp_head', 'print_emoji_detection_script', 7);
1617remove_action('wp_print_styles', 'print_emoji_styles');
1618
1619// Dequeue block library + global styles (theme is fully custom)
1620add_action('wp_enqueue_scripts', function () {
1621  wp_dequeue_style('wp-block-library');
1622  wp_dequeue_style('wp-block-library-theme');
1623  wp_dequeue_style('global-styles');
1624}, 100);
1625\`\`\`
1626
1627---
1628
1629## 26. Per-Section Asset Conventions (image markup)
1630
1631To keep §24's lazy loader working everywhere, every section partial MUST
1632follow this image markup contract:
1633
1634\`\`\`php
1635<!-- Below-the-fold image (default) -->
1636<img data-url="<?= esc_url($img) ?>"
1637     alt="<?= esc_attr($alt) ?>"
1638     width="<?= (int) $w ?>"
1639     height="<?= (int) $h ?>"
1640     decoding="async">
1641
1642<!-- LCP / above-the-fold (home-banner.php only) -->
1643<img src="<?= esc_url($img) ?>"
1644     alt="<?= esc_attr($alt) ?>"
1645     width="<?= (int) $w ?>"
1646     height="<?= (int) $h ?>"
1647     fetchpriority="high"
1648     decoding="async">
1649\`\`\`
1650
1651Rules: (a) Always emit explicit \`width\` + \`height\` to prevent CLS.
1652(b) Never use \`loading="lazy"\` — the observer handles it.
1653(c) Background images go in the scoped \`apply_{slug}_styles\` block, not inline \`style="..."\`.
1654
1655---
1656
1657## 27. Launch-Readiness Generation Contract (SOP Phases 3–5)
1658
1659The generator MUST emit, in addition to the theme files, a sibling
1660\`LAUNCH-CHECKLIST.md\` per build that mirrors the Arcbound SOP so QA can
1661tick items without re-deriving them:
1662
1663- Phase 3.1 Updates & Plugins — Yoast SEO, Forms plugin, Redirection listed as required
1664- Phase 3.2 Forms — every \`[internal_contact]\` / form shortcode must declare its recipient + thank-you URL in the build payload
1665- Phase 3.3 SEO — every \`page.php\` / section pair must ship a \`<title>\` + meta description + single \`<h1>\` (enforced by §11/§17 templates)
1666- Phase 3.3 Yoast — archives (\`archive.php\`, author/category/tag) MUST be flagged \`noindex\` in the generated Yoast import file
1667- Phase 3.4 Performance — \`home-banner.php\` is the ONLY section allowed to inline its \`<style>\` and use \`fetchpriority="high"\` (§14, §26)
1668- Phase 3.5 Cleanup — \`404.php\` (§22) is mandatory;
1668 build fails if absent
1669- Phase 5.1 Post-launch — Post SMTP + HTTPS notes included in the checklist; not generated as code
1670
1671> The checklist is a deliverable, not a suggestion. A build payload that
1672> omits \`LAUNCH-CHECKLIST.md\` is incomplete and MUST be regenerated.
1673
1674---
1675
1676## 28. AI Component Generation System Prompt (MANDATORY — html components only)
1677
1678When the generator is asked to produce ONE section/component (not a full
1679page), it MUST operate under the following system prompt verbatim. This is
1680the source of truth for the Arcbound WordPress theme boilerplate; deviating
1681from any rule is a build failure.
1682
1683> You are generating PHP template section files for a custom WordPress theme
1684> called the Arcbound boilerplate. Every section you create must follow all
1685> of the rules below exactly. Do not deviate from these patterns even if a
1686> different approach seems cleaner or more conventional.
1687
1688### 28.1 — 1:1:1 Naming Contract
1689
1690The section slug is the single source of truth. It drives the file name,
1691the root CSS class, AND the shortcode name.
1692
1693| Element | Pattern | Example |
1694|---|---|---|
1695| File name | \`{slug}.php\` | \`home-banner.php\` |
1696| Root CSS class | \`.{slug}\` | \`.home-banner\` |
1697| Shortcode name | \`{slug}\` with \`-\` → \`_\` | \`home_banner\` |
1698
1699Location: \`template-parts/sections/home/{slug}.php\` (home) or
1700\`template-parts/sections/internal/{slug}.php\` (internal).
1701The shortcode is registered in \`includes/shortcodes.php\` — NEVER inside
1702the template file:
1703
1704\`\`\`php
1705function home_banner($atts, $content = null) {
1706    ob_start();
1707    include(locate_template('template-parts/sections/home/home-banner.php'));
1708    return ob_get_clean();
1709}
1710add_shortcode('home_banner', 'home_banner');
1711\`\`\`
1712
1713### 28.2 — Template File Top-to-Bottom Order (STRICT)
1714
1715Every section file MUST contain these four blocks in this exact order and
1716nothing else:
1717
17181. PHP attribute block (\`shortcode_atts()\`)
17192. \`<style>\` block (scoped to root class)
17203. HTML markup
17214. PHP JS function (registered to \`wp_footer\`) — OMIT entirely if no JS
1722
1723Forbidden in the file: \`wp_enqueue_style\`, \`wp_enqueue_script\`, external
1724\`<link>\` or \`<script src>\`, inline \`style="..."\` on HTML elements,
1725section markup in \`header.php\`/\`footer.php\`.
1726
1727### 28.3 — PHP Attribute Block (always first)
1728
1729\`\`\`php
1730<?php $atts = shortcode_atts(array(
1731    'title'   => '',
1732    'content' => '',
1733), $atts); ?>
1734\`\`\`
1735
1736If the section has no attributes yet, use a placeholder so it remains
1737extensible without restructuring:
1738
1739\`\`\`php
1740<?php $atts = shortcode_atts(array('' => ''), $atts); ?>
1741\`\`\`
1742
1743### 28.4 — The \`<style>\` Block (scoped CSS only)
1744
1745Rules:
1746- EVERY selector starts with \`.{slug}\`. No bare tag selectors. No global
1747  class without the slug prefix.
1748- Use the theme's CSS custom properties for ALL colors, sizes, and fonts.
1749  Hardcoded hex/px values are a build failure.
1750- Include responsive overrides at \`max-width: 1000px\` AND \`max-width: 750px\`.
1751- Reuse global utilities in the HTML, do NOT re-declare them: \`.section-padding\`,
1752  \`.content-width\`, \`.absolute-cover\`, \`.fade-from-left/-right/-bottom\`.
1753
1754Available CSS custom properties (theme contract):
1755
1756\`\`\`css
1757/* Colors */         var(--color-1)  var(--color-2)  var(--color-3)
1758/* Font sizes */     var(--xl)  /* h1: 55→40→35 */
1759                     var(--lg)  /* h2: 40→30→25 */
1760                     var(--md)  /* h3: 30→20→20 */
1761                     var(--sm)  /* h4: 20→18→18 */
1762                     var(--default) /* body 16 */
1763/* Font families */  var(--heading-font)  var(--default-font)  var(--accent-font)
1764\`\`\`
1765
1766### 28.5 — HTML Markup Rules
1767
1768- Outermost element is ALWAYS \`<section class="{slug} section-padding">\`.
1769- Wrap content in \`<div class="content-width">\`.
1770- Sub-classes use BEM scoped to the slug: \`.home-banner__title\`,
1771  \`.home-banner__grid\`, \`.home-banner__item\`.
1772- Full-bleed backgrounds: \`<img class="absolute-cover" ...>\` inside the
1773  section + \`position: relative; overflow: hidden;\` on \`.{slug}\` in
1774  \`<style>\`.
1775- Lazy-loaded images use \`data-url=\` instead of \`src=\` (see §24).
1776- Above-the-fold LCP image (home-banner only) uses \`src=\` + \`fetchpriority="high"\`.
1777- Animation classes: \`.fade-from-left\`, \`.fade-from-right\`, \`.fade-from-bottom\`
1778  on any element — the theme observer adds \`.active\` (and disables on
1779  mobile automatically).
1780- Output attribute values with the short echo tag: \`<?= $atts['key']; ?>\`.
1781- ACF/custom field access is allowed: \`the_field()\`, \`get_field()\`,
1782  \`get_post_meta()\`.
1783
1784### 28.6 — JavaScript Block (last; omit if none)
1785
1786\`\`\`php
1787<?php if(!function_exists('apply_home_banner_styles')) {
1788    function apply_home_banner_styles() { ?>
1789        <script>
1790            window.addEventListener('load', function() {
1791                const banner = document.querySelector('.home-banner');
1792                if (!banner) return;
1793                // scoped logic here
1794            });
1795        <\/script>
1796    <?php }
1797    add_action('wp_footer', 'apply_home_banner_styles');
1798} ?>
1799\`\`\`
1800
1801Rules:
1802- Function name = \`apply_{slug_with_underscores}_styles\`.
1803- ALWAYS guard with \`if(!function_exists(...))\` — shortcodes may render multiple times per page.
1804- Register via \`add_action('wp_footer', ...)\`.
1805- Use \`window.addEventListener('load', ...)\` — never \`document.ready\`.
1806- Query only by \`.{slug}\` or selectors unique to this section.
1807- No inline library imports. Assume libraries (if any) are globally enqueued.
1808- If the section needs no JS, OMIT this block entirely. Do NOT ship an empty function.
1809
1810### 28.7 — Canonical Empty Starter
1811
1812\`\`\`php
1813<?php $atts = shortcode_atts(array(
1814    'title'   => '',
1815    'content' => '',
1816), $atts); ?>
1817
1818<style type="text/css">
1819    .{slug} {}
1820    .{slug} h1 { font-family: var(--heading-font); font-size: var(--xl); }
1821    @media(max-width: 1000px) { .{slug} {} }
1822    @media(max-width: 750px)  { .{slug} {} }
1823</style>
1824
1825<section class="{slug} section-padding">
1826  <div class="content-width">
1827    <!-- markup -->
1828  </div>
1829</section>
1830
1831<?php if(!function_exists('apply_{slug_us}_styles')) {
1832    function apply_{slug_us}_styles() { ?>
1833        <script>window.addEventListener('load', function(){ /* ... */ });<\/script>
1834    <?php }
1835    add_action('wp_footer', 'apply_{slug_us}_styles');
1836} ?>
1837\`\`\`
1838
1839### 28.8 — Pre-Built Slug Registry (do NOT recreate)
1840
1841If a design calls for one of these, EXTEND the existing file. Do not generate a duplicate under a different slug.
1842
1843Homepage (\`template-parts/sections/home/\`):
1844\`home-banner\`, \`home-services\`, \`home-about\`, \`home-team\`, \`home-cta\`,
1845\`home-results\`, \`home-testimonials\`, \`home-social\`, \`home-news\`,
1846\`home-contact\`, \`home-mission\`, \`home-awards\`, \`home-portfolio\`.
1847
1848Internal (\`template-parts/sections/internal/\`):
1849\`internal-banner\`, \`internal-content\`, \`internal-fullwidth\`,
1850\`internal-cta\`, \`internal-contact\`, \`internal-services\`.
1851
1852### 28.9 — Global File Boundaries
1853
1854\`header.php\` — \`<!doctype>\`, \`<html>\`, \`<head>\`, \`wp_head()\`,
1855opens \`<body>\` + \`wp_body_open()\`, renders \`.masthead\` (logo + nav),
1856opens \`#main\` and \`#main-content\`, includes \`.skip-menu\`. NO section
1857markup, NO inline styles, NO inline scripts.
1858
1859\`footer.php\` — closes \`#main-content\` and \`#main\`, calls \`wp_footer()\`
1860(this is what triggers every section's \`apply_{slug}_styles\` registration),
1861closes \`</body>\` and \`</html>\`. NO section markup.
1862
1863\`theme-styles.php\` — global ONLY: \`:root\` custom properties, reset,
1864typography defaults, navigation, buttons, animation keyframes. NO selectors
1865beginning with \`.home-\` or \`.internal-\`. When a client's brand colors or
1866fonts change, ONLY the \`:root\` block changes.
1867
1868### 28.10 — Per-Section Self-QA Checklist (run before emitting)
1869
1870Every generated section file must pass ALL of:
1871
1872- [ ] File name matches slug exactly (\`{slug}.php\`).
1873- [ ] Root \`<section>\` class matches slug exactly.
1874- [ ] Shortcode function name matches slug exactly (\`-\` → \`_\`).
1875- [ ] Shortcode registered in \`includes/shortcodes.php\`, NOT in template.
1876- [ ] Every CSS selector scoped to \`.{slug}\`.
1877- [ ] No hardcoded colors — \`var(--color-*)\` only.
1878- [ ] No hardcoded font sizes — \`var(--xl|lg|md|sm|default)\` only.
1879- [ ] Responsive overrides at 1000px AND 750px.
1880- [ ] Lazy images use \`data-url=\` (except LCP in \`home-banner\`).
1881- [ ] Animations use \`.fade-from-*\` classes — no inline keyframes.
1882- [ ] JS wrapped in \`apply_{slug}_styles()\` + \`function_exists\` guard.
1883- [ ] JS uses \`window.addEventListener('load', ...)\`.
1884- [ ] If section has no JS, the JS block is OMITTED (no empty function).
1885- [ ] No \`wp_enqueue_*\`, no external \`<link>\`/\`<script src>\` in the file.
1886
1887> Generator behaviour: when asked to produce a single component, output
1888> ONLY the contents of \`{slug}.php\` per §28.7, plus the matching
1889> \`add_shortcode\` registration that belongs in \`includes/shortcodes.php\`
1890> (clearly labelled as a separate snippet). Do not emit page-level wrappers,
1891> \`header.php\`, or \`footer.php\` for single-component requests.
1892
1893### 28.11 — Theme Token Bridge (compat with §13/§20)
1894
1895The Arcbound boilerplate uses the SHORT tokens in §28.4 (\`--xl\`, \`--lg\`,
1896\`--heading-font\`, etc.). Earlier sections of this brief reference longer
1897tokens (\`--font-display\`, \`--color-1\`). \`theme-styles.php\` (§20) MUST
1898declare both spellings in \`:root\` so generated sections under either
1899contract resolve correctly:
1900
1901\`\`\`css
1902:root {
1903  /* canonical (§28) */
1904  --color-1: <hex>; --color-2: <hex>; --color-3: <hex>;
1905  --xl: 55px; --lg: 40px; --md: 30px; --sm: 20px; --default: 16px;
1906  --heading-font: '<Display>', serif;
1907  --default-font: '<Body>', sans-serif;
1908  --accent-font:  '<Accent>', sans-serif;
1909
1910  /* aliases for earlier sections of this brief */
1911  --font-display: var(--heading-font);
1912  --font-body:    var(--default-font);
1913}
1914@media(max-width: 1000px) { :root { --xl: 40px; --lg: 30px; --md: 20px; --sm: 18px; } }
1915@media(max-width: 750px)  { :root { --xl: 35px; --lg: 25px; --md: 20px; --sm: 18px; } }
1916\`\`\``;const Y=t.homepageSections.find(s=>{var o,a;return((o=s.heading)==null?void 0:o.toLowerCase().includes("hero"))||((a=s.heading)==null?void 0:a.toLowerCase().includes("header"))}),Ie=(Y==null?void 0:Y.copy)||((_e=t.homepageSections[0])==null?void 0:_e.copy)||"";r["hero-concept"]=`# ⭐ HERO & FULL HOMEPAGE DESIGN CONCEPT
1917
1918## ⚡ Click "Generate Hero Concept" to create an AI-powered design concept
1919This will:
19201. Scrape award-winning designs from Godly.website, Awwwards, and OnePageLove
19212. Extract hero HTML/CSS patterns from featured sites
19223. Generate a bespoke hero concept with production-ready code
19234. Include parallax, custom cursor, reactive elements, and scroll animations
19245. Create section-by-section visual direction for the entire homepage
1925
1926## Current Hero Copy (from Homepage Copy section)
1927**Heading:** ${(Y==null?void 0:Y.heading)||((xe=t.homepageSections[0])==null?void 0:xe.heading)||"TBD"}
1928
1929${Ie}
1930
1931## Design Parameters That Will Be Applied
1932- Display Font: **${d}**
1933- Body Font: **${g}**
1934- Colors: ${l}
1935- Mood: ${t.mood.join(", ")}
1936
1937## Interactive Elements to Include
1938- ✦ Custom cursor (subtle dot/ring that reacts to hoverable elements)
1939- ✦ Parallax scrolling on hero background layers
1940- ✦ Mouse-tracking gradient orbs or light effects
1941- ✦ Magnetic buttons that subtly pull toward cursor
1942- ✦ Scroll-triggered animations (stagger reveal, parallax sections)
1943- ✦ Animated counters for statistics/impact numbers
1944- ✦ Smooth page transitions between sections
1945- ✦ Reactive floating elements that respond to scroll position
1946- ✦ Infographics and diagrams with brand colors
1947- ✦ Icon system with consistent visual language
1948
1949> Click the **"Generate Hero Concept"** button above to create a full design concept with code.`,ue(r)},Ae=t=>{const i=z[t];i&&(navigator.clipboard.writeText(i),Z(t),x.success("Copied to clipboard!"),setTimeout(()=>Z(null),2e3))},$e=()=>{if(!m)return;const t=K.map(r=>`${r.title}
1950${"=".repeat(r.title.length)}
1951
1952${z[r.key]||""}
1953
1954
1955`).join(""),i=new Blob([t],{type:"text/plain"}),l=URL.createObjectURL(i),n=document.createElement("a");n.href=l,n.download=`${m.clientName.replace(/\s+/g,"-")}-Website-Brief.txt`,n.click(),URL.revokeObjectURL(l)},ge=()=>{if(!m)return;const t=K.map(i=>`${i.title}
1956${"=".repeat(i.title.length)}
1957
1958${z[i.key]||""}
1959
1960
1961`).join("");navigator.clipboard.writeText(t),x.success("All brief sections copied to clipboard!")},fe=()=>{if(!m)return;const t=new Ge({orientation:"p",unit:"mm",format:"a4"}),i=210,l=15,n=i-l*2;let r=l;
1961const c=(d,g,v=!1)=>{t.setFontSize(g),v?t.setFont("helvetica","bold"):t.setFont("helvetica","normal");const S=t.splitTextToSize(d,n),$=g*.45;for(const _ of S)r+$>282&&(t.addPage(),r=l),t.text(_,l,r),r+=$};t.setFontSize(24),t.setFont("helvetica","bold"),t.text("Website Design Brief",l,40),t.setFontSize(14),t.setFont("helvetica","normal"),t.text(m.clientName,l,52),t.setFontSize(10),t.text(new Date().toLocaleDateString(),l,60),t.addPage(),r=l,K.forEach((d,g)=>{g>0&&(t.addPage(),r=l),c(d.title,16,!0),r+=4,(z[d.key]||"").split(`
1962`).forEach(S=>{S.startsWith("# ")?(c(S.slice(2),14,!0),r+=2):S.startsWith("## ")?(c(S.slice(3),12,!0),r+=1):S.startsWith("### ")?c(S.slice(4),11,!0):S.trim()===""?r+=3:c(S,9)})}),t.save(`${m.clientName.replace(/\s+/g,"-")}-Website-Brief.pdf`),x.success("Brief exported as PDF!")},f=async t=>{var i;if(y){x.loading("Loading Brand DNA...",{id:"dna-export"});try{const{data:l}=await k.from("brand_dna").select("profile_data").eq("client_id",y).single(),n=l==null?void 0:l.profile_data;if(!n){x.error("No Brand DNA found",{id:"dna-export"});return}const r=JSON.stringify(n,null,2);if(t==="clipboard"){await navigator.clipboard.writeText(r),x.success("Brand DNA copied to clipboard!",{id:"dna-export"});return}const c=new Ge({orientation:"p",unit:"mm",format:"a4"}),d=15,g=180;let v=d;c.setFontSize(20),c.setFont("helvetica","bold"),c.text("Brand DNA Profile",d,v+10),c.setFontSize(11),c.setFont("helvetica","normal"),c.text((m==null?void 0:m.clientName)||"",d,v+18),c.text(new Date().toLocaleDateString(),d,v+24),v=d+34;const S=($,_=0)=>{if(!$||typeof $!="object")return;const O=Array.isArray($)?$.map((j,P)=>[String(P),j]):Object.entries($);for(const[j,P]of O){v>280&&(c.addPage(),v=d);const G=d+_*4;if(P&&typeof P=="object"){c.setFont("helvetica","bold"),c.setFontSize(_===0?12:10);const R=j.replace(/([A-Z])/g," $1").replace(/^./,U=>U.toUpperCase());c.text(R,G,v),v+=5,c.setFont("helvetica","normal"),S(P,_+1)}else{c.setFont("helvetica","normal"),c.setFontSize(9);const U=`${j.replace(/([A-Z])/g," $1").replace(/^./,A=>A.toUpperCase())}: ${String(P??"")}`,W=c.splitTextToSize(U,g-_*4);for(const A of W)v>280&&(c.addPage(),v=d),c.text(A,G,v),v+=4}}};S(n),c.save(`${((i=m==null?void 0:m.clientName)==null?void 0:i.replace(/\s+/g,"-"))||"Client"}-Brand-DNA.pdf`),x.success("Brand DNA exported as PDF!",{id:"dna-export"})}catch(l){x.error("Export failed: "+(l.message||"Unknown error"),{id:"dna-export"})}}},u=async()=>{var t;if(y){X(!0),oe("hero-concept"),x.loading("Scraping award-winning designs & generating hero concept... This takes 30-60 seconds.",{id:"hero-gen"});try{const{data:i,error:l}=await k.functions.invoke("generate-hero-concept",{body:{clientId:y}});if(l)throw l;if(i!=null&&i.error)throw new Error(i.error);const n=i.data,r=`# ⭐ HERO & FULL HOMEPAGE DESIGN CONCEPT
1963## Generated from Award-Winning Design Analysis
1964
1965> This concept was generated by analyzing ${n.heroCodeExamplesCount} award-winning hero sections from sites featured on Godly.website, Awwwards, and OnePageLove. The design has been tailored to your exact brand fonts, colors, and messaging.
1966
1967## Inspiration Sources Analyzed
1968${((t=n.gallerySources)==null?void 0:t.map(c=>{var d;return`### ${c.source}
1969Featured sites studied: ${((d=c.featuredLinks)==null?void 0:d.join(", "))||"N/A"}`}).join(`
1970
1971`))||"N/A"}
1972
1973---
1974
1975${n.heroConcept}
1976
1977---
1978
1979## How to Use This Concept
19801. **Copy the entire concept** and paste it into Claude, v0, or Lovable as your primary design brief
19812. **The HTML/CSS/JS code is production-ready** — paste it directly into your builder
19823. **The design direction covers every section** — use it as your visual North Star
19834. **Customize the copy** — replace placeholder text with the exact copy from the "Homepage Copy" section
19845. **Maintain the interactive elements** — parallax, custom cursor, and reactive elements are what make it award-worthy`;ue(c=>({...c,"hero-concept":r})),x.success("Hero concept generated! 🎨",{id:"hero-gen"})}catch(i){console.error("Hero gen error:",i),x.error(i.message||"Failed to generate hero concept",{id:"hero-gen"})}X(!1)}};if(H)return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background",children:e.jsx(he,{className:"w-6 h-6 animate-spin text-muted-foreground"})});if(!m)return e.jsx("div",{className:"min-h-screen flex items-center justify-center bg-background",children:e.jsx("p",{className:"text-muted-foreground",children:"No brand data found. Complete earlier steps first."})});const D=K.find(t=>t.key===T).icon;return e.jsxs("div",{className:"min-h-screen bg-background text-foreground",children:[e.jsx("div",{className:"border-b bg-card",children:e.jsx("div",{className:"max-w-7xl mx-auto px-6 py-4",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsxs(F,{variant:"ghost",size:"sm",onClick:()=>se(`/admin/client/${y}`),children:[e.jsx(mt,{className:"w-4 h-4 mr-1"})," Back"]}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-lg font-semibold",children:"Website Design Brief"}),e.jsxs("p",{className:"text-sm text-muted-foreground",children:["AI prompts for ",m.clientName]})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(F,{variant:"outline",size:"sm",onClick:()=>ie(),disabled:H,children:[H?e.jsx(he,{className:"w-4 h-4 mr-1 animate-spin"}):e.jsx(ut,{className:"w-4 h-4 mr-1"}),"Reload"]}),e.jsxs(tt,{children:[e.jsx(st,{asChild:!0,children:e.jsxs(F,{variant:"outline",size:"sm",children:[e.jsx(Le,{className:"w-4 h-4 mr-1"})," Export ",e.jsx(gt,{className:"w-3 h-3 ml-1"})]})}
1984),e.jsxs(ot,{align:"end",className:"w-56",children:[e.jsxs(pe,{onClick:ge,children:[e.jsx(Ye,{className:"w-4 h-4 mr-2"})," Copy All Brief to Clipboard"]}),e.jsxs(pe,{onClick:$e,children:[e.jsx(Le,{className:"w-4 h-4 mr-2"})," Download Brief as TXT"]}),e.jsxs(pe,{onClick:fe,children:[e.jsx(Ce,{className:"w-4 h-4 mr-2"})," Export Brief as PDF"]}),e.jsx(at,{}),e.jsxs(pe,{onClick:()=>f("clipboard"),children:[e.jsx(qe,{className:"w-4 h-4 mr-2"})," Copy Brand DNA to Clipboard"]}),e.jsxs(pe,{onClick:()=>f("pdf"),children:[e.jsx(qe,{className:"w-4 h-4 mr-2"})," Export Brand DNA as PDF"]})]})]})]})]})})}),e.jsx("div",{className:"max-w-7xl mx-auto px-6 py-6",children:e.jsxs("div",{className:"flex gap-6",children:[e.jsx("div",{className:"w-64 shrink-0",children:e.jsxs("div",{className:"sticky top-6 space-y-1",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3",children:"Brief Sections"}),K.map(t=>{const i=t.icon;return e.jsxs("button",{onClick:()=>oe(t.key),className:`w-full flex items-center gap-2.5 px-3 py-2 rounded-md text-left text-sm transition-colors ${T===t.key?"bg-primary text-primary-foreground":"text-muted-foreground hover:bg-muted hover:text-foreground"}`,children:[e.jsx(i,{className:"w-4 h-4 shrink-0"}),e.jsx("span",{className:"truncate",children:t.title})]},t.key)}),e.jsxs("div",{className:"mt-6 p-3 rounded-md bg-muted/50 text-xs space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 text-muted-foreground",children:[e.jsx(Te,{className:"w-3.5 h-3.5"}),K.length," detailed sections"]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-muted-foreground",children:[e.jsx(Ze,{className:"w-3.5 h-3.5"}),Object.keys(m.colors).length," brand colors"]}),e.jsxs("div",{className:"flex items-center gap-1.5 text-muted-foreground",children:[e.jsx(Ce,{className:"w-3.5 h-3.5"}),m.homepageSections.length," copy sections"]})]})]})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between mb-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"w-10 h-10 rounded-md bg-primary/10 flex items-center justify-center",children:e.jsx(D,{className:"w-5 h-5 text-primary"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold",children:K.find(t=>t.key===T).title}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Copy this prompt to guide website generation"})]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[T==="hero-concept"&&e.jsx(F,{size:"sm",onClick:u,disabled:ne,className:"bg-gradient-to-r from-primary to-primary/80",children:ne?e.jsxs(e.Fragment,{children:[e.jsx(he,{className:"w-4 h-4 mr-1 animate-spin"})," Generating..."]}):e.jsxs(e.Fragment,{children:[e.jsx(ft,{className:"w-4 h-4 mr-1"})," Generate Hero Concept"]})}),e.jsx(F,{variant:"outline",size:"sm",onClick:()=>Ae(T),children:me===T?e.jsxs(e.Fragment,{children:[e.jsx(Te,{className:"w-4 h-4 mr-1 text-green-600"})," Copied!"]}):e.jsxs(e.Fragment,{children:[e.jsx(Ve,{className:"w-4 h-4 mr-1"})," Copy Section"]})})]})]}),e.jsx("div",{className:"rounded-lg border bg-card overflow-hidden",children:e.jsx("pre",{className:"p-6 text-sm leading-relaxed whitespace-pre-wrap font-mono text-foreground/90 max-h-[70vh] overflow-y-auto",children:z[T]||"Loading..."})}),T==="design-system"&&Object.keys(m.colors).length>0&&e.jsxs("div",{className:"mt-4 p-4 rounded-lg border bg-card",children:[e.jsx("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3",children:"Color Preview"}),e.jsx("div",{className:"flex gap-3 flex-wrap",children:Object.values(m.colors).map((t,i)=>e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"w-8 h-8 rounded-md border",style:{backgroundColor:t.hex}}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs font-medium",children:t.name}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:t.hex})]})]},i))})]}),T==="imagery-graphics"&&J.length>0&&e.jsxs("div",{className:"mt-4 p-4 rounded-lg border bg-card",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("p",{className:"text-xs font-medium text-muted-foreground uppercase tracking-wider",children:["Client Media Assets (",J.length,")"]}),e.jsxs(F,{variant:"outline",size:"sm",onClick:async()=>{const t=await Promise.all(J.map(async i=>{const{data:l}=await k.storage.from("client-media").createSignedUrl(i.file_path,3600);return(l==null?void 0:l.signedUrl)||""}));await navigator.clipboard.writeText(t.filter(Boolean).join(`
1985`)),x.success("All media URLs copied to clipboard!")},children:[e.jsx(Ye,{className:"w-3.5 h-3.5 mr-1"})," Copy All URLs"]})]}),e.jsx("div",{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3",children:J.map(t=>{var l;const i=(l=t.file_type)==null?void 0:l.startsWith("image/");return e.jsxs("div",{className:"group relative rounded-md border bg-muted/30 overflow-hidden",children:[i?e.jsx(wt,{filePath:t.file_path,fileName:t.file_name}):e.jsx("div",{className:"aspect-square flex items-center justify-center",children:e.jsx(Ce,{className:"w-8 h-8 text-muted-foreground"})}),e.jsxs("div",{className:"p-2",children:[e.jsx("p",{className:"text-[10px] text-muted-foreground truncate",children:t.file_name}),t.category&&e.jsx("p",{className:"text-[9px] text-muted-foreground
1985/60",children:t.category})]}),e.jsxs("div",{className:"absolute top-1 right-1 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity",children:[e.jsx("button",{className:"p-1 rounded bg-background/80 hover:bg-background shadow-sm",title:"Copy URL",onClick:async()=>{const{data:n}=await k.storage.from("client-media").createSignedUrl(t.file_path,3600);n!=null&&n.signedUrl&&(await navigator.clipboard.writeText(n.signedUrl),x.success("URL copied!"))},children:e.jsx(Ve,{className:"w-3 h-3"})}),e.jsx("button",{className:"p-1 rounded bg-background/80 hover:bg-background shadow-sm",title:"Download",onClick:async()=>{const{data:n}=await k.storage.from("client-media").createSignedUrl(t.file_path,3600);if(n!=null&&n.signedUrl){const r=document.createElement("a");r.href=n.signedUrl,r.download=t.file_name,r.click()}},children:e.jsx(Le,{className:"w-3 h-3"})})]})]},t.id)})})]}),e.jsx(xt,{clientId:y,clientName:m.clientName}),e.jsxs("div",{className:"mt-4 p-4 rounded-lg border bg-muted/30",children:[e.jsx("p",{className:"text-xs font-medium mb-2",children:"How to use"}),e.jsxs("ul",{className:"text-xs text-muted-foreground space-y-1 list-disc list-inside",children:[e.jsx("li",{children:"Copy each section and feed to your AI website builder (Claude, GPT, v0.dev, Lovable)"}),e.jsx("li",{children:'Start with "Brand Identity" to ground the AI in who the client is'}),e.jsx("li",{children:'Use "Homepage Copy" for exact text — no improvisation needed'}),e.jsx("li",{children:'Download client media from "Imagery" section for real assets'}),e.jsx("li",{children:"Iterate section by section for best results"})]})]})]})]})})]})}export{ts as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.