/* global React, MachineRender */ const { useState: useSP, useEffect: useEP } = React; const isSubdir = window.location.pathname.includes("/products/"); const prefix = isSubdir ? "../../" : ""; function getProductBrochure(data) { if (data && data.brochureUrl) return data.brochureUrl; const name = ((data && data.name) || "").toLowerCase(); const p = window.location.pathname.toLowerCase(); // 1. Auto Coater Tablet -> Tablet Coating brochure if (name.includes("auto tablet coater") || name.includes("auto coater") || p.includes("auto-coater")) { return `${prefix}assets/brochure/Brochure - Mark Maker - Tablet Coating.pdf`; } // 2. EFF PACK, EFF PRO, VTD -> Effervescent brochure const isEffPack = name.includes("eff pack") || name.includes("eff-pack") || name.includes("tube filling") || p.includes("eff-pack"); const isEffPro = name.includes("eff pro") || name.includes("eff-pro") || name.includes("effervescent processing") || p.includes("eff-pro"); const isVtd = name.includes("vacuum tray dryer") || name.includes("vtd") || p.includes("vtd"); if (isEffPack || isEffPro || isVtd) { return `${prefix}assets/brochure/Brochure - Mark Maker - Effervescent.pdf`; } // 3. Rest of the product pages -> Granulation brochure return `${prefix}assets/brochure/Brochure - Mark Maker - Granulation.pdf`; } function getProductGADrawing(data) { if (data && data.gaDrawingUrl) return data.gaDrawingUrl; const name = ((data && data.name) || "").toLowerCase(); const p = window.location.pathname.toLowerCase(); // 1. RMG -> RMG 150 PDF.pdf if (name.includes("rapid mixer") || name.includes("rapid mixing") || name.includes("rmg") || p.includes("rapid-mixing-granulator")) { return `${prefix}assets/2d-drawings/2D DWG/RMG 150 PDF.pdf`; } // 2. Auto Tablet Coater -> AUTOCOATER 48.pdf if (name.includes("auto tablet coater") || name.includes("auto coater") || p.includes("auto-coater")) { return `${prefix}assets/2d-drawings/2D DWG/auto-tablet-coater/AUTOCOATER 48.pdf`; } // 3. Conta Pillar Blender (CPB) -> CPB-2000LTRS.pdf if (name.includes("conta pillar") || name.includes("cpb") || p.includes("cpb.html")) { return `${prefix}assets/2d-drawings/2D DWG/conta-pillar-blender/CPB-2000LTRS.pdf`; } // 4. Effervescent Packaging (EFF-PACK) -> EFF PACK 100.pdf if (name.includes("eff pack") || name.includes("eff-pack") || name.includes("tube filling") || p.includes("eff-pack")) { return `${prefix}assets/2d-drawings/2D DWG/effervescent-packaging/EFF PACK 100.pdf`; } // 5. Effervescent Processing (EFF-PRO) -> EFF PRO 250.pdf if (name.includes("eff pro") || name.includes("eff-pro") || name.includes("effervescent processing") || p.includes("eff-pro")) { return `${prefix}assets/2d-drawings/2D DWG/effervescent-processing/EFF PRO 250.pdf`; } // 6. Fluid Bed Coater (FBC) -> FBC-300KG.pdf if (name.includes("fluid bed coater") || name.includes("fbc") || p.includes("fbc.html")) { return `${prefix}assets/2d-drawings/2D DWG/fluid-bed-coater/FBC-300KG.pdf`; } // 7. Fluid Bed Dryer (FBD) -> MMPE-FBD-120KG.pdf if (name.includes("fluid bed dryer") || name.includes("fbd") || p.includes("fbd.html")) { return `${prefix}assets/2d-drawings/2D DWG/fluid-bed-dryer/MMPE-FBD-120KG.pdf`; } // 8. IPC Bin / IBC Bin Container -> IPC BIN.pdf if (name.includes("ipc bin") || name.includes("ibc bin") || p.includes("ipc-bin")) { return `${prefix}assets/2d-drawings/2D DWG/ibc-bin-container/IPC BIN.pdf`; } // 9. Lifting & Positioning Device (LPD) -> LPU.pdf if (name.includes("lifting and positioning") || name.includes("lifting & positioning") || name.includes("lpd") || p.includes("lpd.html")) { return `${prefix}assets/2d-drawings/2D DWG/lifting-and-positioning-device/LPU.pdf`; } // 10. Vacuum Tray Dryer (VTD) -> VTS.pdf if (name.includes("vacuum tray dryer") || name.includes("vtd") || p.includes("vtd.html")) { return `${prefix}assets/2d-drawings/2D DWG/vaccum-tray-dryer/VTS.pdf`; } return null; } function getProductLayoutKey(data) { const name = ((data && data.name) || "").toLowerCase(); const p = window.location.pathname.toLowerCase(); if (name.includes("rapid mixer") || name.includes("rapid mixing") || name.includes("rmg") || p.includes("rapid-mixing-granulator")) return "rmg"; if (name.includes("auto tablet coater") || name.includes("auto coater") || p.includes("auto-coater")) return "auto-coater"; if (name.includes("conta pillar") || name.includes("cpb") || p.includes("cpb.html")) return "cpb"; if (name.includes("eff pack") || name.includes("eff-pack") || name.includes("tube filling") || p.includes("eff-pack")) return "eff-pack"; if (name.includes("eff pro") || name.includes("eff-pro") || name.includes("effervescent processing") || p.includes("eff-pro")) return "eff-pro"; if (name.includes("fluid bed coater") || name.includes("fbc") || p.includes("fbc.html")) return "fbc"; if (name.includes("fluid bed dryer") || name.includes("fbd") || p.includes("fbd.html")) return "fbd"; if (name.includes("ipc bin") || name.includes("ibc bin") || p.includes("ipc-bin")) return "ipc-bin"; if (name.includes("lifting and positioning") || name.includes("lifting & positioning") || name.includes("lpd") || p.includes("lpd.html")) return "lpd"; if (name.includes("vacuum tray dryer") || name.includes("vtd") || p.includes("vtd.html")) return "vtd"; return null; } const PRODUCT_LAYOUT_CONFIG = { rmg: { title: "Compact footprint, easy cleanroom integration.", desc: "Our Rapid Mixer Granulator (RMG 150) is built on a space-saving 2.1 × 1.2 m base. It offers 3-side operator access for easy parameter tweaking, while maintenance doors open from the back.", specs: [ ["Mixing Bowl Diameter", "750 mm"], ["Total Height (Lid Closed)", "1950 mm"], ["Discharge Valve Clearance", "1000 mm (suited for direct FBD connection)"], ["Required Room Height", "Minimum 2500 mm clearance"], ["Net Weight", "Approx. 1200 kg"], ] }, "auto-coater": { title: "Ergonomic layout, fast cleanroom duct integration.", desc: "Our Auto Tablet Coater 48 offers front-facing operator access for spray gun calibration and pan loading, with rear service doors for exhaust and drive systems.", specs: [ ["Coating Pan Diameter", "48 inches (1220 mm)"], ["Total Height", "2150 mm"], ["Peristaltic Pump Clearance", "800 mm front access"], ["Required Room Height", "Minimum 2800 mm clearance"], ["Net Weight", "Approx. 1850 kg"], ] }, cpb: { title: "Flexible blending footprint, 360° safety envelope.", desc: "Our Conta Pillar Blender is engineered with a compact clamping column and generous 360° rotation clearance, suitable for varied IBC bin capacities.", specs: [ ["Blending Arm Rotation", "360° dynamic rotation"], ["Total Column Height", "3200 mm"], ["Bin Clamping Range", "300 L – 2000 L bins"], ["Safety Radius Clearance", "2500 mm perimeter envelope"], ["Net Weight", "Approx. 2200 kg"], ] }, fbd: { title: "Streamlined air-handling layout, direct granulation link.", desc: "Our Fluid Bed Dryer (FBD 120) features modular bowl docking for seamless gravity or vacuum transfer from upstream RMG mixers, with top-access filter bag inspection.", specs: [ ["Batch Capacity", "120 kg processing bowl"], ["Total Machine Height", "2850 mm"], ["Bowl Docking Clearance", "1100 mm floor clearance"], ["Required Room Height", "Minimum 3200 mm clearance"], ["Net Weight", "Approx. 1450 kg"], ] }, fbc: { title: "Vertical Wurster coating tower, ergonomic docking.", desc: "Our Fluid Bed Coater (FBC 300) delivers high precision bottom-spray coating with isolated operator zones, easy-access Wurster tube adjustment, and sanitary spray nozzle manifolds.", specs: [ ["Processing Capacity", "300 kg batch volume"], ["Total Unit Height", "3100 mm"], ["Wurster Column Clearance", "1200 mm servicing zone"], ["Required Room Height", "Minimum 3500 mm clearance"], ["Net Weight", "Approx. 1650 kg"], ] }, lpd: { title: "Ergonomic lifting mast, versatile bin positioning.", desc: "Our Lifting and Positioning Device features a rigid hydraulic/mechanical column with smooth 180°–360° swivel capability for dust-free blender and coater docking.", specs: [ ["Lifting Stroke Range", "1500 mm – 2400 mm"], ["Swivel Arc", "180° / 360° manual or powered"], ["Safe Working Load (SWL)", "Up to 500 kg+"], ["Required Room Height", "Minimum 3200 mm clearance"], ["Net Weight", "Approx. 850 kg"], ] }, vtd: { title: "Compact vacuum footprint, wide door swing radius.", desc: "Our Vacuum Tray Dryer is engineered with heavily reinforced vacuum chambers and uniform heating shelves, optimized for solvent extraction and heat-sensitive API drying.", specs: [ ["Chamber Dimensions", "2250 × 1550 mm footprint"], ["Door Swing Clearance", "1200 mm 90° swing arc"], ["Shelf Tray Spacing", "100 mm uniform shelf pitch"], ["Required Room Height", "Minimum 2700 mm clearance"], ["Net Weight", "Approx. 1950 kg"], ] }, "ipc-bin": { title: "Modular stacking envelope, sanitary funnel discharge.", desc: "Our IPC Bin Containers feature precision-formed 60° conical bases, stackable corner castings, and an ergonomic mobile trolley base for cleanroom transport.", specs: [ ["Bin Footprint", "1150 × 1150 mm base"], ["Overall Stacking Height", "1450 mm with lid"], ["Discharge Cone Angle", "60° sanitary frustum"], ["Valve Floor Clearance", "350 mm under-valve clearance"], ["Net Weight (Empty)", "Approx. 220 kg"], ] }, "eff-pro": { title: "Integrated processing skid, multi-vessel arrangement.", desc: "Our Effervescent Processing System (EFF-PRO 250) unifies formulation reactors, vacuum mixing, and condenser systems onto a single sanitary skid platform with dedicated operator access.", specs: [ ["Skid Footprint", "3200 × 1800 mm skid base"], ["Total Skid Height", "2450 mm top flange"], ["Sanitary Connection", "DN 100 tri-clamp ports"], ["Required Room Height", "Minimum 3000 mm clearance"], ["Net Weight", "Approx. 2800 kg"], ] }, "eff-pack": { title: "Continuous linear packaging line, high throughput.", desc: "Our EFF-PACK 100 tube filling line incorporates vibratory tablet sorting, automated tube indexing, desiccant cap insertion, and end-of-line collection in a compact linear cell.", specs: [ ["Line Envelope", "3600 × 1200 mm footprint"], ["Operating Speed", "100–120 tubes / minute"], ["Infeed Conveyor Height", "950 ± 50 mm working level"], ["Required Room Height", "Minimum 2600 mm clearance"], ["Net Weight", "Approx. 2100 kg"], ] } }; // ============ PRODUCT 3D VIEWER WITH LOADER ============ function ProductModelViewer({ src, alt }) { const [progress, setProgress] = useSP(0); const [loaded, setLoaded] = useSP(false); const [error, setError] = useSP(false); const viewerRef = React.useRef(null); useEP(() => { setProgress(0); setLoaded(false); setError(false); const el = viewerRef.current; if (!el) return; if (el.loaded) { setProgress(100); setLoaded(true); return; } const onProgress = (e) => { const p = Math.min(100, Math.max(0, Math.round((e.detail && e.detail.totalProgress ? e.detail.totalProgress : 0) * 100))); setProgress(p); }; const onLoad = () => { setProgress(100); setLoaded(true); }; const onError = () => { setError(true); }; el.addEventListener("progress", onProgress); el.addEventListener("load", onLoad); el.addEventListener("error", onError); return () => { el.removeEventListener("progress", onProgress); el.removeEventListener("load", onLoad); el.removeEventListener("error", onError); }; }, [src]); return (
LIVE 3D
{error ? "3D model preview unavailable" : progress > 0 && progress < 100 ? `Loading model asset (${progress}%)...` : "Loading 3D model..."}
{progress}%
); } // ============ PRODUCT HERO ============ function ProductHero() { const d = window.PRODUCT_DATA || {}; const [activeModelIdx, setActiveModelIdx] = useSP(0); const breadcrumb = d.breadcrumb || ["Home", "Products", "Granulation", "Rapid Mixer Granulator"]; const chips = d.chips || ["Flagship", "Granulation", "High-Shear"]; const name = d.name || "Rapid Mixer Granulator (RMG)"; const lede = d.description || "The Rapid Mixer Granulator (RMG) is engineered for fast, efficient, and uniform wet granulation across pharmaceutical, nutraceutical, food, and chemical manufacturing processes."; const subdesc = d.subDescription || "Manufactured in compliance with cGMP standards, our RMG offers robust construction, user-friendly operation, and reliable performance to meet the demands of modern production facilities."; const metrics = d.metrics || [["45–120", "Working L"], ["8–15", "mixing min"], ["SS 316L", "contact parts"]]; const modelsList = Array.isArray(d.models3d) && d.models3d.length > 0 ? d.models3d : null; const activeModel = modelsList ? (modelsList[activeModelIdx] || modelsList[0]) : null; const model3d = activeModel ? activeModel.src : (d.model3d || ""); const modelAlt = (activeModel && activeModel.alt) || d.modelAlt || `${name} 3D model`; const heroImage = d.heroImage || d.image || null; const brochureUrl = getProductBrochure(d); const gaDrawingUrl = getProductGADrawing(d); const hasHeroMedia = !!(model3d || heroImage); return (
{/* Breadcrumb */}
{breadcrumb.map((b, idx) => ( {idx > 0 && /} {idx < breadcrumb.length - 1 ? ( {b} ) : ( {b} )} ))}
{chips.map((c, i) => ( {c} ))}

