{"id":10003,"date":"2026-09-24T13:50:00","date_gmt":"2026-09-24T20:50:00","guid":{"rendered":"https:\/\/fargotechs.com\/?page_id=10003"},"modified":"2026-09-25T04:37:11","modified_gmt":"2026-09-25T04:37:11","slug":"visual-journey","status":"publish","type":"page","link":"https:\/\/fargotechs.com\/?page_id=10003","title":{"rendered":"Visual Journey"},"content":{"rendered":"\n<style>\n:root{\n  --blue:#046bd2; --blue-d:#045cb4; --ink:#1e293b; --body:#334155; --bg:#ffffff;\n  --bg2:#F0F5FA; --line:#e7e7e7; --border2:#D1D5DB; --muted:#64748b; --dark:#111111;\n  --green:#2e7d32; --amber:#b38600; --red:#c62828;\n  --font:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif;\n}\n*{box-sizing:border-box;margin:0;padding:0;font-family:var(--font);}\nbody{background:var(--bg);color:var(--body);font-size:15px;line-height:1.6;-webkit-font-smoothing:antialiased;}\na{color:var(--blue);}\n.banner{background:var(--ink);color:#fff;font-size:12px;text-align:center;padding:7px 16px;letter-spacing:.4px;font-weight:600;}\n.site-header{background:#fff;border-bottom:1px solid var(--line);position:sticky;top:0;z-index:50;}\n.site-header .bar{max-width:1200px;margin:0 auto;padding:14px 24px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;}\n.brand{font-size:18px;font-weight:700;color:var(--ink);text-decoration:none;display:flex;align-items:center;gap:10px;}\n.brand .mark{width:28px;height:28px;border-radius:6px;background:var(--blue);color:#fff;display:inline-flex;align-items:center;justify-content:center;font-weight:800;font-size:14px;}\n.nav a{color:var(--body);text-decoration:none;margin-left:22px;font-size:14px;font-weight:500;}\n.nav a:hover,.nav a.active{color:var(--blue);}\n.section{max-width:1200px;margin:0 auto;padding:56px 24px;}\n.section.alt{background:var(--bg2);}\n.eyebrow{color:var(--blue);font-weight:700;font-size:12px;letter-spacing:1.2px;text-transform:uppercase;}\nh1.hero-title{font-size:40px;line-height:1.14;color:var(--ink);font-weight:700;margin:10px 0 16px;letter-spacing:-.4px;}\n.lead{font-size:17px;color:var(--body);max-width:640px;}\n.btn{display:inline-block;background:var(--blue);color:#fff;padding:11px 20px;border-radius:3px;font-weight:600;font-size:14px;text-decoration:none;border:1px solid var(--blue);cursor:pointer;}\n.btn:hover{background:var(--blue-d);border-color:var(--blue-d);}\n.btn.ghost{background:#fff;color:var(--blue);}\n.btn.ghost:hover{background:var(--bg2);}\n.flow{display:grid;grid-template-columns:minmax(0,1fr) 350px;gap:22px;align-items:start;}\n@media(max-width:980px){.flow{grid-template-columns:1fr;}}\n.scene-card{background:#fff;border:1px solid var(--line);border-radius:10px;padding:14px;box-shadow:0 1px 3px rgba(16,24,42,.06);}\n.scene-card svg{width:100%;height:auto;display:block;border-radius:8px;user-select:none;}\n.controls{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-top:14px;}\n.controls button{background:var(--blue);color:#fff;border:1px solid var(--blue);border-radius:3px;padding:9px 15px;font-size:13px;font-weight:600;cursor:pointer;font-family:var(--font);}\n.controls button:hover{background:var(--blue-d);}\n.controls button.ghost{background:#fff;color:var(--blue);}\n.controls button:disabled{opacity:.5;cursor:not-allowed;}\n.controls .grow{flex:1;}\n.speed{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--muted);}\n.speed input[type=range]{width:96px;accent-color:var(--blue);}\n.benefit{margin-top:14px;background:var(--bg2);border:1px solid #dbe4ee;border-left:4px solid var(--blue);border-radius:6px;padding:13px 16px;font-size:14px;color:var(--ink);}\n.benefit b{display:block;margin-bottom:4px;color:var(--blue);font-size:14px;}\n.legend{display:flex;flex-wrap:wrap;gap:14px;font-size:12.5px;color:var(--muted);margin-top:12px;}\n.legend span{display:flex;align-items:center;gap:6px;}\n.swatch{width:14px;height:14px;border-radius:3px;border:1px solid rgba(0,0,0,.25);}\n.note{font-size:12px;color:var(--muted);margin-top:10px;}\n.side{display:flex;flex-direction:column;gap:16px;}\n.card{background:#fff;border:1px solid var(--line);border-radius:10px;padding:16px;box-shadow:0 1px 3px rgba(16,24,42,.06);}\n.card h2{font-size:13px;color:var(--ink);text-transform:uppercase;letter-spacing:.6px;margin-bottom:10px;}\n.kpis{display:grid;grid-template-columns:1fr 1fr;gap:8px;}\n.kpi{background:var(--bg2);border:1px solid var(--line);border-radius:6px;padding:10px;text-align:center;}\n.kpi .v{font-size:22px;font-weight:700;color:var(--ink);line-height:1.1;}\n.kpi .l{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.4px;margin-top:2px;}\n.tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);margin-bottom:10px;}\n.tabs button{background:none;border:none;padding:8px 10px;cursor:pointer;font-size:12.5px;color:var(--muted);border-bottom:3px solid transparent;font-family:var(--font);font-weight:600;}\n.tabs button.active{color:var(--blue);border-bottom-color:var(--blue);}\n.panel-body table{width:100%;border-collapse:collapse;font-size:12.5px;}\n.panel-body th{background:var(--bg2);text-align:left;padding:6px 8px;border:1px solid var(--line);font-weight:600;color:var(--ink);}\n.panel-body td{padding:6px 8px;border:1px solid var(--line);vertical-align:top;color:var(--body);}\n.log{font-family:Menlo,Consolas,monospace;font-size:11px;background:#0f172a;color:#cde3ff;padding:10px;border-radius:6px;max-height:200px;overflow:auto;white-space:pre-wrap;line-height:1.5;}\n.pill{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10.5px;font-weight:700;}\n.pill.g{background:#e2efda;color:var(--green);}.pill.y{background:#fff2cc;color:var(--amber);}.pill.r{background:#fce4ec;color:var(--red);}.pill.b{background:#ddebf7;color:var(--blue);}\n.exception{background:#fce4ec;border:1px solid #e8b4c0;color:var(--red);padding:11px 13px;border-radius:6px;font-size:13px;margin-top:6px;display:none;}\n.exception.visible{display:block;}\n.exception button{background:var(--red);color:#fff;border:none;border-radius:4px;padding:5px 11px;font-size:12px;cursor:pointer;margin-left:8px;font-weight:600;font-family:var(--font);}\n.clickable{cursor:pointer;}\n.clickable:hover{filter:brightness(1.04);}\n.checkpoint{opacity:.6;transition:opacity .2s;}\n.checkpoint.active{opacity:1;}\n.checkpoint.pulse circle{animation:cp 0.6s ease-out 2;}\n@keyframes cp{0%{r:5;opacity:1;}100%{r:20;opacity:0;}}\n.box-label{font-size:9px;font-weight:700;fill:var(--ink);text-anchor:middle;pointer-events:none;}\n@media(prefers-reduced-motion:reduce){*{transition-duration:.001ms!important;animation-duration:.001ms!important;}}\n.gallery{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:18px;margin-top:24px;}\n.thumb{background:#fff;border:1px solid var(--line);border-radius:10px;padding:14px;cursor:pointer;transition:box-shadow .2s,transform .15s;position:relative;}\n.thumb:hover{box-shadow:0 6px 18px rgba(16,24,42,.10);transform:translateY(-2px);}\n.thumb svg{width:100%;height:140px;}\n.thumb .cap{font-size:13px;color:var(--ink);font-weight:600;margin-top:8px;text-align:center;}\n.thumb .badge{position:absolute;top:10px;right:10px;background:#fff8e6;color:#6b5416;font-size:9px;font-weight:700;padding:3px 7px;border-radius:4px;border:1px solid #ecd9a0;}\n.lightbox{display:none;position:fixed;inset:0;background:rgba(15,23,42,.85);z-index:1000;justify-content:center;align-items:center;padding:40px 20px;}\n.lightbox.open{display:flex;}\n.lightbox-content{background:#fff;border-radius:10px;max-width:880px;width:100%;max-height:90vh;overflow:auto;padding:24px;position:relative;}\n.lightbox-close{position:absolute;top:12px;right:16px;font-size:26px;color:#555;cursor:pointer;line-height:1;}\n.lightbox svg{width:100%;height:auto;max-height:460px;}\n.lightbox-cap{margin-top:14px;color:var(--ink);font-size:15px;font-weight:600;}\n.lightbox-meta{font-size:13px;color:var(--muted);margin-top:6px;}\n.gallery-notice{background:#fff8e6;border:1px solid #ecd9a0;border-radius:6px;padding:12px 16px;font-size:13px;color:#6b5416;margin-top:18px;}\n.site-footer{background:var(--bg2);border-top:1px solid var(--line);margin-top:30px;}\n.site-footer .bar{max-width:1200px;margin:0 auto;padding:22px 24px;font-size:13px;color:var(--muted);display:flex;justify-content:space-between;flex-wrap:wrap;gap:10px;}\n<\/style><style>body.elementor-template-canvas{margin:0} .e-con,.elementor-widget-container{padding:0} @media(max-width:600px){h1.hero-title{font-size:32px}.section{padding:36px 18px}.nav{display:flex;flex-wrap:wrap;gap:12px}.nav a{margin-left:0}.credits{overflow:auto}}<\/style>\n\n\n\n<header class=\"site-header\">\n  <div class=\"bar\">\n    <a class=\"brand\" href=\"\/\"><span class=\"mark\">F<\/span> Fargo Techs Inc.<\/a>\n    <nav class=\"nav\">\n      <a href=\"\/\">Home<\/a>\n      <a href=\"\/?pagename=returnable-container-traceability\">RCT Solution<\/a>\n      <a href=\"\/?pagename=visual-journey\" class=\"active\">Visual Journey<\/a>\n      <a href=\"\/?pagename=operational-dashboard\">Operational Dashboard<\/a>\n      <a href=\"\/#contact\">Contact<\/a>\n    <\/nav>\n  <\/div>\n<\/header>\n\n<section class=\"section\">\n  <div class=\"eyebrow\">Returnable Container Traceability<\/div>\n  <h1 class=\"hero-title\">Watch a truck collect reusable boxes from a recycling depot.<\/h1>\n  <p class=\"lead\">A closed-loop WMS workflow, shown as a single coherent scene. Press Play to run the loop \u2014 every box keeps its asset ID, every scan is validated against the manifest, and any discrepancy is flagged and resolved.<\/p>\n  <p style=\"margin-top:14px;\">\n    <button class=\"btn\" onclick=\"play()\">\u25b6 Play the loop<\/button>\n    <a class=\"btn ghost\" href=\"\/?pagename=operational-dashboard\">Open the operational dashboard \u2192<\/a>\n  <\/p>\n<\/section>\n\n<section class=\"section alt\" style=\"padding-top:24px;\">\n  <div class=\"flow\">\n    <div>\n      <div class=\"scene-card\">\n        <svg viewBox=\"0 0 1000 540\" id=\"scene\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" role=\"img\" aria-label=\"Side-view scene: a recycling depot with collection bays on the left, a warehouse with loading docks on the right, and a box truck collecting reusable pallet boxes.\">\n          <defs>\n            <linearGradient id=\"sky\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#eaf1f8\"\/><stop offset=\"1\" stop-color=\"#f7fafc\"\/><\/linearGradient>\n            <linearGradient id=\"wallDepot\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#e6ecf2\"\/><stop offset=\"1\" stop-color=\"#d2dce4\"\/><\/linearGradient>\n            <linearGradient id=\"wallWh\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#e9eef3\"\/><stop offset=\"1\" stop-color=\"#d6dee6\"\/><\/linearGradient>\n            <linearGradient id=\"truckBody\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#fbfdfe\"\/><stop offset=\"1\" stop-color=\"#e7edf2\"\/><\/linearGradient>\n            <linearGradient id=\"cab\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#1a7fe0\"\/><stop offset=\"1\" stop-color=\"#045cb4\"\/><\/linearGradient>\n          <\/defs>\n\n          <!-- sky + ground -->\n          <rect width=\"1000\" height=\"540\" fill=\"url(#sky)\"\/>\n          <rect x=\"0\" y=\"392\" width=\"1000\" height=\"148\" fill=\"#e2e8ee\"\/>\n          <rect x=\"0\" y=\"402\" width=\"1000\" height=\"46\" fill=\"#c3ccd4\"\/>\n          <line x1=\"0\" y1=\"425\" x2=\"1000\" y2=\"425\" stroke=\"#f4d35e\" stroke-width=\"3\" stroke-dasharray=\"22 18\" opacity=\".55\"\/>\n\n          <!-- ===== RECYCLING DEPOT (left) ===== -->\n          <g id=\"depot\" class=\"clickable\" onclick=\"showDetail('Depot A')\">\n            <rect x=\"20\" y=\"70\" width=\"344\" height=\"262\" rx=\"4\" fill=\"url(#wallDepot)\" stroke=\"#aeb9c4\" stroke-width=\"2\"\/>\n            <rect x=\"12\" y=\"58\" width=\"360\" height=\"20\" rx=\"3\" fill=\"#9aa7b3\"\/>\n            <rect x=\"12\" y=\"74\" width=\"360\" height=\"4\" fill=\"#8a98a5\"\/>\n            <rect x=\"64\" y=\"92\" width=\"256\" height=\"34\" rx=\"4\" fill=\"#046bd2\"\/>\n            <text x=\"192\" y=\"115\" text-anchor=\"middle\" fill=\"#fff\" font-size=\"16\" font-weight=\"700\" letter-spacing=\".5\">RECYCLING DEPOT<\/text>\n            <!-- subtle windows -->\n            <rect x=\"40\" y=\"150\" width=\"60\" height=\"40\" rx=\"2\" fill=\"#cdd8e1\" stroke=\"#b3c0cb\" stroke-width=\"1\"\/>\n            <rect x=\"288\" y=\"150\" width=\"60\" height=\"40\" rx=\"2\" fill=\"#cdd8e1\" stroke=\"#b3c0cb\" stroke-width=\"1\"\/>\n            <!-- collection bays: 3 open-front frames holding pallet boxes -->\n            <g id=\"bays\">\n              <rect x=\"36\" y=\"356\" width=\"84\" height=\"20\" rx=\"2\" fill=\"#b9c2cb\"\/>\n              <rect x=\"36\" y=\"250\" width=\"84\" height=\"106\" rx=\"2\" fill=\"#dfe6ec\" stroke=\"#b3c0cb\" stroke-width=\"1\"\/>\n              <rect x=\"44\" y=\"262\" width=\"6\" height=\"92\" fill=\"#c2ccd5\"\/><rect x=\"106\" y=\"262\" width=\"6\" height=\"92\" fill=\"#c2ccd5\"\/>\n              <text x=\"78\" y=\"346\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"700\" fill=\"#64748b\">BAY 1<\/text>\n\n              <rect x=\"146\" y=\"356\" width=\"84\" height=\"20\" rx=\"2\" fill=\"#b9c2cb\"\/>\n              <rect x=\"146\" y=\"250\" width=\"84\" height=\"106\" rx=\"2\" fill=\"#dfe6ec\" stroke=\"#b3c0cb\" stroke-width=\"1\"\/>\n              <rect x=\"154\" y=\"262\" width=\"6\" height=\"92\" fill=\"#c2ccd5\"\/><rect x=\"216\" y=\"262\" width=\"6\" height=\"92\" fill=\"#c2ccd5\"\/>\n              <text x=\"188\" y=\"346\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"700\" fill=\"#64748b\">BAY 2<\/text>\n\n              <rect x=\"256\" y=\"356\" width=\"84\" height=\"20\" rx=\"2\" fill=\"#b9c2cb\"\/>\n              <rect x=\"256\" y=\"250\" width=\"84\" height=\"106\" rx=\"2\" fill=\"#dfe6ec\" stroke=\"#b3c0cb\" stroke-width=\"1\"\/>\n              <rect x=\"264\" y=\"262\" width=\"6\" height=\"92\" fill=\"#c2ccd5\"\/><rect x=\"326\" y=\"262\" width=\"6\" height=\"92\" fill=\"#c2ccd5\"\/>\n              <text x=\"298\" y=\"346\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"700\" fill=\"#64748b\">BAY 3<\/text>\n            <\/g>\n          <\/g>\n\n          <!-- ===== WAREHOUSE (right) ===== -->\n          <g id=\"wh\" class=\"clickable\" onclick=\"showDetail('WH')\">\n            <rect x=\"640\" y=\"58\" width=\"344\" height=\"274\" rx=\"4\" fill=\"url(#wallWh)\" stroke=\"#aeb9c4\" stroke-width=\"2\"\/>\n            <rect x=\"632\" y=\"46\" width=\"360\" height=\"20\" rx=\"3\" fill=\"#8b98a5\"\/>\n            <rect x=\"632\" y=\"62\" width=\"360\" height=\"4\" fill=\"#76838f\"\/>\n            <rect x=\"700\" y=\"80\" width=\"224\" height=\"30\" rx=\"4\" fill=\"#1e293b\"\/>\n            <text x=\"812\" y=\"101\" text-anchor=\"middle\" fill=\"#fff\" font-size=\"16\" font-weight=\"700\" letter-spacing=\".5\">WAREHOUSE<\/text>\n            <!-- loading docks -->\n            <rect x=\"690\" y=\"250\" width=\"116\" height=\"84\" rx=\"3\" fill=\"#5b6b78\"\/>\n            <rect x=\"698\" y=\"258\" width=\"100\" height=\"68\" rx=\"2\" fill=\"#46535f\"\/>\n            <rect x=\"748\" y=\"300\" width=\"40\" height=\"26\" fill=\"#2f3a44\"\/>\n            <rect x=\"836\" y=\"250\" width=\"116\" height=\"84\" rx=\"3\" fill=\"#5b6b78\"\/>\n            <rect x=\"844\" y=\"258\" width=\"100\" height=\"68\" rx=\"2\" fill=\"#46535f\"\/>\n            <rect x=\"894\" y=\"300\" width=\"40\" height=\"26\" fill=\"#2f3a44\"\/>\n            <!-- dock bumpers + levelers -->\n            <rect x=\"686\" y=\"334\" width=\"8\" height=\"16\" fill=\"#1e293b\"\/><rect x=\"802\" y=\"334\" width=\"8\" height=\"16\" fill=\"#1e293b\"\/>\n            <rect x=\"832\" y=\"334\" width=\"8\" height=\"16\" fill=\"#1e293b\"\/><rect x=\"948\" y=\"334\" width=\"8\" height=\"16\" fill=\"#1e293b\"\/>\n          <\/g>\n\n          <!-- ===== RFID checkpoints (subtle) ===== -->\n          <g id=\"cp-wh-out\" class=\"checkpoint\" transform=\"translate(624,372)\"><circle r=\"5\" fill=\"#046bd2\"\/><rect x=\"-9\" y=\"-15\" width=\"18\" height=\"8\" rx=\"2\" fill=\"#046bd2\"\/><text x=\"0\" y=\"20\" text-anchor=\"middle\" fill=\"#046bd2\" font-size=\"9\" font-weight=\"700\">RFID<\/text><\/g>\n          <g id=\"cp-a-in\" class=\"checkpoint\" transform=\"translate(372,372)\"><circle r=\"5\" fill=\"#046bd2\"\/><rect x=\"-9\" y=\"-15\" width=\"18\" height=\"8\" rx=\"2\" fill=\"#046bd2\"\/><text x=\"0\" y=\"20\" text-anchor=\"middle\" fill=\"#046bd2\" font-size=\"9\" font-weight=\"700\">RFID<\/text><\/g>\n          <g id=\"cp-a-out\" class=\"checkpoint\" transform=\"translate(372,392)\"><circle r=\"5\" fill=\"#046bd2\"\/><rect x=\"-9\" y=\"-15\" width=\"18\" height=\"8\" rx=\"2\" fill=\"#046bd2\"\/><text x=\"0\" y=\"20\" text-anchor=\"middle\" fill=\"#046bd2\" font-size=\"9\" font-weight=\"700\">RFID<\/text><\/g>\n          <g id=\"cp-wh-in\" class=\"checkpoint\" transform=\"translate(624,392)\"><circle r=\"5\" fill=\"#046bd2\"\/><rect x=\"-9\" y=\"-15\" width=\"18\" height=\"8\" rx=\"2\" fill=\"#046bd2\"\/><text x=\"0\" y=\"20\" text-anchor=\"middle\" fill=\"#046bd2\" font-size=\"9\" font-weight=\"700\">RFID<\/text><\/g>\n\n          <!-- ===== BOXES (populated by JS) ===== -->\n          <g id=\"boxes\"><\/g>\n\n          <!-- ===== TRUCK ===== -->\n          <g id=\"truck\" class=\"clickable\" onclick=\"showDetail('TRUCK')\" style=\"transform:translate(640px,410px);\">\n            <ellipse cx=\"132\" cy=\"24\" rx=\"142\" ry=\"9\" fill=\"#000\" opacity=\"0.12\"\/>\n            <!-- chassis -->\n            <rect x=\"8\" y=\"-6\" width=\"252\" height=\"12\" rx=\"2\" fill=\"#4b5762\"\/>\n            <!-- cargo box -->\n            <rect x=\"8\" y=\"-104\" width=\"182\" height=\"98\" rx=\"6\" fill=\"url(#truckBody)\" stroke=\"#b9c4ce\" stroke-width=\"2\"\/>\n            <line x1=\"14\" y1=\"-78\" x2=\"184\" y2=\"-78\" stroke=\"#d4dde5\" stroke-width=\"1\"\/>\n            <line x1=\"14\" y1=\"-52\" x2=\"184\" y2=\"-52\" stroke=\"#d4dde5\" stroke-width=\"1\"\/>\n            <rect x=\"26\" y=\"-96\" width=\"78\" height=\"22\" rx=\"3\" fill=\"#046bd2\"\/>\n            <text x=\"44\" y=\"-80\" font-size=\"13\" font-weight=\"800\" fill=\"#fff\">FARGO<\/text>\n            <text x=\"108\" y=\"-82\" font-size=\"9\" font-weight=\"700\" fill=\"#5b6b78\" letter-spacing=\"1\">RETURN\u00b7IT<\/text>\n            <!-- cab -->\n            <rect x=\"190\" y=\"-72\" width=\"66\" height=\"66\" rx=\"9\" fill=\"url(#cab)\" stroke=\"#034b94\" stroke-width=\"1\"\/>\n            <rect x=\"210\" y=\"-64\" width=\"36\" height=\"30\" rx=\"4\" fill=\"#cfe0f2\" stroke=\"#9bb6d4\" stroke-width=\"1\"\/>\n            <rect x=\"196\" y=\"-22\" width=\"60\" height=\"10\" rx=\"2\" fill=\"#2b3640\"\/>\n            <!-- wheels -->\n            <g>\n              <circle cx=\"54\" cy=\"6\" r=\"16\" fill=\"#1f2630\"\/><circle cx=\"54\" cy=\"6\" r=\"7\" fill=\"#8b97a3\"\/><circle cx=\"54\" cy=\"6\" r=\"3\" fill=\"#cfd6dd\"\/>\n              <circle cx=\"138\" cy=\"6\" r=\"16\" fill=\"#1f2630\"\/><circle cx=\"138\" cy=\"6\" r=\"7\" fill=\"#8b97a3\"\/><circle cx=\"138\" cy=\"6\" r=\"3\" fill=\"#cfd6dd\"\/>\n              <circle cx=\"220\" cy=\"6\" r=\"16\" fill=\"#1f2630\"\/><circle cx=\"220\" cy=\"6\" r=\"7\" fill=\"#8b97a3\"\/><circle cx=\"220\" cy=\"6\" r=\"3\" fill=\"#cfd6dd\"\/>\n            <\/g>\n            <text x=\"120\" y=\"-118\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"700\" fill=\"#334155\">COLLECTION TRUCK<\/text>\n          <\/g>\n        <\/svg>\n      <\/div>\n\n      <div class=\"controls\">\n        <button id=\"btnPlay\" onclick=\"togglePlay()\">\u25b6 Play<\/button>\n        <button class=\"ghost\" onclick=\"nextStep()\">Next step \u2192<\/button>\n        <button class=\"ghost\" onclick=\"runGuided()\">Guided tour<\/button>\n        <button class=\"ghost\" onclick=\"replay()\">\u21ba Replay<\/button>\n        <button class=\"ghost\" onclick=\"resetAll()\">Reset<\/button>\n        <span class=\"grow\"><\/span>\n        <span class=\"speed\"><label for=\"speed\">Speed<\/label>\n          <input id=\"speed\" type=\"range\" min=\"0.4\" max=\"2\" step=\"0.2\" value=\"1\" aria-label=\"animation speed\">\n          <span id=\"speedVal\">1\u00d7<\/span>\n        <\/span>\n      <\/div>\n\n      <div class=\"benefit\" id=\"benefit\"><b>Ready.<\/b> Press Play or Guided tour to run the closed-loop demonstration. Each step explains the operational benefit.<\/div>\n\n      <div class=\"legend\">\n        <span><span class=\"swatch\" style=\"background:#eef2f5;border-color:#1e293b;\"><\/span> Empty<\/span>\n        <span><span class=\"swatch\" style=\"background:#d8ecdb;\"><\/span> Full<\/span>\n        <span><span class=\"swatch\" style=\"background:#d7e6f7;\"><\/span> Cleaning<\/span>\n        <span><span class=\"swatch\" style=\"background:#f6d6d6;\"><\/span> Exception<\/span>\n        <span><span class=\"swatch\" style=\"background:#046bd2;\"><\/span> RFID check<\/span>\n      <\/div>\n      <p class=\"note\">Truck movement is an illustrative journey, not live GPS. RFID reads are simulated checkpoint observations validated against the manifest before custody is confirmed. Illustrative demo \u00b7 Synthetic data \u00b7 Simulated RFID \u00b7 Not connected to any production or customer system.<\/p>\n    <\/div>\n\n    <div class=\"side\">\n      <div class=\"card\">\n        <h2>Loop progress<\/h2>\n        <div class=\"kpis\" id=\"kpis\">\n          <div class=\"kpi\"><div class=\"v\" id=\"kpi-wh\">&#8211;<\/div><div class=\"l\">@ Warehouse<\/div><\/div>\n          <div class=\"kpi\"><div class=\"v\" id=\"kpi-a\">&#8211;<\/div><div class=\"l\">@ Depot<\/div><\/div>\n          <div class=\"kpi\"><div class=\"v\" id=\"kpi-truck\">&#8211;<\/div><div class=\"l\">On truck<\/div><\/div>\n          <div class=\"kpi\"><div class=\"v\" id=\"kpi-ex\">&#8211;<\/div><div class=\"l\">Open exceptions<\/div><\/div>\n        <\/div>\n        <div class=\"exception\" id=\"exceptionBanner\">\n          <b>Exception:<\/b> <span id=\"exceptionText\"><\/span>\n          <button onclick=\"resolveException()\">Resolve with audit record<\/button>\n        <\/div>\n      <\/div>\n\n      <div class=\"card\">\n        <div class=\"tabs\">\n          <button class=\"active\" onclick=\"setPanel('manifest')\" id=\"tab-manifest\">Trip<\/button>\n          <button onclick=\"setPanel('inventory')\" id=\"tab-inventory\">Inventory<\/button>\n          <button onclick=\"setPanel('events')\" id=\"tab-events\">Events<\/button>\n          <button onclick=\"setPanel('details')\" id=\"tab-details\">Details<\/button>\n        <\/div>\n        <div class=\"panel-body\">\n          <div id=\"panel-manifest\"><p class=\"note\">No active trip yet. Start the demo to see the manifest.<\/p><\/div>\n          <div id=\"panel-inventory\" style=\"display:none;\"><\/div>\n          <div id=\"panel-events\" style=\"display:none;\"><div class=\"log\" id=\"eventLog\">No events yet.<\/div><\/div>\n          <div id=\"panel-details\" style=\"display:none;\"><p class=\"note\">Click the truck, the depot, the warehouse, or a box to see details.<\/p><\/div>\n        <\/div>\n      <\/div>\n\n      <a class=\"btn ghost\" style=\"text-align:center;\" href=\"\/?pagename=operational-dashboard\">Open the full operational dashboard \u2192<\/a>\n    <\/div>\n  <\/div>\n<\/section>\n\n<section class=\"section\" id=\"gallery\">\n  <div class=\"eyebrow\">Product<\/div>\n  <h2 style=\"color:var(--ink);font-size:28px;margin:8px 0 6px;\">The reusable sleeve-box system<\/h2>\n  <p style=\"color:var(--body);max-width:760px;\">Our traceability workflow is built around collapsible, returnable bulk containers \u2014 a pallet base, a foldable sleeve, and a lid (\u5929\u5730\u76d6). These are original Fargo Techs illustrations, not supplier photographs.<\/p>\n  <div class=\"gallery\">\n    <div class=\"thumb\" onclick=\"openBox(0)\"><span class=\"badge\">ILLUSTRATION<\/span><div id=\"g0\"><\/div><div class=\"cap\">Assembled box<\/div><\/div>\n    <div class=\"thumb\" onclick=\"openBox(1)\"><span class=\"badge\">ILLUSTRATION<\/span><div id=\"g1\"><\/div><div class=\"cap\">Collapsed box<\/div><\/div>\n    <div class=\"thumb\" onclick=\"openBox(2)\"><span class=\"badge\">ILLUSTRATION<\/span><div id=\"g2\"><\/div><div class=\"cap\">Components<\/div><\/div>\n    <div class=\"thumb\" onclick=\"openBox(3)\"><span class=\"badge\">ILLUSTRATION<\/span><div id=\"g3\"><\/div><div class=\"cap\">Handling &amp; stacking<\/div><\/div>\n  <\/div>\n  <div class=\"gallery-notice\">Illustrative container designs. Final dimensions, materials and handling ratings are confirmed during product selection and testing.<\/div>\n<\/section>\n\n<section class=\"section alt\" id=\"contact\">\n  <div class=\"eyebrow\">Contact<\/div>\n  <h2 style=\"color:var(--ink);font-size:28px;margin:8px 0 10px;\">Talk about a warehouse system, RFID idea, or returnable-container loop.<\/h2>\n  <p style=\"color:var(--body);\">Share what you are trying to improve, what systems or devices are already in place, and what a successful result would look like.<\/p>\n  <p style=\"margin-top:14px;color:var(--body);\"><b>Address<\/b> \u00b7 108-2971 Viking Way, Richmond, BC V6V 1Y1<br><b>Email<\/b> \u00b7 <a href=\"mailto:info@fargotechs.com\">info@fargotechs.com<\/a><\/p>\n<\/section>\n\n<footer class=\"site-footer\">\n  <div class=\"bar\">\n    <span>Fargo Techs Inc. \u2014 Returnable Container Traceability <\/span>\n    <span>Illustrative demo \u00b7 Synthetic data \u00b7 Simulated RFID<\/span>\n  <\/div>\n<\/footer>\n\n<div id=\"lightbox\" class=\"lightbox\" onclick=\"closeBox(event)\">\n  <div class=\"lightbox-content\" onclick=\"event.stopPropagation()\">\n    <span class=\"lightbox-close\" onclick=\"closeBox()\">&times;<\/span>\n    <div id=\"lightbox-svg\"><\/div>\n    <div id=\"lightbox-cap\" class=\"lightbox-cap\"><\/div>\n    <div id=\"lightbox-meta\" class=\"lightbox-meta\"><\/div>\n  <\/div>\n<\/div>\n\n<script>\n\"use strict\";\n\/* ================= CORE WMS MODEL (reused verbatim from tested fargo_rct_animated.html) ================= *\/\nconst SITES = {WH:\"Warehouse WH1\", DA:\"Depot A\", DB:\"Depot B\", TRUCK:\"Truck (in transit)\", WASH:\"Wash\/Inspect Bay\"};\nconst GROUND = [SITES.WH, SITES.DA, SITES.DB, SITES.WASH];\nconst ASSET_IDS = [\"AST-001\",\"AST-002\",\"AST-003\",\"AST-004\",\"AST-005\",\"AST-008\"]; \/\/ 008 reserved; 003 is the collection discrepancy\nlet assets={}, tags={}, trips=[], events=[], exceptions=[], idemSeen=new Set(), seq=1000;\n\nfunction ts0(i){const d=new Date(\"2026-09-23T08:00:00\");d.setMinutes(d.getMinutes()+i*3);return d.toISOString();}\nfunction now(){return new Date().toISOString();}\nfunction logEvent(e){e.ingestedAt=now();e.eventId=\"EV-\"+(++seq);events.push(e);return e;}\n\nfunction freshState(){\n  seq=1000; idemSeen=new Set(); assets={}; tags={}; trips=[]; events=[]; exceptions=[];\n  ASSET_IDS.forEach((id,i)=>{\n    const epc=\"E280.6894.0000.\"+(2000+i);\n    assets[id]={id, status:\"active\", confirmedSite:SITES.WH, lastSite:SITES.WH, lastRead:null, contents:null, epcs:[epc], createdAt:ts0(i)};\n    tags[epc]={epc, assetId:id, position:\"body\", status:\"active\"};\n    logEvent({type:\"COMMISSION\", assetId:id, epc, site:SITES.WH, src:\"handheld\", op:\"OP-01\", idemKey:\"seed-\"+id, at:ts0(i)});\n  });\n}\nfunction ingest(type, assetId, epc, site, src, op, idemKey){\n  if(!assets[assetId]) return {status:\"UNKNOWN_ASSET\", key:idemKey};\n  if(idemSeen.has(idemKey)) return {status:\"DUPLICATE_IDEMPOTENCY\", key:idemKey};\n  const BURST_MS=3000;\n  const SCAN=[\"DISPATCH\",\"RECEIPT\",\"MOVE\",\"RETURN\"];\n  const last=[...events].reverse().find(ev=>ev.assetId===assetId&&ev.site===site&&SCAN.includes(ev.type));\n  if(SCAN.includes(type)&&last && (Date.parse(now())-Date.parse(last.ingestedAt))<BURST_MS) return {status:\"DEDUPED_BURST\", key:idemKey};\n  idemSeen.add(idemKey);\n  const a=assets[assetId];\n  const ev=logEvent({type, assetId, epc, site, src, op, idemKey, observedAt:now()});\n  const CONFLICT_MS=600000; \/\/ synthetic-demo window: prevents false conflict exceptions from compressed playback; genuine cross-site conflicts in a real deployment still detected\n  const recent=[...events].reverse().find(x=>x.assetId===assetId&&x.site!==site&&GROUND.includes(x.site)&&[\"DISPATCH\",\"RECEIPT\",\"MOVE\",\"RETURN\"].includes(x.type));\n  if(recent && Math.abs(Date.parse(ev.ingestedAt)-Date.parse(recent.ingestedAt))<CONFLICT_MS){\n    a.lastSite=site; a.lastRead=now();\n    exceptions.push({id:\"EX-\"+(++seq), assetId, kind:\"CONFLICTING_OBSERVATION\", detail:`Read at ${site} within ${CONFLICT_MS\/1000}s of ${recent.site} \u2014 both retained; custody unconfirmed`, resolved:false});\n    return {status:\"CONFLICT\", event:ev};\n  }\n  a.lastSite=site; a.lastRead=now();\n  return {status:\"OK\", event:ev};\n}\nfunction confirmLocation(assetId, site){\n  assets[assetId].confirmedSite=site;\n  logEvent({type:\"LOCATION_CONFIRMED\", assetId, site, src:\"manual\", op:\"SUP-01\", idemKey:\"conf-\"+(++seq)});\n}\nfunction createTrip(kind, legs){\n  const t={id:\"TR-\"+(++seq), kind, legs, status:\"DRAFT\", manifest:null, received:null, createdAt:now(), _at:0};\n  trips.push(t); return t;\n}\nfunction loadTrip(tripId){\n  const t=trips.find(x=>x.id===tripId); const loaded=[];\n  for(const leg of t.legs) for(const id of leg.items){\n    const r=ingest(\"DISPATCH\", id, assets[id].epcs[0], SITES.TRUCK, \"handheld\", \"OP-02\", \"ld-\"+id+\"-\"+tripId);\n    if(r.status===\"OK\"||r.status===\"CONFLICT\") loaded.push(id);\n  }\n  t.status=\"IN_TRANSIT\";\n  t.manifest={tripId:t.id, kind:t.kind, stops:t.legs.map(l=>({site:l.site,dir:l.dir,count:l.items.length})), items:t.legs.flatMap(l=>l.items), generatedAt:now()};\n  return loaded;\n}\nfunction dispatchLeg(tripId, legIdx, subset){\n  const t=trips.find(x=>x.id===tripId); const leg=t.legs[legIdx]; const loaded=[];\n  const ids=subset||leg.items;\n  for(const id of ids){\n    const r=ingest(\"DISPATCH\", id, assets[id].epcs[0], SITES.TRUCK, \"handheld\", \"OP-02\", \"ld-\"+id+\"-\"+tripId+\"-\"+legIdx);\n    if(r.status===\"OK\"||r.status===\"CONFLICT\") loaded.push(id);\n  }\n  if(t.status===\"DRAFT\"){ t.status=\"IN_TRANSIT\"; t.manifest={tripId:t.id, kind:t.kind, stops:t.legs.map(l=>({site:l.site,dir:l.dir,count:l.items.length})), items:t.legs.flatMap(l=>l.items), generatedAt:now()}; }\n  return loaded;\n}\nfunction arriveStop(tripId, legIdx){\n  const t=trips.find(x=>x.id===tripId); const leg=t.legs[legIdx]; const done=[];\n  for(const id of leg.items){\n    const r=ingest(\"RECEIPT\", id, assets[id].epcs[0], leg.site, leg.dir===\"deliver\"?\"handheld\":\"portal\", \"OP-03\", \"ar-\"+id+\"-\"+tripId+\"-\"+legIdx);\n    if(r.status===\"OK\"||r.status===\"CONFLICT\"){ assets[id].confirmedSite=leg.site; done.push(id); }\n  }\n  return done;\n}\nfunction receiveAtWH(tripId, scannedIds){\n  const t=trips.find(x=>x.id===tripId);\n  const all=t.legs.flatMap(l=>l.items);\n  const rec={scanned:scannedIds.slice(), missing:[], extra:[], reconciled:false, at:now()};\n  for(const id of all) if(!scannedIds.includes(id)) rec.missing.push(id);\n  for(const id of scannedIds) if(!all.includes(id)) rec.extra.push(id);\n  for(const id of scannedIds.filter(x=>all.includes(x))){\n    ingest(\"RECEIPT\", id, assets[id].epcs[0], SITES.WH, \"portal\", \"OP-03\", \"rc-\"+id+\"-\"+tripId);\n    assets[id].confirmedSite=SITES.WH;\n  }\n  t.received=rec; t.status=rec.missing.length||rec.extra.length?\"EXCEPTION\":\"RECONCILED\";\n  if(t.status===\"EXCEPTION\") exceptions.push({id:\"EX-\"+(++seq), assetId:rec.missing[0]||rec.extra[0], kind:\"RECEIVING_MISMATCH\", detail:`${t.id}: missing ${rec.missing.length}, extra ${rec.extra.length} \u2014 reconcile before closing`, resolved:false});\n  return rec;\n}\nfunction fillStore(site, ids, contents){\n  ids.forEach(id=>{ assets[id].contents=contents; logEvent({type:\"FILL\", assetId:id, site, src:\"manual\", op:\"OP-05\", idemKey:\"fill-\"+id, contents}); });\n}\nfunction emptyReturn(ids, site){\n  ids.forEach(id=>{ assets[id].contents=null; ingest(\"EMPTY_RETURN\", id, assets[id].epcs[0], site, \"handheld\", \"OP-04\", \"er-\"+id); assets[id].confirmedSite=site; });\n}\nfunction inspect(ids){\n  ids.forEach(id=>{ assets[id].status=\"active\"; logEvent({type:\"INSPECT\", assetId:id, site:SITES.WH, src:\"manual\", op:\"OP-06\", idemKey:\"ins-\"+id, result:\"passed\"}); });\n}\nfunction auditResolve(exId, note){\n  const e=exceptions.find(x=>x.id===exId); if(!e) return;\n  e.resolved=true;\n  logEvent({type:\"AUDIT_RESOLVED\", assetId:e.assetId, site:assets[e.assetId].lastSite, src:\"manual\", op:\"SUP-01\", idemKey:\"audit-\"+(++seq), detail:note});\n}\nfunction inventoryConsistency(){\n  const issues=[];\n  const ids=Object.keys(assets);\n  if(new Set(ids).size!==ids.length) issues.push(\"duplicate asset keys\");\n  Object.values(assets).forEach(a=>{ if(!a.confirmedSite) issues.push(a.id+\" no custody\"); if(!GROUND.includes(a.confirmedSite)) issues.push(a.id+\" bad custody\"); });\n  const bySite={}; GROUND.forEach(s=>bySite[s]=0);\n  Object.values(assets).forEach(a=>{ if(bySite[a.confirmedSite]!==undefined) bySite[a.confirmedSite]++; });\n  const sum=Object.values(bySite).reduce((x,y)=>x+y,0);\n  if(sum!==ids.length) issues.push(`totals mismatch: ${sum} != ${ids.length}`);\n  return {ok:issues.length===0, issues, bySite, total:ids.length};\n}\n\n\/* ================= VISUAL LAYOUT (new polished scene) ================= *\/\nconst POS = {\n  whSlots:[{x:690,y:300},{x:780,y:300},{x:870,y:300},{x:690,y:236},{x:780,y:236},{x:870,y:236}],\n  aSlots:[{x:78,y:300},{x:188,y:300},{x:298,y:300}],\n  truckSlots:[{x:30,y:-100},{x:90,y:-100},{x:150,y:-100},{x:30,y:-150},{x:90,y:-150},{x:150,y:-150}],\n  washSlots:[{x:700,y:300},{x:790,y:300},{x:880,y:300},{x:700,y:236},{x:790,y:236},{x:880,y:236}]\n};\nconst WAY = {WH:{x:640,y:410}, DA:{x:30,y:410}};\nlet truckPos={x:WAY.WH.x,y:WAY.WH.y};\nlet visual={};\nlet currentTrip=null, currentStep=0, playing=false, guided=false, timer=null, reducedMotion=false;\n\nfunction boxColor(id){\n  const a=assets[id];\n  if(exceptions.some(e=>e.assetId===id&&!e.resolved)) return \"#f6d6d6\";\n  if(a.status===\"cleaning\") return \"#d7e6f7\";\n  if(a.contents) return \"#d8ecdb\";\n  return \"#eef2f5\";\n}\nfunction boxStroke(id){\n  const a=assets[id];\n  if(exceptions.some(e=>e.assetId===id&&!e.resolved)) return \"#c62828\";\n  if(a.contents) return \"#1b5e20\";\n  return \"#1e293b\";\n}\nfunction boxLabel2(id){\n  const a=assets[id];\n  if(exceptions.some(e=>e.assetId===id&&!e.resolved)) return \"EXC\";\n  if(a.status===\"cleaning\") return \"CLEAN\";\n  if(a.contents) return \"FULL\";\n  return \"EMPTY\";\n}\nfunction animMs(){ return reducedMotion?0:620*parseFloat(document.getElementById(\"speed\").value); }\nfunction ease(){ return \"transform \"+animMs()+\"ms cubic-bezier(.42,0,.2,1)\"; }\n\nfunction drawBoxInner(id){\n  const a=assets[id];\n  const fill=boxColor(id), stroke=boxStroke(id);\n  const isEx=exceptions.some(e=>e.assetId===id&&!e.resolved);\n  const lidOn = !(!a.contents && a.status!==\"cleaning\"); \/\/ lid present when full or cleaning; off only when plainly empty\n  const sleeve = fill;\n  let inner = `\n    <ellipse cx=\"0\" cy=\"30\" rx=\"26\" ry=\"5\" fill=\"#000\" opacity=\"0.10\"\/>\n    <rect x=\"-22\" y=\"14\" width=\"44\" height=\"9\" rx=\"2\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"1\"\/>\n    <rect x=\"-22\" y=\"23\" width=\"7\" height=\"6\" fill=\"#8a754f\"\/><rect x=\"-3\" y=\"23\" width=\"7\" height=\"6\" fill=\"#8a754f\"\/><rect x=\"15\" y=\"23\" width=\"7\" height=\"6\" fill=\"#8a754f\"\/>\n    <rect x=\"-20\" y=\"-20\" width=\"40\" height=\"34\" rx=\"2\" fill=\"${sleeve}\" stroke=\"${stroke}\" stroke-width=\"2\"\/>\n    <line x1=\"-12\" y1=\"-18\" x2=\"-12\" y2=\"12\" stroke=\"rgba(0,0,0,0.10)\" stroke-width=\"1\"\/>\n    <line x1=\"-4\" y1=\"-18\" x2=\"-4\" y2=\"12\" stroke=\"rgba(0,0,0,0.10)\" stroke-width=\"1\"\/>\n    <line x1=\"4\" y1=\"-18\" x2=\"4\" y2=\"12\" stroke=\"rgba(0,0,0,0.10)\" stroke-width=\"1\"\/>\n    <line x1=\"12\" y1=\"-18\" x2=\"12\" y2=\"12\" stroke=\"rgba(0,0,0,0.10)\" stroke-width=\"1\"\/>\n    ${a.contents?`<rect x=\"-18\" y=\"2\" width=\"36\" height=\"11\" rx=\"2\" fill=\"#2e7d32\" opacity=\"0.88\"\/><text x=\"0\" y=\"11\" text-anchor=\"middle\" font-size=\"7\" fill=\"#fff\" font-weight=\"700\">FULL<\/text>`:''}\n    ${lidOn?`<rect x=\"-23\" y=\"-27\" width=\"46\" height=\"8\" rx=\"2\" fill=\"#e7edf2\" stroke=\"${stroke}\" stroke-width=\"1.5\"\/><rect x=\"-23\" y=\"-27\" width=\"46\" height=\"3\" rx=\"1\" fill=\"#cfd8e0\"\/>`:''}\n    <rect x=\"12\" y=\"-14\" width=\"11\" height=\"8\" rx=\"1\" fill=\"#046bd2\" stroke=\"#03407d\" stroke-width=\"0.5\"\/>\n    <text x=\"0\" y=\"-34\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"700\" fill=\"#1e293b\">${id.replace('AST-','#')}<\/text>\n    ${isEx?`<circle cx=\"18\" cy=\"-22\" r=\"7\" fill=\"#c62828\"\/><text x=\"18\" y=\"-19\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"800\" fill=\"#fff\">!<\/text>`:''}\n  `;\n  return inner;\n}\nfunction initVisual(){\n  visual={}; truckPos={x:WAY.WH.x,y:WAY.WH.y};\n  ASSET_IDS.forEach((id,i)=>{\n    \/\/ 001,002,003 start at warehouse staging; 004,005,008 stay at warehouse\n    visual[id]={x:POS.whSlots[i].x, y:POS.whSlots[i].y, site:SITES.WH, onTruck:false, state:\"empty\"};\n  });\n  renderTruck(); renderBoxes();\n}\nfunction renderBoxes(){\n  const g=document.getElementById(\"boxes\"); g.innerHTML=\"\";\n  ASSET_IDS.forEach(id=>{\n    const v=visual[id];\n    const group=document.createElementNS(\"http:\/\/www.w3.org\/2000\/svg\",\"g\");\n    group.setAttribute(\"class\",\"clickable box\");\n    group.setAttribute(\"id\",\"box-\"+id);\n    group.style.transition=ease();\n    group.style.transform=`translate(${v.x}px,${v.y}px)`;\n    group.onclick=()=>showDetail(\"BOX\",id);\n    group.innerHTML=drawBoxInner(id);\n    g.appendChild(group);\n  });\n}\nfunction renderTruck(){\n  const t=document.getElementById(\"truck\");\n  t.style.transition=ease();\n  t.style.transform=`translate(${truckPos.x}px,${truckPos.y}px)`;\n}\nfunction moveBox(id, slot, onTruck){\n  const v=visual[id]; v.onTruck=!!onTruck;\n  if(onTruck){ v.x=truckPos.x+slot.x; v.y=truckPos.y+slot.y; v.site=SITES.TRUCK; }\n  else { v.x=slot.x; v.y=slot.y; }\n  const el=document.getElementById(\"box-\"+id);\n  if(el){ el.style.transition=ease(); el.style.transform=`translate(${v.x}px,${v.y}px)`; }\n}\nfunction updateBoxVisuals(){\n  ASSET_IDS.forEach(id=>{\n    const el=document.getElementById(\"box-\"+id); if(!el) return;\n    const v=visual[id];\n    if(v.onTruck){ const idx=ASSET_IDS.indexOf(id); const s=POS.truckSlots[idx]; v.x=truckPos.x+s.x; v.y=truckPos.y+s.y; }\n    el.style.transition=ease();\n    el.style.transform=`translate(${v.x}px,${v.y}px)`;\n    el.innerHTML=drawBoxInner(id);\n  });\n}\nfunction truckTo(pos){\n  truckPos={x:pos.x,y:pos.y}; renderTruck();\n  ASSET_IDS.forEach((id,i)=>{ if(visual[id].onTruck){ const s=POS.truckSlots[i]; moveBox(id,{x:truckPos.x+s.x,y:truckPos.y+s.y},true); } });\n}\nfunction pulse(cpId){ const cp=document.getElementById(cpId); if(!cp) return; cp.classList.add(\"active\",\"pulse\"); setTimeout(()=>cp.classList.remove(\"active\",\"pulse\"),600); }\n\n\/* ================= SCENARIO STEPS (single-depot collection loop) ================= *\/\nlet deliveryTrip=null, pickupTrip=null, correctiveTrip=null;\nconst TRAVEL = [\"AST-001\",\"AST-002\",\"AST-003\"]; \/\/ boxes that travel to the depot\n\nconst STEPS=[\n  {key:\"seed\", label:\"Warehouse stages empty boxes\", benefit:\"The warehouse starts with a known pool of available, empty, inspected boxes \u2014 each with a stable asset ID.\",\n   run(){ freshState(); initVisual(); deliveryTrip=pickupTrip=correctiveTrip=null; setBenefit(this.label,this.benefit); }},\n  {key:\"load\", label:\"Truck loads empties at the warehouse\", benefit:\"Dispatch scans every box onto the truck. The manifest is built from actual reads, not assumptions.\",\n   run(){\n     deliveryTrip=createTrip(\"delivery\",[{site:SITES.DA,dir:\"deliver\",items:TRAVEL}]);\n     loadTrip(deliveryTrip.id);\n     TRAVEL.forEach((id,i)=>moveBox(id,POS.truckSlots[i],true));\n     pulse(\"cp-wh-out\");\n     setBenefit(this.label,this.benefit+` <span class=\"pill b\">${deliveryTrip.id}<\/span>`);\n   }},\n  {key:\"toDepot\", label:\"Truck travels to the recycling depot\", benefit:\"The truck makes an illustrative run along the route. RFID gates observe the departure.\",\n   run(){ truckTo(WAY.DA); setBenefit(this.label,this.benefit); }},\n  {key:\"unload\", label:\"Deliver empties into the collection bays\", benefit:\"RFID confirms arrival at the depot. Custody transfers only after the manifest and the read match.\",\n   run(){\n     arriveStop(deliveryTrip.id,0);\n     TRAVEL.forEach((id,i)=>moveBox(id,POS.aSlots[i],false));\n     pulse(\"cp-a-in\");\n     updateBoxVisuals(); renderAll();\n     setBenefit(this.label,this.benefit+` <span class=\"pill g\">${deliveryTrip.id} ARRIVED<\/span>`);\n   }},\n  {key:\"fill\", label:\"Depot fills the boxes\", benefit:\"Contents are declared by location and lot. The box tag identifies the asset; contents are a separate record.\",\n   run(){\n     fillStore(SITES.DA, TRAVEL, \"Recovered plastics \u2014 Lot D-201\");\n     updateBoxVisuals(); renderAll();\n     setBenefit(this.label,this.benefit);\n   }},\n  {key:\"collect\", label:\"Truck collects full boxes from the depot\", benefit:\"Outbound RFID reads update the manifest. The system knows which boxes left and which stayed.\",\n   run(){\n     pickupTrip=createTrip(\"pickup\",[{site:SITES.DA,dir:\"pickup\",items:TRAVEL}]);\n     truckTo(WAY.DA);\n     setTimeout(()=>{\n       \/\/ Deliberately leave AST-003 in Bay 3 \u2014 the collection discrepancy\n       dispatchLeg(pickupTrip.id,0,[\"AST-001\",\"AST-002\"]);\n       [\"AST-001\",\"AST-002\"].forEach((id,i)=>moveBox(id,POS.truckSlots[i],true));\n       pulse(\"cp-a-out\");\n       updateBoxVisuals(); renderAll();\n     }, animMs()\/2);\n     setBenefit(this.label,this.benefit+` <span class=\"pill b\">${pickupTrip.id}<\/span>`);\n   }},\n  {key:\"return\", label:\"Return to the warehouse for receiving\", benefit:\"The warehouse reconciles scanned boxes against the manifest before custody is confirmed.\",\n   run(){ truckTo(WAY.WH); setTimeout(()=>{ pulse(\"cp-wh-in\"); }, animMs()\/2); setBenefit(this.label,this.benefit); }},\n  {key:\"receive\", label:\"Receiving finds a missing box\", benefit:\"The manifest expected 3 boxes; only 2 were scanned. The missing box becomes an exception, not a silent loss.\",\n   run(){\n     const scanned=[\"AST-001\",\"AST-002\"];\n     const rec=receiveAtWH(pickupTrip.id, scanned);\n     scanned.forEach((id,i)=>moveBox(id,POS.whSlots[i],false));\n     visual[\"AST-003\"].onTruck=false; visual[\"AST-003\"].site=SITES.DA;\n     updateBoxVisuals(); renderAll();\n     showException(rec);\n     setBenefit(this.label,this.benefit+` <span class=\"pill r\">1 missing<\/span>`);\n   }},\n  {key:\"resolve\", label:\"Operator resolves the exception with an audit record\", benefit:\"A recorded audit note confirms the missing box was left in the depot bay. The exception is closed with attribution.\",\n   run(){\n     const ex=exceptions.find(e=>!e.resolved && e.assetId===\"AST-003\");\n     if(ex){ assets[\"AST-003\"].confirmedSite=SITES.DA; auditResolve(ex.id,\"AST-003 confirmed left in Depot Bay 3 during pickup; corrective trip scheduled.\"); }\n     hideException();\n     updateBoxVisuals(); renderAll();\n     setBenefit(this.label,this.benefit);\n   }},\n  {key:\"corrective\", label:\"Corrective trip fetches the missing box\", benefit:\"Once the exception is audited, a corrective trip closes the loop and brings the last box home.\",\n   run(){\n     correctiveTrip=createTrip(\"corrective-pickup\",[{site:SITES.DA,dir:\"pickup\",items:[\"AST-003\"]}]);\n     truckTo(WAY.DA);\n     setTimeout(()=>{\n       loadTrip(correctiveTrip.id);\n       moveBox(\"AST-003\",POS.truckSlots[0],true);\n       pulse(\"cp-a-out\");\n       updateBoxVisuals(); renderAll();\n       setTimeout(()=>{\n         truckTo(WAY.WH);\n         setTimeout(()=>{\n           receiveAtWH(correctiveTrip.id,[\"AST-003\"]);\n           moveBox(\"AST-003\",POS.whSlots[2],false);\n           pulse(\"cp-wh-in\");\n           updateBoxVisuals(); renderAll();\n         }, animMs()\/2);\n       }, animMs()+200);\n     }, animMs()\/2);\n     setBenefit(this.label,this.benefit+` <span class=\"pill b\">${correctiveTrip.id}<\/span>`);\n   }},\n  {key:\"empty\", label:\"Empty, inspect, and clean at the warehouse\", benefit:\"Contents are cleared while the asset ID and history persist. Boxes are ready for redeployment.\",\n   run(){\n     emptyReturn(ASSET_IDS, SITES.WH);\n     ASSET_IDS.forEach(id=>assets[id].status=\"cleaning\");\n     ASSET_IDS.forEach((id,i)=>moveBox(id,POS.washSlots[i],false));\n     setTimeout(()=>{\n       inspect(ASSET_IDS);\n       ASSET_IDS.forEach((id,i)=>moveBox(id,POS.whSlots[i],false));\n       updateBoxVisuals(); renderAll();\n     }, animMs()+100);\n     updateBoxVisuals(); renderAll();\n     setBenefit(this.label,this.benefit);\n   }},\n  {key:\"done\", label:\"Loop complete \u2014 boxes ready to redeploy\", benefit:\"All boxes are back at the warehouse, empty, inspected, and reconciled. Inventory matches the event log.\",\n   run(){\n     const c=inventoryConsistency();\n     setBenefit(this.label,this.benefit+` <span class=\"pill ${c.ok?'g':'r'}\">${c.ok?'RECONCILED':'MISMATCH'}<\/span>`);\n     updateBoxVisuals(); renderAll();\n   }}\n];\n\nfunction setBenefit(title, html){ document.getElementById(\"benefit\").innerHTML=`<b>${title}<\/b>${html}`; }\nfunction showException(rec){\n  const b=document.getElementById(\"exceptionBanner\"); b.classList.add(\"visible\");\n  document.getElementById(\"exceptionText\").textContent=`${pickupTrip.id}: missing ${rec.missing.join(\", \")}. Reconcile before closing.`;\n}\nfunction hideException(){ document.getElementById(\"exceptionBanner\").classList.remove(\"visible\"); }\nfunction resolveException(){ if(currentStep===8){ nextStep(); } }\n\nfunction runStep(idx){\n  if(idx>=STEPS.length){ playing=false; updatePlayButton(); return; }\n  currentStep=idx;\n  STEPS[idx].run();\n  renderAll();\n}\nfunction nextStep(){ pause(); if(currentStep<STEPS.length) runStep(currentStep+1); }\nfunction togglePlay(){ if(playing){ pause(); } else { play(); } }\nfunction play(){ if(currentStep>=STEPS.length-1){ currentStep=0; runStep(0); } playing=true; updatePlayButton(); scheduleNext(); }\nfunction pause(){ playing=false; updatePlayButton(); clearTimeout(timer); }\nfunction updatePlayButton(){ document.getElementById(\"btnPlay\").textContent=playing?\"\u23f8 Pause\":\"\u25b6 Play\"; }\nfunction scheduleNext(){\n  if(!playing) return;\n  const delay=guided?3200:2400;\n  timer=setTimeout(()=>{\n    if(currentStep<STEPS.length-1){ runStep(currentStep+1); if(playing) scheduleNext(); }\n    else { playing=false; updatePlayButton(); }\n  }, delay+animMs());\n}\nfunction replay(){ pause(); currentStep=0; runStep(0); play(); }\nfunction runGuided(){ pause(); guided=true; currentStep=0; runStep(0); play(); setTimeout(()=>{guided=false;},16000); }\nfunction resetAll(){ pause(); currentStep=0; freshState(); initVisual(); hideException(); renderAll(); setBenefit(\"Ready.\",\"Press Play or Guided tour to run the closed-loop demonstration. Each step explains the operational benefit.\"); }\n\n\/* ================= UI PANELS ================= *\/\nlet panelTab=\"manifest\";\nfunction setPanel(t){ panelTab=t; document.querySelectorAll(\".tabs button\").forEach(b=>b.classList.remove(\"active\")); document.getElementById(\"tab-\"+t).classList.add(\"active\"); [\"manifest\",\"inventory\",\"events\",\"details\"].forEach(id=>document.getElementById(\"panel-\"+id).style.display=id===t?\"block\":\"none\"); renderAll(); }\nfunction renderAll(){ renderKPIs(); renderManifest(); renderInventory(); renderEvents(); if(panelTab===\"details\") renderDetails(lastDetailType,lastDetailId); updateBoxVisuals(); }\nfunction renderKPIs(){\n  const c=inventoryConsistency();\n  document.getElementById(\"kpi-wh\").textContent=c.bySite[SITES.WH]||0;\n  document.getElementById(\"kpi-a\").textContent=c.bySite[SITES.DA]||0;\n  document.getElementById(\"kpi-truck\").textContent=Object.values(assets).filter(a=>a.lastSite===SITES.TRUCK).length;\n  document.getElementById(\"kpi-ex\").textContent=exceptions.filter(e=>!e.resolved).length;\n}\nfunction renderManifest(){\n  const active=trips.length?trips[trips.length-1]:null;\n  const el=document.getElementById(\"panel-manifest\");\n  if(!active || !active.manifest){ el.innerHTML='<p class=\"note\">No active trip manifest yet. Start the demo to see the manifest.<\/p>'; return; }\n  const statusPill=active.status===\"RECONCILED\"?'<span class=\"pill g\">RECONCILED<\/span>':active.status===\"EXCEPTION\"?'<span class=\"pill r\">EXCEPTION<\/span>':active.status===\"COMPLETED\"?'<span class=\"pill g\">COMPLETED<\/span>':'<span class=\"pill y\">'+active.status+'<\/span>';\n  let html=`<table><tr><th>Trip<\/th><td><b>${active.id}<\/b> ${statusPill}<\/td><\/tr><tr><th>Kind<\/th><td>${active.kind}<\/td><\/tr>`;\n  html+=`<tr><th>Stops<\/th><td>${active.manifest.stops.map(s=>s.site+\" (\"+s.dir+\", \"+s.count+\")\").join(\"<br>\")}<\/td><\/tr>`;\n  html+=`<tr><th>Expected boxes<\/th><td>${active.manifest.items.join(\", \")}<\/td><\/tr>`;\n  if(active.received){\n    html+=`<tr><th>Scanned<\/th><td>${active.received.scanned.join(\", \")||\"\u2014\"}<\/td><\/tr>`;\n    html+=`<tr><th>Missing<\/th><td style=\"color:${active.received.missing.length?'var(--red)':'inherit'}\">${active.received.missing.join(\", \")||\"none\"}<\/td><\/tr>`;\n    html+=`<tr><th>Extra<\/th><td style=\"color:${active.received.extra.length?'var(--red)':'inherit'}\">${active.received.extra.join(\", \")||\"none\"}<\/td><\/tr>`;\n  }\n  html+=\"<\/table>\";\n  el.innerHTML=html;\n}\nfunction renderInventory(){\n  const c=inventoryConsistency();\n  const byObs={}; Object.values(assets).forEach(a=>byObs[a.lastSite]=(byObs[a.lastSite]||0)+1);\n  let html='<table><tr><th>Site<\/th><th>Confirmed custody<\/th><th>Last observed<\/th><\/tr>';\n  [SITES.WH,SITES.DA,SITES.TRUCK].forEach(s=>{\n    html+=`<tr><td>${s}<\/td><td>${c.bySite[s]!==undefined?c.bySite[s]:'\u2014'}<\/td><td>${byObs[s]||0}<\/td><\/tr>`;\n  });\n  html+=`<tr><td><b>Total<\/b><\/td><td><b>${c.total}<\/b> <span class=\"pill ${c.ok?'g':'r'}\">${c.ok?'RECONCILED':'MISMATCH'}<\/span><\/td><td><b>${Object.values(byObs).reduce((a,b)=>a+b,0)}<\/b><\/td><\/tr><\/table>`;\n  document.getElementById(\"panel-inventory\").innerHTML=html;\n}\nfunction renderEvents(){\n  const log=events.slice(-30).reverse().map(e=>`${e.eventId}  ${e.type.padEnd(16)} ${(e.assetId||\"\u2014\").padEnd(8)} ${(e.site||\"\u2014\").padEnd(18)} ${(e.observedAt||e.ingestedAt).slice(11,19)}`).join(\"\\n\");\n  document.getElementById(\"eventLog\").textContent=log||\"No events yet.\";\n}\nlet lastDetailType=null, lastDetailId=null;\nfunction showDetail(type,id){ lastDetailType=type; lastDetailId=id; setPanel(\"details\"); }\nfunction renderDetails(type,id){\n  const el=document.getElementById(\"panel-details\");\n  if(type===\"BOX\"){\n    const a=assets[id]; const ex=exceptions.filter(e=>e.assetId===id);\n    el.innerHTML=`<table><tr><th>Asset ID<\/th><td><b>${id}<\/b><\/td><\/tr><tr><th>EPC<\/th><td>${a.epcs[0]}<\/td><\/tr><tr><th>Confirmed site<\/th><td>${a.confirmedSite}<\/td><\/tr><tr><th>Last observed<\/th><td>${a.lastSite}<\/td><\/tr><tr><th>Contents<\/th><td>${a.contents||\"<i>none recorded<\/i>\"}<\/td><\/tr><tr><th>Status<\/th><td>${a.status}<\/td><\/tr><tr><th>Events<\/th><td>${events.filter(e=>e.assetId===id).length}<\/td><\/tr><tr><th>Exceptions<\/th><td>${ex.length?ex.map(e=>e.id+\" \"+(e.resolved?\"(resolved)\":\"(open)\")).join(\"<br>\"):\"none\"}<\/td><\/tr><\/table>`;\n  } else if(type===\"TRUCK\"){\n    const active=trips.length?trips[trips.length-1]:null;\n    el.innerHTML=`<table><tr><th>Current load<\/th><td>${ASSET_IDS.filter(id=>visual[id].onTruck).join(\", \")||\"empty\"}<\/td><\/tr><tr><th>Position<\/th><td>${truckPos.x.toFixed(0)}, ${truckPos.y.toFixed(0)} (illustrative)<\/td><\/tr><tr><th>Active trip<\/th><td>${active?active.id+\" (\"+active.status+\")\":\"none\"}<\/td><\/tr><\/table>`;\n  } else if(type===\"WH\"){\n    const avail=Object.values(assets).filter(a=>a.confirmedSite===SITES.WH&&!a.contents).length;\n    const full=Object.values(assets).filter(a=>a.confirmedSite===SITES.WH&&a.contents).length;\n    const open=exceptions.filter(e=>!e.resolved).length;\n    el.innerHTML=`<table><tr><th>Available empties<\/th><td>${avail}<\/td><\/tr><tr><th>Full boxes awaiting empty<\/th><td>${full}<\/td><\/tr><tr><th>Open exceptions<\/th><td>${open}<\/td><\/tr><tr><th>Function<\/th><td>Commissioning, dispatch, receiving reconciliation, wash\/inspect, redeployment<\/td><\/tr><\/table>`;\n  } else if(type===\"Depot A\"){\n    const here=Object.values(assets).filter(a=>a.confirmedSite===SITES.DA);\n    el.innerHTML=`<table><tr><th>Boxes in custody<\/th><td>${here.length}<\/td><\/tr><tr><th>Full boxes<\/th><td>${here.filter(a=>a.contents).length}<\/td><\/tr><tr><th>Empty boxes<\/th><td>${here.filter(a=>!a.contents).length}<\/td><\/tr><tr><th>Recent events<\/th><td>${events.filter(e=>e.site===SITES.DA).slice(-4).map(e=>e.type).join(\", \")||\"\u2014\"}<\/td><\/tr><\/table>`;\n  } else { el.innerHTML='<p class=\"note\">Click the truck, the depot, the warehouse, or a box to see details.<\/p>'; }\n}\n\n\/* ================= PRODUCT GALLERY (original illustrations) ================= *\/\nconst boxSVG=(inner,caption)=>`<svg viewBox=\"0 0 200 170\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:100%;height:140px;\">${inner}<\/svg>`;\nfunction buildGallery(){\n  \/\/ Assembled\n  document.getElementById(\"g0\").innerHTML=boxSVG(`\n    <rect width=\"200\" height=\"170\" fill=\"#f4f8fb\"\/>\n    <g transform=\"translate(100,100)\">\n      <ellipse cx=\"0\" cy=\"46\" rx=\"56\" ry=\"9\" fill=\"#000\" opacity=\"0.08\"\/>\n      <rect x=\"-50\" y=\"22\" width=\"100\" height=\"20\" rx=\"2\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"1.5\"\/>\n      <rect x=\"-46\" y=\"-34\" width=\"92\" height=\"58\" rx=\"3\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"2.5\"\/>\n      <line x1=\"-30\" y1=\"-32\" x2=\"-30\" y2=\"22\" stroke=\"rgba(0,0,0,0.10)\"\/><line x1=\"-12\" y1=\"-32\" x2=\"-12\" y2=\"22\" stroke=\"rgba(0,0,0,0.10)\"\/><line x1=\"12\" y1=\"-32\" x2=\"12\" y2=\"22\" stroke=\"rgba(0,0,0,0.10)\"\/><line x1=\"30\" y1=\"-32\" x2=\"30\" y2=\"22\" stroke=\"rgba(0,0,0,0.10)\"\/>\n      <rect x=\"-58\" y=\"-44\" width=\"116\" height=\"12\" rx=\"3\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"2\"\/>\n      <rect x=\"20\" y=\"-26\" width=\"14\" height=\"11\" rx=\"1\" fill=\"#046bd2\"\/>\n      <text x=\"0\" y=\"6\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"700\" fill=\"#1e293b\">ASSEMBLED<\/text>\n    <\/g>`);\n  \/\/ Collapsed\n  document.getElementById(\"g1\").innerHTML=boxSVG(`\n    <rect width=\"200\" height=\"170\" fill=\"#f4f8fb\"\/>\n    <g transform=\"translate(100,108)\">\n      <ellipse cx=\"0\" cy=\"40\" rx=\"64\" ry=\"8\" fill=\"#000\" opacity=\"0.08\"\/>\n      <rect x=\"-62\" y=\"-18\" width=\"124\" height=\"22\" rx=\"3\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"1.5\"\/>\n      <rect x=\"-58\" y=\"-50\" width=\"116\" height=\"28\" rx=\"3\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"2\"\/>\n      <rect x=\"-54\" y=\"-44\" width=\"108\" height=\"6\" fill=\"#dbe4ea\"\/>\n      <text x=\"0\" y=\"38\" text-anchor=\"middle\" font-size=\"11\" font-weight=\"700\" fill=\"#1e293b\">COLLAPSED<\/text>\n    <\/g>`);\n  \/\/ Components\n  document.getElementById(\"g2\").innerHTML=boxSVG(`\n    <rect width=\"200\" height=\"170\" fill=\"#f4f8fb\"\/>\n    <g transform=\"translate(58,118)\"><rect x=\"-44\" y=\"-12\" width=\"88\" height=\"20\" rx=\"2\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"1.5\"\/><text x=\"0\" y=\"26\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"700\" fill=\"#1e293b\">Pallet base<\/text><\/g>\n    <g transform=\"translate(122,80)\"><rect x=\"-34\" y=\"-34\" width=\"68\" height=\"68\" rx=\"3\" fill=\"none\" stroke=\"#046bd2\" stroke-width=\"2.5\" stroke-dasharray=\"5 3\"\/><text x=\"0\" y=\"4\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"700\" fill=\"#046bd2\">Foldable sleeve<\/text><\/g>\n    <g transform=\"translate(160,52)\"><rect x=\"-44\" y=\"-10\" width=\"88\" height=\"16\" rx=\"3\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"2\"\/><text x=\"0\" y=\"24\" text-anchor=\"middle\" font-size=\"9\" font-weight=\"700\" fill=\"#1e293b\">Lid (\u5929\u5730\u76d6)<\/text><\/g>`);\n  \/\/ Handling & stacking\n  document.getElementById(\"g3\").innerHTML=boxSVG(`\n    <rect width=\"200\" height=\"170\" fill=\"#f4f8fb\"\/>\n    <g transform=\"translate(86,108)\"><rect x=\"-44\" y=\"-36\" width=\"88\" height=\"72\" rx=\"3\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"2.5\"\/><rect x=\"-52\" y=\"-46\" width=\"104\" height=\"11\" rx=\"3\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"1.5\"\/><text x=\"0\" y=\"6\" text-anchor=\"middle\" font-size=\"10\" font-weight=\"700\" fill=\"#1e293b\">STACK<\/text><\/g>\n    <g transform=\"translate(86,52)\"><rect x=\"-44\" y=\"-36\" width=\"88\" height=\"72\" rx=\"3\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"2.5\"\/><rect x=\"-52\" y=\"-46\" width=\"104\" height=\"11\" rx=\"3\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"1.5\"\/><\/g>\n    <g transform=\"translate(158,128)\"><rect x=\"-26\" y=\"-8\" width=\"52\" height=\"14\" rx=\"2\" fill=\"#4b5762\"\/><rect x=\"-30\" y=\"-18\" width=\"8\" height=\"30\" rx=\"2\" fill=\"#046bd2\"\/><circle cx=\"-18\" cy=\"8\" r=\"5\" fill=\"#1f2630\"\/><circle cx=\"18\" cy=\"8\" r=\"5\" fill=\"#1f2630\"\/><\/g>`);\n}\nconst boxData=[\n  {title:\"Assembled box\", svg:`<svg viewBox=\"0 0 400 320\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><rect width=\"400\" height=\"320\" fill=\"#f4f8fb\"\/><g transform=\"translate(200,180)\"><ellipse cx=\"0\" cy=\"86\" rx=\"106\" ry=\"16\" fill=\"#000\" opacity=\"0.08\"\/><rect x=\"-96\" y=\"42\" width=\"192\" height=\"38\" rx=\"3\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"2\"\/><rect x=\"-88\" y=\"-62\" width=\"176\" height=\"110\" rx=\"4\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"3\"\/><line x1=\"-56\" y1=\"-58\" x2=\"-56\" y2=\"44\" stroke=\"rgba(0,0,0,0.10)\"\/><line x1=\"-20\" y1=\"-58\" x2=\"-20\" y2=\"44\" stroke=\"rgba(0,0,0,0.10)\"\/><line x1=\"20\" y1=\"-58\" x2=\"20\" y2=\"44\" stroke=\"rgba(0,0,0,0.10)\"\/><line x1=\"56\" y1=\"-58\" x2=\"56\" y2=\"44\" stroke=\"rgba(0,0,0,0.10)\"\/><rect x=\"-110\" y=\"-82\" width=\"220\" height=\"22\" rx=\"4\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"2.5\"\/><rect x=\"40\" y=\"-50\" width=\"24\" height=\"18\" rx=\"2\" fill=\"#046bd2\"\/><text x=\"0\" y=\"10\" text-anchor=\"middle\" font-size=\"20\" font-weight=\"700\" fill=\"#1e293b\">ASSEMBLED BOX<\/text><\/g><text x=\"200\" y=\"300\" text-anchor=\"middle\" fill=\"#6b5416\" font-size=\"13\">Pallet base + foldable sleeve + lid (\u5929\u5730\u76d6). Illustration only.<\/text><\/svg>`, meta:\"Original illustration. Dimensions and ratings pending supplier confirmation.\"},\n  {title:\"Collapsed box\", svg:`<svg viewBox=\"0 0 400 320\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><rect width=\"400\" height=\"320\" fill=\"#f4f8fb\"\/><g transform=\"translate(200,190)\"><ellipse cx=\"0\" cy=\"74\" rx=\"122\" ry=\"14\" fill=\"#000\" opacity=\"0.08\"\/><rect x=\"-118\" y=\"-32\" width=\"236\" height=\"42\" rx=\"4\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"2\"\/><rect x=\"-110\" y=\"-92\" width=\"220\" height=\"54\" rx=\"4\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"3\"\/><rect x=\"-102\" y=\"-82\" width=\"204\" height=\"12\" fill=\"#dbe4ea\"\/><text x=\"0\" y=\"78\" text-anchor=\"middle\" font-size=\"18\" font-weight=\"700\" fill=\"#1e293b\">COLLAPSED \/ FOLDED<\/text><\/g><text x=\"200\" y=\"300\" text-anchor=\"middle\" fill=\"#6b5416\" font-size=\"13\">Sleeve folds flat on the pallet base for efficient return transport. Illustration only.<\/text><\/svg>`, meta:\"Original illustration. Folded height and return quantity pending supplier confirmation.\"},\n  {title:\"Components\", svg:`<svg viewBox=\"0 0 400 320\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><rect width=\"400\" height=\"320\" fill=\"#f4f8fb\"\/><g transform=\"translate(96,210)\"><rect x=\"-78\" y=\"-22\" width=\"156\" height=\"36\" rx=\"3\" fill=\"#c9a36b\" stroke=\"#8a754f\" stroke-width=\"2\"\/><text x=\"0\" y=\"42\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"#1e293b\">Pallet base<\/text><\/g><g transform=\"translate(220,130)\"><rect x=\"-66\" y=\"-66\" width=\"132\" height=\"132\" rx=\"4\" fill=\"none\" stroke=\"#046bd2\" stroke-width=\"3.5\" stroke-dasharray=\"7 4\"\/><text x=\"0\" y=\"6\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"#046bd2\">Foldable sleeve<\/text><\/g><g transform=\"translate(330,92)\"><rect x=\"-80\" y=\"-18\" width=\"160\" height=\"30\" rx=\"4\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"2.5\"\/><text x=\"0\" y=\"44\" text-anchor=\"middle\" font-size=\"14\" font-weight=\"700\" fill=\"#1e293b\">Lid (\u5929\u5730\u76d6)<\/text><\/g><text x=\"200\" y=\"300\" text-anchor=\"middle\" fill=\"#6b5416\" font-size=\"13\">Three-piece system: base, sleeve, and lid. Illustration only.<\/text><\/svg>`, meta:\"Original illustration. Component options pending supplier confirmation.\"},\n  {title:\"Handling & stacking\", svg:`<svg viewBox=\"0 0 400 320\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><rect width=\"400\" height=\"320\" fill=\"#f4f8fb\"\/><g transform=\"translate(160,200)\"><rect x=\"-80\" y=\"-64\" width=\"160\" height=\"128\" rx=\"4\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"3\"\/><rect x=\"-92\" y=\"-82\" width=\"184\" height=\"20\" rx=\"4\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"2\"\/><\/g><g transform=\"translate(160,110)\"><rect x=\"-80\" y=\"-64\" width=\"160\" height=\"128\" rx=\"4\" fill=\"#eef2f5\" stroke=\"#1e293b\" stroke-width=\"3\"\/><rect x=\"-92\" y=\"-82\" width=\"184\" height=\"20\" rx=\"4\" fill=\"#e7edf2\" stroke=\"#1e293b\" stroke-width=\"2\"\/><\/g><g transform=\"translate(300,232)\"><rect x=\"-44\" y=\"-12\" width=\"88\" height=\"22\" rx=\"3\" fill=\"#4b5762\"\/><rect x=\"-50\" y=\"-26\" width=\"14\" height=\"46\" rx=\"3\" fill=\"#046bd2\"\/><circle cx=\"-30\" cy=\"12\" r=\"8\" fill=\"#1f2630\"\/><circle cx=\"30\" cy=\"12\" r=\"8\" fill=\"#1f2630\"\/><\/g><text x=\"200\" y=\"300\" text-anchor=\"middle\" fill=\"#6b5416\" font-size=\"13\">Illustrative two-high stacking and forklift handling. Actual fit to be measured on-site.<\/text><\/svg>`, meta:\"Original illustration. Stacking rating and truck fit pending supplier confirmation.\"}\n];\nfunction openBox(i){ document.getElementById(\"lightbox-svg\").innerHTML=boxData[i].svg; document.getElementById(\"lightbox-cap\").innerHTML=\"<b>\"+boxData[i].title+\"<\/b>\"; document.getElementById(\"lightbox-meta\").textContent=boxData[i].meta; document.getElementById(\"lightbox\").classList.add(\"open\"); }\nfunction closeBox(e){ if(!e || e.target.id===\"lightbox\" || e.target.classList.contains(\"lightbox-close\")) document.getElementById(\"lightbox\").classList.remove(\"open\"); }\n\n\/* ================= KEYBOARD & INIT ================= *\/\ndocument.addEventListener(\"keydown\",e=>{\n  if(e.target.tagName===\"INPUT\") return;\n  if(e.code===\"Space\"){ e.preventDefault(); togglePlay(); }\n  if(e.code===\"ArrowRight\"){ e.preventDefault(); nextStep(); }\n  if(e.code===\"KeyR\"){ e.preventDefault(); resetAll(); }\n  if(e.code===\"KeyG\"){ e.preventDefault(); runGuided(); }\n});\ndocument.getElementById(\"speed\").addEventListener(\"input\",e=>{document.getElementById(\"speedVal\").textContent=e.target.value+\"\u00d7\";});\nwindow.addEventListener(\"load\",()=>{\n  reducedMotion=window.matchMedia&&window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n  buildGallery();\n  freshState(); initVisual(); renderAll(); setPanel(\"manifest\");\n});\n<\/script>\n\n<!-- \/wp:html --","protected":false},"excerpt":{"rendered":"<p>F Fargo Techs Inc. Home RCT Solution Visual Journey Operational Dashboard Contact Returnable Container Traceability Watch a truck collect reusable [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-10003","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Visual Journey - Fargo Techs Inc.<\/title>\n<meta name=\"description\" content=\"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fargotechs.com\/?page_id=10003\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Visual Journey - Fargo Techs Inc.\" \/>\n<meta property=\"og:description\" content=\"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fargotechs.com\/?page_id=10003\" \/>\n<meta property=\"og:site_name\" content=\"Fargo Techs Inc.\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-25T04:37:11+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10003\",\"url\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10003\",\"name\":\"Visual Journey - Fargo Techs Inc.\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/fargotechs.com\\\/#website\"},\"datePublished\":\"2026-09-24T20:50:00+00:00\",\"dateModified\":\"2026-09-25T04:37:11+00:00\",\"description\":\"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10003#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/fargotechs.com\\\/?page_id=10003\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/fargotechs.com\\\/?page_id=10003#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/fargotechs.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Visual Journey\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/fargotechs.com\\\/#website\",\"url\":\"https:\\\/\\\/fargotechs.com\\\/\",\"name\":\"Fargo Techs Inc.\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/fargotechs.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Visual Journey - Fargo Techs Inc.","description":"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fargotechs.com\/?page_id=10003","og_locale":"en_US","og_type":"article","og_title":"Visual Journey - Fargo Techs Inc.","og_description":"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.","og_url":"https:\/\/fargotechs.com\/?page_id=10003","og_site_name":"Fargo Techs Inc.","article_modified_time":"2026-09-25T04:37:11+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/fargotechs.com\/?page_id=10003","url":"https:\/\/fargotechs.com\/?page_id=10003","name":"Visual Journey - Fargo Techs Inc.","isPartOf":{"@id":"https:\/\/fargotechs.com\/#website"},"datePublished":"2026-09-24T20:50:00+00:00","dateModified":"2026-09-25T04:37:11+00:00","description":"Reusable container traceability for recycling depots, transport and warehouses. Explore Fargo Techs workflows, animations and an illustrative operational demo.","breadcrumb":{"@id":"https:\/\/fargotechs.com\/?page_id=10003#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fargotechs.com\/?page_id=10003"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fargotechs.com\/?page_id=10003#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/fargotechs.com\/"},{"@type":"ListItem","position":2,"name":"Visual Journey"}]},{"@type":"WebSite","@id":"https:\/\/fargotechs.com\/#website","url":"https:\/\/fargotechs.com\/","name":"Fargo Techs Inc.","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fargotechs.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages\/10003","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fargotechs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10003"}],"version-history":[{"count":1,"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages\/10003\/revisions"}],"predecessor-version":[{"id":10007,"href":"https:\/\/fargotechs.com\/index.php?rest_route=\/wp\/v2\/pages\/10003\/revisions\/10007"}],"wp:attachment":[{"href":"https:\/\/fargotechs.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10003"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}