// catalog.jsx — WooCommerce-style B2B product catalogue (no cart / checkout / pricing)
const { useState: useStateCat } = React;
const CAT = window;

const LINE_URL = "https://line.me/R/ti/p/@512sgltn";

/* ----------------------------------------------------------------
   CATEGORY REGISTRY — maps category slug → division + labels + route
-----------------------------------------------------------------*/
const CATALOG_CATEGORIES = {
  "ppe": { division: "Safety", divisionHref: "#/safety", label: "PPE", href: "#/safety/ppe" },
  "footwear": { division: "Safety", divisionHref: "#/safety", label: "Protective Footwear", href: "#/safety/footwear" },
  "workwear": { division: "Safety", divisionHref: "#/safety", label: "Workwear", href: "#/safety/workwear" },
  "fall-protection": { division: "Safety", divisionHref: "#/safety", label: "Fall Protection", href: "#/safety/fall-protection" },
  "machines": { division: "Welding", divisionHref: "#/welding", label: "Welding Machines", href: "#/welding/machines" },
  "cutting": { division: "Welding", divisionHref: "#/welding", label: "Cutting & Preparation", href: "#/welding/cutting" },
  "automation": { division: "Welding", divisionHref: "#/welding", label: "Automation & Alignment", href: "#/welding/automation" },
  "quality-control": { division: "Welding", divisionHref: "#/welding", label: "Quality Control", href: "#/welding/quality-control" },
};

const IMG = (id) => `https://images.unsplash.com/photo-${id}?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&w=1400&q=85`;