{name}

{lede}

{subdesc}

{/* Metric strip */}
{metrics.map(([n, l]) => (
{n}
{l}
))}
{gaDrawingUrl && ( View layout )} Download brochure
{hasHeroMedia && (
{model3d ? ( ) : heroImage ? (
{name}
) : null} {model3d ? (
Live 3D explorer
) : heroImage ? (
Engineering Model
) : null} {modelsList && modelsList.length > 1 && (
{modelsList.map((m, idx) => ( ))}
)}
)}
); } // ============ PROCESS FLOW ============ function ProcessFlow() { const d = window.PRODUCT_DATA || {}; const [active, setActive] = useSP(0); const subtitle = d.processSubtitle || "Eight processing zones, high-shear, fully validated."; const steps = d.processSteps || [ { num: "01", label: "Dry charging", t: "Raw powder materials loaded into the mixing bowl via gravity, vacuum, or manually." }, { num: "02", label: "Dry mixing", t: "Impeller rotates at slow speed to homogenize and blend dry powders thoroughly." }, { num: "03", label: "Binder addition", t: "Liquid binder solution is sprayed or poured uniformly across the dry powder mix." }, { num: "04", label: "Wet mixing", t: "Impeller distributes binder solution to build a cohesive, consistent wet mass." }, { num: "05", label: "Granulation", t: "High-shear side-mounted chopper cuts the wet mass to form uniform granules." }, { num: "06", label: "Wet milling", t: "Optional online co-mill refines granule sizes and distribution before discharge." }, { num: "07", label: "Pneumatic discharge", t: "Automated discharge valve opens, transferring wet granules to the FBD bowl smoothly." }, { num: "08", label: "CIP / Washdown", t: "Easy access washdown with optional WIP/CIP spray balls for fast cleanups." }, ]; if (!steps || steps.length === 0) return null; return (
Process flow

