1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[1812],{38253:(e,t,s)=>{"use strict";s.r(t),s.d(t,{default:()=>_});var a=s(33499),n=s(65235),r=s(71694),i=s(17369),l=s(68644),o=s(74730),d=s(6615),c=s(61528),m=s(37729),u=s(95332),x=s(12918),h=s(95400),p=s(94524),g=s(6077),f=s(34346),b=s(97095),y=s(61049),w=s(65423),v=s(17554),j=s(63151),N=s(45773),M=s(59255),k=s(30982),A=s(88665);let F=[{value:"floor",label:"General / Floor",alignmentType:"floor"},{value:"sunglasses",label:"Sunglasses / Eyewear",alignmentType:"floor"},{value:"wall",label:"Wall-Mounted",alignmentType:"wall"},{value:"ceiling",label:"Ceiling-Mounted",alignmentType:"ceiling"},{value:"shoes",label:"Footwear",alignmentType:"floor"}],T=[{id:"syntax",name:"Syntax & Formatting",status:"pending",message:"Checks for structural GLTF errors and unsupported extensions."},{id:"poly",name:"Poly Count",status:"pending",message:"Amazon hard limit: 200K triangles. Aim for < 100K on simple products."},{id:"nodes",name:"Node Count",status:"pending",message:"No cameras, lights, or modifiers. Aim for ⤠30 scene nodes."},{id:"size",name:"File Size",status:"pending",message:"Limit: 100MB (< 5MB recommended for mobile performance)."},{id:"grounded",name:"Alignment & Origin",status:"pending",message:"Model must be correctly aligned for its product type."},{id:"maps",name:"Required Maps",status:"pending",message:"BaseColour, Metallic, Roughness required. All PBR metal-rough."},{id:"scale",name:"Real-World Scale",status:"pending",message:"1 unit = 1 meter. Dimensions must match the assembled product."},{id:"textures",name:"Textures Check",status:"pending",message:"2Kâ4K, square, power-of-two. One texture atlas (0â1 UV space)."},{id:"uv_channels",name:"UV Channels",status:"pending",message:"Max 2 UV sets. All UVs must stay within the 0â1 UV space."},{id:"animations",name:"No Animations / Cameras / Lights",status:"pending",message:"Scene must be static. No keyframes, cameras, or lights."}],L=[{id:"eyewear_nodes",name:"Eyewear Node Names",status:"pending",message:"Required: Frame, TempleR, TempleL, LensR + LensL (or Lens for continuous)."},{id:"eyewear_transmission",name:"Lens Transmission Extension",status:"pending",message:"Lenses must use KHR_materials_transmission, not basic alpha transparency."}],z=e=>[...T,..."sunglasses"===e?L:[]],R=[{id:"materials",label:"Materials & Transparency",description:"No Z-fighting, correct alpha mode (Opaque/Blend/Mask), no backface issues on double-sided materials."},{id:"no_shadows",label:"No Baked Shadows",description:"Textures have no painted-on shadows or ambient occlusion baked into the base colour."},{id:"no_zfighting",label:"No Z-Fighting in Viewer",description:"Visually confirmed. no flickering or striped polygon overlap in the 3D viewer."},{id:"gltf_validator",label:"Khronos glTF Validator",description:"The official industry 'Grammar Check' has been run with zero errors.",link:{href:"https://github.khronos.org/glTF-Validator/",text:"Open Validator â"}},{id:"uv_overlap",label:"UV Map. No Overlapping UVs",description:"All UV islands within 0â1 UV space with no overlapping. Maximise UV space usage."},{id:"no_hidden_geo",label:"No Hidden / Duplicate Geometry",description:"No invisible meshes, duplicate faces, or geometry hidden inside the model."},{id:"normal_direction",label:"Correct Normal Direction",description:"All face normals point outward (blue in Blender's Face Orientation overlay). No dark or see-through patches."},{id:"eyewear_roughness",label:"Lens Roughness: 0 or 1 Only",description:"Amazon only supports lens roughness of exactly 0 (mirror) or 1 (frosted). In-between values are not rendered correctly in the AR viewer.",productTypes:["sunglasses"]},{id:"eyewear_alpha",label:"Lens alphaMode = OPAQUE",description:"When using KHR_materials_transmission, alphaMode must be 'OPAQUE' and transmissionFactor must be in the (0, 1] range.",productTypes:["sunglasses"]},{id:"eyewear_pivot",label:"Pivot at Nose Bridge Centre",description:"The model pivot (0,0,0) must sit at the centre of the eyewear bridge. not the geometric centre of the full frame.",productTypes:["sunglasses"]},{id:"eyewear_orientation",label:"Eyewear Axis Orientation",description:"Lenses face +Z. Top of frame aligns with +Y. Side aligns with \xb1X. Uses floor alignment: Y=0 at the bottom of the temples.",productTypes:["sunglasses"]}
1,{id:"wall_alignment",label:"Wall Alignment Verified",description:"Model backside is flush with the XY plane (Z=0). All geometry extends into +Z. Centred on X and Y axes. Pivot at 0,0,0.",productTypes:["wall"]},{id:"ceiling_alignment",label:"Ceiling Alignment Verified",description:"Model hangs from Y=0. All geometry extends into âY space. Centred on X and Z axes. Pivot at 0,0,0.",productTypes:["ceiling"]},{id:"shoes_toes",label:"Toes Face +Z Direction",description:"The front of the shoe (toe cap) points toward +Z. Sole rests at Y=0 (floor alignment). Side aligns with \xb1X.",productTypes:["shoes"]}],_=()=>{let[e,t]=(0,n.useState)(null),[s,T]=(0,n.useState)(null),[L,_]=(0,n.useState)(!1),[C,S]=(0,n.useState)("floor"),[E,O]=(0,n.useState)(()=>z("floor")),[U,P]=(0,n.useState)(new Set),[V,B]=(0,n.useState)(!1),[Z,D]=(0,n.useState)(!0),Y=(0,n.useRef)(Z),q=(0,n.useRef)(null);(0,n.useEffect)(()=>{Y.current=Z},[Z]),(0,n.useEffect)(()=>()=>{s&&URL.revokeObjectURL(s)},[s]),(0,n.useEffect)(()=>{if(!s||L)return;let e=!1,t=null,a=requestAnimationFrame(()=>{if(e)return;let s=document.querySelector("model-viewer");if(!s)return;let a=()=>{if(e)return;let a=1;try{let e=s.getDimensions();a=2*Math.max(e.x,e.y,e.z)}catch(e){}let n=(e=>{let t=e;for(;t&&t!==HTMLElement.prototype;){for(let s of Object.getOwnPropertySymbols(t))try{let t=e[s];if(t&&"object"==typeof t&&t.isScene)return t}catch(e){}t=Object.getPrototypeOf(t)}return null})(s);if(!n)return;let i=new r.YJl;i.name="__axis_lines__",i.visible=Y.current;let l=(e,t)=>{let s=new r.LoY().setFromPoints([e.clone().multiplyScalar(-a),e.clone().multiplyScalar(a)]),n=new r.mrM({color:t,depthTest:!0});return new r.N1A(s,n)};i.add(l(new r.Pq0(1,0,0),0xef4444)),i.add(l(new r.Pq0(0,1,0),2278750)),i.add(l(new r.Pq0(0,0,1),3900150));let o=n.model||n;o.add(i),t=o,q.current=i};s.loaded?a():s.addEventListener("load",a,{once:!0})});return()=>{e=!0,cancelAnimationFrame(a);let s=q.current;s&&t&&(t.remove(s),s.traverse(e=>{e.geometry&&e.geometry.dispose(),e.material&&e.material.dispose()}),q.current=null)}},[s,L]),(0,n.useEffect)(()=>{q.current&&(q.current.visible=Z)},[Z]);let X=(0,n.useCallback)(t=>{S(t),O(z(t)),e&&B(!0)},[e]),K=(0,n.useCallback)(()=>{t(null),s&&URL.revokeObjectURL(s),T(null),O(z(C)),_(!1),B(!1)},[s,C]),G=(0,n.useCallback)((e,t,s)=>{O(a=>a.map(a=>a.id===e?{...a,status:t,message:s}:a))},[]),H=(0,n.useCallback)(e=>{P(t=>{let s=new Set(t);return s.has(e)?s.delete(e):s.add(e),s})},[]),W=(0,n.useCallback)(async e=>{if(!e.name.toLowerCase().endsWith(".glb"))return void alert("Please upload a .glb file.");t(e),s&&URL.revokeObjectURL(s),T(URL.createObjectURL(e)),_(!0),B(!1),O(z(C));let a=(F.find(e=>e.value===C)||F[0]).alignmentType;try{let t=await e.arrayBuffer(),s=e.size/1048576;s>100?G("size","failing","".concat(s.toFixed(2),"MB. exceeds Amazon's 100MB limit.")):s>5?G("size","warning","".concat(s.toFixed(2),"MB. Amazon recommends < 5MB for optimal mobile ranking.")):G("size","passing","".concat(s.toFixed(2),"MB. Optimal for mobile performance."));let n=await o.q3(new Uint8Array(t)),d=n.issues.numErrors>0,c=new TextDecoder().decode(t),m=/KHR_materials_pbrSpecularGlossiness/i.test(c),u=d?"failing":"passing",x=d?"Found ".concat(n.issues.numErrors," error(s). Run the Khronos Validator for details."):"No structural errors. glTF 2.0 Core spec compliant.";m&&(u="failing",x='KHR_materials_pbrSpecularGlossiness found. not supported by Amazon. Re-export using the standard PBR metallic/roughness workflow to fix "Invisible Model" errors.'),G("syntax",u,x);let h=new i.B,p=new l.Z;p.setDecoderPath("https://www.gstatic.com/draco/versioned/decoders/1.5.6/"),h.setDRACOLoader(p),h.parse(t,"",e=>{var t,s;let n=0,i=0,l=!0,o=!0,d="All textures valid. Ensure labels have dedicated UV padding.",m=0,u=new Set,x=!1;e.scene.traverse(e=>{var t,s;if(i++,(null==(t=e.name)?void 0:t.trim())&&u.add(e.name.trim()),(e.type.endsWith("Camera")||e.type.endsWith("Light"))&&(x=!0),e.isMesh){if((null==(s=e.geometry)?void 0:s.attributes.position)&&(n+=e.geometry.attributes.position.count/3),e.geometry){let t=0;e.geometry.attributes.uv&&t++,(e.geometry.attributes.uv2||e.geometry.attributes.uv1)&&t++;for(let s=3;s<=8;s++)e.geometry.attributes["uv".concat(s)]&&t++;m=Math.max(m,t)}
1(Array.isArray(e.material)?e.material:[e.material]).forEach(e=>{for(let t in"MeshStandardMaterial"!==e.type&&"MeshPhysicalMaterial"!==e.type&&(l=!1),e){let s=e[t];if(s&&"object"==typeof s&&"isTexture"in s&&"image"in s&&s.image){let e=s.image,t=e.width||0,a=e.height||0;(t>4096||a>4096||t<2048||a<2048)&&(o=!1,d="Texture ".concat(t,"\xd7").concat(a,"px found. Must be 2Kâ4K, square, power-of-two."))}}})}}),n>2e5?G("poly","failing","".concat(Math.round(n).toLocaleString()," triangles. exceeds Amazon's 200K hard limit. Decimate in Blender.")):n>1e5?G("poly","warning","".concat(Math.round(n).toLocaleString()," triangles. Approaching the 200K limit. Acceptable for complex products.")):n>3e4?G("poly","passing","".concat(Math.round(n).toLocaleString()," triangles. Good. aim for < 30K on simple products.")):G("poly","passing","".concat(Math.round(n).toLocaleString()," triangles. Excellent optimization.")),i>30?G("nodes","failing","".concat(i," nodes. Amazon recommends ⤠30. Merge meshes (Ctrl+J in Blender) or flatten the scene hierarchy.")):G("nodes","passing","".concat(i," nodes. Within the recommended limit."));let h=new r.NRn().setFromObject(e.scene),g=new r.Pq0;if(h.getCenter(g),"floor"===a){let e=.001>Math.abs(h.min.y),t=.001>Math.abs(g.x)&&.001>Math.abs(g.z);if(e&&t)G("grounded","passing","Floor-aligned. X=".concat(g.x.toFixed(4),"m, Y(min)=").concat(h.min.y.toFixed(4),"m, Z=").concat(g.z.toFixed(4),"m"));else{let t=[];e||t.push(h.min.y>0?"Y(min)=".concat(h.min.y.toFixed(4),"m. Floating above floor. Move down ").concat(Math.abs(h.min.y).toFixed(4),"m (âY)."):"Y(min)=".concat(h.min.y.toFixed(4),"m. Sunk below floor. Move up ").concat(Math.abs(h.min.y).toFixed(4),"m (+Y).")),Math.abs(g.x)>=.001&&t.push(g.x>0?"X=".concat(g.x.toFixed(4),"m. Offset right. Move left ").concat(Math.abs(g.x).toFixed(4),"m (âX)."):"X=".concat(g.x.toFixed(4),"m. Offset left. Move right ").concat(Math.abs(g.x).toFixed(4),"m (+X).")),Math.abs(g.z)>=.001&&t.push(g.z>0?"Z=".concat(g.z.toFixed(4),"m. Offset forward. Move back ").concat(Math.abs(g.z).toFixed(4),"m (âZ)."):"Z=".concat(g.z.toFixed(4),"m. Offset backward. Move forward ").concat(Math.abs(g.z).toFixed(4),"m (+Z).")),G("grounded","warning",t.join(" | "))}}else if("wall"===a){let e=.001>Math.abs(h.min.z),t=.001>Math.abs(g.x)&&.001>Math.abs(g.y);if(e&&t)G("grounded","passing","Wall-aligned. Z(min)=".concat(h.min.z.toFixed(4),"m, X=").concat(g.x.toFixed(4),"m, Y=").concat(g.y.toFixed(4),"m"));else{let t=[];e||t.push(h.min.z>0?"Z(min)=".concat(h.min.z.toFixed(4),"m. Gap from wall. Move forward ").concat(Math.abs(h.min.z).toFixed(4),"m (âZ)."):"Z(min)=".concat(h.min.z.toFixed(4),"m. Backside behind Z=0. Move toward wall ").concat(Math.abs(h.min.z).toFixed(4),"m (+Z).")),Math.abs(g.x)>=.001&&t.push(g.x>0?"X=".concat(g.x.toFixed(4),"m. Off-centre right. Move left ").concat(Math.abs(g.x).toFixed(4),"m (âX)."):"X=".concat(g.x.toFixed(4),"m. Off-centre left. Move right ").concat(Math.abs(g.x).toFixed(4),"m (+X).")),Math.abs(g.y)>=.001&&t.push(g.y>0?"Y=".concat(g.y.toFixed(4),"m. Off-centre up. Move down ").concat(Math.abs(g.y).toFixed(4),"m (âY)."):"Y=".concat(g.y.toFixed(4),"m. Off-centre down. Move up ").concat(Math.abs(g.y).toFixed(4),"m (+Y).")),G("grounded","warning",t.join(" | "))}}else if("ceiling"===a){let e=.001>Math.abs(h.max.y),t=.001>Math.abs(g.x)&&.001>Math.abs(g.z);if(e&&t)G("grounded","passing","Ceiling-aligned. Y(max)=".concat(h.max.y.toFixed(4),"m, X=").concat(g.x.toFixed(4),"m, Z=").concat(g.z.toFixed(4),"m"));else{let t=[];e||t.push(h.max.y>0?"Y(max)=".concat(h.max.y.toFixed(4),"m. Top extends above ceiling. Move down ").concat(Math.abs(h.max.y).toFixed(4),"m (âY)."):"Y(max)=".concat(h.max.y.toFixed(4),"m. Gap from ceiling. Move up ").concat(Math.abs(h.max.y).toFixed(4),"m (+Y).")),Math.abs(g.x)>=.001&&t.push(g.x>0?"X=".concat(g.x.toFixed(4),"m. Off-centre right. Move left ").concat(Math.abs(g.x).toFixed(4),"m (âX)."):"X=".concat(g.x.toFixed(4),"m. Off-centre left. Move right ").concat(Math.abs(g.x).toFixed(4),"m (+X).")),Math.abs(g.z)>=.001&&t.push(g.z>0?"Z=".concat(g.z.toFixed(4),"m. Offset forward. Move back ").concat(Math.abs(g.z).toFixed(4),"m (âZ)."):"Z=".concat(g.z.toFixed(4),"m. Offset backward. Move forward ").concat(Math.abs(g.z).toFixed(4),"m (+Z).")),G("grounded","warning",t.join(" | "))}}G("maps",l?"passing":"failing",l?"All PBR metal-rough materials. Flat metallic/roughness values are accepted.":"Non-PBR material found (e.g. Unlit/Lambert). Amazon requires standard PBR metallic-roughness shading."),G("textures",o?"passing":"failing",d);let f=new r.Pq0;h.getSize(f);let b=Math.max(f.x,f.y,f.z),y="".concat(f.x.toFixed(2),"m \xd7 ").concat(f.y.toFixed(2),"m \xd7 ").concat(f.z.toFixed(2),"m.");b>5||b<.05?G("scale","warning","".concat(y," Unusually large or small. verify dimensions match the real product.")):G("scale","passing",y),m>2?G("uv_channels","failing","".concat(m," UV sets found. Amazon allows max 2. Remove extra UV maps in Blender's UV editor.")):G("uv_channels","passing",m<=1?"1 UV set. Within Amazon's limit.":"2 UV sets. Within Amazon's limit.");let w=null!=(s=null==(t=e.animations)?void 0:t.length)?s:0;if(w>0||x){let e=[];w>0&&e.push("".concat(w," animation(s)")),x&&e.push("cameras or lights"),G("animations","warning","Found ".concat(e.join(" and "),". Amazon requires a static sce
1ne. Remove in Blender's Dope Sheet / Outliner."))}else G("animations","passing","No animations, cameras, or lights. Scene is static.");if("sunglasses"===C){let e=u.has("LensR")&&u.has("LensL"),t=u.has("Lens"),s=e||t,a=["Frame","TempleR","TempleL"].filter(e=>!u.has(e));if(0===a.length&&s)G("eyewear_nodes","passing","All required nodes found: Frame, TempleR, TempleL, ".concat(e?"LensR, LensL":"Lens (continuous)","."));else{let e=[...a];s||e.push("LensR + LensL (or Lens for continuous)");let t=Array.from(u).filter(e=>["Frame","TempleR","TempleL","LensR","LensL","Lens"].includes(e));G("eyewear_nodes","failing","Missing required nodes: ".concat(e.join(", "),". ")+(t.length>0?"Found: ".concat(t.join(", "),"."):"No eyewear nodes found.")+" Split the mesh and name each part: Frame, TempleR, TempleL, LensR, LensL.")}let n=/KHR_materials_transmission/i.test(c);G("eyewear_transmission",n?"passing":"failing",n?"KHR_materials_transmission found. Lenses will render correctly in AR.":"KHR_materials_transmission not found. Required for lens materials. do not use basic alpha transparency. In Blender: Material Properties > glTF Extensions > Transmission.")}p.dispose(),_(!1)},e=>{console.error("Error parsing GLTF",e);let t=e instanceof Error?e.message:"Failed to parse 3D data.";O(e=>e.map(e=>"pending"===e.status?{...e,status:"failing",message:"poly"===e.id?"Parse Error: ".concat(t):"Skipped due to parse error."}:e)),p.dispose(),_(!1)})}catch(t){console.error("Validation error",t);let e=t instanceof Error?t.message:"Exception occurred.";O(t=>t.map(t=>"pending"===t.status?{...t,status:"failing",message:"Exception: ".concat(e)}:t)),_(!1)}},[s,G,C]),I=(0,n.useCallback)(e=>{e.preventDefault();let t=e.dataTransfer.files[0];t&&W(t)},[W]),Q=E.filter(e=>"passing"===e.status).length,J=E.filter(e=>"failing"===e.status).length,$=E.filter(e=>"warning"===e.status).length,ee=R.filter(e=>!e.productTypes||e.productTypes.includes(C)),et=ee.filter(e=>U.has(e.id)).length;return(0,a.jsxs)("div",{className:"max-w-6xl mx-auto p-6 space-y-8",children:[(0,a.jsxs)("div",{className:"text-center space-y-2",children:[(0,a.jsx)("h1",{className:"text-3xl font-bold tracking-tight text-text",children:"Amazon 3D Model Checker"}),(0,a.jsx)("p",{className:"text-muted",children:"Upload a .glb file to verify compliance with Amazon QA standards."})]}),(0,a.jsxs)("div",{className:"flex items-center gap-3 flex-wrap",children:[(0,a.jsx)("span",{className:"text-sm font-medium text-text whitespace-nowrap",children:"Product Type:"}),F.map(e=>(0,a.jsxs)("button",{onClick:()=>X(e.value),className:"flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors ".concat(C===e.value?"bg-primary text-white":"bg-muted/10 text-muted hover:bg-primary/10 hover:text-primary border border-border/50"),children:["sunglasses"===e.value&&(0,a.jsx)(d.A,{className:"w-3.5 h-3.5 shrink-0"}),e.label]},e.value))]}),(0,a.jsxs)("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-8",children:[(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between",children:[(0,a.jsx)("h2",{className:"text-xl font-semibold text-text",children:e?"Model Preview":"Upload Model"}),e&&(0,a.jsxs)("button",{onClick:K,className:"text-sm font-medium text-primary hover:text-primary/80 transition-colors flex items-center gap-2 bg-primary/10 px-3 py-1.5 rounded-md",children:[(0,a.jsx)(c.A,{className:"w-4 h-4"})," Upload New Model"]})]}),e?(0,a.jsxs)("div",{className:"w-full aspect-square rounded-xl overflow-hidden border border-border bg-muted/10 relative",children:[L&&(0,a.jsxs)("div",{className:"absolute inset-0 flex flex-col items-center justify-center bg-background/80 backdrop-blur-sm z-10 space-y-4",children:[(0,a.jsx)(m.A,{className:"w-10 h-10 animate-spin text-primary"}),(0,a.jsx)("p",{className:"text-sm font-medium text-text",children:"Analyzing Model..."})]}),s&&!L&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(A.A,{}),(0,a.jsx)("model-viewer",{src:s,alt:"GLB Preview","auto-rotate":!0,"camera-controls":!0,ar:!0,style:{width:"100%",height:"100%"},className:"w-full h-full",children:(0,a.jsx)("div",{slot:"poster",className:"absolute inset-0 flex items-center justify-center",children:(0,a.jsx)(m.A,{className:"w-10 h-10 animate-spin text-primary"})})}),(0,a.jsxs)("div",{className:"absolute bottom-3 left-3 flex gap-1.5 z-10 pointer-events-none",children:[Q>0&&(0,a.jsxs)("span",{className:"flex items-center gap-1 bg-green-600/90 backdrop-blur-sm text-white text-xs font-semibold px-2 py-1 rounded-md",children:[(0,a.jsx)(u.A,{className:"w-3 h-3"}),Q," passing"]}),$>0&&(0,a.jsxs)("span",{className:"flex items-center gap-1 bg-yellow-500/90 backdrop-blur-sm text-white text-xs font-semibold px-2 py-1 rounded-md",children:[(0,a.jsx)(x.A,{className:"w-3 h-3"}),$," warning",$>1?"s":""]}),J>0&&(0,a.jsxs)("span",{className:"flex items-center gap-1 bg-red-600/90 backdrop-blur-sm text-white text-xs font-semibold px-2 py-1 rounded-md",children:[(0,a.jsx)(h.A,{className:"w-3 h-3"}),J," failing"]})]})]})]}):(0,a.jsxs)("div",{onDragOver:e=>e.preventDefault(),onDrop:I,className:"w-full aspect-square border-2 border-dashed rounded-xl flex flex-col items-center justify-center text-center transition-colors cursor-pointer border-border/50 hover:border-primary/50 hover:bg-primary/5",onClick:()=>{var e;
1return null==(e=document.getElementById("file-upload"))?void 0:e.click()},children:[(0,a.jsx)("input",{id:"file-upload",type:"file",accept:".glb",className:"hidden",onChange:e=>{var t;return(null==(t=e.target.files)?void 0:t[0])&&W(e.target.files[0])}}),(0,a.jsxs)("div",{className:"flex flex-col items-center gap-4 p-8",children:[(0,a.jsx)("div",{className:"w-16 h-16 rounded-full bg-primary/10 flex items-center justify-center",children:L?(0,a.jsx)(m.A,{className:"w-8 h-8 text-primary animate-spin"}):(0,a.jsx)(c.A,{className:"w-8 h-8 text-primary"})}),(0,a.jsxs)("div",{children:[(0,a.jsx)("p",{className:"text-lg font-medium text-text",children:"Click or drag GLB here"}),(0,a.jsx)("p",{className:"text-sm text-muted",children:"Supporting .glb files only"})]})]})]}),e&&(0,a.jsxs)("button",{onClick:()=>D(e=>!e),className:"text-sm font-medium transition-colors flex items-center gap-2 px-3 py-1.5 rounded-md ".concat(Z?"text-primary bg-primary/10":"text-muted bg-muted/10 hover:bg-primary/10 hover:text-primary"),children:[(0,a.jsx)(p.A,{className:"w-4 h-4"})," ",Z?"Hide":"Show"," Axes"]})]}),(0,a.jsxs)("div",{className:"space-y-4",children:[(0,a.jsx)("h2",{className:"text-xl font-semibold text-text",children:"Validation Results"}),V&&e&&(0,a.jsxs)("div",{className:"flex items-center gap-3 p-3 rounded-lg bg-yellow-500/10 border border-yellow-500/30",children:[(0,a.jsx)(x.A,{className:"w-4 h-4 text-yellow-500 shrink-0"}),(0,a.jsx)("p",{className:"text-xs text-amber-700 dark:text-yellow-500 flex-1",children:"Product type changed. re-run to update validation."}),(0,a.jsxs)("button",{onClick:()=>{B(!1),W(e)},className:"flex items-center gap-1.5 text-xs font-semibold text-white bg-yellow-500 hover:bg-yellow-600 px-2.5 py-1.5 rounded-md transition-colors shrink-0",children:[(0,a.jsx)(g.A,{className:"w-3.5 h-3.5"})," Re-run"]})]}),(0,a.jsx)("div",{className:"grid grid-cols-1 gap-3",children:E.map(e=>(0,a.jsxs)("div",{className:"p-4 rounded-lg border border-border bg-card-bg flex items-start gap-4 transition-all",children:[(0,a.jsxs)("div",{className:"mt-1 shrink-0",children:["passing"===e.status&&(0,a.jsx)(u.A,{className:"w-5 h-5 text-green-500"}),"failing"===e.status&&(0,a.jsx)(h.A,{className:"w-5 h-5 text-red-500"}),"warning"===e.status&&(0,a.jsx)(x.A,{className:"w-5 h-5 text-yellow-500"}),"pending"===e.status&&(0,a.jsx)(f.A,{className:"w-5 h-5 text-muted/50"})]}),(0,a.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,a.jsxs)("p",{className:"font-semibold text-sm flex items-center gap-2 ".concat("warning"===e.status?"text-amber-700 dark:text-yellow-400":"text-text"),children:["syntax"===e.id&&(0,a.jsx)(b.A,{className:"w-4 h-4 shrink-0"}),"poly"===e.id&&(0,a.jsx)(y.A,{className:"w-4 h-4 shrink-0"}),"nodes"===e.id&&(0,a.jsx)(w.A,{className:"w-4 h-4 shrink-0"}),"size"===e.id&&(0,a.jsx)(b.A,{className:"w-4 h-4 shrink-0"}),"grounded"===e.id&&(0,a.jsx)(p.A,{className:"w-4 h-4 shrink-0"}),"maps"===e.id&&(0,a.jsx)(b.A,{className:"w-4 h-4 shrink-0"}),"scale"===e.id&&(0,a.jsx)(p.A,{className:"w-4 h-4 shrink-0"}),"textures"===e.id&&(0,a.jsx)(v.A,{className:"w-4 h-4 shrink-0"}),"uv_channels"===e.id&&(0,a.jsx)(w.A,{className:"w-4 h-4 shrink-0"}),"animations"===e.id&&(0,a.jsx)(j.A,{className:"w-4 h-4 shrink-0"}),"eyewear_nodes"===e.id&&(0,a.jsx)(d.A,{className:"w-4 h-4 shrink-0"}),"eyewear_transmission"===e.id&&(0,a.jsx)(d.A,{className:"w-4 h-4 shrink-0"}),e.name]}),(0,a.jsx)("p",{className:"text-xs mt-0.5 ".concat("warning"===e.status?"text-amber-700/80 dark:text-yellow-400/80":"text-muted"),children:e.message})]})]},e.id))})]})]}),(0,a.jsxs)("div",{className:"border border-border/50 rounded-xl p-6 space-y-4 bg-muted/5",children:[(0,a.jsxs)("div",{className:"flex items-center justify-between flex-wrap gap-2",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2",children:[(0,a.jsx)(N.A,{className:"w-5 h-5 text-primary"}),(0,a.jsx)("h2",{className:"text-lg font-semibold text-text",children:"Manual QA Checklist"})]}),(0,a.jsxs)("span",{className:"text-sm font-medium px-2.5 py-1 rounded-full ".concat(et===ee.length&&et>0?"bg-green-500/10 text-green-500":"bg-muted/10 text-muted"),children:[et,"/",ee.length," checked"]})]}),(0,a.jsx)("p",{className:"text-sm text-muted",children:"These items require visual or manual inspection that can't be automated. Tick each one off before submitting."}),(0,a.jsx)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:ee.map(e=>{var t,s;let n=U.has(e.id);return(0,a.jsxs)("div",{onClick:()=>H(e.id),className:"flex items-start gap-3 p-3 rounded-lg border cursor-pointer transition-all ".concat(n?"border-primary/50 bg-primary/5":"border-border/50 hover:border-primary/30 hover:bg-primary/5"),children:[(0,a.jsx)("div",{className:"mt-0.5 shrink-0",children:n?(0,a.jsx)(M.A,{className:"w-5 h-5 text-primary"}):(0,a.jsx)(k.A,{className:"w-5 h-5 text-muted/40"})}),(0,a.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,a.jsxs)("p",{className:"text-sm font-medium ".concat(n?"text-primary":"text-text"),children:[e.label,e.productTypes&&(0,a.jsx)("span",{className:"ml-2 text-xs bg-primary/10 text-primary px-1.5 py-0.5 rounded font-normal",children:null!=(s=null==(t=F.find(t=>{var s;return t.value===(null==(s=e.productTypes)?void 0:s[0])}))?void 0:t.label)?s:e.productTypes[0]})]}),(0,a.jsx)("p",{className:"text-xs text-muted mt-0.5",children:e.description}),e.link&&(0,a.jsx)("a",{href:e.link.href,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-primary hover:underline mt-1 inline-block",onClick:e=>e.stopPropagation(),children:e.link.text})]})]},e.id)})})]}),(0,a.jsxs)("div",{className:"pt-12 border-t border-border/20 space-y-8",children:[(0,a.jsxs)("div",{className:"bg-muted/5 border border-border/50 rounded-xl p-6 space-y-4",children:[(0,a.jsx)("h2",{className:"text-lg font-semibold text-text",children:"How to use this pre-flight tool:"}),(0,a.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-6",children:[(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 font-medium text-text",children:[(0,a.jsx)("span",{className:"flex items-center justify-center w-6 h-6 rounded-full bg-primary/10 text-primary text-xs",children:"1"}),"Set Product Type"]}),(0,a.jsx)("p",{className:"text-sm text-muted leading-relaxed",children:"Select your product type above. Different categories have different alignment, node, and material requirements. This changes which checks run and what thresholds apply."})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 font-medium text-text",children:[(0,a.jsx)("span",{className:"flex items-center justify-center w-6 h-6 rounded-full bg-primary/10 text-primary text-xs",children:"2"}),"Drop & Scan"]}),(0,a.jsx)("p",{className:"text-sm text-muted leading-relaxed",children:"Upload your .glb file. Everything runs locally. the file is never sent to a server. Fix any red flags in Blender/Maya before re-uploading."})]}),(0,a.jsxs)("div",{className:"space-y-2",children:[(0,a.jsxs)("div",{className:"flex items-center gap-2 font-medium text-text",children:[(0,a.jsx)("span",{className:"flex items-center justify-center w-6 h-6 rounded-full bg-primary/10 text-primary text-xs",children:"3"}),"Visual & Checklist"]}),(0,a.jsx)("p",{className:"text-sm text-muted leading-relaxed",children:"Spin the model in the viewer to check for Z-fighting and baked shadows, then work through the Manual QA Checklist before final submission."})]})]})]}),(0,a.jsxs)("div",{className:"bg-muted/5 border border-border/50 rounded-xl p-6 space-y-4",children:[(0,a.jsx)("h2",{className:"text-lg font-semibold text-text",children:"Exter
1nal QA Tools"}),(0,a.jsx)("p",{className:"text-sm text-muted",children:"Run your file through these industry-standard validators before final submission."}),(0,a.jsxs)("ul",{className:"list-disc pl-5 space-y-2 text-sm text-text",children:[(0,a.jsxs)("li",{children:[(0,a.jsx)("a",{href:"https://github.khronos.org/glTF-Validator/",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline font-medium",children:"Khronos glTF Validator"}),': The official industry "Grammar Check" for 3D files.']}),(0,a.jsxs)("li",{children:[(0,a.jsx)("a",{href:"https://modelviewer.dev/editor/",target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline font-medium",children:"Google Model-Viewer Editor"}),": The closest preview to Amazon's own rendering environment."]}),(0,a.jsxs)("li",{children:[(0,a.jsx)("span",{className:"font-medium",children:"Apple Reality Composer"}),": Test the .usdz conversion for iPhone AR (macOS/iOS app)."]})]})]})]})]})}},62362:e=>{function t(e){var t=Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}t.keys=()=>[],t.resolve=t,t.id=62362,e.exports=t},88665:(e,t,s)=>{"use strict";s.d(t,{A:()=>l,a:()=>i});var a=s(33499),n=s(65235);let r=null;function i(){return window.customElements.get("model-viewer")?Promise.resolve():(r||(r=new Promise((e,t)=>{let s=document.createElement("script");s.type="module",s.src="/vendor/model-viewer-4.1.0.min.js",s.onload=()=>{window.customElements.whenDefined("model-viewer").then(()=>{window.customElements.get("model-viewer").dracoDecoderLocation="/vendor/draco/",e()})},s.onerror=()=>{s.remove(),t(Error("Unable to load model-viewer"))},document.head.appendChild(s)}).catch(e=>{throw r=null,e})),r)}function l(e){let{onLoad:t,rootMargin:s="500px"}=e,r=(0,n.useRef)(null),l=(0,n.useRef)(t);return(0,n.useEffect)(()=>{l.current=t},[t]),(0,n.useEffect)(()=>{let e=!1,t=()=>{i().then(()=>{var t;e||null==(t=l.current)||t.call(l)}).catch(e=>console.error("Unable to load the 3D viewer",e))};if(window.customElements.get("model-viewer"))return t(),()=>{e=!0};let a=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&(a.disconnect(),t())},{rootMargin:s});return r.current&&a.observe(r.current),()=>{e=!0,a.disconnect()}},[s]),(0,a.jsx)("div",{ref:r,style:{height:1,visibility:"hidden",pointerEvents:"none"},"aria-hidden":"true"})}}}]);
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.