/* ----------------------------------------------------------------
   PRODUCT CATALOGUE
-----------------------------------------------------------------*/
const PRODUCTS = [
  /* ---------------- PPE ---------------- */
  {
    slug: "honeywell-north-7600-respirator",
    category: "ppe", brand: "Honeywell",
    name: "North 7600 Full-Facepiece Respirator",
    short: "Silicone full-face respirator with a wide field of vision for chemical and particulate protection.",
    overview: "The North 7600 Series full-facepiece respirator is built for demanding industrial environments where eye and respiratory protection are both critical. A soft silicone seal delivers all-shift comfort while the wide, distortion-free lens maximises field of vision. Compatible with the full North bayonet cartridge and filter range for tailored protection.",
    image: IMG("1589939705384-5185137a7f0f"),
    gallery: ["1589939705384-5185137a7f0f", "1622612023350-b15f063eabe6", "1507497806295-753c4108560c"],
    specs: [
      { label: "Facepiece Material", value: "Silicone" },
      { label: "Lens", value: "Polycarbonate, anti-scratch coated" },
      { label: "Connection", value: "North bayonet, dual cartridge" },
      { label: "Sizes", value: "S / M / L" },
      { label: "Certification", value: "EN 136, NIOSH approved" },
      { label: "Applications", value: "Petrochemical, paint spray, abrasive blasting" },
    ],
    features: ["Wide distortion-free field of vision", "Low-profile dual cartridge connection", "All-shift silicone comfort seal", "Compatible with North filter range"],
  },
  {
    slug: "edge-zorge-safety-eyewear",
    category: "ppe", brand: "Edge",
    name: "Zorge G2 Safety Eyewear",
    short: "Lightweight wrap-around safety glasses with anti-fog, anti-scratch coated lenses.",
    overview: "Edge Zorge G2 safety eyewear combines a sleek wrap-around frame with the optical clarity industrial users demand. The Vapor Shield anti-fog and anti-scratch coatings keep vision clear across temperature swings and abrasive conditions, while integrated side protection meets high-mass and high-velocity impact requirements.",
    image: IMG("1507497806295-753c4108560c"),
    gallery: ["1507497806295-753c4108560c", "1622612023350-b15f063eabe6", "1589939705384-5185137a7f0f"],
    specs: [
      { label: "Lens Coating", value: "Vapor Shield anti-fog / anti-scratch" },
      { label: "Lens Options", value: "Clear, smoke, polarized" },
      { label: "Impact Rating", value: "ANSI Z87.1+ / EN 166" },
      { label: "Frame", value: "Nylon, wrap-around" },
      { label: "UV Protection", value: "99.9% UVA / UVB" },
      { label: "Weight", value: "26 g" },
    ],
    features: ["Permanent anti-fog coating", "High-velocity impact certified", "Wrap-around side protection", "Multiple lens tints available"],
  },
  {
    slug: "ringers-r067-impact-gloves",
    category: "ppe", brand: "Ringers Gloves",
    name: "R-067 Roughneck Impact Glove",
    short: "Impact-resistant gloves with TPR back-of-hand protection for heavy material handling.",
    overview: "The Ringers R-067 Roughneck is engineered for the toughest material-handling tasks. Moulded TPR across the back of the hand and fingers absorbs impact and pinch hazards, while the textured palm delivers grip in wet and oily conditions. A staple on drilling rigs, fabrication yards and heavy maintenance crews.",
    image: IMG("1730584474196-b0e8a29303e8"),
    gallery: ["1730584474196-b0e8a29303e8", "1672748341520-6a839e6c05bb", "1589939705384-5185137a7f0f"],
    specs: [
      { label: "Impact Protection", value: "TPR back-of-hand & fingers" },
      { label: "Palm", value: "Synthetic leather, textured" },
      { label: "Cut Resistance", value: "ANSI A4" },
      { label: "Sizes", value: "S – XXL" },
      { label: "Standard", value: "EN 388: 2016" },
      { label: "Applications", value: "Oil & gas, heavy fabrication, mining" },
    ],
    features: ["Moulded TPR impact protection", "Oil-resistant textured grip palm", "ANSI A4 cut resistance", "Reinforced thumb crotch"],
  },
  /* ---------------- FOOTWEAR ---------------- */
  {
    slug: "red-wing-2412-metguard-boot",
    category: "footwear", brand: "Red Wing",
    name: "2412 King Toe MetGuard Boot",
    short: "8-inch metatarsal safety boot with oversized toe box for all-day protection.",
    overview: "The Red Wing 2412 King Toe pairs an internal metatarsal guard with the brand's signature oversized toe box for protection that doesn't compromise comfort. Built on a welt construction for repeated re-soling, with a heat- and slip-resistant outsole rated for petrochemical and heavy fabrication environments.",
    image: IMG("1593583810872-ddee4d6bd55a"),
    gallery: ["1593583810872-ddee4d6bd55a", "1593313637552-29c2c0dacd35", "1681812508281-7589b75b2e46"],
    specs: [
      { label: "Height", value: "8 inch" },
      { label: "Toe", value: "Steel, King Toe oversized" },
      { label: "Metatarsal", value: "Internal met guard" },
      { label: "Outsole", value: "Heat & slip resistant, oil resistant" },
      { label: "Construction", value: "Goodyear welt, re-soleable" },
      { label: "Standard", value: "ASTM F2413, TIS compliant" },
    ],
    features: ["Internal metatarsal protection", "Oversized King Toe comfort box", "Re-soleable welt construction", "Heat-resistant outsole to 300°C"],
  },
  {
    slug: "dunlop-purofort-thermo-boot",
    category: "footwear", brand: "Dunlop",
    name: "Purofort Thermo+ Safety Wellington",
    short: "Insulated chemical-resistant wellington for cold, wet and processing environments.",
    overview: "Dunlop Purofort Thermo+ wellingtons deliver lightweight insulation to -50°C without sacrificing flexibility. The closed-cell Purofort material is chemical and abrasion resistant, making these boots a mainstay in food processing, cold storage and outdoor industrial work where standard rubber boots fail.",
    image: IMG("1681812508281-7589b75b2e46"),
    gallery: ["1681812508281-7589b75b2e46", "1593583810872-ddee4d6bd55a", "1747999461210-a56f72294428"],
    specs: [
      { label: "Insulation", value: "Rated to -50°C" },
      { label: "Material", value: "Purofort closed-cell PU" },
      { label: "Toe", value: "Steel toe cap" },
      { label: "Midsole", value: "Penetration-resistant" },
      { label: "Standard", value: "EN ISO 20345 S5 CI" },
      { label: "Applications", value: "Food, cold storage, processing" },
    ],
    features: ["Insulation to -50°C", "Full chemical resistance", "Steel toe & penetration midsole", "Lightweight all-day comfort"],
  },
  {
    slug: "red-wing-petroking-boot",
    category: "footwear", brand: "Red Wing",
    name: "PetroKing 6-inch Safety Boot",
    short: "Oil- and heat-resistant boot engineered for petrochemical and refinery work.",
    overview: "Purpose-built for the petrochemical sector, the PetroKing combines a heat-resistant nitrile outsole with a chemical-resistant upper. Electrical-hazard rated and slip-tested on oily surfaces, it is the standard-issue boot for refinery turnarounds and offshore platforms across the region.",
    image: IMG("1593313637552-29c2c0dacd35"),
    gallery: ["1593313637552-29c2c0dacd35", "1593583810872-ddee4d6bd55a", "1730584474196-b0e8a29303e8"],
    specs: [
      { label: "Height", value: "6 inch" },
      { label: "Outsole", value: "Nitrile, heat resistant to 300°C" },
      { label: "Toe", value: "Composite, non-metallic" },
      { label: "Electrical Hazard", value: "EH rated" },
      { label: "Standard", value: "ASTM F2413 EH" },
      { label: "Applications", value: "Refinery, offshore, petrochemical" },
    ],
    features: ["Heat-resistant nitrile outsole", "Non-metallic composite toe", "Electrical hazard protection", "Oil & slip resistant tread"],
  },
  /* ---------------- WORKWEAR ---------------- */
  {
    slug: "fr-cotton-coverall",
    category: "workwear", brand: "Leeden Select",
    name: "FR Cotton Coverall — Hot Work",
    short: "Flame-resistant cotton coverall for welding, hot work and arc-flash environments.",
    overview: "Engineered for hot-work crews, this flame-resistant coverall uses inherently treated cotton that self-extinguishes and resists ignition. Generous action-back tailoring allows full movement for welders and fitters, while reinforced seams and brass hardware survive industrial laundering cycles.",
    image: IMG("1730584474196-b0e8a29303e8"),
    gallery: ["1730584474196-b0e8a29303e8", "1672748341520-6a839e6c05bb", "1747999461210-a56f72294428"],
    specs: [
      { label: "Fabric", value: "350 gsm FR-treated cotton" },
      { label: "Protection", value: "Flame resistant, anti-static option" },
      { label: "Arc Rating", value: "ATPV 8.7 cal/cm²" },
      { label: "Sizes", value: "S – 4XL" },
      { label: "Standard", value: "EN ISO 11612, EN 1149-5" },
      { label: "Applications", value: "Welding, hot work, arc flash" },
    ],
    features: ["Inherently flame resistant", "Action-back for mobility", "Industrial-launder durable", "Anti-static option available"],
  },
  {
    slug: "hi-vis-class3-jacket",
    category: "workwear", brand: "Leeden Select",
    name: "Class 3 Hi-Vis Bomber Jacket",
    short: "ANSI Class 3 high-visibility jacket with detachable sleeves and waterproof shell.",
    overview: "Maximum-visibility outerwear for roadside, rail and night operations. The Class 3 bomber features 360° retroreflective tape, a waterproof breathable shell and a detachable-sleeve design that adapts from full jacket to vest as conditions change.",
    image: IMG("1681812508281-7589b75b2e46"),
    gallery: ["1681812508281-7589b75b2e46", "1730584474196-b0e8a29303e8", "1614326014420-1f0c741ca7e1"],
    specs: [
      { label: "Class", value: "ANSI/ISEA 107 Class 3" },
      { label: "Shell", value: "Waterproof breathable, 5000 mm" },
      { label: "Reflective", value: "360° segmented tape" },
      { label: "Configuration", value: "Detachable sleeves" },
      { label: "Sizes", value: "S – 4XL" },
      { label: "Applications", value: "Roadworks, rail, logistics" },
    ],
    features: ["360-degree visibility", "Waterproof breathable shell", "Convertible jacket-to-vest", "Multi-pocket utility design"],
  },
  {
    slug: "chemical-splash-suit",
    category: "workwear", brand: "Leeden Select",
    name: "Type 3/4 Chemical Splash Suit",
    short: "Liquid-tight coverall for chemical handling and decontamination tasks.",
    overview: "A Type 3/4 barrier garment for jet-liquid and spray-tight chemical protection. Taped seams and a storm flap over the zip create a continuous liquid barrier, while the microporous laminate keeps the wearer cooler than impermeable alternatives during decontamination and chemical transfer work.",
    image: IMG("1747999461210-a56f72294428"),
    gallery: ["1747999461210-a56f72294428", "1672748341520-6a839e6c05bb", "1730584474196-b0e8a29303e8"],
    specs: [
      { label: "Type", value: "Type 3 (jet) / Type 4 (spray)" },
      { label: "Material", value: "Microporous laminate" },
      { label: "Seams", value: "Fully taped" },
      { label: "Closure", value: "Double zip with storm flap" },
      { label: "Standard", value: "EN 14605, EN 13034" },
      { label: "Applications", value: "Chemical transfer, decontamination" },
    ],
    features: ["Liquid-tight taped seams", "Breathable microporous fabric", "Storm flap zip protection", "Single-use hygienic design"],
  },
  /* ---------------- FALL PROTECTION ---------------- */
  {
    slug: "msa-v-form-harness",
    category: "fall-protection", brand: "MSA",
    name: "V-FORM+ Full Body Harness",
    short: "Ergonomic full-body harness with racing-style buckles for working at height.",
    overview: "The MSA V-FORM+ harness applies athletic design principles to fall protection. The contoured shoulder and leg padding distributes arrest forces comfortably, while colour-coded racing-style buckles speed up donning and inspection. An integrated tongue-buckle leg strap and clear labelling make it audit-ready.",
    image: IMG("1589939705384-5185137a7f0f"),
    gallery: ["1589939705384-5185137a7f0f", "1614326014420-1f0c741ca7e1", "1672748341520-6a839e6c05bb"],
    specs: [
      { label: "Type", value: "Full body, single D-ring" },
      { label: "Buckles", value: "Racing-style quick-connect" },
      { label: "Capacity", value: "140 kg" },
      { label: "Sizes", value: "S – XL" },
      { label: "Standard", value: "EN 361, ANSI Z359.11" },
      { label: "Applications", value: "Construction, tower, maintenance" },
    ],
    features: ["Contoured load-distributing padding", "Colour-coded quick-connect buckles", "Integrated inspection labelling", "Lightweight athletic fit"],
  },
  {
    slug: "msa-latchways-srl",
    category: "fall-protection", brand: "MSA",
    name: "Latchways Personal SRL",
    short: "Compact self-retracting lifeline for hands-free mobility at height.",
    overview: "The Latchways Personal Self-Retracting Lifeline gives workers continuous fall protection with twin-leg, hands-free mobility. A sealed, maintenance-free brake mechanism arrests falls within centimetres, and the lightweight housing mounts directly to the harness dorsal connection.",
    image: IMG("1614326014420-1f0c741ca7e1"),
    gallery: ["1614326014420-1f0c741ca7e1", "1589939705384-5185137a7f0f", "1730584476141-232435a40c32"],
    specs: [
      { label: "Type", value: "Twin-leg personal SRL" },
      { label: "Lifeline Length", value: "2.0 m per leg" },
      { label: "Mechanism", value: "Sealed maintenance-free brake" },
      { label: "Capacity", value: "140 kg" },
      { label: "Standard", value: "EN 360, ANSI Z359.14" },
      { label: "Applications", value: "Steel erection, tower work" },
    ],
    features: ["Hands-free twin-leg mobility", "Sealed maintenance-free brake", "Harness-mounted lightweight design", "Rapid fall arrest distance"],
  },
  {
    slug: "safetylink-roof-anchor",
    category: "fall-protection", brand: "SafetyLink",
    name: "SafetyLink Roof Anchor Point",
    short: "Permanent engineered anchorage point for metal and concrete roofs.",
    overview: "SafetyLink anchor points provide certified, permanent attachment for roof access and fall-arrest systems. Each anchor is engineered and load-tested to support a fall-arrest event, with corrosion-resistant fixings suitable for tropical coastal environments and full compliance documentation supplied.",
    image: IMG("1614326014420-1f0c741ca7e1"),
    gallery: ["1614326014420-1f0c741ca7e1", "1672748341520-6a839e6c05bb", "1589939705384-5185137a7f0f"],
    specs: [
      { label: "Type", value: "Permanent roof anchorage" },
      { label: "Substrate", value: "Metal sheet, concrete, timber" },
      { label: "Load Rating", value: "15 kN fall arrest" },
      { label: "Finish", value: "316 stainless, marine grade" },
      { label: "Standard", value: "EN 795, AS/NZS 5532" },
      { label: "Applications", value: "Roof access, abseil, anchorage" },
    ],
    features: ["Engineered & load-tested", "Marine-grade corrosion resistance", "Multi-substrate fixings", "Compliance documentation included"],
  },
  /* ---------------- WELDING MACHINES ---------------- */
  {
    slug: "kemppi-master-m-358",
    category: "machines", brand: "Kemppi",
    name: "Master M 358 Multi-Process Welder",
    short: "350 A multi-process power source for MIG/MAG, MMA and TIG fabrication.",
    overview: "The Kemppi Master M 358 is a robust 350 A multi-process power source built for daily industrial fabrication. It delivers stable MIG/MAG, MMA and DC TIG performance with a clear control interface and proven Kemppi arc quality. Built for high duty cycles and connectivity to Kemppi WeldEye for weld data traceability.",
    image: IMG("1730584476141-232435a40c32"),
    gallery: ["1730584476141-232435a40c32", "1730584475795-f0be0efd606e", "1747999461210-a56f72294428"],
    specs: [
      { label: "Output", value: "350 A" },
      { label: "Processes", value: "MIG/MAG, MMA, DC TIG" },
      { label: "Duty Cycle", value: "350 A @ 60%" },
      { label: "Input", value: "400 V 3-phase" },
      { label: "Connectivity", value: "WeldEye weld data" },
      { label: "Protection", value: "IP23S" },
    ],
    features: ["Multi-process flexibility", "High 60% duty cycle", "WeldEye data traceability", "Industrial IP23S build"],
  },
  {
    slug: "lincoln-flextec-500",
    category: "machines", brand: "Lincoln Electric",
    name: "Flextec 500 Multi-Process Source",
    short: "Rugged 500 A inverter for stick, MIG, flux-cored and gouging.",
    overview: "The Lincoln Electric Flextec 500 is a multi-process inverter engineered for the harshest job-site conditions. With a wide 500 A output range and simple knob control, it handles stick, MIG, flux-cored, TIG and air carbon-arc gouging — making it the workhorse of structural and pipeline crews.",
    image: IMG("1730584475795-f0be0efd606e"),
    gallery: ["1730584475795-f0be0efd606e", "1730584476141-232435a40c32", "1614326014420-1f0c741ca7e1"],
    specs: [
      { label: "Output", value: "500 A" },
      { label: "Processes", value: "Stick, MIG, FCAW, TIG, gouging" },
      { label: "Duty Cycle", value: "500 A @ 60%" },
      { label: "Input", value: "380–575 V 3-phase" },
      { label: "Gouging", value: "Up to 6.4 mm carbons" },
      { label: "Protection", value: "IP23, F.A.N. cooling" },
    ],
    features: ["Five welding processes", "Job-site rugged enclosure", "Air carbon-arc gouging capable", "Simple knob-set control"],
  },
  {
    slug: "kemppi-minarc-evo-180",
    category: "machines", brand: "Kemppi",
    name: "Minarc Evo 180 Portable MMA",
    short: "Ultra-portable 180 A stick welder for maintenance and site repair.",
    overview: "Weighing under 5 kg, the Kemppi Minarc Evo 180 packs full 180 A stick-welding performance into a case a technician can carry up a ladder. Generator-compatible and forgiving on long supply cables, it is purpose-built for plant maintenance teams and remote site repair.",
    image: IMG("1747999461210-a56f72294428"),
    gallery: ["1747999461210-a56f72294428", "1730584476141-232435a40c32", "1730584475795-f0be0efd606e"],
    specs: [
      { label: "Output", value: "180 A" },
      { label: "Process", value: "MMA, DC TIG" },
      { label: "Weight", value: "4.9 kg" },
      { label: "Input", value: "230 V single phase" },
      { label: "Generator", value: "Compatible, PFC" },
      { label: "Electrodes", value: "Up to 4.0 mm" },
    ],
    features: ["Under 5 kg portability", "Generator compatible PFC", "Tolerant of long cables", "Full 180 A stick output"],
  },
  /* ---------------- CUTTING & PREPARATION ---------------- */
  {
    slug: "climax-bw3000-bevel-machine",
    category: "cutting", brand: "Climax",
    name: "BW3000 Boiler Tube Bevel Machine",
    short: "Portable end-prep machine for precision tube and pipe bevels.",
    overview: "The Climax BW3000 mounts inside the bore and machines a precision weld bevel without heat-affected zones. Self-centring mandrels lock the tool concentric to the pipe ID for repeatable, machine-grade preparation — eliminating the hand-grinding rework that slows code-quality welding.",
    image: IMG("1747999461210-a56f72294428"),
    gallery: ["1747999461210-a56f72294428", "1614326014420-1f0c741ca7e1", "1730584476141-232435a40c32"],
    specs: [
      { label: "Pipe Range", value: "12 – 76 mm ID mount" },
      { label: "Prep Type", value: "Bevel, face, bore" },
      { label: "Drive", value: "Pneumatic / electric" },
      { label: "Mounting", value: "Self-centring mandrel" },
      { label: "Finish", value: "Cold cut, no HAZ" },
      { label: "Applications", value: "Boiler tube, heat exchanger" },
    ],
    features: ["Cold cutting, no heat-affected zone", "Self-centring mandrel mount", "Repeatable machine-grade bevels", "Pneumatic or electric drive"],
  },
  {
    slug: "protem-usm-pipe-cutter",
    category: "cutting", brand: "Protem",
    name: "USM Series Split-Frame Cutter",
    short: "Split-frame clamshell lathe for cutting and beveling large-bore pipe.",
    overview: "The Protem USM split-frame clamshell mounts around in-situ pipe to perform simultaneous cutting and beveling on large diameters. Ideal for pipeline tie-ins and pressure-vessel work where pipe cannot be rotated, it delivers square, weld-ready ends in a single setup.",
    image: IMG("1614326014420-1f0c741ca7e1"),
    gallery: ["1614326014420-1f0c741ca7e1", "1747999461210-a56f72294428", "1730584475795-f0be0efd606e"],
    specs: [
      { label: "Pipe Range", value: "168 – 1220 mm OD" },
      { label: "Operation", value: "Cut + bevel simultaneous" },
      { label: "Frame", value: "Split clamshell, in-situ" },
      { label: "Drive", value: "Pneumatic / hydraulic" },
      { label: "Wall", value: "Heavy wall capable" },
      { label: "Applications", value: "Pipeline tie-in, vessel" },
    ],
    features: ["Cuts in-situ without rotation", "Simultaneous cut and bevel", "Heavy-wall capability", "Square weld-ready ends"],
  },
  {
    slug: "procut-orbital-pipe-saw",
    category: "cutting", brand: "Procut",
    name: "Orbital Pipe Cutting Saw",
    short: "Lightweight chain-mount saw for fast, square field pipe cuts.",
    overview: "The Procut orbital saw clamps to the pipe with a roller chain and orbits a cutting blade for a fast, burr-free square cut. Compact and field-rugged, it replaces abrasive wheels and oxy-cutting where clean, cold cuts are needed for stainless and alloy pipe.",
    image: IMG("1730584475795-f0be0efd606e"),
    gallery: ["1730584475795-f0be0efd606e", "1747999461210-a56f72294428", "1614326014420-1f0c741ca7e1"],
    specs: [
      { label: "Pipe Range", value: "50 – 300 mm OD" },
      { label: "Cut Type", value: "Cold orbital, square" },
      { label: "Mounting", value: "Roller chain clamp" },
      { label: "Drive", value: "Pneumatic" },
      { label: "Material", value: "Carbon, stainless, alloy" },
      { label: "Applications", value: "Field pipe, stainless lines" },
    ],
    features: ["Burr-free cold cutting", "Fast chain-clamp setup", "Stainless & alloy safe", "Compact field-rugged build"],
  },
  /* ---------------- AUTOMATION & ALIGNMENT ---------------- */
  {
    slug: "magnatech-pipemaster-516",
    category: "automation", brand: "Magnatech",
    name: "Pipemaster 516 Orbital Welding System",
    short: "Programmable orbital TIG system for code-quality pipe welds.",
    overview: "The Magnatech Pipemaster 516 automates orbital TIG welding for repeatable, code-quality joints. A programmable power source stores weld procedures by joint type, and the lightweight orbital head clamps to the pipe for hands-off circumferential welds in carbon, stainless and alloy materials.",
    image: IMG("1730584476141-232435a40c32"),
    gallery: ["1730584476141-232435a40c32", "1730584475795-f0be0efd606e", "1747999461210-a56f72294428"],
    specs: [
      { label: "Pipe Range", value: "8 – 168 mm OD" },
      { label: "Process", value: "Orbital GTAW (TIG)" },
      { label: "Programs", value: "Stored weld procedures" },
      { label: "Head", value: "Clamp-on orbital, water cooled" },
      { label: "Wire Feed", value: "Optional cold wire" },
      { label: "Applications", value: "Power piping, process, pharma" },
    ],
    features: ["Programmable weld procedures", "Repeatable code-quality welds", "Clamp-on orbital head", "Optional cold wire feed"],
  },
  {
    slug: "bortech-pipe-aligner",
    category: "automation", brand: "Bortech",
    name: "Internal Pipe Alignment Clamp",
    short: "Hydraulic internal line-up clamp for high-low-free pipe fit-up.",
    overview: "This internal alignment clamp expands inside the pipe bore to bring two joints into concentric, high-low-free alignment before welding. Even root reinforcement and integrated copper backing produce consistent root passes — critical for automated and code pipeline welding.",
    image: IMG("1614326014420-1f0c741ca7e1"),
    gallery: ["1614326014420-1f0c741ca7e1", "1730584476141-232435a40c32", "1730584475795-f0be0efd606e"],
    specs: [
      { label: "Pipe Range", value: "200 – 1220 mm ID" },
      { label: "Type", value: "Internal expanding clamp" },
      { label: "Drive", value: "Hydraulic" },
      { label: "Backing", value: "Integrated copper shoes" },
      { label: "Fit-up", value: "High-low-free alignment" },
      { label: "Applications", value: "Pipeline, process piping" },
    ],
    features: ["Concentric high-low-free fit", "Hydraulic internal expansion", "Integrated copper backing", "Even root reinforcement"],
  },
  {
    slug: "climax-bore-welder",
    category: "automation", brand: "Climax",
    name: "BW5000 Portable Bore Welder",
    short: "Automated bore cladding and build-up welder for worn housings.",
    overview: "The Climax BW5000 portable bore welder restores worn bores and housings in place with automated wire deposition. A boring-bar mounted torch lays a controlled weld overlay for re-machining, returning expensive components to service without removal to a workshop.",
    image: IMG("1730584475795-f0be0efd606e"),
    gallery: ["1730584475795-f0be0efd606e", "1747999461210-a56f72294428", "1730584476141-232435a40c32"],
    specs: [
      { label: "Bore Range", value: "50 – 1000 mm" },
      { label: "Process", value: "Automated MIG overlay" },
      { label: "Mounting", value: "Boring bar / face plate" },
      { label: "Control", value: "Programmable pitch & speed" },
      { label: "Use", value: "In-situ repair welding" },
      { label: "Applications", value: "Heavy equipment, hydro" },
    ],
    features: ["In-situ bore restoration", "Automated overlay deposition", "Programmable weld pitch", "No component removal needed"],
  },
  /* ---------------- QUALITY CONTROL ---------------- */
  {
    slug: "tempil-tempilstik-crayons",
    category: "quality-control", brand: "Tempil",
    name: "Tempilstik Temperature Crayons",
    short: "Calibrated marking crayons for verifying preheat and interpass temperature.",
    overview: "Tempilstik crayons mark a surface that melts cleanly at a precise rated temperature, giving welders a fast, reliable check of preheat and interpass conditions. Available across the full temperature range required by welding procedure specifications — an essential, traceable QC consumable.",
    image: IMG("1526634140919-468dc3ae3870"),
    gallery: ["1526634140919-468dc3ae3870", "1730584476141-232435a40c32", "1730584475795-f0be0efd606e"],
    specs: [
      { label: "Type", value: "Phase-change marking crayon" },
      { label: "Range", value: "38 – 1093 °C" },
      { label: "Accuracy", value: "±1% of rating" },
      { label: "Use", value: "Preheat / interpass check" },
      { label: "Form", value: "Crayon stick" },
      { label: "Applications", value: "WPS compliance, preheat QC" },
    ],
    features: ["Precise phase-change rating", "Fast surface verification", "Full WPS temperature range", "Traceable QC consumable"],
  },
  {
    slug: "victor-flowmeter-regulator",
    category: "quality-control", brand: "Victor",
    name: "EDGE 2.0 Flowmeter Regulator",
    short: "Precision shielding-gas flowmeter regulator for consistent weld quality.",
    overview: "The Victor EDGE 2.0 flowmeter regulator delivers accurate, repeatable shielding-gas flow — a quiet but critical factor in weld porosity and bead quality. A durable encapsulated gauge and colour-coded flow tube make setting and verifying flow fast on the shop floor.",
    image: IMG("1730584476141-232435a40c32"),
    gallery: ["1730584476141-232435a40c32", "1526634140919-468dc3ae3870", "1747999461210-a56f72294428"],
    specs: [
      { label: "Type", value: "Flowmeter regulator" },
      { label: "Gas", value: "Argon, CO₂, mixed" },
      { label: "Flow Range", value: "0 – 60 SCFH" },
      { label: "Gauge", value: "Encapsulated, shock resistant" },
      { label: "Inlet", value: "CGA standard" },
      { label: "Applications", value: "MIG / TIG shielding gas" },
    ],
    features: ["Accurate repeatable gas flow", "Shock-resistant encapsulated gauge", "Colour-coded flow tube", "Reduces weld porosity"],
  },
  {
    slug: "weiler-tiger-flap-disc",
    category: "quality-control", brand: "Weiler",
    name: "Tiger Ceramic Flap Disc",
    short: "Long-life ceramic flap disc for weld dressing and surface finishing.",
    overview: "Weiler Tiger ceramic flap discs cut faster and last longer on stainless and high-alloy steels, where weld dressing and blending are critical to final inspection. Self-sharpening ceramic grain maintains an aggressive cut rate across the life of the disc, improving finishing consistency.",
    image: IMG("1730584475795-f0be0efd606e"),
    gallery: ["1730584475795-f0be0efd606e", "1526634140919-468dc3ae3870", "1747999461210-a56f72294428"],
    specs: [
      { label: "Abrasive", value: "Self-sharpening ceramic" },
      { label: "Sizes", value: "115 / 125 / 178 mm" },
      { label: "Grits", value: "40 / 60 / 80" },
      { label: "Backing", value: "Trimmable phenolic" },
      { label: "Max RPM", value: "Rated per size" },
      { label: "Applications", value: "Weld dressing, finishing" },
    ],
    features: ["Self-sharpening ceramic grain", "Fast cut on stainless", "Long service life", "Consistent finish quality"],
  },
];