{subtitle}

{/* Timeline */}
{/* connector line */}
{steps.map((s, i) => ( ))}
{steps[active].num} · {steps[active].label}
{steps[active].t}
); } // ============ FEATURES GRID ============ function FeaturesGrid() { const d = window.PRODUCT_DATA || {}; const [showOptional, setShowOptional] = useSP(false); const subtitle = d.featuresSubtitle || "Engineered for high performance and process control."; const keyFeatures = d.keyFeatures || [ "Product contact parts manufactured in SS 316 / SS 316L", "High-shear impeller for rapid and uniform mixing", "Side-mounted chopper for efficient granulation", "Pneumatic discharge system for smooth material transfer", "cGMP-compliant design with easy access for cleaning and maintenance", "Robust construction with low maintenance requirements", "Dust-free processing with enhanced containment", "Safety interlocks for secure operation" ]; const optionalFeatures = d.optionalFeatures || [ "Vacuum charging system", "Binder solution preparation vessel", "Online wet milling system", "Explosion-proof execution", "CIP/WIP system", "OEB containment design", "SCADA integration" ]; const featuresToDisplay = showOptional ? [...keyFeatures, ...optionalFeatures] : keyFeatures; return (
Engineering Features

{subtitle}

{featuresToDisplay.map((feat, i) => { const isOptional = i >= keyFeatures.length; return (
{ e.currentTarget.style.transform = "translateY(-4px)"; e.currentTarget.style.borderColor = isOptional ? "rgba(32,199,232,0.4)" : "var(--ink-3)"; e.currentTarget.style.background = isOptional ? "rgba(32,199,232,0.06)" : "#e2e8f0"; }} onMouseLeave={(e) => { e.currentTarget.style.transform = "none"; e.currentTarget.style.borderColor = "var(--line)"; e.currentTarget.style.background = isOptional ? "rgba(32,199,232,0.02)" : "var(--metal-3)"; }} > {isOptional ? "OPTIONAL FEATURE" : "KEY FEATURE"}

{feat}

); })}
); } // ============ ADVANTAGES SECTION ============ function AdvantagesSection() { const d = window.PRODUCT_DATA || {}; const advantages = d.advantages || [ { title: "Reduced processing time", desc: "Shortens dry mixing and wet granulation cycles to just 8-15 minutes, boosting overall throughput." }, { title: "Uniform size distribution", desc: "Delivers a consistent granule sizing with minimized fine particles, ideal for tablet compressing." }, { title: "Improved flow properties", desc: "Produces dense granules with excellent flowability, preventing downstream tableting hopper jams." }, { title: "Increased production efficiency", desc: "Automates charging and discharging to reduce manual processing, downtime, and operator labor." }, { title: "Reduced manual handling", desc: "Pneumatic systems and gravity feeds minimize operator contact with product powders." }, { title: "Consistent batch repeatability", desc: "Pre-programmed recipe cycles guarantee identical batch outputs, securing strict QA standards." }, ]; const title = d.advantagesTitle || "Engineering without compromise."; const desc = d.advantagesDesc || "Every Mark Maker machine is built on a foundation of rigorous pharmaceutical standards, leveraging modern automation to guarantee repeatability, yield, and operator safety."; // Carousel images configuration const rawCarousel = d.advantagesCarousel || (d.advantagesImage ? [{ src: d.advantagesImage, tag: "Engineering" }] : d.carouselItems); const carouselItems = (Array.isArray(rawCarousel) && rawCarousel.length > 0) ? rawCarousel.filter(item => item && item.src && !item.src.includes("placehold.co")) : null; const hasCarousel = !!(carouselItems && carouselItems.length > 0); const [currentSlide, setCurrentSlide] = React.useState(0); const prevSlide = () => { if (!hasCarousel) return; setCurrentSlide((prev) => (prev === 0 ? carouselItems.length - 1 : prev - 1)); }; const nextSlide = () => { if (!hasCarousel) return; setCurrentSlide((prev) => (prev === carouselItems.length - 1 ? 0 : prev + 1)); }; return (