/* ----------------------------------------------------------------
   LOOKUPS
-----------------------------------------------------------------*/
function productsByCategory(slug) { return PRODUCTS.filter((p) => p.category === slug); }
function getProduct(slug) { return PRODUCTS.find((p) => p.slug === slug); }
function relatedProducts(product, n = 3) {
  return PRODUCTS.filter((p) => p.category === product.category && p.slug !== product.slug).slice(0, n);
}

/* ----------------------------------------------------------------
   SHARED — small brand badge
-----------------------------------------------------------------*/
function BrandBadge({ brand }) {
  const logo = CAT.brandLogo(brand);
  return (
    <div className="flex items-center gap-2.5">
      {logo ? (
        <img src={logo} alt={brand} className="h-5 max-w-[88px] w-auto object-contain" loading="lazy" />
      ) : (
        <span className="text-[12px] tracking-[0.16em] uppercase text-slate-500" style={{ fontWeight: 600 }}>{brand}</span>
      )}
    </div>
  );
}

/* ----------------------------------------------------------------
   PRODUCT LISTING — drop into a category page
-----------------------------------------------------------------*/
function ProductListing({ category, eyebrow = "Product Catalogue", title, dark = false }) {
  const items = productsByCategory(category);
  if (!items.length) return null;
  const heading = title || "Browse the product range.";
  return (
    <section className={dark ? "bg-[#0A1628] py-28 text-white" : "bg-white py-28"}>
      <div className="mx-auto max-w-[1300px] px-6">
        <div className="max-w-2xl mb-12">
          <CAT.SectionEyebrow dark={dark}>{eyebrow}</CAT.SectionEyebrow>
          <h2 className={`mt-4 tracking-tight ${dark ? "" : "text-[#0A1628]"}`} style={{ fontSize: "clamp(1.75rem, 3vw, 2.5rem)", lineHeight: 1.12, fontWeight: 700 }}>
            {heading}
          </h2>
          <p className={`mt-4 ${dark ? "text-slate-300" : "text-slate-600"}`} style={{ fontSize: 16, lineHeight: 1.7 }}>
            Browse representative products in this category. Download technical brochures or send an enquiry — our engineers respond within one business day.
          </p>
        </div>
        <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
          {items.map((p) => (
            <ProductCard key={p.slug} product={p} />
          ))}
        </div>
      </div>
    </section>
  );
}

function ProductCard({ product: p }) {
  const href = `#/product/${p.slug}`;
  return (
    <div className="group flex flex-col bg-white rounded-2xl border border-slate-200 overflow-hidden hover:border-emerald-300 hover:shadow-xl hover:shadow-emerald-900/5 transition-all">
      <a href={href} className="block relative aspect-[4/3] overflow-hidden bg-slate-100">
        <CAT.ImageWithFallback src={p.image} alt={p.name} className="absolute inset-0 w-full h-full object-cover group-hover:scale-105 transition-transform duration-500" />
        <div className="absolute top-4 left-4 bg-white/95 backdrop-blur-sm rounded-lg px-3 py-1.5 shadow-sm">
          <BrandBadge brand={p.brand} />
        </div>
      </a>
      <div className="flex flex-col flex-1 p-6">
        <a href={href}>
          <h3 className="text-[#0A1628] tracking-tight group-hover:text-emerald-700 transition" style={{ fontSize: 18.5, fontWeight: 700, lineHeight: 1.25 }}>{p.name}</h3>
        </a>
        <p className="mt-3 text-slate-600 text-[14.5px] flex-1" style={{ lineHeight: 1.6 }}>{p.short}</p>
        <div className="mt-6 flex flex-col gap-2.5">
          <a href={href} className="group/btn inline-flex items-center justify-center gap-2 px-5 py-3 rounded-full bg-[#0A1628] hover:bg-[#152a47] text-white transition" style={{ fontWeight: 600, fontSize: 14.5 }}>
            View Product
            <CAT.ArrowRight className="w-4 h-4 transition-transform group-hover/btn:translate-x-0.5" />
          </a>
          <div className="grid grid-cols-2 gap-2.5">
            <a href={p.brochure || "#"} className="inline-flex items-center justify-center gap-1.5 px-4 py-2.5 rounded-full border border-slate-300 text-slate-700 hover:border-emerald-500 hover:text-emerald-700 transition text-[13.5px]" style={{ fontWeight: 600 }}>
              <CAT.Download className="w-4 h-4" />
              Brochure
            </a>
            <a href="#/contact" className="inline-flex items-center justify-center gap-1.5 px-4 py-2.5 rounded-full border border-slate-300 text-slate-700 hover:border-emerald-500 hover:text-emerald-700 transition text-[13.5px]" style={{ fontWeight: 600 }}>
              Enquire Now
            </a>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ----------------------------------------------------------------
   PRODUCT DETAIL PAGE  — route: #/product/<slug>
-----------------------------------------------------------------*/
function ProductDetailPage() {
  const slug = (typeof window !== "undefined" ? window.location.hash : "").replace(/^#\/product\//, "").replace(/[?#].*$/, "");
  const product = getProduct(slug);
  if (!product) return <CAT.NotFoundPage />;

  const cat = CATALOG_CATEGORIES[product.category] || {};
  const [active, setActive] = useStateCat(0);
  const gallery = product.gallery && product.gallery.length ? product.gallery : [product.image];
  const mainSrc = IMG(gallery[active]);
  const related = relatedProducts(product);

  return (
    <>
      {/* Breadcrumb bar */}
      <div className="bg-[#0A1628] text-slate-300">
        <div className="mx-auto max-w-[1300px] px-6 py-4">
          <nav className="flex flex-wrap items-center gap-2 text-[13px]">
            <a href="#/" className="hover:text-emerald-300 transition">Home</a>
            <CAT.ChevronRight className="w-3.5 h-3.5 opacity-50" />
            <a href={cat.divisionHref} className="hover:text-emerald-300 transition">{cat.division}</a>
            <CAT.ChevronRight className="w-3.5 h-3.5 opacity-50" />
            <a href={cat.href} className="hover:text-emerald-300 transition">{cat.label}</a>
            <CAT.ChevronRight className="w-3.5 h-3.5 opacity-50" />
            <span className="text-white">{product.name}</span>
          </nav>
        </div>
      </div>

      {/* Gallery + Overview */}
      <section className="bg-white py-16 lg:py-20">
        <div className="mx-auto max-w-[1300px] px-6 grid lg:grid-cols-2 gap-12 lg:gap-16">
          {/* Gallery */}
          <div>
            <div className="rounded-2xl overflow-hidden border border-slate-200 bg-slate-100 aspect-[4/3]">
              <CAT.ImageWithFallback src={mainSrc} alt={product.name} className="w-full h-full object-cover" />
            </div>
            <div className="mt-4 grid grid-cols-3 gap-4">
              {gallery.map((g, i) => (
                <button
                  key={g + i}
                  onClick={() => setActive(i)}
                  className={`rounded-xl overflow-hidden border-2 aspect-[4/3] transition ${active === i ? "border-emerald-500" : "border-slate-200 hover:border-slate-300"}`}
                >
                  <CAT.ImageWithFallback src={IMG(g)} alt={`${product.name} view ${i + 1}`} className="w-full h-full object-cover" />
                </button>
              ))}
            </div>
          </div>

          {/* Overview */}
          <div>
            <a href={cat.href} className="inline-flex items-center gap-2 text-[12px] tracking-[0.18em] uppercase text-emerald-700 hover:text-emerald-600 transition" style={{ fontWeight: 600 }}>
              {cat.label}
            </a>
            <div className="mt-4"><BrandBadge brand={product.brand} /></div>
            <h1 className="mt-3 text-[#0A1628] tracking-tight" style={{ fontSize: "clamp(1.9rem, 3.4vw, 2.75rem)", lineHeight: 1.1, fontWeight: 700 }}>
              {product.name}
            </h1>
            <p className="mt-5 text-slate-600" style={{ fontSize: 16.5, lineHeight: 1.7 }}>{product.overview}</p>

            {product.features && (
              <ul className="mt-7 grid sm:grid-cols-2 gap-x-6 gap-y-3">
                {product.features.map((f) => (
                  <li key={f} className="flex items-start gap-2.5 text-slate-700 text-[14.5px]">
                    <CAT.CheckCircle2 className="w-5 h-5 text-emerald-600 shrink-0 mt-px" />
                    <span style={{ lineHeight: 1.5 }}>{f}</span>
                  </li>
                ))}
              </ul>
            )}

            {/* CTAs */}
            <div className="mt-9 flex flex-col gap-3">
              <div className="flex flex-wrap gap-3">
                <a href={product.brochure || "#"} className="group inline-flex items-center gap-2 px-7 py-3.5 rounded-full bg-blue-600 hover:bg-blue-500 text-white transition" style={{ fontWeight: 600, fontSize: 15 }}>
                  <CAT.Download className="w-4.5 h-4.5" />
                  Download PDF Brochure
                </a>
                <a href={LINE_URL} target="_blank" rel="noreferrer" className="group inline-flex items-center gap-2 px-7 py-3.5 rounded-full text-white transition" style={{ fontWeight: 600, fontSize: 15, background: "#06C755" }}>
                  <CAT.LineIcon className="w-5 h-5" />
                  Enquire via Line
                </a>
              </div>
              <a href="#/contact" className="group inline-flex items-center gap-2 text-[#0A1628] hover:text-emerald-700 transition" style={{ fontWeight: 600, fontSize: 15 }}>
                Or send a detailed enquiry through our form
                <CAT.ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-1" />
              </a>
            </div>
          </div>
        </div>
      </section>

      {/* Technical specifications */}
      <section className="bg-slate-50 py-20">
        <div className="mx-auto max-w-[1300px] px-6">
          <div className="grid lg:grid-cols-[0.8fr_1.2fr] gap-12">
            <div>
              <CAT.SectionEyebrow>Technical Specifications</CAT.SectionEyebrow>
              <h2 className="mt-4 text-[#0A1628] tracking-tight" style={{ fontSize: "clamp(1.5rem, 2.6vw, 2.25rem)", lineHeight: 1.15, fontWeight: 700 }}>
                Specified for the field.
              </h2>
              <p className="mt-4 text-slate-600" style={{ fontSize: 15.5, lineHeight: 1.7 }}>
                Full technical data is provided in the product brochure. Contact our engineers for sizing, certification documents and application support.
              </p>
            </div>
            <div className="rounded-2xl overflow-hidden border border-slate-200 bg-white">
              <table className="w-full text-left">
                <tbody>
                  {product.specs.map((s, i) => (
                    <tr key={s.label} className={i % 2 ? "bg-slate-50/60" : "bg-white"}>
                      <th className="px-6 py-4 text-slate-500 text-[13px] tracking-[0.08em] uppercase align-top w-2/5" style={{ fontWeight: 600 }}>{s.label}</th>
                      <td className="px-6 py-4 text-[#0A1628] text-[15px]" style={{ fontWeight: 500 }}>{s.value}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </section>

      {/* Enquiry CTA */}
      <section className="bg-[#0A1628] text-white py-20">
        <div className="mx-auto max-w-[1300px] px-6">
          <div className="rounded-3xl bg-white/[0.04] border border-white/10 p-10 lg:p-14 flex flex-col lg:flex-row lg:items-center justify-between gap-8">
            <div className="max-w-2xl">
              <div className="inline-flex items-center gap-2 text-emerald-300 text-[13px] tracking-[0.18em] uppercase">
                <span className="w-8 h-px bg-emerald-400" />
                Request information
              </div>
              <h2 className="mt-4 tracking-tight" style={{ fontSize: "clamp(1.6rem, 3vw, 2.4rem)", lineHeight: 1.12, fontWeight: 700 }}>
                Enquire about the {product.name}.
              </h2>
              <p className="mt-4 text-slate-300" style={{ fontSize: 16, lineHeight: 1.65 }}>
                Send us your specification and we will reply with documentation, availability and an engineer's recommendation — no obligation.
              </p>
            </div>
            <div className="flex flex-col gap-3 shrink-0">
              <a href="#/contact" className="group inline-flex items-center justify-center gap-2 px-8 py-4 rounded-full bg-gradient-to-r from-emerald-500 to-teal-500 hover:from-emerald-400 hover:to-teal-400 text-white transition shadow-lg shadow-emerald-900/30" style={{ fontWeight: 600 }}>
                Open Enquiry Form
                <CAT.ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-1" />
              </a>
              <a href={LINE_URL} target="_blank" rel="noreferrer" className="inline-flex items-center justify-center gap-2 px-8 py-4 rounded-full text-white transition" style={{ fontWeight: 600, background: "#06C755" }}>
                <CAT.LineIcon className="w-5 h-5" />
                Chat on Line
              </a>
            </div>
          </div>
        </div>
      </section>

      {/* Related products */}
      {related.length > 0 && (
        <section className="bg-white py-24">
          <div className="mx-auto max-w-[1300px] px-6">
            <div className="flex items-end justify-between gap-6 mb-10">
              <div>
                <CAT.SectionEyebrow>Related Products</CAT.SectionEyebrow>
                <h2 className="mt-4 text-[#0A1628] tracking-tight" style={{ fontSize: "clamp(1.6rem, 2.8vw, 2.25rem)", lineHeight: 1.15, fontWeight: 700 }}>
                  More in {cat.label}.
                </h2>
              </div>
              <a href={cat.href} className="group hidden sm:inline-flex items-center gap-2 text-[#0A1628] hover:text-emerald-700 transition shrink-0" style={{ fontWeight: 600 }}>
                View all
                <CAT.ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-1" />
              </a>
            </div>
            <div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
              {related.map((p) => <ProductCard key={p.slug} product={p} />)}
            </div>
          </div>
        </section>
      )}
    </>
  );
}

/* ----------------------------------------------------------------
   ALL PRODUCTS PAGE — route: #/products
-----------------------------------------------------------------*/
const CATALOG_GROUPS = [
  { group: "Safety", division: "#/safety", items: ["ppe", "footwear", "workwear", "fall-protection"] },
  { group: "Welding", division: "#/welding", items: ["machines", "cutting", "automation", "quality-control"] },
];

/* Sidebar category filter — sticky on desktop, grouped by division */
function CategorySidebar({ filter, setFilter }) {
  const rowBase = "w-full flex items-center justify-between gap-3 text-left rounded-lg px-3.5 py-2.5 text-[14px] transition";
  const Count = ({ n, active }) => (
    <span
      className={`shrink-0 inline-flex items-center justify-center min-w-[26px] h-[22px] px-1.5 rounded-full text-[12px] tabular-nums ${active ? "bg-white/15 text-white" : "bg-slate-100 text-slate-500"}`}
      style={{ fontWeight: 600 }}
    >
      {n}
    </span>
  );

  return (
    <aside className="hidden lg:block lg:sticky lg:top-28 lg:self-start">
      <div className="rounded-2xl border border-slate-200 bg-white p-5">
        <div className="flex items-center gap-2.5 px-1 pb-4 mb-3 border-b border-slate-100">
          <CAT.SlidersHorizontal className="w-4 h-4 text-emerald-600" />
          <span className="text-[12px] tracking-[0.18em] uppercase text-slate-400" style={{ fontWeight: 600 }}>
            Categories
          </span>
        </div>

        {/* All products */}
        <button
          onClick={() => setFilter("all")}
          className={`${rowBase} ${filter === "all" ? "bg-[#0A1628] text-white" : "text-slate-700 hover:bg-slate-50"}`}
          style={{ fontWeight: 600 }}
        >
          <span>All Products</span>
          <Count n={PRODUCTS.length} active={filter === "all"} />
        </button>

        {/* Grouped categories */}
        {CATALOG_GROUPS.map((g) => (
          <div key={g.group} className="mt-5">
            <div className="px-1 mb-1.5 text-[11px] tracking-[0.2em] uppercase text-slate-400" style={{ fontWeight: 700 }}>
              {g.group}
            </div>
            <div className="flex flex-col gap-0.5">
              {g.items.map((key) => {
                const cat = CATALOG_CATEGORIES[key];
                const activeF = filter === key;
                const n = productsByCategory(key).length;
                return (
                  <button
                    key={key}
                    onClick={() => setFilter(key)}
                    className={`${rowBase} ${activeF ? "bg-[#0A1628] text-white" : "text-slate-600 hover:bg-slate-50 hover:text-[#0A1628]"}`}
                    style={{ fontWeight: activeF ? 600 : 500 }}
                  >
                    <span>{cat.label}</span>
                    <Count n={n} active={activeF} />
                  </button>
                );
              })}
            </div>
          </div>
        ))}
      </div>

      {/* Help block */}
      <div className="hidden lg:block mt-5 rounded-2xl border border-slate-200 bg-slate-50 p-5">
        <p className="text-[#0A1628] text-[15px]" style={{ fontWeight: 700 }}>Need help choosing?</p>
        <p className="mt-1.5 text-slate-600 text-[13.5px]" style={{ lineHeight: 1.6 }}>
          Our engineers help you specify the right product for your application.
        </p>
        <a href="#/contact" className="group mt-3.5 inline-flex items-center gap-1.5 text-emerald-700 hover:text-emerald-600 transition text-[14px]" style={{ fontWeight: 600 }}>
          Talk to an engineer
          <CAT.ArrowRight className="w-4 h-4 transition-transform group-hover:translate-x-0.5" />
        </a>
      </div>
    </aside>
  );
}

/* Horizontal scrolling filter row — mobile / tablet only */
function MobileFilterBar({ filter, setFilter }) {
  const chips = [{ key: "all", label: "All Products" }].concat(
    CATALOG_GROUPS.flatMap((g) => g.items.map((key) => ({ key, label: CATALOG_CATEGORIES[key].label })))
  );
  return (
    <div className="lg:hidden -mx-6 px-6 mb-7 overflow-x-auto" style={{ scrollbarWidth: "none" }}>
      <div className="flex gap-2.5 w-max pb-1">
        {chips.map((c) => {
          const activeF = filter === c.key;
          return (
            <button
              key={c.key}
              onClick={() => setFilter(c.key)}
              className={`shrink-0 px-4 py-2.5 rounded-full text-[14px] transition border ${activeF ? "bg-[#0A1628] text-white border-[#0A1628]" : "bg-white text-slate-600 border-slate-200 hover:border-emerald-400 hover:text-emerald-700"}`}
              style={{ fontWeight: 600 }}
            >
              {c.label}
            </button>
          );
        })}
      </div>
    </div>
  );
}

function AllProductsPage() {
  const initialFilter = (() => {
    const m = (typeof window !== "undefined" ? window.location.hash : "").match(/[?&]cat=([^&]+)/);
    return m && CATALOG_CATEGORIES[m[1]] ? m[1] : "all";
  })();
  const [filter, setFilter] = useStateCat(initialFilter);
  const items = filter === "all" ? PRODUCTS : productsByCategory(filter);
  const activeCat = filter === "all" ? null : CATALOG_CATEGORIES[filter];

  return (
    <>
      <CAT.PageHero
        eyebrow="Product Catalogue"
        title="Browse the Full"
        accent="Leeden Catalogue."
        subtitle="Explore our complete range of safety and welding products from the world's leading industrial brands. Filter by category, download technical brochures, or send an enquiry — our engineers respond within one business day."
        image="https://images.unsplash.com/photo-1730584476141-232435a40c32?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&w=2400&q=85"
        breadcrumbs={[{ label: "Products" }]}
        ctaLabel={null}
      />

      <section className="bg-white py-16 lg:py-20">
        <div className="mx-auto max-w-[1300px] px-6">
          <div className="grid lg:grid-cols-[268px_1fr] gap-8 lg:gap-12 items-start">
            {/* Left sidebar filter */}
            <CategorySidebar filter={filter} setFilter={setFilter} />

            {/* Results column */}
            <div className="min-w-0">
              <MobileFilterBar filter={filter} setFilter={setFilter} />
              <div className="flex flex-wrap items-baseline justify-between gap-3 pb-6 border-b border-slate-200">
                <h2 className="text-[#0A1628] tracking-tight" style={{ fontSize: "clamp(1.35rem, 2.2vw, 1.75rem)", lineHeight: 1.15, fontWeight: 700 }}>
                  {activeCat ? activeCat.label : "All Products"}
                </h2>
                <span className="shrink-0 text-slate-500 text-[13.5px]" style={{ fontWeight: 600 }}>
                  {items.length} {items.length === 1 ? "product" : "products"}
                </span>
              </div>

              <div className="mt-8 grid sm:grid-cols-2 xl:grid-cols-3 gap-6">
                {items.map((p) => <ProductCard key={p.slug} product={p} />)}
              </div>
            </div>
          </div>
        </div>
      </section>

      <CAT.PageCta
        title="Can't find what you're"
        accent="looking for?"
        description="Our catalogue is a sample of what we supply. Tell us your specification and our engineers will source the right product from our global brand partners."
        primaryLabel="Send an Enquiry"
        secondaryLabel="Talk to an Engineer"
      />
    </>
  );
}

Object.assign(window, {
  CATALOG_CATEGORIES, PRODUCTS,
  productsByCategory, getProduct, relatedProducts,
  ProductListing, ProductCard, ProductDetailPage, AllProductsPage,
});
