{"id":7506,"date":"2026-09-28T19:10:42","date_gmt":"2026-09-28T19:10:42","guid":{"rendered":"https:\/\/truestarairsystems.com\/index.php\/new-home\/"},"modified":"2026-09-29T07:48:29","modified_gmt":"2026-09-29T07:48:29","slug":"home-2026","status":"publish","type":"page","link":"https:\/\/truestarairsystems.com\/","title":{"rendered":"Home"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"7506\" class=\"elementor elementor-7506\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-1478122 elementor-section-full_width elementor-section-stretched elementor-section-height-default elementor-section-height-default\" data-id=\"1478122\" data-element_type=\"section\" data-e-type=\"section\" data-settings=\"{&quot;stretch_section&quot;:&quot;section-stretched&quot;}\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-no\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-eb2e86b\" data-id=\"eb2e86b\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-747989c elementor-widget elementor-widget-html\" data-id=\"747989c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"ts26a\"><link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=Archivo:wdth,wght@62..125,500..900&family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@500&display=swap\">\n<!--noptimize--><style>:root{\n  --navy:#0b1526;--navy2:#13213a;--line:#243556;--ground:#eef1f4;--white:#ffffff;\n  --ink:#111827;--ink2:#4b5565;--mute:#5b6576;--soft:#c3cddc;--dim:#8d9bb3;\n  --red:#d7261e;--red-ink:#b3201a;--coral:#ff6b5e;--blue:#2a47c9;\n  --display:\"Archivo\",\"Arial Narrow\",Arial,sans-serif;\n  --body:\"IBM Plex Sans\",system-ui,-apple-system,\"Segoe UI\",sans-serif;\n  --mono:\"IBM Plex Mono\",ui-monospace,Menlo,monospace;\n  color-scheme:light;\n}:is(#ts26a,#ts26b) [hidden]{display:none!important}:is(#ts26a,#ts26b) *{box-sizing:border-box}html{scroll-behavior:smooth}:is(#ts26a,#ts26b){margin:0;background:var(--ground);color:var(--ink);font:400 16px\/1.6 var(--body);-webkit-font-smoothing:antialiased}:is(#ts26a,#ts26b) img,:is(#ts26a,#ts26b) video{max-width:100%;display:block}:is(#ts26a,#ts26b) a{color:var(--blue)}:is(#ts26a,#ts26b) :focus-visible{outline:3px solid var(--blue);outline-offset:2px}:is(#ts26a,#ts26b) .wrap{max-width:1280px;margin:0 auto;padding-inline:24px}:is(#ts26a,#ts26b) h1,:is(#ts26a,#ts26b) h2,:is(#ts26a,#ts26b) h3{font-family:var(--display);margin:0;text-wrap:balance;letter-spacing:-.01em}:is(#ts26a,#ts26b) .eyebrow{font:500 12px\/1 var(--mono);letter-spacing:.16em;text-transform:uppercase;color:var(--red-ink)}:is(#ts26a,#ts26b) .dark .eyebrow{color:var(--coral)}:is(#ts26a,#ts26b) .h2{font-weight:800;font-stretch:85%;font-size:clamp(34px,4.4vw,54px);line-height:1}:is(#ts26a,#ts26b) .btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:50px;padding:0 24px;border-radius:8px;font:600 15px var(--body);text-decoration:none;border:2px solid transparent;cursor:pointer}:is(#ts26a,#ts26b) .btn-red{background:var(--red);color:#fff}:is(#ts26a,#ts26b) .btn-red:hover{background:var(--red-ink)}:is(#ts26a,#ts26b) .btn-ghost{border-color:#3a4a66;color:#fff;background:transparent}:is(#ts26a,#ts26b) .btn-ghost:hover{border-color:#fff}:is(#ts26a,#ts26b) .btn-dark{background:var(--navy);color:#fff}:is(#ts26a,#ts26b) section{scroll-margin-top:72px}:is(#ts26a,#ts26b) .dark{background:var(--navy);color:#fff}:is(#ts26a,#ts26b) .lift{transition:transform .25s ease,box-shadow .25s ease}:is(#ts26a,#ts26b) .lift:hover{transform:translateY(-5px);box-shadow:0 18px 40px rgba(11,21,38,.18)}:is(#ts26a,#ts26b) .ph{background:repeating-linear-gradient(135deg,#f3f5f8 0 14px,#e6ebf1 14px 28px);display:flex;align-items:center;justify-content:center;color:var(--mute);font-weight:600;font-size:14px;text-align:center;padding:12px}:is(#ts26a,#ts26b) .cover{background-size:cover;background-position:center;background-color:#1b2c4a}:is(#ts26a,#ts26b) .cap{position:absolute;left:12px;bottom:12px;padding:5px 10px;border-radius:6px;background:rgba(11,21,38,.86);color:#fff;font-size:13px;font-weight:600}\/* preview banner *\/:is(#ts26a,#ts26b) .banner{background:#fff4d6;color:#5c4400;font-size:13px;text-align:center;padding:8px 16px;border-bottom:1px solid #f0dca0}\/* header *\/:is(#ts26a,#ts26b) header.top{position:sticky;top:env(safe-area-inset-top,0px);z-index:40;background:rgba(11,21,38,.97);backdrop-filter:blur(8px);border-bottom:1px solid #1c2a44}:is(#ts26a,#ts26b) header.top .wrap{display:flex;align-items:center;gap:32px;min-height:72px}:is(#ts26a,#ts26b) .brand{display:flex;align-items:center;gap:12px;color:#fff;text-decoration:none;font:800 21px\/1 var(--display);letter-spacing:.06em;font-stretch:112%}:is(#ts26a,#ts26b) .nav{display:flex;gap:28px;margin-left:auto}:is(#ts26a,#ts26b) .nav a{color:var(--soft);text-decoration:none;font-weight:500;font-size:15px;padding:8px 0;border-bottom:2px solid transparent}:is(#ts26a,#ts26b) .nav a:hover,:is(#ts26a,#ts26b) .nav a.on{color:#fff;border-bottom-color:var(--red)}:is(#ts26a,#ts26b) .menu-btn{display:none;margin-left:auto;width:46px;height:46px;border:1px solid var(--line);border-radius:8px;background:transparent;cursor:pointer;align-items:center;justify-content:center}:is(#ts26a,#ts26b) .mnav{display:none}@media (max-width:960px){:is(#ts26a,#ts26b) .nav,:is(#ts26a,#ts26b) header.top .btn{display:none}:is(#ts26a,#ts26b) .menu-btn{display:flex}:is(#ts26a,#ts26b) .mnav.open{display:flex;flex-direction:column;padding:4px 24px 20px;border-top:1px solid #1c2a44}:is(#ts26a,#ts26b) .mnav a{color:#fff;text-decoration:none;padding:14px 0;border-bottom:1px solid #1c2a44;font-size:17px}\n}\/* hero *\/:is(#ts26a,#ts26b) .hero{position:relative;overflow:hidden}:is(#ts26a,#ts26b) .hero video.bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.38}:is(#ts26a,#ts26b) .hero .shade{position:absolute;inset:0;background:linear-gradient(90deg,rgba(11,21,38,.97) 0%,rgba(11,21,38,.8) 45%,rgba(11,21,38,.55) 100%)}:is(#ts26a,#ts26b) .hero .wrap{position:relative;display:grid;grid-template-columns:1.05fr .95fr;gap:40px;align-items:center;padding-block:72px 64px}:is(#ts26a,#ts26b) .hero h1{font-weight:800;font-stretch:76%;font-size:clamp(46px,6.2vw,86px);line-height:.95;text-transform:uppercase}:is(#ts26a,#ts26b) .hero h1 span{color:#ff5a4d}:is(#ts26a,#ts26b) .hero p.lead{font-size:clamp(16px,1.5vw,19px);color:var(--soft);max-width:34em;margin:24px 0 30px}:is(#ts26a,#ts26b) .ctas{display:flex;flex-wrap:wrap;gap:12px}:is(#ts26a,#ts26b) .viewer{display:flex;flex-direction:column;align-items:center;gap:16px}:is(#ts26a,#ts26b) .stage{width:100%;max-width:560px;aspect-ratio:560\/480;perspective:1400px;display:flex;align-items:center;justify-content:center;cursor:grab;touch-action:none;border-radius:16px;background:radial-gradient(circle at 50% 55%,rgba(27,44,74,.92),rgba(11,21,38,.85) 70%);border:1px solid var(--line);position:relative;overflow:hidden}:is(#ts26a,#ts26b) .stage:active{cursor:grabbing}:is(#ts26a,#ts26b) .model{transform-style:preserve-3d}:is(#ts26a,#ts26b) .spin{transform-style:preserve-3d;animation:spin 22s linear infinite}:is(#ts26a,#ts26b) .stage.dragging .spin{animation-play-state:paused}\n@keyframes spin{from{transform:rotateY(0)}to{transform:rotateY(360deg)}}:is(#ts26a,#ts26b) .face{position:absolute;left:0;top:0;box-sizing:border-box}:is(#ts26a,#ts26b) .ahu-view{width:88%;height:78%;border-radius:12px;background:#f4f5f6 url(\/wp-content\/uploads\/2026\/09\/ts26-ahu-studio.jpg) center\/contain no-repeat;box-shadow:0 30px 60px rgba(0,0,0,.45);transition:transform .15s ease-out}:is(#ts26a,#ts26b) .seg{display:flex;gap:6px;padding:5px;border-radius:10px;background:var(--navy2);flex-wrap:wrap;justify-content:center}:is(#ts26a,#ts26b) .seg button{min-height:44px;padding:0 16px;border-radius:7px;border:0;cursor:pointer;font:600 14px var(--body);background:transparent;color:var(--soft)}:is(#ts26a,#ts26b) .seg button.on{background:#fff;color:var(--navy)}:is(#ts26a,#ts26b) .hint{font:500 12px var(--mono);color:var(--dim);letter-spacing:.08em;text-align:center}@media (max-width:960px){:is(#ts26a,#ts26b) .hero .wrap{grid-template-columns:1fr;padding-block:48px}}\/* stats *\/:is(#ts26a,#ts26b) .stats{background:var(--navy2);color:var(--soft)}:is(#ts26a,#ts26b) .stats .wrap{display:grid;grid-template-columns:repeat(5,minmax(0,1fr))}:is(#ts26a,#ts26b) .stats div.s{padding:24px 0 24px 28px;border-left:1px solid var(--line)}:is(#ts26a,#ts26b) .stats div.s:first-child{border-left:0;padding-left:0}:is(#ts26a,#ts26b) .stats b{display:block;font:800 30px\/1.1 var(--display);font-stretch:85%;color:#fff;margin-bottom:4px}@media (max-width:760px){:is(#ts26a,#ts26b) .stats .wrap{grid-template-columns:1fr 1fr}:is(#ts26a,#ts26b) .stats div.s:nth-child(3){border-left:0;padding-left:0}}\/* generic section *\/:is(#ts26a,#ts26b) .sec{padding-block:88px}:is(#ts26a,#ts26b) .head{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:flex-end;gap:16px 40px;margin-bottom:36px}:is(#ts26a,#ts26b) .head p{margin:0;max-width:30em;color:var(--ink2);font-size:17px}:is(#ts26a,#ts26b) .dark .head p{color:var(--soft)}\/* products *\/:is(#ts26a,#ts26b) .tabs{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:24px}:is(#ts26a,#ts26b) .tabs button{min-height:46px;padding:0 20px;border-radius:999px;border:2px solid #d4dae3;background:#fff;color:#1f2937;font:600 15px var(--body);cursor:pointer}:is(#ts26a,#ts26b) .tabs button.on{background:var(--navy);border-color:var(--navy);color:#fff}:is(#ts26a,#ts26b) .panel{display:grid;grid-template-columns:1fr 1fr;border-radius:18px;overflow:hidden;background:#fff;min-height:440px}:is(#ts26a,#ts26b) .panel .txt{padding:48px;display:flex;flex-direction:column;gap:18px}:is(#ts26a,#ts26b) .panel h3{font-weight:800;font-stretch:88%;font-size:clamp(28px,3vw,40px)}:is(#ts26a,#ts26b) .panel p{margin:0;color:var(--ink2);font-size:17px}:is(#ts26a,#ts26b) .chips{display:flex;flex-wrap:wrap;gap:8px}:is(#ts26a,#ts26b) .chips span{padding:7px 13px;border-radius:6px;background:var(--ground);font-size:14px;font-weight:500}:is(#ts26a,#ts26b) .panel .img{min-height:300px}@media (max-width:860px){:is(#ts26a,#ts26b) .panel{grid-template-columns:1fr}:is(#ts26a,#ts26b) .panel .img{order:-1;min-height:240px}:is(#ts26a,#ts26b) .panel .txt{padding:28px}}\/* plants *\/:is(#ts26a,#ts26b) .plants .wrap{display:grid;grid-template-columns:5fr 7fr;gap:56px;align-items:center}:is(#ts26a,#ts26b) .plist{display:flex;flex-direction:column;gap:10px;margin-top:20px}:is(#ts26a,#ts26b) .plist button{display:flex;align-items:center;gap:16px;padding:16px 18px;border-radius:10px;border:1px solid var(--line);background:transparent;color:#fff;cursor:pointer;text-align:left;font-family:var(--body)}:is(#ts26a,#ts26b) .plist button.on{border-color:#ff5a4d;background:#1b2c4a}:is(#ts26a,#ts26b) .plist .y{font:500 12px var(--mono);color:var(--coral);width:74px}:is(#ts26a,#ts26b) .plist .n{font:700 22px var(--display);width:110px}:is(#ts26a,#ts26b) .plist .st{font-size:14px;color:var(--soft)}:is(#ts26a,#ts26b) .map{height:460px;border-radius:18px;position:relative;overflow:hidden}:is(#ts26a,#ts26b) .map{transition:background-image .4s}:is(#ts26a,#ts26b) .map .veil{position:absolute;inset:0;background:rgba(11,21,38,.45)}:is(#ts26a,#ts26b) .pin{position:absolute;width:16px;height:16px}:is(#ts26a,#ts26b) .pin i{position:absolute;inset:0;border-radius:50%;background:#ff5a4d}:is(#ts26a,#ts26b) .pin i.p{animation:pulse 2.4s ease-out infinite}:is(#ts26a,#ts26b) .pin i.c{border:3px solid #fff}:is(#ts26a,#ts26b) .pin.soon i.c{border-style:dashed;background:transparent}:is(#ts26a,#ts26b) .pin.soon i.p{background:#ffb35a}:is(#ts26a,#ts26b) .pin.soon span{color:#ffd1a1}:is(#ts26a,#ts26b) .pin span{position:absolute;left:26px;top:-7px;white-space:nowrap;font:700 18px var(--display);color:#fff;text-shadow:0 1px 6px rgba(0,0,0,.6)}\n@keyframes pulse{0%{transform:scale(1);opacity:.6}100%{transform:scale(3.2);opacity:0}}:is(#ts26a,#ts26b) .pinfo{position:absolute;left:24px;right:24px;bottom:24px;padding:18px 22px;border-radius:12px;background:rgba(11,21,38,.92);border:1px solid var(--line)}:is(#ts26a,#ts26b) .pinfo b{font:700 21px var(--display)}:is(#ts26a,#ts26b) .pinfo div{color:var(--soft);font-size:15px}@media (max-width:860px){:is(#ts26a,#ts26b) .plants .wrap{grid-template-columns:1fr}:is(#ts26a,#ts26b) .map{height:360px}}\/* factory *\/:is(#ts26a,#ts26b) .factory .wrap{display:grid;grid-template-columns:4fr 8fr;gap:48px}:is(#ts26a,#ts26b) .mosaic{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:170px;gap:14px}:is(#ts26a,#ts26b) .mosaic div{border-radius:14px;position:relative}:is(#ts26a,#ts26b) .m-big{grid-column:span 2;grid-row:span 2}:is(#ts26a,#ts26b) .m-w{grid-column:span 2}:is(#ts26a,#ts26b) .tour-btn{align-self:flex-start;display:flex;align-items:center;gap:14px;min-height:60px;padding:0 24px 0 8px;border-radius:999px;border:0;background:var(--navy);color:#fff;font:600 16px var(--body);cursor:pointer}:is(#ts26a,#ts26b) .tour-btn i{width:44px;height:44px;border-radius:50%;background:var(--red);display:flex;align-items:center;justify-content:center}@media (max-width:960px){:is(#ts26a,#ts26b) .factory .wrap{grid-template-columns:1fr}:is(#ts26a,#ts26b) .mosaic{grid-auto-rows:130px}}@media (max-width:560px){:is(#ts26a,#ts26b) .mosaic{grid-template-columns:1fr 1fr}:is(#ts26a,#ts26b) .m-big{grid-column:span 2;grid-row:span 2}:is(#ts26a,#ts26b) .m-w{grid-column:span 2}}\/* industries *\/:is(#ts26a,#ts26b) .ind{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}:is(#ts26a,#ts26b) .ind .card{padding:26px;border-radius:14px;background:var(--ground);display:flex;gap:16px}:is(#ts26a,#ts26b) .ind .code{width:48px;height:48px;flex-shrink:0;border-radius:10px;background:var(--navy);display:flex;align-items:center;justify-content:center;font:500 12px var(--mono);color:var(--coral)}:is(#ts26a,#ts26b) .ind b{display:block;font:700 20px var(--display);margin-bottom:4px}:is(#ts26a,#ts26b) .ind p{margin:0;color:var(--ink2);font-size:15px}@media (max-width:860px){:is(#ts26a,#ts26b) .ind{grid-template-columns:1fr 1fr}}@media (max-width:560px){:is(#ts26a,#ts26b) .ind{grid-template-columns:1fr}}\/* teaser tiles *\/:is(#ts26a,#ts26b) .tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}:is(#ts26a,#ts26b) .tile{height:280px;border-radius:16px;padding:28px;display:flex;flex-direction:column;justify-content:flex-end;color:#fff;text-decoration:none;position:relative;overflow:hidden}:is(#ts26a,#ts26b) .tile b{font:800 26px var(--display);position:relative}:is(#ts26a,#ts26b) .tile span{font-size:15px;color:#dfe5ee;position:relative}:is(#ts26a,#ts26b) .tile .sh{position:absolute;inset:0;background:linear-gradient(0deg,rgba(11,21,38,.92) 0%,rgba(11,21,38,.25) 70%)}@media (max-width:860px){:is(#ts26a,#ts26b) .tiles{grid-template-columns:1fr}:is(#ts26a,#ts26b) .tile{height:200px}}\/* contact *\/:is(#ts26a,#ts26b) .contact .wrap{display:grid;grid-template-columns:5fr 7fr;gap:56px;align-items:center}:is(#ts26a,#ts26b) form.enq{display:grid;grid-template-columns:1fr 1fr;gap:14px;padding:32px;border-radius:16px;background:var(--navy2);border:1px solid var(--line)}:is(#ts26a,#ts26b) form.enq .full{grid-column:1\/-1}:is(#ts26a,#ts26b) label{display:block;font-size:13px;font-weight:500;color:var(--soft);margin-bottom:6px}:is(#ts26a,#ts26b) input,:is(#ts26a,#ts26b) select,:is(#ts26a,#ts26b) textarea{width:100%;min-height:46px;padding:10px 12px;border-radius:6px;border:1px solid #33456a;background:var(--navy);color:#fff;font:15px var(--body)}:is(#ts26a,#ts26b) textarea{min-height:96px;resize:vertical}:is(#ts26a,#ts26b) input[type=file]{padding:10px;border-style:dashed}:is(#ts26a,#ts26b) .note{font-size:14px;color:var(--dim);margin:0}@media (max-width:860px){:is(#ts26a,#ts26b) .contact .wrap{grid-template-columns:1fr}:is(#ts26a,#ts26b) form.enq{grid-template-columns:1fr;padding:22px}}:is(#ts26a,#ts26b) footer{background:#070e1a;color:var(--dim);font-size:14px;padding-block:44px}:is(#ts26a,#ts26b) footer .wrap{display:flex;flex-wrap:wrap;justify-content:space-between;gap:28px}:is(#ts26a,#ts26b) footer a{color:var(--dim);text-decoration:none}:is(#ts26a,#ts26b) footer a:hover{color:#fff}:is(#ts26a,#ts26b) footer .cols{display:flex;gap:56px;flex-wrap:wrap}:is(#ts26a,#ts26b) footer .cols div{display:flex;flex-direction:column;gap:8px}:is(#ts26a,#ts26b) footer .cols strong{color:#fff}\/* resources page *\/:is(#ts26a,#ts26b) .rhero{padding-block:72px}:is(#ts26a,#ts26b) .rhero h1{font-weight:800;font-stretch:80%;font-size:clamp(40px,6vw,72px);line-height:.95;text-transform:uppercase;margin:14px 0}:is(#ts26a,#ts26b) .rhero p{margin:0;color:var(--soft);font-size:18px;max-width:40em}:is(#ts26a,#ts26b) .filters{position:sticky;top:72px;z-index:20;background:#fff;border-bottom:1px solid #d4dae3}:is(#ts26a,#ts26b) .filters .wrap{display:flex;flex-wrap:wrap;gap:10px;align-items:center;padding-block:16px}:is(#ts26a,#ts26b) .filters button{min-height:44px;padding:0 20px;border-radius:999px;border:2px solid #d4dae3;background:#fff;color:#1f2937;font:600 15px var(--body);cursor:pointer}:is(#ts26a,#ts26b) .filters button.on{background:var(--navy);border-color:var(--navy);color:#fff}:is(#ts26a,#ts26b) .filters button small{opacity:.7;font-weight:500;margin-left:4px}:is(#ts26a,#ts26b) .cats{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:18px}:is(#ts26a,#ts26b) .cat{border-radius:14px;background:#fff;overflow:hidden;display:flex;flex-direction:column}:is(#ts26a,#ts26b) .cat .cv{height:230px;padding:22px;display:flex;flex-direction:column;justify-content:space-between;color:#fff;position:relative}:is(#ts26a,#ts26b) .cat .cv>*{position:relative}:is(#ts26a,#ts26b) .cat .cv::before{content:\"\";position:absolute;inset:0;background:var(--tint)}:is(#ts26a,#ts26b) .cat .cv small{font:500 12px var(--mono);letter-spacing:.12em;opacity:.9}:is(#ts26a,#ts26b) .cat .cv b{font:800 28px\/1.05 var(--display);font-stretch:85%}:is(#ts26a,#ts26b) .cat .bd{padding:18px 20px 20px;display:flex;flex-direction:column;gap:14px;flex:1}:is(#ts26a,#ts26b) .cat .bd p{margin:0;font-size:14px;color:var(--ink2)}:is(#ts26a,#ts26b) .cat .row{margin-top:auto;display:flex;justify-content:space-between;align-items:center}:is(#ts26a,#ts26b) .cat .row span{font:500 12px var(--mono);color:var(--mute)}:is(#ts26a,#ts26b) .gal{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:220px;gap:14px}:is(#ts26a,#ts26b) .gal button{border:0;padding:0;border-radius:14px;overflow:hidden;cursor:zoom-in;position:relative;font-family:var(--body)}:is(#ts26a,#ts26b) .gal button.w{grid-column:span 2}:is(#ts26a,#ts26b) .gal .lbl{position:absolute;left:0;right:0;bottom:0;padding:12px 14px;text-align:left;background:linear-gradient(0deg,rgba(11,21,38,.88),rgba(11,21,38,0));color:#fff}:is(#ts26a,#ts26b) .gal .lbl b{display:block;font-size:15px}:is(#ts26a,#ts26b) .gal .lbl small{font:500 11px var(--mono);opacity:.85}:is(#ts26a,#ts26b) .vids{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}:is(#ts26a,#ts26b) .vids button{height:280px;border:0;padding:0;border-radius:14px;overflow:hidden;cursor:pointer;position:relative;color:#fff;text-align:left;font-family:var(--body);background:var(--navy2)}:is(#ts26a,#ts26b) .vids .grid{position:absolute;inset:0;background-image:linear-gradient(#1a2a45 1px,transparent 1px),linear-gradient(90deg,#1a2a45 1px,transparent 1px);background-size:32px 32px}:is(#ts26a,#ts26b) .vids .play{position:absolute;left:50%;top:42%;width:70px;height:70px;margin:-35px 0 0 -35px;border-radius:50%;background:var(--red);display:flex;align-items:center;justify-content:center}:is(#ts26a,#ts26b) .vids .t{position:absolute;left:22px;right:22px;bottom:20px}:is(#ts26a,#ts26b) .vids .t b{display:block;font:700 21px var(--display)}:is(#ts26a,#ts26b) .vids .t span{font-size:14px;color:var(--soft)}:is(#ts26a,#ts26b) .admin{border:2px dashed #9aa5b5;border-radius:16px;background:#fff;padding:28px;display:grid;grid-template-columns:5fr 7fr;gap:32px;align-items:center}:is(#ts26a,#ts26b) .admin .ups{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}:is(#ts26a,#ts26b) .admin .ups div{min-height:130px;border-radius:12px;border:1px solid #d4dae3;background:#f6f8fa;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;text-align:center;padding:10px}:is(#ts26a,#ts26b) .admin .ups b{font-size:15px}:is(#ts26a,#ts26b) .admin .ups span{font-size:12px;color:var(--mute)}@media (max-width:960px){:is(#ts26a,#ts26b) .cats{grid-template-columns:1fr 1fr}:is(#ts26a,#ts26b) .gal{grid-template-columns:1fr 1fr;grid-auto-rows:170px}:is(#ts26a,#ts26b) .vids{grid-template-columns:1fr}:is(#ts26a,#ts26b) .admin{grid-template-columns:1fr}}@media (max-width:520px){:is(#ts26a,#ts26b) .cats{grid-template-columns:1fr}:is(#ts26a,#ts26b) .admin .ups{grid-template-columns:1fr}}\/* light header with real logo *\/:is(#ts26a,#ts26b) header.top{background:rgba(255,255,255,.97);border-bottom:1px solid #dde3ea}:is(#ts26a,#ts26b) header.top .brand img{height:52px;width:auto}:is(#ts26a,#ts26b) .nav a{color:#3a4659}:is(#ts26a,#ts26b) .nav a:hover,:is(#ts26a,#ts26b) .nav a.on{color:var(--navy)}:is(#ts26a,#ts26b) .menu-btn{border-color:#d4dae3}:is(#ts26a,#ts26b) .mnav.open a{color:var(--navy);border-bottom-color:#e6ebf1}@media (max-width:960px){:is(#ts26a,#ts26b) .mnav.open{border-top-color:#e6ebf1}}\/* clients marquee *\/:is(#ts26a,#ts26b) .clients{background:#fff;border-bottom:1px solid #e6ebf1;overflow:hidden}:is(#ts26a,#ts26b) .clients .lbl{font:500 12px var(--mono);letter-spacing:.16em;color:var(--mute);text-align:center;padding-top:26px}:is(#ts26a,#ts26b) .track{display:flex;gap:56px;width:max-content;padding:22px 0 28px;animation:marq 40s linear infinite}:is(#ts26a,#ts26b) .clients:hover .track{animation-play-state:paused}:is(#ts26a,#ts26b) .track img{height:64px;width:auto;filter:grayscale(1);opacity:.7;transition:filter .3s,opacity .3s}:is(#ts26a,#ts26b) .track img:hover{filter:none;opacity:1}\n@keyframes marq{from{transform:translateX(0)}to{transform:translateX(-50%)}}\/* product explorer *\/:is(#ts26a,#ts26b) .pbar{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:22px}:is(#ts26a,#ts26b) .pbar .tabs{margin:0}:is(#ts26a,#ts26b) .search{margin-left:auto;position:relative}:is(#ts26a,#ts26b) .search input{min-height:46px;width:260px;padding:0 14px 0 40px;border-radius:999px;border:2px solid #d4dae3;background:#fff;color:var(--ink)}:is(#ts26a,#ts26b) .search svg{position:absolute;left:14px;top:14px}:is(#ts26a,#ts26b) .pgrid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}:is(#ts26a,#ts26b) .pcard{background:#fff;border-radius:14px;border:0;padding:0;cursor:pointer;text-align:left;font-family:var(--body);overflow:hidden;display:flex;flex-direction:column;transition:transform .25s,box-shadow .25s}:is(#ts26a,#ts26b) .pcard:hover{transform:translateY(-5px);box-shadow:0 18px 40px rgba(11,21,38,.14)}:is(#ts26a,#ts26b) .pcard .pi{height:190px;background:#fff center\/contain no-repeat;margin:12px;transition:transform .35s}:is(#ts26a,#ts26b) .pcard:hover .pi{transform:scale(1.07)}:is(#ts26a,#ts26b) .pcard .pt{padding:0 16px 16px;display:flex;flex-direction:column;gap:4px}:is(#ts26a,#ts26b) .pcard .pt b{font:700 18px var(--display);color:var(--ink)}:is(#ts26a,#ts26b) .pcard .pt span{font:500 11px var(--mono);letter-spacing:.1em;color:var(--red-ink)}:is(#ts26a,#ts26b) .pcard .pt em{font-style:normal;font-size:13px;color:var(--blue);font-weight:600;margin-top:4px}:is(#ts26a,#ts26b) .pempty{grid-column:1\/-1;padding:40px;text-align:center;color:var(--mute);background:#fff;border-radius:14px}@media (max-width:960px){:is(#ts26a,#ts26b) .pgrid{grid-template-columns:repeat(2,minmax(0,1fr))}:is(#ts26a,#ts26b) .search{margin-left:0;width:100%}:is(#ts26a,#ts26b) .search input{width:100%}}@media (max-width:420px){:is(#ts26a,#ts26b) .pcard .pi{height:130px}}\/* quick view *\/:is(#ts26a,#ts26b) .qv{display:grid;grid-template-columns:1fr 1fr;gap:0;background:#fff;border-radius:16px;overflow:hidden;color:var(--ink)}:is(#ts26a,#ts26b) .qv .qi{min-height:380px;background:#fff center\/contain no-repeat;margin:24px}:is(#ts26a,#ts26b) .qv .qt{padding:36px;display:flex;flex-direction:column;gap:14px;background:var(--ground)}:is(#ts26a,#ts26b) .qv h3{font:800 34px\/1.05 var(--display);font-stretch:88%}:is(#ts26a,#ts26b) .qv p{margin:0;color:var(--ink2)}@media (max-width:760px){:is(#ts26a,#ts26b) .qv{grid-template-columns:1fr}:is(#ts26a,#ts26b) .qv .qi{min-height:220px}}\/* catalogue band + flipbook *\/:is(#ts26a,#ts26b) .catband{margin-top:36px;display:grid;grid-template-columns:260px 1fr;gap:36px;align-items:center;background:#fff;border-radius:18px;padding:28px}:is(#ts26a,#ts26b) .catcover{border:0;padding:0;background:none;cursor:pointer;perspective:900px}:is(#ts26a,#ts26b) .catcover img{width:100%;border-radius:6px;box-shadow:0 20px 40px rgba(11,21,38,.25);transform:rotateY(-14deg);transition:transform .4s}:is(#ts26a,#ts26b) .catcover:hover img{transform:rotateY(0) scale(1.03)}:is(#ts26a,#ts26b) .catstats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}:is(#ts26a,#ts26b) .catstats div{border-top:3px solid var(--red);padding-top:10px;font-size:13px;color:var(--mute)}:is(#ts26a,#ts26b) .catstats b{display:block;font:800 22px var(--display);color:var(--navy)}@media (max-width:760px){:is(#ts26a,#ts26b) .catband{grid-template-columns:1fr}:is(#ts26a,#ts26b) .catcover{max-width:220px}:is(#ts26a,#ts26b) .catstats{grid-template-columns:1fr}}:is(#ts26a,#ts26b) .flip{display:flex;flex-direction:column;gap:12px;align-items:center}:is(#ts26a,#ts26b) .spread{display:flex;gap:0;justify-content:center;max-height:calc(100vh - 250px)}:is(#ts26a,#ts26b) .spread img{max-height:calc(100vh - 250px);width:auto;max-width:50%;background:#fff;box-shadow:0 10px 30px rgba(0,0,0,.4)}:is(#ts26a,#ts26b) .spread.single img{max-width:100%}:is(#ts26a,#ts26b) .thumbs{display:flex;gap:6px;overflow-x:auto;max-width:100%;padding-bottom:6px}:is(#ts26a,#ts26b) .thumbs button{flex:0 0 auto;border:2px solid transparent;padding:0;background:none;cursor:pointer;border-radius:3px}:is(#ts26a,#ts26b) .thumbs button.on{border-color:var(--red)}:is(#ts26a,#ts26b) .thumbs img{height:64px;width:auto;display:block}\/* group *\/:is(#ts26a,#ts26b) .group{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}:is(#ts26a,#ts26b) .gcard{background:#fff;border-radius:18px;padding:36px;display:flex;flex-direction:column;gap:16px;border-top:5px solid var(--red)}:is(#ts26a,#ts26b) .gcard.vt{border-top-color:#a8894a}:is(#ts26a,#ts26b) .gcard img{height:96px;width:auto;align-self:flex-start}:is(#ts26a,#ts26b) .gcard p{margin:0;color:var(--ink2)}:is(#ts26a,#ts26b) .brands{display:flex;flex-wrap:wrap;gap:8px}:is(#ts26a,#ts26b) .brands span,:is(#ts26a,#ts26b) .brands a{padding:8px 14px;border-radius:6px;border:1px solid #d4dae3;font:600 14px var(--body)}:is(#ts26a,#ts26b) .brands a{display:inline-flex;align-items:center;gap:6px;color:var(--navy);text-decoration:none;transition:background .2s,color .2s}:is(#ts26a,#ts26b) .brands a:hover{background:var(--navy);color:#fff;border-color:var(--navy)}:is(#ts26a,#ts26b) .catalso{margin-top:18px;display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding:12px;border:1px solid #d4dae3;border-radius:12px;background:#fff}:is(#ts26a,#ts26b) .catalso img{width:44px;border-radius:4px;box-shadow:0 4px 10px rgba(0,0,0,.15)}:is(#ts26a,#ts26b) .catalso div{flex:1;min-width:180px;display:flex;flex-direction:column;font-size:13px;color:var(--mute)}:is(#ts26a,#ts26b) .catalso b{color:var(--navy);font-size:15px}:is(#ts26a,#ts26b) .catalso .btn{min-height:40px;padding:0 14px;font-size:14px}:is(#ts26a,#ts26b) .catalso .btn-ghost{color:var(--navy);border-color:#c9d1dc}:is(#ts26a,#ts26b) .qspec{margin:4px 0;padding:0;list-style:none;display:grid;gap:6px;font-size:14px;color:var(--ink2)}:is(#ts26a,#ts26b) .qspec li{padding-left:16px;position:relative}:is(#ts26a,#ts26b) .qspec li::before{content:\"\";position:absolute;left:0;top:.55em;width:7px;height:7px;border-radius:2px;background:var(--red)}\/* featured 3D studio *\/:is(#ts26a,#ts26b) .feat{background:linear-gradient(180deg,#0b1526 0%,#111f38 100%);color:#fff}:is(#ts26a,#ts26b) .fgrid{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,.7fr);gap:24px;align-items:stretch}:is(#ts26a,#ts26b) .fstage{position:relative;border-radius:18px;min-height:540px;background:radial-gradient(circle at 50% 38%,#223a63 0%,#0e1a30 72%);overflow:hidden;border:1px solid var(--line)}:is(#ts26a,#ts26b) .fstage .gl{position:absolute;inset:0}:is(#ts26a,#ts26b) .fstage .fb{position:absolute;inset:40px 40px 70px;background:center\/contain no-repeat}:is(#ts26a,#ts26b) .ftools{position:absolute;left:16px;right:16px;bottom:14px;display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap;pointer-events:none}:is(#ts26a,#ts26b) .ftools>*{pointer-events:auto}:is(#ts26a,#ts26b) .fbadge{font:500 11px var(--mono);letter-spacing:.12em;color:var(--dim)}:is(#ts26a,#ts26b) .fbtn{min-height:42px;padding:0 16px;border-radius:8px;border:1px solid #4a5b7a;background:rgba(11,21,38,.75);color:#fff;font:600 14px var(--body);cursor:pointer}:is(#ts26a,#ts26b) .fbtn:hover{border-color:#fff}:is(#ts26a,#ts26b) .flabel{position:absolute;left:18px;top:16px;font:500 11px var(--mono);letter-spacing:.14em;color:var(--coral);pointer-events:none}:is(#ts26a,#ts26b) .fside{display:flex;flex-direction:column;gap:14px;min-width:0}:is(#ts26a,#ts26b) .fbrands{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:4px;padding:5px;border-radius:10px;background:var(--navy2)}:is(#ts26a,#ts26b) .fbrands button{min-height:42px;border:0;border-radius:7px;background:transparent;color:var(--soft);font:600 14px var(--body);cursor:pointer}:is(#ts26a,#ts26b) .fbrands button.on{background:#fff;color:var(--navy)}:is(#ts26a,#ts26b) .fitems{display:flex;flex-direction:column;gap:6px}:is(#ts26a,#ts26b) .fitems button{display:flex;align-items:center;gap:12px;text-align:left;min-height:54px;padding:8px 14px;border-radius:10px;border:1px solid var(--line);background:transparent;color:#fff;cursor:pointer;font:600 15px\/1.25 var(--body)}:is(#ts26a,#ts26b) .fitems button small{display:block;font:500 11px var(--mono);letter-spacing:.08em;color:var(--dim);margin-top:2px}:is(#ts26a,#ts26b) .fitems button.on{border-color:var(--coral);background:rgba(215,38,30,.14)}:is(#ts26a,#ts26b) .fitems .n3d{margin-left:auto;flex:none;font:600 10px var(--mono);color:var(--coral);border:1px solid currentColor;border-radius:4px;padding:2px 5px}:is(#ts26a,#ts26b) .finfo{background:#fff;color:var(--ink);border-radius:16px;padding:22px;display:flex;flex-direction:column;gap:12px;flex:1}:is(#ts26a,#ts26b) .finfo h3{font:800 26px\/1.05 var(--display)}:is(#ts26a,#ts26b) .finfo .tag{font:500 11px var(--mono);letter-spacing:.12em;color:var(--red-ink);text-transform:uppercase}:is(#ts26a,#ts26b) .finfo p{margin:0;color:var(--ink2);font-size:15px}:is(#ts26a,#ts26b) .finfo .acts{display:flex;flex-wrap:wrap;gap:8px;margin-top:auto}:is(#ts26a,#ts26b) .finfo .acts .btn{min-height:42px;padding:0 14px;font-size:14px}:is(#ts26a,#ts26b) .finfo .acts .btn-ghost{color:var(--navy);border-color:#c9d1dc}:is(#ts26a,#ts26b) .finfo .note{font-size:12px;color:var(--mute);margin:0}:is(#ts26a,#ts26b) .lsdash{position:absolute;inset:48px 28px 72px;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:auto 1fr;gap:12px}:is(#ts26a,#ts26b) .lsdash .t{background:rgba(255,255,255,.06);border:1px solid var(--line);border-radius:12px;padding:14px 16px;font-size:13px;color:var(--soft)}:is(#ts26a,#ts26b) .lsdash .t b{display:block;font:800 30px\/1.1 var(--display);color:#fff}:is(#ts26a,#ts26b) .lsdash .t i{font-style:normal;color:#3ee07a;font-size:12px}:is(#ts26a,#ts26b) .lsdash .chart{grid-column:1\/-1;display:flex;align-items:flex-end;gap:6px;padding:40px 18px 18px}:is(#ts26a,#ts26b) .lsdash .chart span{flex:1;border-radius:4px 4px 0 0;background:linear-gradient(180deg,#4f8cff,#2a47c9)}:is(#ts26a,#ts26b) .lsdash .chart span.lo{background:linear-gradient(180deg,#3ee07a,#1f7a4d)}:is(#ts26a,#ts26b) .gnote{font-size:13px;color:var(--mute);margin:0}:is(#ts26a,#ts26b) .brands button{padding:8px 14px;border-radius:6px;border:1px solid #d4dae3;font:600 14px var(--body);background:#fff;color:var(--navy);cursor:pointer}:is(#ts26a,#ts26b) .brands button:hover{background:var(--navy);color:#fff}:is(#ts26a,#ts26b) .gcard.ifl{border-top-color:#2a47c9}:is(#ts26a,#ts26b) .iflow-word{font:800 44px\/1 var(--display);letter-spacing:-.02em;color:#1d3fbf}:is(#ts26a,#ts26b) .iflow-word span{color:var(--red)}@media (max-width:960px){:is(#ts26a,#ts26b) .fgrid{grid-template-columns:1fr}:is(#ts26a,#ts26b) .fstage{min-height:400px}}@media (max-width:520px){:is(#ts26a,#ts26b) .fbrands{grid-template-columns:repeat(2,minmax(0,1fr))}:is(#ts26a,#ts26b) .fstage{min-height:340px}:is(#ts26a,#ts26b) .lsdash{inset:44px 12px 70px}:is(#ts26a,#ts26b) .lsdash .t b{font-size:22px}}:is(#ts26a,#ts26b) .social{display:flex;flex-wrap:wrap;gap:8px;margin-top:4px}:is(#ts26a,#ts26b) .social a{display:inline-flex;align-items:center;gap:8px;min-height:40px;padding:0 14px;border-radius:8px;border:1px solid var(--line);color:#fff;text-decoration:none;font-weight:600;font-size:14px}:is(#ts26a,#ts26b) .social a:hover{background:#fff;color:var(--navy)}:is(#ts26a,#ts26b) footer .social{flex-direction:column;align-items:flex-start}:is(#ts26a,#ts26b) footer .social a{border:0;padding:0;min-height:28px;color:var(--dim)}:is(#ts26a,#ts26b) footer .social a:hover{background:none;color:#fff}:is(#ts26a,#ts26b) .menu-btn{padding:0!important;min-width:46px}:is(#ts26a,#ts26b) .dd{position:relative;display:flex;align-items:center}:is(#ts26a,#ts26b) .dd>a span{font-size:11px;margin-left:2px}:is(#ts26a,#ts26b) .mega{position:absolute;top:calc(100% + 14px);left:50%;transform:translate(-50%,6px);width:min(920px,92vw);background:#fff;border:1px solid #dde3ea;border-radius:16px;box-shadow:0 24px 60px rgba(11,21,38,.18);padding:24px 26px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:18px 26px;opacity:0;visibility:hidden;transition:opacity .18s,transform .18s,visibility 0s .18s;z-index:60}:is(#ts26a,#ts26b) .mega::before{content:\"\";position:absolute;left:0;right:0;top:-16px;height:16px}:is(#ts26a,#ts26b) .dd:hover .mega,:is(#ts26a,#ts26b) .dd:focus-within .mega{opacity:1;visibility:visible;transform:translate(-50%,0);transition:opacity .18s,transform .18s}:is(#ts26a,#ts26b) .mega b{display:block;font:700 12px\/1.2 var(--mono);letter-spacing:.12em;text-transform:uppercase;color:var(--red-ink);margin-bottom:10px}:is(#ts26a,#ts26b) .mega a{display:block;color:#1f2937!important;text-decoration:none;font-size:14.5px;padding:6px 0!important;border:0!important;line-height:1.35}:is(#ts26a,#ts26b) .mega a:hover{color:var(--red)!important}:is(#ts26a,#ts26b) .mega .mfoot{grid-column:1\/-1;display:flex;flex-wrap:wrap;gap:22px;align-items:center;border-top:1px solid #e6ebf1;padding-top:14px;margin-top:4px}:is(#ts26a,#ts26b) .mega .mfoot button{background:var(--navy);color:#fff;border:0;border-radius:8px;min-height:40px;padding:0 16px;font:600 14px var(--body);cursor:pointer}:is(#ts26a,#ts26b) .mega .mfoot a{font-weight:600}\/* air path strip *\/:is(#ts26a,#ts26b) .path{padding-block:56px;background:#fff;border-bottom:1px solid #e6ebf1}:is(#ts26a,#ts26b) .path .grid3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;margin-top:26px}:is(#ts26a,#ts26b) .pcard2{position:relative;border:1px solid #d4dae3;border-radius:16px;padding:26px;display:flex;flex-direction:column;gap:10px;text-decoration:none;color:var(--ink);transition:transform .25s,box-shadow .25s,border-color .25s;background:#fff}:is(#ts26a,#ts26b) .pcard2:hover{transform:translateY(-4px);box-shadow:0 18px 40px rgba(11,21,38,.1);border-color:var(--navy)}:is(#ts26a,#ts26b) .pcard2 .k{font:500 12px var(--mono);letter-spacing:.14em;color:var(--red-ink)}:is(#ts26a,#ts26b) .pcard2 h3{font:800 24px\/1.1 var(--display)}:is(#ts26a,#ts26b) .pcard2 p{margin:0;color:var(--ink2);font-size:15px}:is(#ts26a,#ts26b) .pcard2 .go{margin-top:auto;font-weight:600;color:var(--navy)}@media (max-width:860px){:is(#ts26a,#ts26b) .path .grid3{grid-template-columns:1fr}}\/* how we work *\/:is(#ts26a,#ts26b) .how .wrap{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:start}:is(#ts26a,#ts26b) .why{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:24px}:is(#ts26a,#ts26b) .why div{background:#fff;border-radius:14px;padding:20px;border:1px solid #e1e6ed}:is(#ts26a,#ts26b) .why b{display:block;font:700 17px\/1.2 var(--display);margin-bottom:6px;color:var(--navy)}:is(#ts26a,#ts26b) .why span{font-size:14.5px;color:var(--ink2)}:is(#ts26a,#ts26b) .steps{list-style:none;margin:0;padding:0;counter-reset:st;display:flex;flex-direction:column;gap:0}:is(#ts26a,#ts26b) .steps li{position:relative;padding:0 0 28px 64px}:is(#ts26a,#ts26b) .steps li::before{counter-increment:st;content:\"0\" counter(st);position:absolute;left:0;top:0;width:44px;height:44px;border-radius:50%;background:var(--navy);color:#fff;display:grid;place-items:center;font:700 14px var(--mono)}:is(#ts26a,#ts26b) .steps li::after{content:\"\";position:absolute;left:21px;top:48px;bottom:4px;width:2px;background:#d4dae3}:is(#ts26a,#ts26b) .steps li:last-child::after{display:none}:is(#ts26a,#ts26b) .steps b{display:block;font:700 19px\/1.2 var(--display);color:var(--navy);margin:9px 0 6px}:is(#ts26a,#ts26b) .steps span{color:var(--ink2);font-size:15px}@media (max-width:860px){:is(#ts26a,#ts26b) .how .wrap{grid-template-columns:1fr}:is(#ts26a,#ts26b) .why{grid-template-columns:1fr}}\/* faq *\/:is(#ts26a,#ts26b) .faq .wrap{display:grid;grid-template-columns:5fr 7fr;gap:48px;align-items:start}:is(#ts26a,#ts26b) .faq details{background:#fff;border:1px solid #e1e6ed;border-radius:12px;margin-bottom:10px;overflow:hidden}:is(#ts26a,#ts26b) .faq summary{cursor:pointer;list-style:none;padding:18px 52px 18px 20px;font:700 17px\/1.3 var(--display);color:var(--navy);position:relative}:is(#ts26a,#ts26b) .faq summary::-webkit-details-marker{display:none}:is(#ts26a,#ts26b) .faq summary::after{content:\"+\";position:absolute;right:20px;top:50%;transform:translateY(-50%);font:400 26px var(--body);color:var(--red)}:is(#ts26a,#ts26b) .faq details[open] summary::after{content:\"\u2013\"}:is(#ts26a,#ts26b) .faq details p{margin:0;padding:0 20px 18px;color:var(--ink2);font-size:15.5px}@media (max-width:860px){:is(#ts26a,#ts26b) .faq .wrap{grid-template-columns:1fr}}:is(#ts26a,#ts26b) .paddr{font-size:13px;color:var(--soft);margin-top:6px}:is(#ts26a,#ts26b) .paddr a{color:#ff9d94;font-weight:600}\/* gate form *\/:is(#ts26a,#ts26b) .gate{background:#fff;border-radius:16px;padding:32px;color:var(--ink);display:grid;grid-template-columns:200px 1fr;gap:28px;align-items:start}:is(#ts26a,#ts26b) .gate img{width:100%;border-radius:6px;box-shadow:0 10px 24px rgba(0,0,0,.2)}:is(#ts26a,#ts26b) .gate form{display:grid;grid-template-columns:1fr 1fr;gap:12px}:is(#ts26a,#ts26b) .gate label{color:var(--ink2)}:is(#ts26a,#ts26b) .gate input{background:#fff;color:var(--ink);border-color:#c9d1dc}:is(#ts26a,#ts26b) .gate .full{grid-column:1\/-1}@media (max-width:700px){:is(#ts26a,#ts26b) .gate{grid-template-columns:1fr}:is(#ts26a,#ts26b) .gate img{max-width:140px}:is(#ts26a,#ts26b) .gate form{grid-template-columns:1fr}}@media (max-width:1100px){:is(#ts26a,#ts26b) .group{grid-template-columns:1fr 1fr}}@media (max-width:760px){:is(#ts26a,#ts26b) .group{grid-template-columns:1fr}}\/* scroll reveal: visible by default, animates once in view *\/:is(#ts26a,#ts26b) .rv{transition:transform .7s ease,opacity .7s ease}:is(#ts26a,#ts26b) .rv.pre{transform:translateY(24px);opacity:.001}\/* modal *\/:is(#ts26a,#ts26b) .modal{position:fixed;inset:0;z-index:90;background:rgba(7,14,26,.94);display:flex;align-items:center;justify-content:center;padding:24px}:is(#ts26a,#ts26b) .modal .box{width:min(1000px,100%);max-height:100%;overflow:auto;display:flex;flex-direction:column;gap:14px}:is(#ts26a,#ts26b) .modal .media{width:100%;aspect-ratio:16\/9;border-radius:14px;background:#000 center\/contain no-repeat}:is(#ts26a,#ts26b) .modal .bar{display:flex;justify-content:space-between;align-items:center;gap:12px;color:#fff;flex-wrap:wrap}:is(#ts26a,#ts26b) .modal .bar b{font:700 22px var(--display)}:is(#ts26a,#ts26b) .modal .bar small{display:block;color:var(--soft);font-size:14px}:is(#ts26a,#ts26b) .round{width:46px;height:46px;border-radius:50%;border:1px solid #3a4a66;background:transparent;color:#fff;font-size:20px;cursor:pointer}:is(#ts26a,#ts26b) .pill{min-height:46px;padding:0 20px;border-radius:23px;border:0;background:#fff;color:var(--navy);font:600 15px var(--body);cursor:pointer}\/* mobile quick bar *\/:is(#ts26a,#ts26b) .mbar{display:none}@media (max-width:760px){:is(#ts26a,#ts26b) .mbar{display:grid;grid-template-columns:1fr 1fr;gap:8px;position:fixed;left:0;right:0;bottom:0;z-index:50;padding:10px 12px calc(10px + env(safe-area-inset-bottom,0px));background:#fff;border-top:1px solid #d4dae3}:is(#ts26a,#ts26b) .mbar a{min-height:48px}:is(#ts26a,#ts26b){padding-bottom:70px}\n}@media (prefers-reduced-motion:reduce){:is(#ts26a,#ts26b) .spin,:is(#ts26a,#ts26b) .pin i.p{animation:none}:is(#ts26a,#ts26b) .hero video.bg{display:none}}\n\n:is(#ts26a,#ts26b) :is(h1,h2,h3,h4,h5,h6){font-family:var(--display);color:inherit;margin:0;text-transform:none;letter-spacing:-.01em;line-height:1.05}\n:is(#ts26a,#ts26b) .hero h1{text-transform:uppercase;line-height:.95}\n:is(#ts26a,#ts26b){font:400 16px\/1.6 var(--body);color:var(--ink);background:var(--ground);-webkit-font-smoothing:antialiased}\n:is(#ts26a,#ts26b) :is(button,input,select,textarea){font-family:var(--body);text-transform:none;letter-spacing:normal}\n:is(#ts26a,#ts26b) p{margin-top:0}\n:is(#ts26a,#ts26b) .dark{color:#fff}\n.elementor-widget-html .elementor-widget-container:has(#ts26a),.elementor-widget-html .elementor-widget-container:has(#ts26b){margin:0;padding:0}\n@media (max-width:760px){#trustedsite-tm-image{margin-bottom:62px!important}}\n.ts26-mfw{display:none!important}\n.elementor-widget:has(#ts26a),.elementor-widget:has(#ts26b){margin:0!important}<\/style><!--\/noptimize-->\n\n\n\n<header class=\"top\">\n  <div class=\"wrap\">\n    <a class=\"brand\" href=\"#home\" aria-label=\"Truestar Air Systems home\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_truestar.webp\" alt=\"Truestar \u2014 Excellence speaks\"><\/a>\n    <nav class=\"nav\" aria-label=\"Main\">\n      <a href=\"#home\" data-route=\"home\">Home<\/a>\n      <a href=\"#featured\" data-route=\"home\">3D products<\/a>\n      <div class=\"dd\"><a href=\"#products\" data-route=\"home\" aria-haspopup=\"true\">Solutions <span aria-hidden=\"true\">\u25be<\/span><\/a>\n        <div class=\"mega\" role=\"menu\">\n          <div><b>Ducting<\/b><a href=\"https:\/\/truestarairsystems.com\/index.php\/rectangular-ducts-manufacturer-noida\">Rectangular GI duct<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/round-ducts-manufacturer-noida\">Spiral round &amp; flat-oval<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/other-range-of-ducts\/\">MS, fire-rated &amp; special ducts<\/a><a href=\"#featured\" data-feat=\"rect\">See ductwork in 3D<\/a><\/div>\n          <div><b>Air distribution<\/b><a href=\"https:\/\/truestarairsystems.com\/index.php\/grilles-manufacturer-in-noida\/\">Grilles<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/diffusers-manufacturer-in-noida\/\">Diffusers<\/a><a href=\"#featured\" data-feat=\"nozzle\">iFlow cone &amp; jet nozzles<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/best-sound-attenuator-manufacturer\/\">Louvers &amp; sound attenuators<\/a><\/div>\n          <div><b>Dampers &amp; life safety<\/b><a href=\"https:\/\/truestarairsystems.com\/index.php\/dampers-manufacturer-in-noida\">Volume control &amp; motorised dampers<\/a><a href=\"#featured\" data-feat=\"fsd60\">Ruskin fire\/smoke dampers (UL 555S)<\/a><a href=\"#featured\" data-feat=\"tfd80\">Ruskin tunnel dampers<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/ruskin\/\">All Ruskin products<\/a><\/div>\n          <div><b>Air handling &amp; IAQ<\/b><a href=\"https:\/\/truestarairsystems.com\/index.php\/air-handling-products\/\">AHUs &amp; TFA units<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/fan-filter-units-ffus\/\">Fan filter units<\/a><a href=\"#featured\" data-feat=\"vav\">Titus VAV boxes<\/a><a href=\"#featured\" data-feat=\"ambinode\">Leapcraft IAQ sensing<\/a><\/div>\n          <div class=\"mfoot\"><button type=\"button\" data-flip=\"group\">Browse the group catalogue \u2192<\/button><a href=\"#products\">All 39 products<\/a><a href=\"#how\">How we work<\/a><\/div>\n        <\/div><\/div>\n      <a href=\"#plants\" data-route=\"home\">Plants<\/a>\n      <a href=\"#factory\" data-route=\"home\">Factory<\/a>\n      <a href=\"#resources\" data-route=\"resources\">Resources<\/a>\n      <a href=\"#contact\" data-route=\"home\">Contact<\/a>\n    <\/nav>\n    <a class=\"btn btn-red\" href=\"#contact\">Send your BOQ<\/a>\n    <button class=\"menu-btn\" id=\"menuBtn\" type=\"button\" aria-label=\"Open menu\" aria-expanded=\"false\"><svg width=\"22\" height=\"22\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#0b1526\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M4 7h16M4 12h16M4 17h16\"\/><\/svg><\/button>\n  <\/div>\n  <nav class=\"mnav\" id=\"mnav\" aria-label=\"Mobile\">\n    <a href=\"#home\">Home<\/a><a href=\"#featured\">3D products<\/a><a href=\"#products\">Products<\/a><a href=\"#how\">How we work<\/a><a href=\"#plants\">Plants<\/a><a href=\"#factory\">Factory<\/a><a href=\"#resources\">Resources<\/a><a href=\"#contact\">Contact<\/a>\n  <\/nav>\n<\/header>\n\n<main id=\"page-home\">\n  <section class=\"hero dark\" id=\"home\" aria-labelledby=\"hero-h\">\n    <video class=\"bg\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-hero-loop.mp4\" poster=\"\/wp-content\/uploads\/2026\/09\/ts26-hero-poster.jpg\" autoplay muted loop playsinline aria-hidden=\"true\"><\/video>\n    <div class=\"shade\"><\/div>\n    <div class=\"wrap\">\n      <div>\n        <div class=\"eyebrow\">Ducts \u00b7 Air handling \u00b7 Air distribution<\/div>\n        <h1 id=\"hero-h\" style=\"margin-top:16px\">Engineered air,<br><span>built in three<\/span><br>Indian plants<\/h1>\n        <p class=\"lead\">Factory-fabricated GI ductwork, air handling units, dampers, grilles and diffusers from Valsad, Medak and Noida, supplied to HVAC contractors and project sites across India.<\/p>\n        <div class=\"ctas\">\n          <a class=\"btn btn-red\" href=\"#contact\">Get a quote on your BOQ<\/a>\n          <a class=\"btn btn-ghost\" href=\"#resources\">Download catalogue<\/a>\n        <\/div>\n      <\/div>\n      <div class=\"viewer\">\n        <div class=\"stage\" id=\"stage\" aria-label=\"3D product viewer. Drag to rotate.\">\n          <div class=\"model\" id=\"model\"><\/div>\n        <\/div>\n        <div class=\"seg\" role=\"group\" aria-label=\"Choose a product to view\">\n          <button type=\"button\" data-model=\"rect\" class=\"on\">Rectangular duct<\/button>\n          <button type=\"button\" data-model=\"round\">Spiral round duct<\/button>\n          <button type=\"button\" data-model=\"ahu\">Air handling unit<\/button>\n        <\/div>\n        <div class=\"hint\" id=\"hint\">DRAG TO ROTATE \u00b7 GI RECTANGULAR DUCT \u00b7 CROSS-BROKEN PANELS<\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"stats\" aria-label=\"At a glance\">\n    <div class=\"wrap\">\n      <div class=\"s\"><b>ISO 9001:2015<\/b>Certified quality system<\/div>\n      <div class=\"s\"><b>3 plants<\/b>Valsad \u00b7 Medak \u00b7 Noida \u00b7 Bengaluru 2027<\/div>\n      <div class=\"s\"><b>40+ products<\/b>Ducts, terminals, dampers, AHUs<\/div>\n      <div class=\"s\"><b>6 global brands<\/b>Ruskin, Titus, Leapcraft and more<\/div>\n      <div class=\"s\"><b>Since 2021<\/b>Supplying projects pan-India<\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"path\" aria-labelledby=\"ap-h\">\n    <div class=\"wrap\">\n      <div class=\"head\" style=\"margin-bottom:0\"><div><div class=\"eyebrow\">TrueStar Group<\/div><h2 class=\"h2\" id=\"ap-h\" style=\"margin-top:12px\">One group. The complete air path.<\/h2><\/div><p>From the air handling unit to the last diffuser: manufactured in our own plants, completed with certified global brands, and delivered by one team.<\/p><\/div>\n      <div class=\"grid3\">\n        <a class=\"pcard2\" href=\"#products\"><span class=\"k\">01 \u00b7 MANUFACTURE<\/span><h3>Truestar<\/h3><p>Factory-fabricated ducting, grilles, diffusers, dampers, attenuators and air handling units from plants in Valsad, Medak and Noida.<\/p><span class=\"go\">Explore the range \u2192<\/span><\/a>\n        <a class=\"pcard2\" href=\"#featured\" data-feat=\"fsd60\"><span class=\"k\">02 \u00b7 GLOBAL BRANDS<\/span><h3>Venti-Tron<\/h3><p>Authorised channel partner for Ruskin, Titus, Leapcraft, Trion, Envirco and Triatek: life-safety dampers, VAV terminals and indoor-air-quality sensing.<\/p><span class=\"go\">See featured products \u2192<\/span><\/a>\n        <a class=\"pcard2\" href=\"#how\"><span class=\"k\">03 \u00b7 PROJECT SUPPORT<\/span><h3>One team, start to finish<\/h3><p>Quantity take-off, shop drawings, factory fabrication marked by zone and level, and deliveries sequenced to your site programme.<\/p><span class=\"go\">How we work \u2192<\/span><\/a>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"clients\" aria-label=\"Clients\">\n    <div class=\"lbl\">TRUSTED ON PROJECTS FOR<\/div>\n    <div class=\"track\" id=\"track\"><\/div>\n  <\/section>\n\n  <section class=\"sec feat dark\" id=\"featured\" aria-labelledby=\"ft-h\">\n    <div class=\"wrap\">\n      <div class=\"head\"><div><div class=\"eyebrow\">Featured product lines<\/div><h2 class=\"h2\" id=\"ft-h\" style=\"margin-top:12px\">Turn it round. Open it up.<\/h2><\/div><p>Our key products from Truestar, plus the Ruskin, Titus and Leapcraft lines supplied through Venti-Tron, as interactive 3D models. Drag to rotate.<\/p><\/div>\n      <div class=\"fgrid\">\n        <div class=\"fstage\" id=\"fstage\" aria-label=\"Interactive 3D model of the selected product. Drag to rotate; arrow keys also work.\">\n          <div class=\"fb\" id=\"ffb\" role=\"img\" aria-label=\"\"><\/div>\n          <div class=\"gl\" id=\"fgl\"><\/div>\n          <div class=\"lsdash\" id=\"lsdash\" hidden aria-label=\"Illustrative LeapSense dashboard\">\n            <div class=\"t\"><b>612 ppm<\/b>CO\u2082 \u00b7 Meeting room 3 <i>\u25cf Good<\/i><\/div>\n            <div class=\"t\"><b>\u221238%<\/b>HVAC fan energy vs. baseline <i>\u25cf Demand-controlled<\/i><\/div>\n            <div class=\"t chart\" aria-hidden=\"true\" style=\"position:relative\"><em style=\"position:absolute;left:16px;top:12px;font:500 11px var(--mono);letter-spacing:.08em;color:var(--dim);font-style:normal\">FAN ENERGY PER DAY \u00b7 BEFORE \/ AFTER DEMAND CONTROL \u00b7 ILLUSTRATIVE<\/em><span style=\"height:70%\"><\/span><span style=\"height:82%\"><\/span><span style=\"height:64%\"><\/span><span class=\"lo\" style=\"height:40%\"><\/span><span class=\"lo\" style=\"height:36%\"><\/span><span class=\"lo\" style=\"height:44%\"><\/span><span class=\"lo\" style=\"height:38%\"><\/span><span class=\"lo\" style=\"height:33%\"><\/span><span class=\"lo\" style=\"height:41%\"><\/span><span class=\"lo\" style=\"height:35%\"><\/span><\/div>\n          <\/div>\n          <div class=\"flabel\" id=\"flabel\"><\/div>\n          <div class=\"ftools\"><span class=\"fbadge\" id=\"fhint\">DRAG TO ROTATE<\/span><button type=\"button\" class=\"fbtn\" id=\"ftoggle\" hidden><\/button><\/div>\n        <\/div>\n        <div class=\"fside\">\n          <div class=\"fbrands\" role=\"tablist\" aria-label=\"Brand\" id=\"fbrands\"><\/div>\n          <div class=\"fitems\" id=\"fitems\"><\/div>\n          <div class=\"finfo\" id=\"finfo\" aria-live=\"polite\"><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec\" id=\"products\" aria-labelledby=\"p-h\">\n    <div class=\"wrap\">\n      <div class=\"head\">\n        <div><div class=\"eyebrow\">Product range<\/div><h2 class=\"h2\" id=\"p-h\" style=\"margin-top:12px\">What we make<\/h2><\/div>\n        <p>Browse the range, search by name, and tap any product for details and a quick quote.<\/p>\n      <\/div>\n      <div class=\"pbar\">\n        <div class=\"tabs\" role=\"tablist\" aria-label=\"Product families\" id=\"tabs\"><\/div>\n        <label class=\"search\"><span class=\"sr\" style=\"position:absolute;left:-9999px\">Search products<\/span><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#5b6576\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"11\" cy=\"11\" r=\"7\"\/><path d=\"M20 20l-4-4\"\/><\/svg><input id=\"psearch\" type=\"search\" placeholder=\"Search e.g. damper, diffuser\"><\/label>\n      <\/div>\n      <div class=\"pgrid\" id=\"pgrid\"><\/div>\n      <div class=\"catband\">\n        <button type=\"button\" class=\"catcover\" data-flip=\"group\" aria-label=\"Open the TrueStar Group Product Catalogue\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-gcat-g01.webp\" alt=\"TrueStar Group Product Catalogue cover\"><\/button>\n        <div>\n          <div class=\"eyebrow\">New \u00b7 Group product catalogue \u00b7 2026<\/div>\n          <h3 style=\"font:800 clamp(26px,3vw,38px)\/1.05 var(--display);margin:10px 0 8px\">TrueStar Group Product Catalogue<\/h3>\n          <p style=\"margin:0 0 18px;color:var(--ink2)\">Every product line on one document: factory-fabricated ducting, dampers, grilles, diffusers, louvers and attenuators, air handling units, plus Ruskin life-safety dampers and Leapcraft IAQ.<\/p>\n          <div class=\"catstats\"><div><b>31 pages<\/b>Full group portfolio<\/div><div><b>SMACNA<\/b>Duct gauge selection tables<\/div><div><b>UL 555 \u00b7 EN 1886<\/b>Standards referenced<\/div><\/div>\n          <div style=\"display:flex;flex-wrap:wrap;gap:10px;margin-top:20px\"><button type=\"button\" class=\"btn btn-red\" data-flip=\"group\">Flip through the catalogue<\/button><button type=\"button\" class=\"btn btn-dark\" data-gate=\"group\">Download PDF<\/button><\/div>\n          <div class=\"catalso\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-cat-p01.webp\" alt=\"\"><div><b>Air Handling Products catalogue<\/b><span>52 pages \u00b7 1,000\u201360,000 CFM \u00b7 EN 1886 casing classes<\/span><\/div><button type=\"button\" class=\"btn btn-ghost\" data-flip=\"ahu\">Preview<\/button><button type=\"button\" class=\"btn btn-dark\" data-gate=\"ahu\">Download<\/button><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec how\" id=\"how\" aria-labelledby=\"hw-h\">\n    <div class=\"wrap\">\n      <div>\n        <div class=\"eyebrow\">Why factory-fabricated<\/div>\n        <h2 class=\"h2\" id=\"hw-h\" style=\"margin-top:12px\">Less leakage. Faster sites.<\/h2>\n        <p style=\"margin:18px 0 0;color:var(--ink2);font-size:17px;max-width:34em\">Duct made in a controlled factory, to the gauge and joint system the pressure class calls for, arrives ready to hang. That means tighter systems, less site rework and fewer suppliers to coordinate.<\/p>\n        <div class=\"why\">\n          <div><b>Tighter systems<\/b><span>Gasketed, sealed joints built to SMACNA pressure classes from 1\u2033 to 10\u2033 w.g.<\/span><\/div>\n          <div><b>Faster installation<\/b><span>Sections fabricated to approved drawings and marked by zone and level.<\/span><\/div>\n          <div><b>Consistent quality<\/b><span>One ISO 9001:2015 quality system across all three plants.<\/span><\/div>\n          <div><b>One point of contact<\/b><span>Ductwork, dampers, air terminals and AHUs from one group, on one order.<\/span><\/div>\n        <\/div>\n      <\/div>\n      <div>\n        <div class=\"eyebrow\">From enquiry to handover<\/div>\n        <ol class=\"steps\" style=\"margin-top:22px\">\n          <li><b>Enquiry &amp; take-off<\/b><span>Drawings and specifications reviewed, quantities taken off and a priced offer issued against the project construction class.<\/span><\/li>\n          <li><b>Shop drawings<\/b><span>Approval drawings and duct layouts issued for consultant review before any material is cut.<\/span><\/li>\n          <li><b>Factory fabrication<\/b><span>Sections fabricated to the approved gauge and joint system, marked by zone and level, and quality-checked before despatch.<\/span><\/li>\n          <li><b>Delivery &amp; support<\/b><span>Sequenced deliveries to the site programme, with technical support through installation and handover.<\/span><\/li>\n        <\/ol>\n        <a class=\"btn btn-red\" href=\"#contact\" style=\"margin-left:64px\">Start with your drawings<\/a>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec dark plants\" id=\"plants\" aria-labelledby=\"pl-h\">\n    <div class=\"wrap\">\n      <div>\n        <div class=\"eyebrow\">Manufacturing<\/div>\n        <h2 class=\"h2\" id=\"pl-h\" style=\"margin:12px 0 18px\">Three plants, a fourth on the way.<br>One standard.<\/h2>\n        <p style=\"margin:0;color:var(--soft);font-size:17px\">Making close to site shortens lead times and freight. West, south and north India each have a Truestar plant, and a new plant in Bengaluru is planned for 2027. Tap a plant to see what it serves.<\/p>\n        <div class=\"plist\" id=\"plist\"><\/div>\n      <\/div>\n      <div class=\"map cover\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-noida-aerial.webp)\" role=\"img\" aria-label=\"Truestar plant locations\">\n        <div class=\"veil\"><\/div>\n        <div id=\"pins\"><\/div>\n        <div class=\"pinfo\" id=\"pinfo\"><\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec factory\" id=\"factory\" aria-labelledby=\"f-h\">\n    <div class=\"wrap\">\n      <div style=\"display:flex;flex-direction:column;gap:18px\">\n        <div class=\"eyebrow\">Inside the Noida plant<\/div>\n        <h2 class=\"h2\" id=\"f-h\">See how we build it<\/h2>\n        <p style=\"margin:0;color:var(--ink2);font-size:17px\">CNC press brakes, roll formers and seam closers for duct; panel lines and fan sections for AHUs; welding and quality checks before dispatch.<\/p>\n        <button class=\"tour-btn\" type=\"button\" data-video=\"tour\"><i><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M8 5v14l11-7z\" fill=\"#fff\"\/><\/svg><\/i>Watch the factory tour \u00b7 2:24<\/button>\n        <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:auto\"><div class=\"cover\" role=\"img\" aria-label=\"The Truestar team at the Noida plant\" style=\"height:150px;border-radius:14px;position:relative;background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-team.webp)\"><span class=\"cap\">Team Noida<\/span><\/div><div class=\"cover\" role=\"img\" aria-label=\"The Truestar team at the Valsad plant\" style=\"height:150px;border-radius:14px;position:relative;background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-valsad-team.webp)\"><span class=\"cap\">Team Valsad<\/span><\/div><\/div>\n      <\/div>\n      <div class=\"mosaic\">\n        <div class=\"cover m-big lift\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-noida-aerial.webp)\" role=\"img\" aria-label=\"Aerial view of the Noida plant\"><span class=\"cap\">Noida plant from above<\/span><\/div>\n        <div class=\"cover m-w lift\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-press-brake.webp)\" role=\"img\" aria-label=\"CNC press brake\"><span class=\"cap\">CNC press brake<\/span><\/div>\n        <div class=\"cover lift\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-roll-former.webp)\" role=\"img\" aria-label=\"Roll forming\"><span class=\"cap\">Roll forming<\/span><\/div>\n        <div class=\"cover lift\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-welding.webp)\" role=\"img\" aria-label=\"Welding\"><span class=\"cap\">Welding<\/span><\/div>\n        <div class=\"cover m-w lift\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-round-ducts.webp)\" role=\"img\" aria-label=\"Round duct ready to ship\"><span class=\"cap\">Round duct, ready to ship<\/span><\/div>\n        <div class=\"cover m-w lift\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-ahu-large.webp)\" role=\"img\" aria-label=\"AHU assembly\"><span class=\"cap\">AHU assembly<\/span><\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec\" id=\"industries\" aria-labelledby=\"i-h\" style=\"background:#fff\">\n    <div class=\"wrap\">\n      <div class=\"head\"><div><div class=\"eyebrow\">Where our products go<\/div><h2 class=\"h2\" id=\"i-h\" style=\"margin-top:12px\">Industries we supply<\/h2><\/div><\/div>\n      <div class=\"ind\">\n        <div class=\"card lift\"><div class=\"code\">MRT<\/div><div><b>Airports &amp; metros<\/b><p>Station air distribution and tunnel ventilation products.<\/p><\/div><\/div>\n        <div class=\"card lift\"><div class=\"code\">COM<\/div><div><b>Commercial buildings<\/b><p>Offices, malls and hotels with concealed and exposed duct.<\/p><\/div><\/div>\n        <div class=\"card lift\"><div class=\"code\">HCR<\/div><div><b>Hospitals &amp; healthcare<\/b><p>OT and ward air distribution and ductwork.<\/p><\/div><\/div>\n        <div class=\"card lift\"><div class=\"code\">PHR<\/div><div><b>Pharma &amp; cleanrooms<\/b><p>Fan filter units, AHUs and insulated duct for classified areas.<\/p><\/div><\/div>\n        <div class=\"card lift\"><div class=\"code\">DCL<\/div><div><b>Data centres &amp; labs<\/b><p>Precision air paths, dampers and acoustic control.<\/p><\/div><\/div>\n        <div class=\"card lift\"><div class=\"code\">IND<\/div><div><b>Industrial &amp; manufacturing<\/b><p>Process ventilation, fresh air and exhaust systems.<\/p><\/div><\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec\" id=\"group\" aria-labelledby=\"g-h\">\n    <div class=\"wrap\">\n      <div class=\"head\"><div><div class=\"eyebrow\">Truestar Group<\/div><h2 class=\"h2\" id=\"g-h\" style=\"margin-top:12px\">Manufacturing plus global brands<\/h2><\/div><p>Three companies, one air-system partner. Truestar makes ductwork, air distribution and air handling products. Venti-Tron brings international HVAC brands to your project on the same order. iFlow India Innovations completes the group.<\/p><\/div>\n      <div class=\"group\">\n        <div class=\"gcard rv\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_truestar.webp\" alt=\"Truestar\"><h3 style=\"font:800 26px var(--display)\">Truestar Air Systems<\/h3><div style=\"font:500 12px var(--mono);color:var(--mute);letter-spacing:.06em\">TRUESTAR AIR SYSTEMS EQUIPMENTS PRIVATE LIMITED<\/div><p>Factory-fabricated ducts, grilles, diffusers, dampers, AHUs, TFA and fan coil units from plants in Valsad, Medak and Noida.<\/p><div class=\"brands\"><button type=\"button\" data-feat=\"rect\">Ductwork<\/button><span>Air terminals<\/span><span>Dampers<\/span><button type=\"button\" data-feat=\"ahu\">Air handling<\/button><button type=\"button\" data-feat=\"nozzle\">iFlow metro nozzles<\/button><\/div><\/div>\n        <div class=\"gcard vt rv\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_ventitron.webp\" alt=\"Venti-Tron\"><h3 style=\"font:800 26px var(--display)\">Venti-Tron<\/h3><div style=\"font:500 12px var(--mono);color:var(--mute);letter-spacing:.06em\">VENTI-TRON ENTERPRISES PRIVATE LIMITED<\/div><p>Authorised channel partner for global HVAC and indoor-air brands.<\/p><div class=\"brands\"><a href=\"https:\/\/www.titus-hvac.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Opens Titus official website\">Titus<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" aria-hidden=\"true\"><path d=\"M14 4h6v6M20 4l-9 9M18 14v6H4V6h6\"\/><\/svg><\/a><a href=\"https:\/\/www.ruskin.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Opens Ruskin official website\">Ruskin<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" aria-hidden=\"true\"><path d=\"M14 4h6v6M20 4l-9 9M18 14v6H4V6h6\"\/><\/svg><\/a><a href=\"https:\/\/www.trioniaq.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Opens Trion official website\">Trion<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" aria-hidden=\"true\"><path d=\"M14 4h6v6M20 4l-9 9M18 14v6H4V6h6\"\/><\/svg><\/a><a href=\"https:\/\/www.envirco-hvac.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Opens Envirco official website\">Envirco<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" aria-hidden=\"true\"><path d=\"M14 4h6v6M20 4l-9 9M18 14v6H4V6h6\"\/><\/svg><\/a><a href=\"https:\/\/www.triatek.com\/\" target=\"_blank\" rel=\"noopener\" title=\"Opens Triatek official website\">Triatek<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" aria-hidden=\"true\"><path d=\"M14 4h6v6M20 4l-9 9M18 14v6H4V6h6\"\/><\/svg><\/a><a href=\"https:\/\/leapcraft.dk\/\" target=\"_blank\" rel=\"noopener\" title=\"Opens Leapcraft official website\">Leapcraft<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" aria-hidden=\"true\"><path d=\"M14 4h6v6M20 4l-9 9M18 14v6H4V6h6\"\/><\/svg><\/a><\/div><p style=\"font-size:13px;color:var(--mute)\">Tap a brand to open its official website, product pages and catalogues.<\/p><div class=\"eyebrow\" style=\"margin-top:4px\">Highlights \u00b7 see them in 3D<\/div><div class=\"brands\"><button type=\"button\" data-feat=\"fsd60\">Ruskin FSD60<\/button><button type=\"button\" data-feat=\"tfd80\">Ruskin TFD80 tunnel damper<\/button><button type=\"button\" data-feat=\"ambinode\">Leapcraft AmbiNode<\/button><button type=\"button\" data-feat=\"leapsense\">LeapSense<\/button><button type=\"button\" data-feat=\"linear\">Titus linear grilles<\/button><button type=\"button\" data-feat=\"ufad\">Titus underfloor<\/button><button type=\"button\" data-feat=\"vav\">VAV boxes<\/button><\/div><\/div>\n        <div class=\"gcard ifl rv\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_iflow.webp\" alt=\"iFlow\"><h3 style=\"font:800 26px var(--display)\">iFlow<\/h3><div style=\"font:500 12px var(--mono);color:var(--mute);letter-spacing:.06em\">IFLOW INDIA INNOVATIONS PRIVATE LIMITED<\/div><p>A TrueStar Group company based in Noida. The iFlow brand name appears on selected Truestar products, such as cone and jet nozzles for metro projects.<\/p><\/div>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec\" aria-labelledby=\"r-h\">\n    <div class=\"wrap\">\n      <div class=\"head\"><div><div class=\"eyebrow\">Resources<\/div><h2 class=\"h2\" id=\"r-h\" style=\"margin-top:12px\">Catalogues, photos and videos<\/h2><\/div><a href=\"#resources\" style=\"font-weight:600;text-decoration:none\">Open Resources \u2192<\/a><\/div>\n      <div class=\"tiles\">\n        <a class=\"tile lift\" href=\"#resources\" style=\"background:var(--navy)\"><b>Catalogues<\/b><span>Ducts, air handling, air terminals, dampers. PDF downloads.<\/span><\/a>\n        <a class=\"tile lift cover\" href=\"#resources\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-shop-floor.webp)\"><div class=\"sh\"><\/div><b>Photo gallery<\/b><span>Products, plants and projects.<\/span><\/a>\n        <a class=\"tile lift cover\" href=\"#resources\" style=\"background-image:url(\/wp-content\/uploads\/2026\/09\/ts26-walkthrough-poster.jpg)\"><div class=\"sh\"><\/div><b>Videos<\/b><span>Factory tour and product demos.<\/span><\/a>\n      <\/div>\n    <\/div>\n  <\/section>\n\n  <section class=\"sec faq\" id=\"faq\" aria-labelledby=\"fq-h\">\n    <div class=\"wrap\">\n      <div><div class=\"eyebrow\">FAQ<\/div><h2 class=\"h2\" id=\"fq-h\" style=\"margin-top:12px\">Questions consultants and contractors ask us<\/h2><p style=\"margin:18px 0 22px;color:var(--ink2);font-size:17px\">Can't find your answer? Call +91 96252 05446 or send your drawings and we will come back to you.<\/p><a class=\"btn btn-dark\" href=\"#contact\">Ask our team<\/a><\/div>\n      <div>\n          <details><summary>What duct construction standards do you follow?<\/summary><p>Ductwork is built to the SMACNA HVAC Duct Construction Standards and applicable IS standards. Sheet gauges and joint reinforcement are selected from the SMACNA tables for pressure classes from 1\u2033 to 10\u2033 w.g. (250 to 2,500 Pa).<\/p><\/details>\n          <details><summary>Which duct joint systems can you supply?<\/summary><p>TDF (rolled-on flange), slip-on flange including the 4-bolt slip-on system, angle flange for heavier duty, and C & S cleats for smaller low-pressure sections. We recommend the joint system to suit the pressure class and site sequence.<\/p><\/details>\n          <details><summary>Do you manufacture air handling units?<\/summary><p>Yes. Truestar builds double-skin modular AHUs, treated fresh air units, hygienic and ceiling-suspended units, configured section by section to the project duty. Casing performance is specified to EN 1886 and the class achieved is confirmed at the time of offer.<\/p><\/details>\n          <details><summary>Can you supply UL-listed fire and smoke dampers?<\/summary><p>Yes. Through Venti-Tron, our group company, we supply the Ruskin life-safety range listed to UL 555 and UL 555S, including the FSD60 combination fire\/smoke damper and the TFD80 tunnel damper for metro and road tunnels.<\/p><\/details>\n          <details><summary>Where are your plants, and do you deliver across India?<\/summary><p>We manufacture in Valsad (Gujarat), Medak (Telangana) and Noida (Uttar Pradesh), with a new plant in Bengaluru planned for 2027, and we supply projects across India.<\/p><\/details>\n          <details><summary>What should I send for a quotation?<\/summary><p>Duct layout drawings and the project specification, the design pressure class and construction standard, schedules for dampers, diffusers, grilles and terminals, and your programme dates or phased delivery needs.<\/p><\/details>\n          <details><summary>Do you provide shop drawings and submittals?<\/summary><p>Yes. Approval drawings and duct layouts are issued for consultant review before fabrication, and submittal data or product samples can be provided on request.<\/p><\/details>\n      <\/div>\n    <\/div>\n    <script type=\"application\/ld+json\">{\"@context\": \"https:\/\/schema.org\", \"@type\": \"FAQPage\", \"mainEntity\": [{\"@type\": \"Question\", \"name\": \"What duct construction standards do you follow?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Ductwork is built to the SMACNA HVAC Duct Construction Standards and applicable IS standards. Sheet gauges and joint reinforcement are selected from the SMACNA tables for pressure classes from 1\u2033 to 10\u2033 w.g. (250 to 2,500 Pa).\"}}, {\"@type\": \"Question\", \"name\": \"Which duct joint systems can you supply?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"TDF (rolled-on flange), slip-on flange including the 4-bolt slip-on system, angle flange for heavier duty, and C & S cleats for smaller low-pressure sections. We recommend the joint system to suit the pressure class and site sequence.\"}}, {\"@type\": \"Question\", \"name\": \"Do you manufacture air handling units?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Yes. Truestar builds double-skin modular AHUs, treated fresh air units, hygienic and ceiling-suspended units, configured section by section to the project duty. Casing performance is specified to EN 1886 and the class achieved is confirmed at the time of offer.\"}}, {\"@type\": \"Question\", \"name\": \"Can you supply UL-listed fire and smoke dampers?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Yes. Through Venti-Tron, our group company, we supply the Ruskin life-safety range listed to UL 555 and UL 555S, including the FSD60 combination fire\/smoke damper and the TFD80 tunnel damper for metro and road tunnels.\"}}, {\"@type\": \"Question\", \"name\": \"Where are your plants, and do you deliver across India?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"We manufacture in Valsad (Gujarat), Medak (Telangana) and Noida (Uttar Pradesh), with a new plant in Bengaluru planned for 2027, and we supply projects across India.\"}}, {\"@type\": \"Question\", \"name\": \"What should I send for a quotation?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Duct layout drawings and the project specification, the design pressure class and construction standard, schedules for dampers, diffusers, grilles and terminals, and your programme dates or phased delivery needs.\"}}, {\"@type\": \"Question\", \"name\": \"Do you provide shop drawings and submittals?\", \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Yes. Approval drawings and duct layouts are issued for consultant review before fabrication, and submittal data or product samples can be provided on request.\"}}]}<\/script>\n  <\/section>\n\n  <section class=\"sec dark contact\" id=\"contact\" aria-labelledby=\"c-h\">\n    <div class=\"wrap\">\n      <div style=\"display:flex;flex-direction:column;gap:18px\">\n        <div class=\"eyebrow\">Request a quote<\/div>\n        <h2 class=\"h2\" id=\"c-h\">Tendering now?<br>Send us the BOQ.<\/h2>\n        <p style=\"margin:0;color:var(--soft);font-size:17px\">Attach drawings or a BOQ and tell us the site location. Our sales team comes back with a line-item offer.<\/p>\n        <div style=\"display:grid;gap:12px\">\n          <div><div class=\"eyebrow\" style=\"font-size:11px;color:var(--dim)\">Phone \/ WhatsApp<\/div>+91 96252 05446<\/div>\n          <div><div class=\"eyebrow\" style=\"font-size:11px;color:var(--dim)\">Email<\/div>Inquiry@truestarairsystems.com<\/div>\n          <div><div class=\"eyebrow\" style=\"font-size:11px;color:var(--dim)\">Follow us<\/div><div class=\"social\"><a href=\"https:\/\/www.linkedin.com\/company\/truestarairsystems\" target=\"_blank\" rel=\"noopener\" aria-label=\"Truestar on LinkedIn\"><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5zM3 9h4v12H3zM9 9h3.8v1.7h.1c.5-1 1.8-2 3.8-2 4 0 4.8 2.6 4.8 6V21h-4v-5.6c0-1.3 0-3-1.9-3s-2.2 1.5-2.2 2.9V21H9z\"\/><\/svg><span>LinkedIn<\/span><\/a><a href=\"https:\/\/www.instagram.com\/truestarairsystems\/\" target=\"_blank\" rel=\"noopener\" aria-label=\"Truestar on Instagram\"><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"5\"\/><circle cx=\"12\" cy=\"12\" r=\"4\"\/><circle cx=\"17.5\" cy=\"6.5\" r=\"1\" fill=\"currentColor\"\/><\/svg><span>Instagram<\/span><\/a><\/div><\/div>\n          <div><div class=\"eyebrow\" style=\"font-size:11px;color:var(--dim)\">Corporate office<\/div>Riana Aureus Towers, Plot 51-52, 6th Floor, Sector 136, Noida, Uttar Pradesh 201304<\/div>\n        <\/div>\n      <\/div>\n      <form class=\"enq\" id=\"enq\">\n        <div><label for=\"f-name\">Name<\/label><input id=\"f-name\" autocomplete=\"name\" required><\/div>\n        <div><label for=\"f-co\">Company<\/label><input id=\"f-co\" autocomplete=\"organization\"><\/div>\n        <div><label for=\"f-ph\">Phone<\/label><input id=\"f-ph\" type=\"tel\" autocomplete=\"tel\" required><\/div>\n        <div><label for=\"f-em\">Email<\/label><input id=\"f-em\" type=\"email\" autocomplete=\"email\"><\/div>\n        <div><label for=\"f-pr\">Product<\/label><select id=\"f-pr\"><option>Rectangular duct<\/option><option>Round \/ oval duct<\/option><option>AHU \/ TFA \/ FCU<\/option><option>Grilles &amp; diffusers<\/option><option>Dampers<\/option><option>Full package<\/option><\/select><\/div>\n        <div><label for=\"f-site\">Site location<\/label><input id=\"f-site\" placeholder=\"City, state\"><\/div>\n        <div class=\"full\"><label for=\"f-file\">BOQ or drawings (PDF, XLS, DWG)<\/label><input id=\"f-file\" type=\"file\"><\/div>\n        <div class=\"full\"><label for=\"f-msg\">Requirement<\/label><textarea id=\"f-msg\" placeholder=\"Quantities, gauges, delivery date\"><\/textarea><\/div>\n        <div class=\"full\" style=\"display:flex;flex-wrap:wrap;align-items:center;gap:14px\"><button class=\"btn btn-red\" type=\"submit\">Send enquiry<\/button><p class=\"note\" id=\"enqNote\" role=\"status\"><\/p><\/div>\n      <\/form>\n    <\/div>\n  <\/section>\n<\/main>\n\n<main id=\"page-resources\" hidden>\n  <section class=\"dark rhero\" aria-labelledby=\"rh\">\n    <div class=\"wrap\">\n      <div class=\"eyebrow\">Resources<\/div>\n      <h1 id=\"rh\">Catalogues, photos &amp; videos<\/h1>\n      <p>Download product catalogues and datasheets, browse our plants and products, and watch the factory at work.<\/p>\n    <\/div>\n  <\/section>\n  <div class=\"filters\"><div class=\"wrap\" id=\"filters\" role=\"group\" aria-label=\"Filter resources\"><\/div><\/div>\n\n  <section class=\"sec\" data-kind=\"cat\" aria-labelledby=\"cat-h\" style=\"padding-bottom:40px\">\n    <div class=\"wrap\">\n      <div class=\"head\"><h2 class=\"h2\" id=\"cat-h\" style=\"font-size:clamp(28px,3.4vw,42px)\">Catalogues &amp; datasheets<\/h2><p style=\"font-size:14px\">PDF \u00b7 free download<\/p><\/div>\n      <div class=\"cats\" id=\"cats\"><\/div>\n    <\/div>\n  <\/section>\n  <section class=\"sec\" data-kind=\"photo\" aria-labelledby=\"ph-h\" style=\"padding-block:40px\">\n    <div class=\"wrap\">\n      <div class=\"head\"><h2 class=\"h2\" id=\"ph-h\" style=\"font-size:clamp(28px,3.4vw,42px)\">Photo gallery<\/h2><p style=\"font-size:14px\">Tap a photo to enlarge<\/p><\/div>\n      <div class=\"gal\" id=\"gal\"><\/div>\n    <\/div>\n  <\/section>\n  <section class=\"sec\" data-kind=\"video\" aria-labelledby=\"vd-h\" style=\"padding-block:40px\">\n    <div class=\"wrap\">\n      <div class=\"head\"><h2 class=\"h2\" id=\"vd-h\" style=\"font-size:clamp(28px,3.4vw,42px)\">Videos<\/h2><p style=\"font-size:14px\">Tap to play<\/p><\/div>\n      <div class=\"vids\" id=\"vids\"><\/div>\n    <\/div>\n  <\/section>\n<\/main>\n\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8215ded ts26-mfw elementor-widget elementor-widget-shortcode\" data-id=\"8215ded\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><div class=\"mf-form-shortcode\">\r\n\t\t<div\r\n\t\t\tid=\"metform-wrap-4175-4175\"\r\n\t\t\tclass=\"mf-form-wrapper\"\r\n\t\t\tdata-form-id=\"4175\"\r\n\t\t\tdata-action=\"https:\/\/truestarairsystems.com\/index.php\/wp-json\/metform\/v1\/entries\/insert\/4175\"\r\n\t\t\tdata-wp-nonce=\"ad47864c8b\"\r\n\t\t\tdata-form-nonce=\"cbb6b4c9a5\"\r\n\t\t\tdata-quiz-summery = \"false\"\r\n\t\t\tdata-save-progress = \"false\"\r\n\t\t\tdata-form-type=\"general-form\"\r\n\t\t\tdata-stop-vertical-effect=\"\"\r\n\t\t\tdata-payment-submit-before=\"0\"\r\n\t\t\t><\/div>\r\n\r\n\r\n\t\t<!----------------------------- \r\n\t\t\t* controls_data : find the the props passed indie of data attribute\r\n\t\t\t* props.SubmitResponseMarkup : contains the markup of error or success message\r\n\t\t\t* https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Template_literals\r\n\t\t--------------------------- -->\r\n\r\n\t\t\t\t<script type=\"text\/mf\" class=\"mf-template\">\r\n\t\t\tfunction controls_data (value){\r\n\t\t\t\tlet currentWrapper = \"mf-response-props-id-4175\";\r\n\t\t\t\tlet currentEl = document.getElementById(currentWrapper);\r\n\t\t\t\t\r\n\t\t\t\treturn currentEl ? currentEl.dataset[value] : false\r\n\t\t\t}\r\n\r\n\r\n\t\t\tlet is_edit_mode = '' ? true : false;\r\n\t\t\tlet message_position = controls_data('messageposition') || 'top';\r\n\r\n\t\t\t\r\n\t\t\tlet message_successIcon = controls_data('successicon') || '';\r\n\t\t\tlet message_errorIcon = controls_data('erroricon') || '';\r\n\t\t\tlet message_editSwitch = controls_data('editswitchopen') === 'yes' ? true : false;\r\n\t\t\tlet message_proClass = controls_data('editswitchopen') === 'yes' ? 'mf_pro_activated' : '';\r\n\t\t\t\r\n\t\t\tlet is_dummy_markup = is_edit_mode && message_editSwitch ? true : false;\r\n\r\n\t\t\t\r\n\t\t\treturn html`\r\n\t\t\t\t<form\r\n\t\t\t\t\tclassName=\"metform-form-content\"\r\n\t\t\t\t\tref=${parent.formContainerRef}\r\n\t\t\t\t\tonSubmit=${ validation.handleSubmit( parent.handleFormSubmit ) }\r\n\t\t\t\t\r\n\t\t\t\t\t>\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\t\t${is_dummy_markup ? message_position === 'top' ?  props.ResponseDummyMarkup(message_successIcon, message_proClass) : '' : ''}\r\n\t\t\t\t\t${is_dummy_markup ? ' ' :  message_position === 'top' ? props.SubmitResponseMarkup`${parent}${state}${message_successIcon}${message_errorIcon}${message_proClass}` : ''}\r\n\r\n\t\t\t\t\t<!--------------------------------------------------------\r\n\t\t\t\t\t*** IMPORTANT \/ DANGEROUS ***\r\n\t\t\t\t\t${html``} must be used as in immediate child of \"metform-form-main-wrapper\"\r\n\t\t\t\t\tclass otherwise multistep form will not run at all\r\n\t\t\t\t\t---------------------------------------------------------->\r\n\r\n\t\t\t\t\t<div className=\"metform-form-main-wrapper\" key=${'hide-form-after-submit'} ref=${parent.formRef}>\r\n\t\t\t\t\t${html`\r\n\t\t\t\t\t\t\t\t<div data-elementor-type=\"wp-post\" key=\"2\" data-elementor-id=\"4175\" className=\"elementor elementor-4175\" data-elementor-post-type=\"metform-form\">\n\t\t\t\t<div className=\"elementor-element elementor-element-46a3f1bf e-con-full e-flex e-con e-parent\" data-id=\"46a3f1bf\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div className=\"elementor-element elementor-element-5356f21a elementor-widget elementor-widget-heading\" data-id=\"5356f21a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t<h3 className=\"elementor-heading-title elementor-size-default\">Enquiry  Form<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div className=\"elementor-element elementor-element-65b14f34 e-con-full e-grid e-con e-child\" data-id=\"65b14f34\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div className=\"elementor-element elementor-element-229b8a8 elementor-widget elementor-widget-mf-text\" data-id=\"229b8a8\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-first-name&quot;}\" data-widget_type=\"mf-text.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\r\n\t\t<div className=\"mf-input-wrapper\">\r\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-text-229b8a8\">\r\n\t\t\t\t\t${ parent.decodeEntities(`Full  Name`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\">*<\/span>\r\n\t\t\t\t<\/label>\r\n\t\t\t\r\n\t\t\t<input\r\n\t\t\t\ttype=\"text\"\r\n\t\t\t\tclassName=\"mf-input mf-conditional-input\"\r\n\t\t\t\tid=\"mf-input-text-229b8a8\"\r\n\t\t\t\tname=\"mf-first-name\"\r\n\t\t\t\tplaceholder=\"${ parent.decodeEntities(`Enter your full name here`) } \"\r\n\t\t\t\t\t\t\t\t\tonInput=${parent.handleChange}\r\n\t\t\t\t\tonBlur=${parent.handleChange}\r\n\t\t\t\t\taria-invalid=${validation.errors['mf-first-name'] ? 'true' : 'false'}\r\n\t\t\t\t\tref=${el =>{\r\n\t\t\t\t\t\t\t\t\t\t\t\tparent.activateValidation({\"message\":\"This field is required.\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":true,\"expression\":\"null\"}, el)\r\n\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\t\/>\r\n\r\n\t\t\t\t\t\t\t<${validation.ErrorMessage}\r\n\t\t\t\t\terrors=${validation.errors}\r\n\t\t\t\t\tname=\"mf-first-name\"\r\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\r\n\t\t\t\t\t\/>\r\n\t\t\t\r\n\t\t\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-49cb04c elementor-widget elementor-widget-mf-telephone\" data-id=\"49cb04c\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-telephone&quot;}\" data-widget_type=\"mf-telephone.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\n\t\t<div className=\"mf-input-wrapper\">\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-telephone-49cb04c\">\n\t\t\t\t\t${ parent.decodeEntities(`Phone Number`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\">*<\/span>\n\t\t\t\t<\/label>\n\t\t\t\n\t\t\t<input\n\t\t\t\ttype=\"tel\"\n\t\t\t\tclassName=\"mf-input \"\n\t\t\t\tid=\"mf-input-telephone-49cb04c\" \n\t\t\t\tname=\"mf-telephone\"\n\t\t\t\tplaceholder=\"${ parent.decodeEntities(`Enter your phone number here`) } \"\n\t\t\t\t\t\t\t\t\tonInput=${parent.handleChange}\n\t\t\t\t\taria-invalid=${validation.errors['mf-telephone'] ? 'true' : 'false'}\n\t\t\t\t\tref=${el => parent.activateValidation({\"message\":\"This field is required.\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":true,\"expression\":\"null\"}, el)}\n\t\t\t\t\t\t\t\t\/>\n\t\t\t\n\t\t\t\t\t\t\t<${validation.ErrorMessage}\n\t\t\t\t\terrors=${validation.errors}\n\t\t\t\t\tname=\"mf-telephone\"\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\n\t\t\t\t\t\/>\n\t\t\t\n\t\t\t\n\t\t<\/div>\n\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-752b6f44 elementor-widget elementor-widget-mf-email\" data-id=\"752b6f44\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-email&quot;}\" data-widget_type=\"mf-email.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\r\n\t\t<div className=\"mf-input-wrapper\">\r\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-email-752b6f44\">\r\n\t\t\t\t\t${ parent.decodeEntities(`Email Address`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\">*<\/span>\r\n\t\t\t\t<\/label>\r\n\t\t\t\r\n\t\t\t<input \r\n\t\t\t\ttype=\"email\" \r\n\t\t\t\t \r\n\t\t\t\tdefaultValue=\"\" \r\n\t\t\t\tclassName=\"mf-input mf-conditional-input\" \r\n\t\t\t\tid=\"mf-input-email-752b6f44\" \r\n\t\t\t\tname=\"mf-email\" \r\n\t\t\t\tplaceholder=\"${ parent.decodeEntities(`Enter your email here`) } \" \r\n\t\t\t\t \r\n\t\t\t\tonBlur=${parent.handleChange} onFocus=${parent.handleChange} aria-invalid=${validation.errors['mf-email'] ? 'true' : 'false' } \r\n\t\t\t\tref=${el=> parent.activateValidation({\"message\":\"This field is required.\",\"emailMessage\":\"Please enter a valid Email address\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":true,\"expression\":\"null\"}, el)}\r\n\t\t\t\t\t\t\t\/>\r\n\r\n\t\t\t\t\t\t<${validation.ErrorMessage} \r\n\t\t\t\terrors=${validation.errors} \r\n\t\t\t\tname=\"mf-email\" \r\n\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\r\n\t\t\t\/>\r\n\t\t\t\r\n\t\t\t\t\t<\/div>\r\n\r\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-99dc6a0 elementor-widget elementor-widget-mf-select\" data-id=\"99dc6a0\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-select&quot;,&quot;mf_input_list&quot;:[{&quot;mf_input_option_text&quot;:&quot;Factory Fabricated Ducts&quot;,&quot;mf_input_option_value&quot;:&quot;value-1&quot;,&quot;_id&quot;:&quot;3b580dc&quot;,&quot;mf_input_option_status&quot;:&quot;&quot;,&quot;mf_input_option_selected&quot;:&quot;&quot;},{&quot;mf_input_option_text&quot;:&quot;Air Distribution Products&quot;,&quot;mf_input_option_value&quot;:&quot;value-2&quot;,&quot;_id&quot;:&quot;567d61e&quot;,&quot;mf_input_option_status&quot;:&quot;&quot;,&quot;mf_input_option_selected&quot;:&quot;&quot;},{&quot;_id&quot;:&quot;b1924a7&quot;,&quot;mf_input_option_text&quot;:&quot;Air Handling Units&quot;,&quot;mf_input_option_value&quot;:&quot;Input Value&quot;,&quot;mf_input_option_status&quot;:&quot;&quot;,&quot;mf_input_option_selected&quot;:&quot;&quot;},{&quot;mf_input_option_text&quot;:&quot;Fan Filter Units&quot;,&quot;mf_input_option_value&quot;:&quot;value-3&quot;,&quot;_id&quot;:&quot;61c0581&quot;,&quot;mf_input_option_status&quot;:&quot;&quot;,&quot;mf_input_option_selected&quot;:&quot;&quot;},{&quot;mf_input_option_text&quot;:&quot;Ruskin Titus Products&quot;,&quot;mf_input_option_value&quot;:&quot;value-3&quot;,&quot;_id&quot;:&quot;4099bf2&quot;,&quot;mf_input_option_status&quot;:&quot;&quot;,&quot;mf_input_option_selected&quot;:&quot;&quot;},{&quot;mf_input_option_text&quot;:&quot;Leapcraft Products&quot;,&quot;mf_input_option_value&quot;:&quot;value-3&quot;,&quot;_id&quot;:&quot;c712833&quot;,&quot;mf_input_option_status&quot;:&quot;&quot;,&quot;mf_input_option_selected&quot;:&quot;&quot;}]}\" data-widget_type=\"mf-select.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\n\t\t\n\t\t<div className=\"mf-input-wrapper\">\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-select-99dc6a0\">\n\t\t\t\t\t${ parent.decodeEntities(`Products`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\">*<\/span>\n\t\t\t\t<\/label>\n            \n            <${props.Select}\n                className=${\"mf-input mf-input-select  \" + ( validation.errors['mf-select'] ? 'mf-invalid' : '' )}\n                classNamePrefix=\"mf_select\"\n                name=\"mf-select\"\n                placeholder=\"${ parent.decodeEntities(`Select from the list`) } \"\n                isSearchable=${false}\n                options=${[{\"label\":\"Factory Fabricated Ducts\",\"value\":\"value-1\",\"isDisabled\":false},{\"label\":\"Air Distribution Products\",\"value\":\"value-2\",\"isDisabled\":false},{\"label\":\"Air Handling Units\",\"value\":\"Input Value\",\"isDisabled\":false},{\"label\":\"Fan Filter Units\",\"value\":\"value-3\",\"isDisabled\":false},{\"label\":\"Ruskin Titus Products\",\"value\":\"value-3\",\"isDisabled\":false},{\"label\":\"Leapcraft Products\",\"value\":\"value-3\",\"isDisabled\":false}]}\n                value=${parent.getValue(\"mf-select\") ? [{\"label\":\"Factory Fabricated Ducts\",\"value\":\"value-1\",\"isDisabled\":false},{\"label\":\"Air Distribution Products\",\"value\":\"value-2\",\"isDisabled\":false},{\"label\":\"Air Handling Units\",\"value\":\"Input Value\",\"isDisabled\":false},{\"label\":\"Fan Filter Units\",\"value\":\"value-3\",\"isDisabled\":false},{\"label\":\"Ruskin Titus Products\",\"value\":\"value-3\",\"isDisabled\":false},{\"label\":\"Leapcraft Products\",\"value\":\"value-3\",\"isDisabled\":false}].filter(item => item.value === parent.getValue(\"mf-select\"))[0] : []}\n                onChange=${(e)=> parent.handleSelect(e, \"mf-select\")}\n                ref=${() => {\n\t\t\t\t                    register(\"mf-select\", parent.activateValidation({\"message\":\"This field is required.\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":true}));\n                    if ( parent.getValue(\"mf-select\") === '' && false ) {\n\t\t\t\t    parent.setValue( 'mf-select', '', true );\n                        parent.handleChange({\n                            target: {\n                                name: 'mf-select',\n                                value: ''\n                            }\n                        });\n                    }\n                }}\n                \/>\n\n            \t\t\t\t<${validation.ErrorMessage}\n\t\t\t\t\terrors=${validation.errors}\n\t\t\t\t\tname=\"mf-select\"\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\n\t\t\t\t\t\/>\n\t\t\t\t\t\t\t\t<\/div>\n\n\t\t\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-055f550 elementor-widget__width-initial elementor-widget elementor-widget-mf-text\" data-id=\"055f550\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-text&quot;}\" data-widget_type=\"mf-text.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\r\n\t\t<div className=\"mf-input-wrapper\">\r\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-text-055f550\">\r\n\t\t\t\t\t${ parent.decodeEntities(`Company Name`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\">*<\/span>\r\n\t\t\t\t<\/label>\r\n\t\t\t\r\n\t\t\t<input\r\n\t\t\t\ttype=\"text\"\r\n\t\t\t\tclassName=\"mf-input \"\r\n\t\t\t\tid=\"mf-input-text-055f550\"\r\n\t\t\t\tname=\"mf-text\"\r\n\t\t\t\tplaceholder=\"${ parent.decodeEntities(`Enter your company name here`) } \"\r\n\t\t\t\t\t\t\t\t\tonInput=${parent.handleChange}\r\n\t\t\t\t\tonBlur=${parent.handleChange}\r\n\t\t\t\t\taria-invalid=${validation.errors['mf-text'] ? 'true' : 'false'}\r\n\t\t\t\t\tref=${el =>{\r\n\t\t\t\t\t\t\t\t\t\t\t\tparent.activateValidation({\"message\":\"This field is required.\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":true,\"expression\":\"null\"}, el)\r\n\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\t\/>\r\n\r\n\t\t\t\t\t\t\t<${validation.ErrorMessage}\r\n\t\t\t\t\terrors=${validation.errors}\r\n\t\t\t\t\tname=\"mf-text\"\r\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\r\n\t\t\t\t\t\/>\r\n\t\t\t\r\n\t\t\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-0d7a735 elementor-widget__width-initial elementor-widget elementor-widget-mf-text\" data-id=\"0d7a735\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-text&quot;}\" data-widget_type=\"mf-text.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\r\n\t\t<div className=\"mf-input-wrapper\">\r\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-text-0d7a735\">\r\n\t\t\t\t\t${ parent.decodeEntities(`City`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\">*<\/span>\r\n\t\t\t\t<\/label>\r\n\t\t\t\r\n\t\t\t<input\r\n\t\t\t\ttype=\"text\"\r\n\t\t\t\tclassName=\"mf-input \"\r\n\t\t\t\tid=\"mf-input-text-0d7a735\"\r\n\t\t\t\tname=\"mf-text\"\r\n\t\t\t\tplaceholder=\"${ parent.decodeEntities(`Enter your city here`) } \"\r\n\t\t\t\t\t\t\t\t\tonInput=${parent.handleChange}\r\n\t\t\t\t\tonBlur=${parent.handleChange}\r\n\t\t\t\t\taria-invalid=${validation.errors['mf-text'] ? 'true' : 'false'}\r\n\t\t\t\t\tref=${el =>{\r\n\t\t\t\t\t\t\t\t\t\t\t\tparent.activateValidation({\"message\":\"This field is required.\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":true,\"expression\":\"null\"}, el)\r\n\t\t\t\t\t}}\r\n\t\t\t\t\t\t\t\t\/>\r\n\r\n\t\t\t\t\t\t\t<${validation.ErrorMessage}\r\n\t\t\t\t\terrors=${validation.errors}\r\n\t\t\t\t\tname=\"mf-text\"\r\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\r\n\t\t\t\t\t\/>\r\n\t\t\t\r\n\t\t\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-dfa3091 elementor-widget elementor-widget-mf-file-upload\" data-id=\"dfa3091\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-file-upload&quot;}\" data-widget_type=\"mf-file-upload.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\r\n\t\t\r\n\t\t<div className=\"mf-input-wrapper\">\r\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-file-upload-dfa3091\">\r\n\t\t\t\t\t${ parent.decodeEntities(`File Upload`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\"><\/span>\r\n\t\t\t\t<\/label>\r\n\t\t\t\r\n\t\t\t<div className=\"mf-file-upload-container multi-option-input-type\">\r\n\t\t\t\t<input\r\n\t\t\t\t\ttype=\"file\"\r\n\t\t\t\t\tclassName=\"mf-input mf-input-file-upload \"\r\n\t\t\t\t\tid=\"mf-input-file-upload-dfa3091\" \r\n\t\t\t\t\tname=\"mf-file-upload\" \r\n\t\t\t\t\t\t\t\t\t\taccept=\".jpg, .jpeg, .gif, .png\"\r\n\t\t\t\t\tonInput=${ parent.handleFileUpload }\r\n\t\t\t\t\taria-invalid=${validation.errors['mf-file-upload'] ? 'true' : 'false'}\r\n\t\t\t\t\tref=${ el => parent.activateValidation({\"message\":\"This field is required.\",\"required\":false,\"file_types\":[\".jpg\",\".jpeg\",\".gif\",\".png\"],\"type_message\":\"Invalid file extension\",\"size_limit\":-1,\"limit_message\":\"This field is required.\"}, el) }\r\n\t\t\t\t\t\/>\r\n\t\t\t\t<label htmlFor=\"mf-input-file-upload-dfa3091\" className=\"mf-input-file-upload-label metform-btn\">\r\n\t\t\t\t\t<span>${ parent.decodeEntities(`Choose a file`) } <\/span>\t\t\t\t<\/label>\r\n\t\t\t\t<div className=\"mf-file-name\">\r\n\t\t\t\t\t${\r\n\t\t\t\t\t\t(parent.state.formData['mf-file-upload'] || []).length > 0\r\n\t\t\t\t\t\t? parent.state.formData['mf-file-upload'].map((file, idx) => html`\r\n\t\t\t\t\t\t\t<span className=\"mf-file-name-item\" key=${idx}>\r\n\t\t\t\t\t\t\t\t<span>${file.name}<\/span>\r\n\t\t\t\t\t\t\t\t<span \r\n\t\t\t\t\t\t\t\t\tclassName=\"mf-file-remove\" \r\n\t\t\t\t\t\t\t\t\tonClick=${() => parent.removeUploadedFile('mf-file-upload', idx)}\r\n\t\t\t\t\t\t\t\t\ttitle=\"Remove\"\r\n\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t<label className=\"mf-file-cross\">\u00d7<\/label>\r\n\t\t\t\t\t\t\t\t<\/span>\r\n\t\t\t\t\t\t\t<\/span>\r\n\t\t\t\t\t\t`)\r\n\t\t\t\t\t\t: html`<span>${parent.getFileLabel('mf-file-upload', 'No file chosen.')}<\/span>`\r\n\t\t\t\t\t}\r\n\t\t\t\t<\/div>\r\n\t\t\t\t\r\n\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t\t<${validation.ErrorMessage}\r\n\t\t\t\t\terrors=${validation.errors}\r\n\t\t\t\t\tname=\"mf-file-upload\"\r\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\r\n\t\t\t\t\t\/>\r\n\t\t\t\r\n\t\t\t\t\t<\/div>\r\n\r\n\t\t\r\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-13f46608 elementor-widget__width-inherit elementor-widget-tablet__width-initial elementor-widget elementor-widget-mf-textarea\" data-id=\"13f46608\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;mf_input_name&quot;:&quot;mf-comment&quot;}\" data-widget_type=\"mf-textarea.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\r\n\t\t<div className=\"mf-input-wrapper\">\r\n\t\t\t\t\t\t\t<label className=\"mf-input-label\" htmlFor=\"mf-input-text-area-13f46608\">\r\n\t\t\t\t\t${ parent.decodeEntities(`Comments \/ Questions`) } \t\t\t\t\t<span className=\"mf-input-required-indicator\"><\/span>\r\n\t\t\t\t<\/label>\r\n\t\t\t\r\n\t\t\t<textarea className=\"mf-input mf-textarea mf-conditional-input\" id=\"mf-input-text-area-13f46608\"\r\n\t\t\t\tname=\"mf-comment\" \r\n\t\t\t\tplaceholder=\"${ parent.decodeEntities(`Enter here`) } \"\r\n\t\t\t\tcols=\"30\" rows=\"10\"\r\n\t\t\t\t\t\t\t\t\tonInput=${ parent.handleChange }\r\n\t\t\t\t\taria-invalid=${validation.errors['mf-comment'] ? 'true' : 'false'}\r\n\t\t\t\t\tref=${ el => parent.activateValidation({\"message\":\"This field is required.\",\"minLength\":1,\"maxLength\":\"\",\"type\":\"none\",\"required\":false,\"expression\":\"null\"}, el)}\r\n\t\t\t\t\t\t\t\t><\/textarea>\r\n\r\n\t\t\t\t\t\t\t<${validation.ErrorMessage}\r\n\t\t\t\t\terrors=${validation.errors}\r\n\t\t\t\t\tname=\"mf-comment\"\r\n\t\t\t\t\tas=${html`<span className=\"mf-error-message\"><\/span>`}\r\n\t\t\t\t\t\/>\r\n\t\t\t\t\t\t\t\t<\/div>\r\n\r\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div className=\"elementor-element elementor-element-54379b03 elementor-widget__width-auto elementor-widget elementor-widget-mf-button\" data-id=\"54379b03\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"mf-button.default\">\n\t\t\t\t<div className=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div className=\"mf-btn-wraper mf-conditional-input\" data-mf-form-conditional-logic-requirement=\"\">\r\n\t\t\t\t\t\t\t<button type=\"submit\" className=\"metform-btn metform-submit-btn \" id=\"\">\r\n\t\t\t\t\t<span>${ parent.decodeEntities(`Send Message`) } <\/span>\r\n\t\t\t\t<\/button>\r\n\t\t\t        <\/div>\r\n        \t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t\t`}\r\n\t\t\t\t\t<\/div>\r\n\r\n\t\t\t\t\t${is_dummy_markup ? message_position === 'bottom' ? props.ResponseDummyMarkup(message_successIcon, message_proClass) : '' : ''}\r\n\t\t\t\t\t${is_dummy_markup ? ' ' : message_position === 'bottom' ? props.SubmitResponseMarkup`${parent}${state}${message_successIcon}${message_errorIcon}${message_proClass}` : ''}\r\n\t\t\t\t\r\n\t\t\t\t<\/form>\r\n\t\t\t`\r\n\t\t<\/script>\r\n\r\n\t\t<\/div><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2ffd0eb elementor-widget elementor-widget-html\" data-id=\"2ffd0eb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div id=\"ts26b\"><footer>\n  <div class=\"wrap\">\n    <div style=\"max-width:420px\"><div style=\"background:#fff;border-radius:10px;padding:10px 14px;display:inline-block;margin-bottom:12px\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_truestar.webp\" alt=\"Truestar\" style=\"height:54px;width:auto\"><\/div><br>Truestar Air Systems Equipments Private Limited<br>Group companies: Venti-Tron Enterprises Private Limited \u00b7 iFlow India Innovations Private Limited<br>Riana Aureus Towers, Plot 51-52, 6th Floor, Sector 136, Noida, Uttar Pradesh 201304<br>ISO 9001:2015<\/div>\n    <div class=\"cols\">\n      <div><strong>Company<\/strong><a href=\"https:\/\/truestarairsystems.com\/index.php\/about\/\">About us<\/a><a href=\"#plants\">Plants<\/a><a href=\"#factory\">Factory<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/contact-us\/\">Contact<\/a><\/div>\n      <div><strong>Truestar products<\/strong><a href=\"https:\/\/truestarairsystems.com\/index.php\/air-handling-products\/\">Air handling products<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/rectangular-ducts-manufacturer-noida\">Rectangular ducts<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/round-ducts-manufacturer-noida\">Round ducts<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/other-range-of-ducts\/\">Other ducts<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/dampers-manufacturer-in-noida\">Dampers<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/diffusers-manufacturer-in-noida\/\">Diffusers<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/grilles-manufacturer-in-noida\/\">Grilles<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/best-sound-attenuator-manufacturer\/\">Sound attenuators<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/fan-filter-units-ffus\/\">Fan filter units<\/a><\/div>\n      <div><strong>Venti-Tron brands<\/strong><a href=\"https:\/\/truestarairsystems.com\/index.php\/ruskin\/\">Ruskin<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/titus\/\">Titus<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/leapcraft\/\">Leapcraft<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/trion\/\">Trion<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/envirco\/\">Envirco<\/a><a href=\"https:\/\/truestarairsystems.com\/index.php\/triatek\/\">Triatek<\/a><\/div>\n      <div><strong>Resources<\/strong><a href=\"#resources\">Catalogues<\/a><a href=\"#resources\">Photos<\/a><a href=\"#resources\">Videos<\/a><\/div>\n      <div><strong>Follow us<\/strong><div class=\"social\"><a href=\"https:\/\/www.linkedin.com\/company\/truestarairsystems\" target=\"_blank\" rel=\"noopener\" aria-label=\"Truestar on LinkedIn\"><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><path d=\"M4.98 3.5a2.5 2.5 0 1 1 0 5 2.5 2.5 0 0 1 0-5zM3 9h4v12H3zM9 9h3.8v1.7h.1c.5-1 1.8-2 3.8-2 4 0 4.8 2.6 4.8 6V21h-4v-5.6c0-1.3 0-3-1.9-3s-2.2 1.5-2.2 2.9V21H9z\"\/><\/svg><span>LinkedIn<\/span><\/a><a href=\"https:\/\/www.instagram.com\/truestarairsystems\/\" target=\"_blank\" rel=\"noopener\" aria-label=\"Truestar on Instagram\"><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"5\"\/><circle cx=\"12\" cy=\"12\" r=\"4\"\/><circle cx=\"17.5\" cy=\"6.5\" r=\"1\" fill=\"currentColor\"\/><\/svg><span>Instagram<\/span><\/a><\/div><\/div>\n    <\/div>\n  <\/div>\n<\/footer>\n\n<div class=\"mbar\" aria-label=\"Quick contact\"><a class=\"btn btn-dark\" href=\"tel:+919625205446\">Call<\/a><a class=\"btn\" href=\"https:\/\/wa.me\/919625205446\" target=\"_blank\" rel=\"noopener\" style=\"background:#1f7a4d;color:#fff\">WhatsApp<\/a><\/div>\n\n<div class=\"modal\" id=\"modal\" hidden role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"mTitle\">\n  <div class=\"box\">\n    <div id=\"mMedia\"><\/div>\n    <div class=\"bar\">\n      <div><b id=\"mTitle\"><\/b><small id=\"mTag\"><\/small><\/div>\n      <div style=\"display:flex;gap:10px\">\n        <button class=\"round\" id=\"mPrev\" type=\"button\" aria-label=\"Previous\">\u2039<\/button>\n        <button class=\"round\" id=\"mNext\" type=\"button\" aria-label=\"Next\">\u203a<\/button>\n        <button class=\"pill\" id=\"mClose\" type=\"button\">Close<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!--noptimize--><script>\n(function(){\n  const $=s=>document.querySelector(s), $$=s=>[...document.querySelectorAll(s)];\n\n  \/* ---------- routing: #resources shows the Resources page, everything else Home ---------- *\/\n  const home=$('#page-home'), res=$('#page-resources');\n  function route(){\n    const h=location.hash.replace('#','')||'home';\n    const isRes=h==='resources';\n    home.hidden=isRes; res.hidden=!isRes;\n    $$('.nav a').forEach(a=>a.classList.toggle('on', isRes ? a.dataset.route==='resources' : a.getAttribute('href')==='#'+h));\n    $('#mnav').classList.remove('open');\n    if(isRes) window.scrollTo(0,0);\n    else { const el=document.getElementById(h); if(el && h!=='home') setTimeout(()=>el.scrollIntoView({behavior:'smooth'}),10); else window.scrollTo(0,0); }\n  }\n  window.addEventListener('hashchange',route);\n  $('#menuBtn').addEventListener('click',e=>{const m=$('#mnav');m.classList.toggle('open');e.currentTarget.setAttribute('aria-expanded',m.classList.contains('open'))});\n\n  \/* ---------- featured 3D studio (UI; WebGL module plugs in via window.feat3d) ---------- *\/\n  const BR={truestar:['Truestar',null],ruskin:['Ruskin','https:\/\/www.ruskin.com\/','https:\/\/truestarairsystems.com\/index.php\/ruskin\/'],titus:['Titus','https:\/\/www.titus-hvac.com\/','https:\/\/truestarairsystems.com\/index.php\/titus\/'],leapcraft:['Leapcraft','https:\/\/leapcraft.dk\/','https:\/\/truestarairsystems.com\/index.php\/leapcraft\/']};\n  const FEAT=[\n    {b:'truestar',k:'ahu',t:'Double-skin modular AHU',s:'Truestar \u00b7 Air handling',img:'p_ahu1',pg:21,cat:'ahu',\n     d:'Built section by section to the project duty on a thermally broken frame with removable panels. Open the doors to see the mixing box, bag filters, coil, plug fan and attenuator.',\n     sp:['Casing classes to EN 1886: D1\u2013D3, L1\u2013L3, T1\u2013T5, TB1\u2013TB5','Double-skin 25 or 45 mm panels, PUF or mineral wool','Plug fans with EC or IE3\/IE4 motors and VFD control','CHW, hot water, steam or DX coils; ISO 16890 filters, terminal HEPA']},\n    {b:'truestar',k:'rect',t:'Rectangular GI ductwork',s:'Truestar \u00b7 Ducting',img:'p_duct_rect',pg:7,\n     d:'Factory-fabricated from galvanised steel, aluminium or stainless steel, with joints and gauges chosen for the design pressure class.',\n     sp:['TDF, slip-on, angle-flange and C &amp; S joints','Pressure classes 1\u2033\u201310\u2033 w.g. (250\u20132,500 Pa)','Gauges from SMACNA selection tables','Factory-applied thermal or acoustic insulation']},\n    {b:'truestar',k:'spiral',t:'Spiral round &amp; flat-oval duct',s:'Truestar \u00b7 Ducting',img:'p_duct_spiral',pg:9,\n     d:'Formed from a continuous galvanised coil. The spiral seam stiffens the duct and the round section gives lower pressure loss and leakage than rectangular runs.',\n     sp:['Wide range of diameters to suit the project','Flat-oval where ceiling depth is tight','Bends, tees, reducers, saddles and couplers','Clean finish for exposed interiors']},\n    {b:'truestar',k:'nozzle',t:'iFlow cone &amp; jet nozzles',logo:'\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_iflow.webp',s:'iFlow brand \u00b7 by Truestar \u00b7 Metro range',img:'p_diff_jet',pg:17,\n     d:'Long-throw nozzles for metro concourses, station halls and other tall, open spaces, supplied by Truestar under the iFlow brand.',\n     sp:['Long throw for large volumes','Adjustable direction to aim the air jet','Selected for throw and noise at the design airflow']},\n    {b:'ruskin',k:'fsd60',t:'FSD60 combination fire\/smoke damper',s:'Ruskin \u00b7 UL 555 \/ UL 555S',img:'p_damp_fire',pg:26,\n     d:'Galvanised frame with airfoil blades for dynamic closure. The FSD60-3 version adds a 3-hour rating, a heat-actuated release and remote reset through the actuator.',\n     sp:['UL 555 fire and UL 555S smoke listing','1\u00bd hr (FSD60) or 3 hr (FSD60-3) fire rating','Leakage class I; dynamic closure','Up to 4,000 fpm \/ 8\u2033 w.g.; AMCA licensed for air performance (FSD60-3)']},\n    {b:'ruskin',k:'tfd80',t:'TFD80 tunnel fire &amp; smoke damper',s:'Ruskin \u00b7 Metro &amp; road tunnels',img:'p_damp_multi',pg:28,\n     d:'Heavy-duty damper for transit tunnel ventilation and smoke control, paired with Truestar smoke-extract ductwork on metro projects.',\n     sp:['4 hr to BS 476:20 (tested at Southwest Research Institute)','NFPA 130 and NFPA 502','UL 555S Class I leakage','Rated 24\u2033 w.g. and 4,000 fpm']},\n    {b:'titus',k:'linear',t:'Linear slot diffusers &amp; linear grilles',s:'Titus \u00b7 Air distribution',img:'p_diff_slot',pg:28,\n     d:'Continuous architectural runs, including the Titus Flowbar linear slot diffuser, for offices, retail and hospitality ceilings.',\n     sp:['Continuous runs with concealed joints','Pattern controllers set the throw for each slot','Supply and return, with plenum options','Selections from the Titus datasheet']},\n    {b:'titus',k:'ufad',t:'Underfloor air distribution',s:'Titus \u00b7 Floor diffusers',img:'p_diff_round',pg:null,\n     d:'Conditioned air is delivered from a pressurised raised-floor plenum through floor diffusers, so supply points move with the floor tiles as layouts change.',\n     sp:['Swirl floor diffusers mix air in the occupied zone','Relocatable with the raised-floor tiles','Suits open offices, auditoria and control rooms','Selections from the Titus datasheet']},\n    {b:'titus',k:'vav',t:'VAV boxes (ESV \/ DESV)',s:'Titus \u00b7 Terminal units',img:'p_plenum',pg:23,\n     d:'Titus ESV \/ DESV variable air volume duct terminals, supplied where AHRI-certified terminals are specified.',\n     sp:['AHRI-certified VAV duct terminals','Varies airflow to each zone to match its load','Inlet flow sensing with DDC control','Integration with the building management system']},\n    {b:'leapcraft',k:'ambinode',t:'AmbiNode\u00ae multi-sensor',s:'Leapcraft \u00b7 Denmark',img:'ambinode',photo:'\/wp-content\/uploads\/2026\/09\/ts26-lib-ambinode.webp',pg:29,\n     d:'Indoor multi-sensor and VAV controller that measures what the space is actually doing and drives demand-controlled ventilation.',\n     sp:['True CO\u2082 (optical), PM1\/PM2.5\/PM10, temperature, RH, pressure, lux, noise','Occupancy and people count with no cameras','WiFi, sub-GHz RF to up to 5 MiniNode satellites; BACnet, Modbus, REST API','150 \u00d7 150 \u00d7 20 mm; power by USB, 24 V or PoE']},\n    {b:'leapcraft',k:'leapsense',t:'LeapSense\u00ae cloud platform',s:'Leapcraft \u00b7 Software',img:null,pg:29,dash:true,\n     d:'Brings energy, HVAC performance, air quality, occupancy and weather data together at campus, building, room and zone level.',\n     sp:['Reporting for Active House, DGNB and ESG','Compliance framing for ASHRAE, WELL, LEED and IGBC','Works with AmbiLink demand-controlled ventilation','Leapcraft publishes 40\u201360% HVAC energy reduction and 2\u20134 yr typical ROI']}\n  ];\n  let fBrand='truestar', fKey='ahu';\n  const fStage=$('#fstage');\n  function fRender(){\n    $('#fbrands').innerHTML=Object.entries(BR).map(([k,[l]])=>`<button type=\"button\" role=\"tab\" aria-selected=\"${k===fBrand}\" class=\"${k===fBrand?'on':''}\" data-b=\"${k}\">${l}<\/button>`).join('');\n    $('#fitems').innerHTML=FEAT.filter(f=>f.b===fBrand).map(f=>`<button type=\"button\" data-k=\"${f.k}\" class=\"${f.k===fKey?'on':''}\"><span>${f.t}<small>${f.s}<\/small><\/span><span class=\"n3d\">${f.dash?'UI':'3D'}<\/span><\/button>`).join('');\n    const f=FEAT.find(x=>x.k===fKey), br=BR[f.b];\n    $('#finfo').innerHTML=`${f.logo?`<img decoding=\"async\" data-no-lazy=\"1\" src=\"${f.logo}\" alt=\"iFlow\" style=\"height:36px;width:auto;align-self:flex-start\">`:''}<div class=\"tag\">${f.s}<\/div><h3>${f.t}<\/h3>${f.photo?`<div style=\"display:flex;gap:14px;align-items:center;background:var(--ground);border-radius:12px;padding:10px\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"${f.photo}\" alt=\"${f.t.replace(\/<[^>]+>\/g,'')} product photo\" style=\"width:84px;height:84px;object-fit:contain\"><span style=\"font-size:13px;color:var(--mute)\">Product photo: Leapcraft. The 3D model on the left uses the same face.<\/span><\/div>`:''}<p>${f.d}<\/p><ul class=\"qspec\">${f.sp.map(x=>`<li>${x}<\/li>`).join('')}<\/ul>${f.dash?'<p class=\"note\">The screen on the left is illustrative, not live data. Savings figures are as published by Leapcraft.<\/p>':''}<div class=\"acts\">${br[1]?`<a class=\"btn btn-dark\" href=\"${br[1]}\" target=\"_blank\" rel=\"noopener\">${br[0]} website \u2197<\/a>`:''}${br[2]?`<a class=\"btn btn-ghost\" href=\"${br[2]}\">${br[0]} at Venti-Tron<\/a>`:''}${f.pg?`<button type=\"button\" class=\"btn btn-ghost\" data-flip=\"group\" data-page=\"${f.pg}\">Catalogue p.${f.pg}<\/button>`:''}${f.cat?`<button type=\"button\" class=\"btn btn-ghost\" data-flip=\"${f.cat}\">AHU catalogue<\/button>`:''}<a class=\"btn btn-red\" href=\"#contact\" data-fq=\"${f.t.replace(\/&amp;\/g,'&')}\">Enquire<\/a><\/div>`;\n    $('#flabel').textContent=(br[0]+' \u00b7 '+f.t.replace(\/&amp;\/g,'&')).toUpperCase();\n    $('#lsdash').hidden=!f.dash;\n    const gl=window.feat3d;\n    $('#ffb').style.backgroundImage=(!gl&&f.img)?`url(\/wp-content\/uploads\/2026\/09\/ts26-lib-${f.img}.webp)`:'none'; $('#ffb').setAttribute('aria-label',f.t);\n    $('#fgl').style.visibility=f.dash?'hidden':'visible';\n    if(gl&&!f.dash) gl.show(f.k==='leapsense'?'ambinode':f.k);\n    if(!gl||f.dash) $('#ftoggle').hidden=true;\n    $('#fhint').textContent=f.dash?'LEAPSENSE \u00b7 ILLUSTRATIVE SCREEN':(gl?'DRAG TO ROTATE':'PRODUCT PHOTO');\n  }\n  $('#fbrands').addEventListener('click',e=>{const b=e.target.closest('button');if(!b)return;fBrand=b.dataset.b;fKey=FEAT.find(f=>f.b===fBrand).k;fRender();});\n  $('#fitems').addEventListener('click',e=>{const b=e.target.closest('button');if(!b)return;fKey=b.dataset.k;fRender();});\n  $('#finfo').addEventListener('click',e=>{const a=e.target.closest('[data-fq]');if(a){$('#f-msg').value='Enquiry about: '+a.dataset.fq+'\\n';}});\n  $('#ftoggle').addEventListener('click',()=>{window.feat3d&&window.feat3d.toggle();});\n  document.addEventListener('click',e=>{const b=e.target.closest('[data-feat]');if(!b)return;const f=FEAT.find(x=>x.k===b.dataset.feat);if(!f)return;fBrand=f.b;fKey=f.k;fRender();$('#featured').scrollIntoView({behavior:'smooth'});});\n  window.featRender=fRender; fRender();\n\n  \/* ---------- 3D viewer ---------- *\/\n  const stage=$('#stage'), model=$('#model');\n  let rx=-16, ry=32, drag=null, current='rect';\n  const metal=(a,b,c,ang)=>`linear-gradient(${ang}deg,${a} 0%,${b} 55%,${c} 100%)`;\n  const cross=(w,h)=>`<svg width=\"${w}\" height=\"${h}\" viewBox=\"0 0 ${w} ${h}\" aria-hidden=\"true\"><path d=\"M0 0L${w} ${h}M${w} 0L0 ${h}\" stroke=\"#737d8d\" stroke-width=\"1.2\" fill=\"none\"\/><\/svg>`;\n  function rectHTML(){\n    return `<div class=\"spin\" style=\"width:320px;height:200px;position:relative\">\n      <div class=\"face\" style=\"width:320px;height:360px;margin-top:-80px;transform:rotateX(90deg) translateZ(100px);background:${metal('#dde2e8','#aab3bf','#c9d0d9',135)};border:1px solid #8a94a3\">${cross(320,360)}<\/div>\n      <div class=\"face\" style=\"width:320px;height:360px;margin-top:-80px;transform:rotateX(-90deg) translateZ(100px);background:${metal('#8d97a5','#6f7988','#7a8493',135)};border:1px solid #5f6977\"><\/div>\n      <div class=\"face\" style=\"width:360px;height:200px;margin-left:-20px;transform:rotateY(90deg) translateZ(160px);background:${metal('#c3cad4','#98a2b0','#b5bdc8',160)};border:1px solid #7c8696\">${cross(360,200)}<\/div>\n      <div class=\"face\" style=\"width:360px;height:200px;margin-left:-20px;transform:rotateY(-90deg) translateZ(160px);background:${metal('#b9c1cc','#8e98a6','#a3acb8',200)};border:1px solid #7c8696\">${cross(360,200)}<\/div>\n      <div class=\"face\" style=\"left:-14px;top:-14px;width:348px;height:228px;transform:translateZ(180px);border:14px solid #5d6776;box-shadow:inset 0 0 0 2px #d7261e\"><\/div>\n      <div class=\"face\" style=\"left:-14px;top:-14px;width:348px;height:228px;transform:translateZ(-180px);border:14px solid #5d6776\"><\/div>\n    <\/div>`;\n  }\n  function roundHTML(){\n    let s='';\n    for(let i=0;i<24;i++){const sh=150+Math.round(55*Math.cos(i\/24*Math.PI*2));\n      s+=`<div class=\"face\" style=\"width:30px;height:340px;transform:rotateY(${i*15}deg) translateZ(112px);background:repeating-linear-gradient(160deg,rgb(${sh},${sh+8},${sh+18}) 0 26px,rgb(${sh-40},${sh-32},${sh-22}) 26px 29px)\"><\/div>`;}\n    return `<div class=\"spin\" style=\"width:30px;height:340px;position:relative\">${s}\n      <div class=\"face\" style=\"left:-104px;top:-10px;width:238px;height:238px;border-radius:50%;border:10px solid #5d6776;transform:rotateX(90deg) translateZ(10px)\"><\/div><\/div>`;\n  }\n  const hints={rect:'DRAG TO ROTATE \u00b7 GI RECTANGULAR DUCT \u00b7 CROSS-BROKEN PANELS',round:'DRAG TO ROTATE \u00b7 SPIRAL-SEAM ROUND DUCT',ahu:'MOVE YOUR POINTER TO TILT \u00b7 TRUESTAR AHU'};\n  function scaleFor(){const w=stage.clientWidth;return Math.min(1,w\/560)*(current==='rect'?1:1);}\n  function apply(){ if(current==='ahu') return; model.style.transform=`scale(${scaleFor()}) rotateX(${rx}deg) rotateY(${ry}deg)`; }\n  function setModel(m){\n    current=m; $$('.seg button').forEach(b=>b.classList.toggle('on',b.dataset.model===m)); $('#hint').textContent=hints[m];\n    if(m==='ahu'){ model.style.transform='none'; model.innerHTML='<div class=\"ahu-view\" id=\"ahuv\" role=\"img\" aria-label=\"Truestar double-skin air handling unit\"><\/div>'; model.style.width='100%';model.style.height='100%';model.style.display='flex';model.style.alignItems='center';model.style.justifyContent='center'; }\n    else { model.removeAttribute('style'); model.innerHTML= m==='rect'?rectHTML():roundHTML(); apply(); }\n  }\n  $$('.seg button').forEach(b=>b.addEventListener('click',()=>setModel(b.dataset.model)));\n  stage.addEventListener('pointerdown',e=>{ if(current==='ahu')return; drag={x:e.clientX,y:e.clientY,rx,ry}; stage.classList.add('dragging'); stage.setPointerCapture(e.pointerId); });\n  stage.addEventListener('pointermove',e=>{\n    if(current==='ahu'){ const r=stage.getBoundingClientRect(); const v=$('#ahuv'); if(v) v.style.transform=`rotateX(${-((e.clientY-r.top)\/r.height-.5)*14}deg) rotateY(${((e.clientX-r.left)\/r.width-.5)*18}deg)`; return; }\n    if(!drag) return; ry=drag.ry+(e.clientX-drag.x)*.5; rx=Math.max(-60,Math.min(40,drag.rx-(e.clientY-drag.y)*.4)); apply();\n  });\n  const end=()=>{ drag=null; stage.classList.remove('dragging'); const v=$('#ahuv'); if(v) v.style.transform=''; };\n  stage.addEventListener('pointerup',end); stage.addEventListener('pointerleave',end); stage.addEventListener('pointercancel',end);\n  window.addEventListener('resize',apply);\n  setModel('rect');\n\n  \/* ---------- product explorer ---------- *\/\n  const L='\/wp-content\/uploads\/2026\/09\/ts26-lib-';\n  const fam={duct:'Ductwork',term:'Air terminals',damp:'Dampers',ahu:'Air handling',spec:'Specials'};\n  const P=[\n    ['Rectangular GI duct','duct','p_duct_rect','Factory-fabricated GI duct with TDF or angle-flange joints, made to SMACNA gauges.'],\n    ['Spiral round duct','duct','p_duct_spiral','Spiral-seam round duct for exposed and high-velocity runs.'],\n    ['Flat oval duct','duct','p_duct_oval','Spiral flat-oval duct where ceiling depth is tight.'],\n    ['Flanged round duct','duct','p_duct_round','Round duct with flanged ends for fast site joints.'],\n    ['Duct elbow','duct','p_duct_elbow','Pressed and gored elbows in matching gauges.'],\n    ['Insulated duct','duct','p_duct_insul','Duct supplied pre-insulated to cut site work.'],\n    ['Large rectangular duct','duct','p_duct_rect2','Heavy-gauge duct for AHU mains and risers.'],\n    ['Square-to-round transition','duct','p_229','Transitions and fittings made to drawing.'],\n    ['Linear slot diffuser','term','p_diff_slot','Continuous linear slots for offices and retail.'],\n    ['Square ceiling diffuser','term','p_diff_square','Multi-cone square diffuser for false ceilings.'],\n    ['4-way diffuser','term','p_diff_4way','Four-way throw diffuser for even room coverage.'],\n    ['Round diffuser','term','p_diff_round','Round multi-cone diffuser.'],\n    ['Plaque diffuser','term','p_diff_plaque','Architectural plaque face for clean ceilings.'],\n    ['Swirl diffuser','term','p_diff_swirl','High-induction swirl diffuser for tall spaces.'],\n    ['iFlow cone & jet nozzle','term','p_diff_jet','iFlow-brand long-throw cone and jet nozzles for metro stations, halls and atria.'],\n    ['Eyeball diffuser','term','p_diff_ball','Adjustable eyeball for spot cooling.'],\n    ['Linear bar grille','term','p_grille_linear','Linear bar grille for supply or return.'],\n    ['Double louver grille','term','p_grille_dbl','Adjustable double-deflection supply grille.'],\n    ['Return grille','term','p_grille_return','Return air grille with filter frame option.'],\n    ['Louver grille','term','p_grille_louver','Fixed-blade louver for exhaust and return.'],\n    ['Motorised fire damper','damp','p_damp_fire','Fire damper with motorised actuator for life-safety systems.'],\n    ['Volume control damper','damp','p_damp_vcd','Opposed-blade VCD for balancing.'],\n    ['Motorised damper','damp','p_damp_394','Actuated damper for BMS control.'],\n    ['Backdraft damper','damp','p_damp_bd','Gravity backdraft damper to stop reverse flow.'],\n    ['Louvered damper','damp','p_damp_louver','Multi-blade louvered damper.'],\n    ['Multi-leaf damper','damp','p_damp_multi','Multi-leaf damper for large openings.'],\n    ['Round damper','damp','p_damp_round','Butterfly damper for round duct.'],\n    ['Inline damper','damp','p_damp_225','Rectangular inline damper with hand quadrant.'],\n    ['Double-skin AHU','ahu','p_ahu1','Double-skin air handling unit for commercial and healthcare projects.'],\n    ['Modular AHU','ahu','p_ahu2','Multi-section AHU with filters, coil and plug fan.'],\n    ['Compact AHU','ahu','p_ahu3','Compact AHU for smaller plant rooms.'],\n    ['Horizontal AHU','ahu','p_ahu4','Horizontal AHU with inspection doors.'],\n    ['TFA unit','ahu','p_ahu5','Treated fresh air unit.'],\n    ['Floor-mounted AHU','ahu','p_ahu6','Floor-mounted AHU with fresh-air and return sections.'],\n    ['Ceiling-suspended unit','ahu','p_ducted','Ceiling-suspended ducted unit.'],\n    ['Sound attenuator','spec','p_atten','Splitter attenuator to cut fan and duct noise.'],\n    ['Plenum box','spec','p_plenum','Plenum box with spigot and damper.'],\n    ['Access door','spec','p_door','Insulated access door for duct inspection.'],\n    ['Fan filter unit','spec','p_ffu','Fan filter unit for cleanrooms.']\n  ].map(([t,f,img,d])=>({t,f,img:L+img+'.webp',d}));\n  const tabs=$('#tabs'), grid=$('#pgrid'), q=$('#psearch'); let curF='all', expanded=false;\n  tabs.innerHTML=[['all','All']].concat(Object.entries(fam)).map(([k,l])=>`<button type=\"button\" role=\"tab\" data-k=\"${k}\">${l} <small style=\"opacity:.6\">${k==='all'?P.length:P.filter(p=>p.f===k).length}<\/small><\/button>`).join('');\n  function renderP(){\n    tabs.querySelectorAll('button').forEach(b=>{const on=b.dataset.k===curF;b.classList.toggle('on',on);b.setAttribute('aria-selected',on)});\n    const term=q.value.trim().toLowerCase();\n    const list=P.filter(p=>(curF==='all'||p.f===curF)&&(!term||(p.t+' '+p.d+' '+fam[p.f]).toLowerCase().includes(term)));\n    const lim=(curF==='all'&&!term&&!expanded)?8:list.length; const shown=list.slice(0,lim);\n    grid.innerHTML=(list.length?shown.map(p=>`<button type=\"button\" class=\"pcard\" data-i=\"${P.indexOf(p)}\" aria-label=\"${p.t}: details\"><div class=\"pi\" style=\"background-image:url(${p.img})\"><\/div><div class=\"pt\"><span>${fam[p.f].toUpperCase()}<\/span><b>${p.t}<\/b><em>View details \u2192<\/em><\/div><\/button>`).join(''):`<div class=\"pempty\">No product matches \u201c${term}\u201d. Try \u201cduct\u201d, \u201cdamper\u201d or \u201cdiffuser\u201d.<\/div>`)+(lim<list.length?`<div style=\"grid-column:1\/-1;text-align:center;padding-top:8px\"><button type=\"button\" class=\"btn btn-dark\" id=\"pmore\">Show all ${list.length} products<\/button><\/div>`:'');\n    const mb=$('#pmore'); if(mb) mb.addEventListener('click',()=>{expanded=true;renderP();});\n  }\n  tabs.addEventListener('click',e=>{const b=e.target.closest('button');if(b){curF=b.dataset.k;renderP();}});\n  q.addEventListener('input',renderP);\n  grid.addEventListener('click',e=>{const b=e.target.closest('.pcard');if(b)openProduct(P[+b.dataset.i]);});\n  renderP();\n\n  \/* ---------- clients marquee ---------- *\/\n  const clients=[['c_bhel','BHEL'],['c_itc','ITC'],['c_tata','Tata'],['c_reliance','Reliance Industries'],['c_relinfra','Reliance Infrastructure'],['c_drdo','DRDO'],['c_kanpurmetro','Kanpur Metro'],['c_431','Serum Institute of India'],['c_cadila','Cadila Pharmaceuticals'],['c_piramal','Piramal'],['c_flipkart','Flipkart'],['c_hyatt','Hyatt'],['c_gacl','GACL'],['c_nirali','Nirali Hospitals'],['c_novatel','NovAtel']];\n  const one=clients.map(([f,n])=>`<img data-no-lazy=\"1\" src=\"${L}${f}.webp\" alt=\"${n}\" decoding=\"async\">`).join('');\n  $('#track').innerHTML=one+one.replace(\/alt=\"[^\"]*\"\/g,'alt=\"\" aria-hidden=\"true\"');\n\n  \/* ---------- plants ---------- *\/\n  const plants=[\n    {name:'Valsad',state:'Gujarat',year:'2021',addr:'Block No. 358, At &amp; Post Sarodhi, NH-48 (East), Valsad, Gujarat 396001',x:18,y:38,serves:'West & Central India \u00b7 AHUs and air washers.',img:'\/wp-content\/uploads\/2026\/09\/ts26-valsad-team.webp'},\n    {name:'Medak',state:'Telangana (Hyderabad)',year:'2022',addr:'Survey No. 30\/AA\/2, 35\/AA\/2, TSIIC Automotive Park, Kallakal, Telangana 502336',x:52,y:50,serves:'South India \u00b7 AHUs, fan coil units, fan filter units and scrubbers.',img:''},\n    {name:'Noida',state:'Uttar Pradesh',year:'2023',addr:'Plot No. 73-74, Sector Ecotech 1 Extension, Greater Noida, Uttar Pradesh 201306',x:60,y:12,serves:'North & East India \u00b7 AHUs, hygienic AHUs and ducting. Corporate office in Sector 136, Noida.',img:'\/wp-content\/uploads\/2026\/09\/ts26-noida-aerial.webp'},\n    {name:'Bengaluru',state:'Karnataka',year:'2027',soon:true,x:44,y:62,serves:'Upcoming plant, planned for 2027, to bring Truestar manufacturing closer to projects across South India.',img:''}\n  ];\n  $('#pins').innerHTML=plants.map(p=>`<div class=\"pin${p.soon?' soon':''}\" style=\"left:${p.x}%;top:${p.y}%\"><i class=\"p\"><\/i><i class=\"c\"><\/i><span>${p.name}<\/span><\/div>`).join('');\n  $('#plist').innerHTML=plants.map((p,i)=>`<button type=\"button\" data-i=\"${i}\"><span class=\"y\">${p.soon?'COMING '+p.year:'EST. '+p.year}<\/span><span class=\"n\">${p.name}<\/span><span class=\"st\">${p.state}<\/span><\/button>`).join('');\n  function showPlant(i){const p=plants[i];const mp=$('.map');mp.style.backgroundImage=p.img?`url(${p.img})`:'none';mp.style.backgroundColor='#13213a';$('#pinfo').innerHTML=`<b>${p.name}, ${p.state}<\/b><div>${p.serves}<\/div>${p.soon?'<div style=\"font-size:13px;margin-top:4px;color:#ff9d94\">Coming in 2027<\/div>':''}${p.addr?`<div class=\"paddr\">${p.addr} \u00b7 <a href=\"https:\/\/www.google.com\/maps\/search\/?api=1&amp;query=${encodeURIComponent('Truestar Air Systems '+p.addr.replace(\/&amp;\/g,'&'))}\" target=\"_blank\" rel=\"noopener\">Directions \u2197<\/a><\/div>`:''}`;$$('#plist button').forEach(b=>b.classList.toggle('on',+b.dataset.i===i));}\n  $('#plist').addEventListener('click',e=>{const b=e.target.closest('button');if(b)showPlant(+b.dataset.i)});\n  $('#plist').addEventListener('mouseover',e=>{const b=e.target.closest('button');if(b)showPlant(+b.dataset.i)});\n  showPlant(2);\n\n  \/* ---------- resources data ---------- *\/\n  const CATS={\n    group:{title:'TrueStar Group Product Catalogue',n:31,dir:'\/wp-content\/uploads\/2026\/09\/ts26-gcat-g',pdf:'\/wp-content\/uploads\/2026\/09\/ts26-TrueStar-Group-Product-Catalogue.pdf',size:'1.3 MB',cover:'\/wp-content\/uploads\/2026\/09\/ts26-gcat-g01.webp'},\n    ahu:{title:'Air Handling Products catalogue',n:52,dir:'\/wp-content\/uploads\/2026\/09\/ts26-cat-p',pdf:'\/wp-content\/uploads\/2026\/09\/ts26-Truestar-Air-Handling-Products-Catalogue.pdf',size:'2.9 MB',cover:'\/wp-content\/uploads\/2026\/09\/ts26-cat-p01.webp'}\n  };\n  const pageSrc=(k,i)=>CATS[k].dir+String(i+1).padStart(2,'0')+'.webp';\n  const cats=[\n    {t:'TrueStar Group Product Catalogue',d:'31 pages. The whole portfolio: ducting, air distribution products, air handling, Ruskin dampers and Leapcraft IAQ.',img:'\/wp-content\/uploads\/2026\/09\/ts26-gcat-g01.webp',tint:'rgba(11,21,38,.3)',k:'group',pg:1},\n    {t:'Air Handling Products',d:'Edition 2026.1 \u00b7 52 pages. Modular, hygienic and cleanroom AHUs, DOAS, air washers, FCU and FFU.',img:'\/wp-content\/uploads\/2026\/09\/ts26-cat-p01.webp',tint:'rgba(11,21,38,.35)',k:'ahu',pg:1},\n    {t:'Ductwork',d:'Rectangular, spiral round and flat-oval, MS and fire-rated duct, 4-bolt slip-on flange and SMACNA gauge tables (pages 6\u201312).',img:'\/wp-content\/uploads\/2026\/09\/ts26-round-ducts.webp',tint:'rgba(11,21,38,.74)',k:'group',pg:6},\n    {t:'Grilles & diffusers',d:'Louver and linear bar grilles; square, plaque, swirl, slot and round diffusers, jet nozzles (pages 16\u201317).',img:'\/wp-content\/uploads\/2026\/09\/ts26-press-brake.webp',tint:'rgba(30,52,160,.78)',k:'group',pg:16},\n    {t:'Dampers',d:'Volume control, pressure relief, back draft, motorised fire, round, butterfly and collar dampers (pages 14\u201315).',img:'\/wp-content\/uploads\/2026\/09\/ts26-shop-floor.webp',tint:'rgba(40,52,76,.8)',k:'group',pg:14}\n  ];\n  const photos=[\n    {t:'Noida plant from above',g:'PLANT \u00b7 NOIDA',img:'\/wp-content\/uploads\/2026\/09\/ts26-noida-aerial.webp',w:1},\n    {t:'Truestar double-skin AHU',g:'PRODUCT \u00b7 AIR HANDLING',img:'\/wp-content\/uploads\/2026\/09\/ts26-ahu-studio.jpg'},\n    {t:'CNC press brake',g:'PLANT \u00b7 NOIDA',img:'\/wp-content\/uploads\/2026\/09\/ts26-press-brake.webp'},\n    {t:'Roll forming duct seams',g:'PLANT \u00b7 NOIDA',img:'\/wp-content\/uploads\/2026\/09\/ts26-roll-former.webp'},\n    {t:'Welding a duct fitting',g:'PLANT \u00b7 NOIDA',img:'\/wp-content\/uploads\/2026\/09\/ts26-welding.webp'},\n    {t:'Round duct ready to ship',g:'PRODUCT \u00b7 DUCTWORK',img:'\/wp-content\/uploads\/2026\/09\/ts26-round-ducts.webp',w:1},\n    {t:'AHU with inspection doors open',g:'PRODUCT \u00b7 AIR HANDLING',img:'\/wp-content\/uploads\/2026\/09\/ts26-ahu-open.webp'},\n    {t:'AHU fan section',g:'PRODUCT \u00b7 AIR HANDLING',img:'\/wp-content\/uploads\/2026\/09\/ts26-ahu-fan.webp'},\n    {t:'Cooling coil',g:'PRODUCT \u00b7 AIR HANDLING',img:'\/wp-content\/uploads\/2026\/09\/ts26-coil.webp'},\n    {t:'AHU panel line',g:'PLANT \u00b7 NOIDA',img:'\/wp-content\/uploads\/2026\/09\/ts26-ahu-panels.webp'},\n    {t:'Main shop floor',g:'PLANT \u00b7 NOIDA',img:'\/wp-content\/uploads\/2026\/09\/ts26-floor-wide.webp',w:1},\n    {t:'The Truestar team',g:'PEOPLE',img:'\/wp-content\/uploads\/2026\/09\/ts26-team.webp',w:1},\n    {t:'Double-skin AHU',g:'PRODUCT \u00b7 AIR HANDLING',img:'\/wp-content\/uploads\/2026\/09\/ts26-lib-p_ahu2.webp'},\n    {t:'Motorised fire damper',g:'PRODUCT \u00b7 DAMPERS',img:'\/wp-content\/uploads\/2026\/09\/ts26-lib-p_damp_fire.webp'},\n    {t:'Swirl diffuser',g:'PRODUCT \u00b7 AIR TERMINALS',img:'\/wp-content\/uploads\/2026\/09\/ts26-lib-p_diff_swirl.webp'},\n    {t:'Spiral flat-oval duct',g:'PRODUCT \u00b7 DUCTWORK',img:'\/wp-content\/uploads\/2026\/09\/ts26-lib-p_duct_oval.webp'},\n    {t:'The Truestar team at the Valsad plant',g:'PLANT \u00b7 VALSAD',img:'\/wp-content\/uploads\/2026\/09\/ts26-valsad-team.webp',w:1}\n  ];\n  const videos=[\n    {t:'Inside our Noida plant',d:'Factory walkthrough \u00b7 2:24',src:'\/wp-content\/uploads\/2026\/09\/ts26-noida-plant-walkthrough.mp4',poster:'\/wp-content\/uploads\/2026\/09\/ts26-walkthrough-poster.jpg'}\n  ];\n  $('#cats').innerHTML=cats.map((c,i)=>`<div class=\"cat lift\"><div class=\"cv cover\" style=\"background-image:url(${c.img});--tint:${c.tint}\"><small>${c.pg>1?'GROUP CATALOGUE \u00b7 SECTION':'TRUESTAR \u00b7 2026'}<\/small><b>${c.t}<\/b><\/div><div class=\"bd\"><p>${c.d}<\/p><div class=\"row\"><span>PDF \u00b7 ${CATS[c.k].size}<\/span><span style=\"display:flex;gap:6px\"><button class=\"btn btn-red\" style=\"min-height:40px;padding:0 14px;font-size:14px\" type=\"button\" data-flip=\"${c.k}\" data-page=\"${c.pg}\">Preview<\/button><button class=\"btn btn-dark\" style=\"min-height:40px;padding:0 14px;font-size:14px\" type=\"button\" data-gate=\"${c.k}\">Download<\/button><\/span><\/div><\/div><\/div>`).join('');\n  $('#cats').addEventListener('click',e=>{const b=e.target.closest('[data-dl]');if(b){b.textContent='Send us this PDF';}});\n  $('#gal').innerHTML=photos.map((p,i)=>`<button type=\"button\" class=\"lift ${p.w?'w':''} ${p.img?'cover':'ph'}\" data-i=\"${i}\" aria-label=\"Enlarge ${p.t}\" ${p.img?`style=\"background-image:url(${p.img});${(p.img.includes('studio')||p.img.includes('\/lib\/'))&&!p.img.includes('valsad')?'background-size:contain;background-repeat:no-repeat;background-color:#f4f5f6':''}\"`:''}>${p.img?'':'Send us this photo'}<div class=\"lbl\"><b>${p.t}<\/b><small>${p.g}<\/small><\/div><\/button>`).join('');\n  $('#vids').innerHTML=videos.map((v,i)=>`<button type=\"button\" class=\"lift\" data-v=\"${i}\" aria-label=\"Play ${v.t}\">${v.poster?`<div class=\"cover\" style=\"position:absolute;inset:0;background-image:url(${v.poster})\"><\/div><div style=\"position:absolute;inset:0;background:linear-gradient(0deg,rgba(11,21,38,.92),rgba(11,21,38,.1) 70%)\"><\/div>`:'<div class=\"grid\"><\/div>'}<div class=\"play\"><svg width=\"26\" height=\"26\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M8 5v14l11-7z\" fill=\"#fff\"\/><\/svg><\/div><div class=\"t\"><b>${v.t}<\/b><span>${v.d}<\/span><\/div><\/button>`).join('');\n\n  const filters=[['all','All',cats.length+photos.length+videos.length],['cat','Catalogues',cats.length],['photo','Photos',photos.length],['video','Videos',videos.length]];\n  $('#filters').innerHTML=filters.map(([k,l,n])=>`<button type=\"button\" data-f=\"${k}\" class=\"${k==='all'?'on':''}\">${l}<small>${n}<\/small><\/button>`).join('');\n  $('#filters').addEventListener('click',e=>{const b=e.target.closest('button');if(!b)return;const f=b.dataset.f;$$('#filters button').forEach(x=>x.classList.toggle('on',x===b));$$('#page-resources [data-kind]').forEach(s=>s.hidden=!(f==='all'||s.dataset.kind===f));});\n\n  \/* ---------- modal: lightbox + video ---------- *\/\n  const modal=$('#modal'), mMedia=$('#mMedia'); let li=-1, lastFocus=null;\n  function openPhoto(i){ li=(i+photos.length)%photos.length; const p=photos[li];\n    mMedia.innerHTML=p.img?`<div class=\"media\" style=\"background-image:url(${p.img})\" role=\"img\" aria-label=\"${p.t}\"><\/div>`:`<div class=\"media ph\" style=\"background-color:transparent\">${p.t}<\/div>`;\n    $('#mTitle').textContent=p.t; $('#mTag').textContent=p.g; $('#mPrev').hidden=false; $('#mNext').hidden=false; show(); }\n  function openVideo(v){ li=-1;\n    mMedia.innerHTML=v.src?`<video class=\"media\" src=\"${v.src}\" poster=\"${v.poster}\" controls autoplay playsinline><\/video>`:`<div class=\"media ph\" style=\"background:#000;color:#8d9bb3\">[${v.t} \u2014 send us this video]<\/div>`;\n    $('#mTitle').textContent=v.t; $('#mTag').textContent=v.d; $('#mPrev').hidden=true; $('#mNext').hidden=true; show(); }\n  const SPEC={\n    duct:['Galvanised steel, aluminium or stainless steel','TDF, slip-on, angle-flange and C &amp; S joints','Pressure classes 1\u2033\u201310\u2033 w.g. (250\u20132,500 Pa)','Gauges selected from SMACNA tables; factory insulation option'],\n    term:['Extruded aluminium; stainless steel for hygienic areas','White powder coat, custom RAL or anodised finish','Opposed-blade volume control damper behind the face','Concealed, screw or spring-clip fixing'],\n    damp:['Galvanised steel or extruded aluminium frame','Opposed, parallel or single blade','Manual quadrant, gear or actuator (on\/off &amp; modulating)','Blade-edge and jamb seals for low-leakage duty'],\n    ahu:['Double-skin 25 or 45 mm panels, thermally broken frame','Casing classes to EN 1886 (D1\u2013D3, L1\u2013L3, T1\u2013T5)','Plug fans with EC or IE3\/IE4 motors, VFD control','CHW, hot water, steam or DX coils; ISO 16890 filters'],\n    spec:['Made alongside the ductwork, delivered as one package','Sized to the damper, coil or diffuser served','Acoustic lining and equalising grid options','Selection confirmed against the project specification']\n  };\n  function gpage(p){ const t=p.t.toLowerCase();\n    if(p.f==='duct') return \/spiral|oval|round\/.test(t)?9:\/insulated|large\/.test(t)?8:\/square-to-round\/.test(t)?19:7;\n    if(p.f==='term') return \/grille\/.test(t)?16:17;\n    if(p.f==='damp') return \/volume\/.test(t)?14:15;\n    if(p.f==='ahu') return 21;\n    return \/atten\/.test(t)?18:\/fan filter\/.test(t)?24:19; }\n  const PPAGE=(p)=>{const t=p.t.toLowerCase(),S='https:\/\/truestarairsystems.com\/index.php\/';\n    if(p.f==='duct') return S+(\/spiral|oval|round\/.test(t)?'round-ducts-manufacturer-noida':\/elbow|transition\/.test(t)?'other-range-of-ducts\/':'rectangular-ducts-manufacturer-noida');\n    if(p.f==='term') return S+(\/grille\/.test(t)?'grilles-manufacturer-in-noida\/':'diffusers-manufacturer-in-noida\/');\n    if(p.f==='damp') return S+'dampers-manufacturer-in-noida';\n    if(p.f==='ahu') return S+'air-handling-products\/';\n    return \/atten\/.test(t)?S+'best-sound-attenuator-manufacturer\/':\/fan filter\/.test(t)?S+'fan-filter-units-ffus\/':S+'other-range-of-ducts\/';};\n  function openProduct(p){ li=-1; const gp=gpage(p);\n    mMedia.innerHTML=`<div class=\"qv\"><div class=\"qi\" role=\"img\" aria-label=\"${p.t}\" style=\"background-image:url(${p.img})\"><\/div><div class=\"qt\"><div class=\"eyebrow\">${fam[p.f]}<\/div><h3>${p.t}<\/h3><p>${p.d}<\/p><ul class=\"qspec\">${SPEC[p.f].map(x=>`<li>${x}<\/li>`).join('')}<\/ul>\n<div style=\"border-top:1px solid #d4dae3;padding-top:12px\"><div class=\"eyebrow\" style=\"margin-bottom:8px\">Catalogue \u00b7 page ${gp} of the Group catalogue<\/div><div style=\"display:flex;flex-wrap:wrap;gap:8px\"><button type=\"button\" class=\"btn btn-ghost\" style=\"color:var(--navy);border-color:#c9d1dc;min-height:44px\" data-flip=\"group\" data-page=\"${gp}\">Preview page ${gp}<\/button><button type=\"button\" class=\"btn btn-dark\" style=\"min-height:44px\" data-gate=\"group\">Download PDF<\/button>${p.f==='ahu'?`<button type=\"button\" class=\"btn btn-ghost\" style=\"color:var(--navy);border-color:#c9d1dc;min-height:44px\" data-flip=\"ahu\">AHU catalogue (52 pages)<\/button>`:''}<\/div><\/div><div style=\"display:flex;flex-wrap:wrap;gap:10px;margin-top:auto\"><a class=\"btn btn-red\" href=\"#contact\" data-quote=\"${p.t}\">Get a quote for this<\/a><a class=\"btn btn-ghost\" style=\"color:var(--navy);border-color:#c9d1dc\" href=\"${PPAGE(p)}\">Full product page \u2192<\/a><\/div><\/div><\/div>`;\n    $('#mTitle').textContent=''; $('#mTag').textContent=''; $('#mPrev').hidden=true; $('#mNext').hidden=true; show();\n    mMedia.querySelector('[data-quote]').addEventListener('click',ev=>{close(); const sel=$('#f-msg'); sel.value='Quote needed for: '+p.t+'\\n'; });\n  }\n  let fp=0, fk='group';\n  function renderFlip(){ const C=CATS[fk];\n    const wide=innerWidth>900; const pair=wide&&fp>0; const a=pair?(fp%2?fp:fp-1):fp;\n    const imgs=pair?[a,a+1].filter(x=>x<C.n):[fp];\n    $('#fSpread').className='spread'+(imgs.length===1?' single':'');\n    $('#fSpread').innerHTML=imgs.map(i=>`<img decoding=\"async\" data-no-lazy=\"1\" src=\"${pageSrc(fk,i)}\" alt=\"${C.title}, page ${i+1}\">`).join('');\n    $('#mTitle').textContent=C.title; $('#mTag').textContent='Page '+(imgs[0]+1)+(imgs[1]!==undefined?'\u2013'+(imgs[1]+1):'')+' of '+C.n+' \u00b7 use \u2190 \u2192 keys';\n    $$('#fThumbs button').forEach((b,i)=>{b.classList.toggle('on',imgs.includes(i)); if(imgs[0]===i) b.scrollIntoView({block:'nearest',inline:'center'});});\n  }\n  function openFlip(k,page){ li=-2; fk=CATS[k]?k:'group'; fp=Math.max(0,Math.min(CATS[fk].n-1,(page||1)-1));\n    mMedia.innerHTML=`<div class=\"flip\"><div class=\"spread\" id=\"fSpread\"><\/div><div class=\"thumbs\" id=\"fThumbs\">${Array.from({length:CATS[fk].n},(_,i)=>`<button type=\"button\" data-p=\"${i}\" aria-label=\"Page ${i+1}\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"${pageSrc(fk,i)}\" alt=\"\" loading=\"lazy\"><\/button>`).join('')}<\/div><div style=\"display:flex;flex-wrap:wrap;gap:10px;justify-content:center\"><button type=\"button\" class=\"btn btn-red\" style=\"min-height:40px;padding:0 16px;font-size:14px\" data-gate=\"${fk}\">Download this PDF<\/button><\/div><\/div>`;\n    $('#fThumbs').addEventListener('click',e=>{const b=e.target.closest('button');if(b){fp=+b.dataset.p;renderFlip();}});\n    $('#mPrev').hidden=false; $('#mNext').hidden=false; show(); renderFlip(); }\n  function flipStep(d){ const wide=innerWidth>900; fp=Math.max(0,Math.min(CATS[fk].n-1, fp+(wide&&fp>0?2*d:d))); if(wide&&fp>0&&fp%2===0) fp-=1; renderFlip(); }\n  document.addEventListener('click',e=>{const b=e.target.closest('[data-flip]'); if(b) openFlip(b.dataset.flip,+b.dataset.page||1);});\n  const dlCap=(window.claude&&window.claude.use)?window.claude.use('downloads').catch(()=>null):Promise.resolve(null);\n  async function savePdf(C,btn){ const dl=await dlCap;\n    if(!dl){ window.open(C.pdf,'_blank','noopener'); return; }\n    const t=btn.textContent; btn.disabled=true; btn.textContent='Preparing\u2026';\n    try{ const blob=await (await fetch(C.pdf)).blob(); await dl.save({filename:C.pdf.split('\/').pop(),data:blob}); btn.textContent='Saved \u2713'; }\n    catch(e){ btn.textContent=(e&&e.code==='declined')?t:'Could not save here'; }\n    finally{ btn.disabled=false; } }\n  async function mfSend(fields,file){\n    const w=document.querySelector('.mf-form-wrapper[data-form-id]');\n    if(!w) throw new Error('form');\n    const fd=new FormData();\n    Object.entries(fields).forEach(([k,v])=>fd.append(k,v));\n    fd.append('form_nonce',w.getAttribute('data-form-nonce')||'');\n    if(file) fd.append('mf-file-upload[]',file);\n    const r=await fetch(w.getAttribute('data-action'),{method:'POST',headers:{'X-WP-Nonce':w.getAttribute('data-wp-nonce')||''},body:fd});\n    const j=await r.json().catch(()=>({}));\n    if(!r.ok||!(j.status||(j.data&&j.data.entry_id))) throw new Error((j.error&&j.error.join?j.error.join(' '):'')||'send');\n    return j;\n  }\n  function openGate(key){ li=-3;\n    const C=CATS[key]; const isAhu=!!C; const name=C?C.title:key;\n    mMedia.innerHTML=`<div class=\"gate\"><img decoding=\"async\" data-no-lazy=\"1\" src=\"${C?C.cover:'\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_truestar.webp'}\" alt=\"\"><div><div class=\"eyebrow\">Download<\/div><h3 style=\"font:800 28px\/1.1 var(--display);margin:8px 0 6px\">${name}<\/h3><p style=\"margin:0 0 16px;color:var(--ink2)\">Tell us who you are and the ${isAhu?'PDF opens straight away':'catalogue is emailed to you'}. ${isAhu?'You can also preview it online without filling this in.':''}<\/p>\n    <form id=\"gform\" novalidate><div><label for=\"g-n\">Name *<\/label><input id=\"g-n\" required autocomplete=\"name\"><\/div><div><label for=\"g-c\">Company *<\/label><input id=\"g-c\" required autocomplete=\"organization\"><\/div><div><label for=\"g-e\">Work email *<\/label><input id=\"g-e\" type=\"email\" required autocomplete=\"email\"><\/div><div><label for=\"g-p\">Phone *<\/label><input id=\"g-p\" type=\"tel\" required autocomplete=\"tel\"><\/div><div class=\"full\"><label for=\"g-r\">Project \/ city (optional)<\/label><input id=\"g-r\"><\/div>\n    <div class=\"full\" style=\"display:flex;flex-wrap:wrap;gap:10px;align-items:center\"><button class=\"btn btn-red\" type=\"submit\">${isAhu?'Download PDF':'Email me the catalogue'}<\/button>${isAhu?`<button type=\"button\" class=\"btn btn-ghost\" style=\"color:var(--navy);border-color:#c9d1dc\" data-flip=\"${key}\">Preview instead<\/button>`:''}<\/div>\n    <p class=\"full\" id=\"gmsg\" role=\"status\" style=\"margin:0;font-size:14px;color:var(--mute)\">We use these details only to send you the catalogue and follow up on your enquiry.<\/p><\/form><\/div><\/div>`;\n    $('#mTitle').textContent=''; $('#mTag').textContent=''; $('#mPrev').hidden=true; $('#mNext').hidden=true; show();\n    $('#gform').addEventListener('submit',ev=>{ev.preventDefault(); const f=ev.target; const bad=[...f.querySelectorAll('[required]')].filter(x=>!x.value.trim()||(x.type==='email'&&!\/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\/.test(x.value)));\n      f.querySelectorAll('input').forEach(x=>x.style.borderColor=bad.includes(x)?'#d7261e':'');\n      if(bad.length){$('#gmsg').textContent='Please fill in: '+bad.map(x=>f.querySelector('label[for='+x.id+']').textContent.replace(' *','')).join(', ')+'.';$('#gmsg').style.color='#b3201a';bad[0].focus();return;}\n      const btn=f.querySelector('[type=submit]'); btn.disabled=true; $('#gmsg').style.color='var(--mute)'; $('#gmsg').textContent='Sending\u2026';\n      const v=id=>f.querySelector(id).value.trim();\n      mfSend({'mf-first-name':v('#g-n'),'mf-telephone':v('#g-p'),'mf-email':v('#g-e'),'mf-select':'Catalogue: '+name,'mf-text':v('#g-c')+(v('#g-r')?' \/ '+v('#g-r'):''),'mf-comment':'Catalogue download request (website): '+name+' | Company: '+v('#g-c')+' | Project\/city: '+(v('#g-r')||'-')}).then(()=>{\n      $('#gmsg').style.color='#1f7a4d';\n      $('#gmsg').innerHTML=isAhu?'Thank you. Your download is ready. <button type=\"button\" class=\"btn btn-dark\" id=\"gdl\" style=\"min-height:40px;padding:0 16px;font-size:14px;margin-left:6px\">Save PDF ('+C.size+')<\/button>':'Thank you. Our team will email the '+name+' to '+f.querySelector('#g-e').value.replace(\/[<>&\"]\/g,'')+'.';\n      const gb=$('#gdl'); if(gb) gb.addEventListener('click',()=>savePdf(C,gb));\n      }).catch(()=>{ $('#gmsg').style.color='#b3201a'; $('#gmsg').innerHTML='Sorry, that did not go through. Please try again, or email <a href=\"mailto:Inquiry@truestarairsystems.com\">Inquiry@truestarairsystems.com<\/a>.'; }).finally(()=>{btn.disabled=false;});\n    });\n  }\n  document.addEventListener('click',e=>{const b=e.target.closest('[data-gate]'); if(b) openGate(b.dataset.gate);});\n  function show(){ lastFocus=document.activeElement; modal.hidden=false; document.body.style.overflow='hidden'; $('#mClose').focus(); }\n  function close(){ modal.hidden=true; mMedia.innerHTML=''; document.body.style.overflow=''; if(lastFocus) lastFocus.focus(); }\n  $('#gal').addEventListener('click',e=>{const b=e.target.closest('button');if(b)openPhoto(+b.dataset.i)});\n  $('#vids').addEventListener('click',e=>{const b=e.target.closest('button');if(b)openVideo(videos[+b.dataset.v])});\n  document.querySelector('[data-video=\"tour\"]').addEventListener('click',()=>openVideo(videos[0]));\n  $('#mClose').addEventListener('click',close); $('#mPrev').addEventListener('click',()=>li===-2?flipStep(-1):openPhoto(li-1)); $('#mNext').addEventListener('click',()=>li===-2?flipStep(1):openPhoto(li+1));\n  modal.addEventListener('click',e=>{if(e.target===modal)close()});\n  modal.addEventListener('keydown',e=>{if(e.key==='Escape')close(); if(li>=0&&e.key==='ArrowLeft')openPhoto(li-1); if(li>=0&&e.key==='ArrowRight')openPhoto(li+1); if(li===-2&&e.key==='ArrowLeft')flipStep(-1); if(li===-2&&e.key==='ArrowRight')flipStep(1);});\n\n  \/* ---------- enquiry form (inactive in preview) ---------- *\/\n  $('#enq').addEventListener('submit',e=>{e.preventDefault(); const f=e.target; const v=id=>f.querySelector(id).value.trim(); const note=$('#enqNote');\n    if(!v('#f-name')||!v('#f-ph')){note.textContent='Please add your name and phone number.';note.style.color='#ff9d94';return;}\n    const btn=f.querySelector('[type=submit]'); btn.disabled=true; note.style.color=''; note.textContent='Sending\u2026';\n    const file=f.querySelector('#f-file').files[0];\n    mfSend({'mf-first-name':v('#f-name'),'mf-telephone':v('#f-ph'),'mf-email':v('#f-em')||'not-given@truestarairsystems.com','mf-select':f.querySelector('#f-pr').value,'mf-text':(v('#f-co')||'-')+' \/ '+(v('#f-site')||'-'),'mf-comment':'Website enquiry | Company: '+(v('#f-co')||'-')+' | Site: '+(v('#f-site')||'-')+' | Product: '+f.querySelector('#f-pr').value+'\\n'+v('#f-msg')},file)\n      .then(()=>{note.style.color='#7ee2a8';note.textContent='Thank you. Your enquiry has reached our sales team; we will contact you shortly.';f.reset();})\n      .catch(()=>{note.style.color='#ff9d94';note.innerHTML='Sorry, that did not go through. Please call +91 96252 05446 or email Inquiry@truestarairsystems.com.';})\n      .finally(()=>{btn.disabled=false;});\n  });\n\n  \/* ---------- scroll reveal (content stays visible if JS or observers fail) ---------- *\/\n  if('IntersectionObserver' in window && !matchMedia('(prefers-reduced-motion: reduce)').matches){\n    const els=$$('.gcard,.pcard,.ind .card,.tile,.mosaic div,.cat');\n    const io=new IntersectionObserver(es=>es.forEach(e=>{if(e.isIntersecting){e.target.classList.remove('pre');io.unobserve(e.target);}}),{rootMargin:'0px 0px -40px 0px'});\n    els.forEach(el=>{const r=el.getBoundingClientRect(); if(r.top>innerHeight){el.classList.add('rv','pre');io.observe(el);}});\n  }\n\n  route();\n})();\n<\/script><!--\/noptimize-->\n<!--noptimize--><script type=\"module\">\nconst boot=async()=>{\n  const THREE=await import(\"https:\/\/cdn.jsdelivr.net\/npm\/three@0.160.0\/build\/three.module.min.js\");\nconst {BackSide,BoxGeometry,Mesh,MeshBasicMaterial,MeshStandardMaterial,PointLight,Scene}=THREE;\n\/**\n * https:\/\/github.com\/google\/model-viewer\/blob\/master\/packages\/model-viewer\/src\/three-components\/EnvironmentScene.ts\n *\/\n\n\n\nclass RoomEnvironment extends Scene {\n\n\tconstructor( renderer = null ) {\n\n\t\tsuper();\n\n\t\tconst geometry = new BoxGeometry();\n\t\tgeometry.deleteAttribute( 'uv' );\n\n\t\tconst roomMaterial = new MeshStandardMaterial( { side: BackSide } );\n\t\tconst boxMaterial = new MeshStandardMaterial();\n\n\t\tlet intensity = 5;\n\n\t\tif ( renderer !== null && renderer._useLegacyLights === false ) intensity = 900;\n\n\t\tconst mainLight = new PointLight( 0xffffff, intensity, 28, 2 );\n\t\tmainLight.position.set( 0.418, 16.199, 0.300 );\n\t\tthis.add( mainLight );\n\n\t\tconst room = new Mesh( geometry, roomMaterial );\n\t\troom.position.set( - 0.757, 13.219, 0.717 );\n\t\troom.scale.set( 31.713, 28.305, 28.591 );\n\t\tthis.add( room );\n\n\t\tconst box1 = new Mesh( geometry, boxMaterial );\n\t\tbox1.position.set( - 10.906, 2.009, 1.846 );\n\t\tbox1.rotation.set( 0, - 0.195, 0 );\n\t\tbox1.scale.set( 2.328, 7.905, 4.651 );\n\t\tthis.add( box1 );\n\n\t\tconst box2 = new Mesh( geometry, boxMaterial );\n\t\tbox2.position.set( - 5.607, - 0.754, - 0.758 );\n\t\tbox2.rotation.set( 0, 0.994, 0 );\n\t\tbox2.scale.set( 1.970, 1.534, 3.955 );\n\t\tthis.add( box2 );\n\n\t\tconst box3 = new Mesh( geometry, boxMaterial );\n\t\tbox3.position.set( 6.167, 0.857, 7.803 );\n\t\tbox3.rotation.set( 0, 0.561, 0 );\n\t\tbox3.scale.set( 3.927, 6.285, 3.687 );\n\t\tthis.add( box3 );\n\n\t\tconst box4 = new Mesh( geometry, boxMaterial );\n\t\tbox4.position.set( - 2.017, 0.018, 6.124 );\n\t\tbox4.rotation.set( 0, 0.333, 0 );\n\t\tbox4.scale.set( 2.002, 4.566, 2.064 );\n\t\tthis.add( box4 );\n\n\t\tconst box5 = new Mesh( geometry, boxMaterial );\n\t\tbox5.position.set( 2.291, - 0.756, - 2.621 );\n\t\tbox5.rotation.set( 0, - 0.286, 0 );\n\t\tbox5.scale.set( 1.546, 1.552, 1.496 );\n\t\tthis.add( box5 );\n\n\t\tconst box6 = new Mesh( geometry, boxMaterial );\n\t\tbox6.position.set( - 2.193, - 0.369, - 5.547 );\n\t\tbox6.rotation.set( 0, 0.516, 0 );\n\t\tbox6.scale.set( 3.875, 3.487, 2.986 );\n\t\tthis.add( box6 );\n\n\n\t\t\/\/ -x right\n\t\tconst light1 = new Mesh( geometry, createAreaLightMaterial( 50 ) );\n\t\tlight1.position.set( - 16.116, 14.37, 8.208 );\n\t\tlight1.scale.set( 0.1, 2.428, 2.739 );\n\t\tthis.add( light1 );\n\n\t\t\/\/ -x left\n\t\tconst light2 = new Mesh( geometry, createAreaLightMaterial( 50 ) );\n\t\tlight2.position.set( - 16.109, 18.021, - 8.207 );\n\t\tlight2.scale.set( 0.1, 2.425, 2.751 );\n\t\tthis.add( light2 );\n\n\t\t\/\/ +x\n\t\tconst light3 = new Mesh( geometry, createAreaLightMaterial( 17 ) );\n\t\tlight3.position.set( 14.904, 12.198, - 1.832 );\n\t\tlight3.scale.set( 0.15, 4.265, 6.331 );\n\t\tthis.add( light3 );\n\n\t\t\/\/ +z\n\t\tconst light4 = new Mesh( geometry, createAreaLightMaterial( 43 ) );\n\t\tlight4.position.set( - 0.462, 8.89, 14.520 );\n\t\tlight4.scale.set( 4.38, 5.441, 0.088 );\n\t\tthis.add( light4 );\n\n\t\t\/\/ -z\n\t\tconst light5 = new Mesh( geometry, createAreaLightMaterial( 20 ) );\n\t\tlight5.position.set( 3.235, 11.486, - 12.541 );\n\t\tlight5.scale.set( 2.5, 2.0, 0.1 );\n\t\tthis.add( light5 );\n\n\t\t\/\/ +y\n\t\tconst light6 = new Mesh( geometry, createAreaLightMaterial( 100 ) );\n\t\tlight6.position.set( 0.0, 20.0, 0.0 );\n\t\tlight6.scale.set( 1.0, 0.1, 1.0 );\n\t\tthis.add( light6 );\n\n\t}\n\n\tdispose() {\n\n\t\tconst resources = new Set();\n\n\t\tthis.traverse( ( object ) => {\n\n\t\t\tif ( object.isMesh ) {\n\n\t\t\t\tresources.add( object.geometry );\n\t\t\t\tresources.add( object.material );\n\n\t\t\t}\n\n\t\t} );\n\n\t\tfor ( const resource of resources ) {\n\n\t\t\tresource.dispose();\n\n\t\t}\n\n\t}\n\n}\n\nfunction createAreaLightMaterial( intensity ) {\n\n\tconst material = new MeshBasicMaterial();\n\tmaterial.color.setScalar( intensity );\n\treturn material;\n\n}\n\n\n\n\/\/ Truestar 3D product studio \u2014 procedural models, no external files.\n\n\n\n\/* ---------- textures ---------- *\/\nfunction canvasTex(w, h, draw, repeat) {\n  const c = document.createElement('canvas'); c.width = w; c.height = h;\n  draw(c.getContext('2d'), w, h);\n  const t = new THREE.CanvasTexture(c); t.colorSpace = THREE.SRGBColorSpace;\n  t.wrapS = t.wrapT = THREE.RepeatWrapping; if (repeat) t.repeat.set(repeat[0], repeat[1]);\n  t.anisotropy = 4; return t;\n}\nconst spangle = () => canvasTex(256, 256, (g, w, h) => {\n  g.fillStyle = '#c4c9cf'; g.fillRect(0, 0, w, h);\n  for (let i = 0; i < 260; i++) {\n    const v = 180 + Math.floor(Math.random() * 50); g.fillStyle = `rgb(${v},${v + 3},${v + 7})`;\n    g.beginPath(); const x = Math.random() * w, y = Math.random() * h, r = 6 + Math.random() * 22;\n    for (let k = 0; k < 6; k++) { const a = k \/ 6 * Math.PI * 2 + Math.random(); g.lineTo(x + Math.cos(a) * r, y + Math.sin(a) * r); }\n    g.fill();\n  }\n}, [2, 2]);\nconst finTex = () => canvasTex(256, 64, (g, w, h) => {\n  g.fillStyle = '#c9ced4'; g.fillRect(0, 0, w, h); g.fillStyle = '#7d8591';\n  for (let x = 0; x < w; x += 4) g.fillRect(x, 0, 1, h);\n}, [6, 1]);\nconst perfTex = () => canvasTex(128, 128, (g, w, h) => {\n  g.fillStyle = '#b9bfc7'; g.fillRect(0, 0, w, h); g.fillStyle = '#5b636e';\n  for (let y = 4; y < h; y += 10) for (let x = (y \/ 10 % 2) * 5 + 4; x < w; x += 10) { g.beginPath(); g.arc(x, y, 2.2, 0, 7); g.fill(); }\n}, [3, 3]);\nconst tileTex = () => canvasTex(256, 256, (g, w, h) => {\n  g.fillStyle = '#9aa0a8'; g.fillRect(0, 0, w, h);\n  for (let i = 0; i < 1400; i++) { const v = 140 + Math.random() * 40; g.fillStyle = `rgba(${v},${v},${v + 5},.5)`; g.fillRect(Math.random() * w, Math.random() * h, 2, 2); }\n  g.strokeStyle = '#6f757d'; g.lineWidth = 3; g.strokeRect(1, 1, w - 2, h - 2);\n}, [1, 1]);\n\nconst loader = new THREE.TextureLoader();\nfunction imgTex(rel) { const t = loader.load(new URL(rel, location.href).href); t.colorSpace = THREE.SRGBColorSpace; t.anisotropy = 8; return t; }\nfunction labelMat(text) {\n  const t = canvasTex(512, 128, (g, w, h) => { g.fillStyle = 'rgba(11,21,38,.88)'; g.beginPath(); g.roundRect(4, 4, w - 8, h - 8, 26); g.fill(); g.strokeStyle = '#d7261e'; g.lineWidth = 6; g.beginPath(); g.moveTo(34, h - 20); g.lineTo(120, h - 20); g.stroke(); g.fillStyle = '#fff'; g.font = '600 52px Arial'; g.textAlign = 'center'; g.textBaseline = 'middle'; g.fillText(text, w \/ 2, h \/ 2 - 4); });\n  t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping; return new THREE.SpriteMaterial({ map: t, transparent: true, depthTest: false });\n}\n\/* ---------- materials ---------- *\/\nfunction makeMats() {\n  const std = (o) => new THREE.MeshStandardMaterial(o);\n  return {\n    galv: std({ color: 0xd3d8de, map: spangle(), metalness: 0.85, roughness: 0.36, side: THREE.DoubleSide }),\n    galvDark: std({ color: 0x9aa2ac, metalness: 0.85, roughness: 0.42, side: THREE.DoubleSide }),\n    skin: std({ color: 0xe9ebee, metalness: 0.25, roughness: 0.45 }),\n    alu: std({ color: 0xa7afb8, metalness: 0.9, roughness: 0.3 }),\n    white: std({ color: 0xf5f6f7, metalness: 0.05, roughness: 0.42 }),\n    dark: std({ color: 0x2a313b, metalness: 0.4, roughness: 0.55 }),\n    black: std({ color: 0x111418, metalness: 0.2, roughness: 0.7 }),\n    red: std({ color: 0xd7261e, metalness: 0.2, roughness: 0.45 }),\n    navy: std({ color: 0x13213a, metalness: 0.3, roughness: 0.5 }),\n    copper: std({ color: 0xc27a45, metalness: 1, roughness: 0.32 }),\n    fin: std({ color: 0xdfe3e8, map: finTex(), metalness: 0.85, roughness: 0.3 }),\n    media: std({ color: 0xf2efe4, metalness: 0, roughness: 0.95, side: THREE.DoubleSide }),\n    perf: std({ color: 0xc9ced4, map: perfTex(), metalness: 0.7, roughness: 0.45, side: THREE.DoubleSide }),\n    orange: std({ color: 0xf07c1a, metalness: 0.15, roughness: 0.45 }),\n    base: std({ color: 0x3a4250, metalness: 0.5, roughness: 0.5 }),\n    glass: std({ color: 0x1b2533, metalness: 0.9, roughness: 0.08, transparent: true, opacity: 0.85 }),\n    tile: std({ color: 0xb8bdc4, map: tileTex(), metalness: 0.1, roughness: 0.8 }),\n    insul: std({ color: 0x23272d, metalness: 0, roughness: 1, side: THREE.DoubleSide }),\n    led: new THREE.MeshBasicMaterial({ color: 0x3ee07a }),\n    ledRed: new THREE.MeshBasicMaterial({ color: 0xff4d3d }),\n    air: new THREE.PointsMaterial({ color: 0x9fd4ff, size: 0.035, transparent: true, opacity: 0.8, depthWrite: false }),\n    wave: new THREE.MeshBasicMaterial({ color: 0x4f8cff, transparent: true, opacity: 0.5, side: THREE.DoubleSide, depthWrite: false }),\n    skinEdge: std({ color: 0xf2f3f5, metalness: 0.2, roughness: 0.38 }),\n    steel: std({ color: 0xd9dde2, metalness: 1, roughness: 0.25 }),\n    blueV: std({ color: 0x2a47c9, metalness: 0.2, roughness: 0.45 }),\n    canvas: std({ color: 0x2b2f35, metalness: 0, roughness: 0.95 }),\n    logo: new THREE.MeshStandardMaterial({ map: imgTex('\/wp-content\/uploads\/2026\/09\/ts26-lib-logo_truestar.webp'), transparent: true, alphaTest: 0.08, metalness: 0, roughness: 0.5 }),\n    ambFace: new THREE.MeshStandardMaterial({ map: imgTex('\/wp-content\/uploads\/2026\/09\/ts26-lib-ambinode.webp'), transparent: true, alphaTest: 0.3, metalness: 0, roughness: 0.55 }),\n    gauge: std({ map: canvasTex(128, 128, (g2, w, h) => { g2.fillStyle = '#fff'; g2.fillRect(0, 0, w, h); g2.strokeStyle = '#222'; g2.lineWidth = 3; for (let i = 0; i <= 10; i++) { const a = Math.PI * 0.75 + i \/ 10 * Math.PI * 1.5; g2.beginPath(); g2.moveTo(64 + Math.cos(a) * 44, 64 + Math.sin(a) * 44); g2.lineTo(64 + Math.cos(a) * 54, 64 + Math.sin(a) * 54); g2.stroke(); } g2.strokeStyle = '#d7261e'; g2.lineWidth = 4; g2.beginPath(); g2.moveTo(64, 64); g2.lineTo(64 + Math.cos(-0.6) * 42, 64 + Math.sin(-0.6) * 42); g2.stroke(); }), metalness: 0, roughness: 0.4 }),\n    plate: std({ map: canvasTex(340, 120, (g2, w, h) => { g2.fillStyle = '#c9ced4'; g2.fillRect(0, 0, w, h); g2.strokeStyle = '#7d8591'; g2.lineWidth = 4; g2.strokeRect(4, 4, w - 8, h - 8); g2.fillStyle = '#13213a'; g2.font = 'bold 34px Arial'; g2.textAlign = 'center'; g2.fillText('TRUESTAR', w \/ 2, 56); g2.font = '20px Arial'; g2.fillText('AIR HANDLING UNIT', w \/ 2, 90); }), metalness: 0.7, roughness: 0.35 })\n  };\n}\n\n\/* ---------- helpers ---------- *\/\nfunction box(parent, w, h, d, mat, x = 0, y = 0, z = 0) {\n  const m = new THREE.Mesh(new THREE.BoxGeometry(w, h, d), mat); m.position.set(x, y, z);\n  m.castShadow = m.receiveShadow = true; parent.add(m); return m;\n}\nfunction cyl(parent, rt, rb, h, mat, x = 0, y = 0, z = 0, seg = 40, open = false) {\n  const m = new THREE.Mesh(new THREE.CylinderGeometry(rt, rb, h, seg, 1, open), mat); m.position.set(x, y, z);\n  m.castShadow = true; parent.add(m); return m;\n}\nfunction frameRect(parent, w, h, t, depth, mat, z = 0) { \/\/ square frame in XY plane\n  box(parent, w, t, depth, mat, 0, h \/ 2 - t \/ 2, z); box(parent, w, t, depth, mat, 0, -h \/ 2 + t \/ 2, z);\n  box(parent, t, h - 2 * t, depth, mat, w \/ 2 - t \/ 2, 0, z); box(parent, t, h - 2 * t, depth, mat, -w \/ 2 + t \/ 2, 0, z);\n}\nfunction airfoil(chord, thick, len, mat) {\n  const s = new THREE.Shape(); const n = 24;\n  for (let i = 0; i <= n; i++) { const a = i \/ n * Math.PI * 2; const x = Math.cos(a) * chord \/ 2; const y = Math.sin(a) * thick \/ 2 * (1 - 0.35 * Math.cos(a)); i ? s.lineTo(x, y) : s.moveTo(x, y); }\n  const g = new THREE.ExtrudeGeometry(s, { depth: len, bevelEnabled: false }); g.translate(0, 0, -len \/ 2);\n  const m = new THREE.Mesh(g, mat); m.castShadow = true; return m; \/\/ chord along X, length along Z\n}\nfunction roundedPlate(w, h, r, depth, mat, bevel = 0.02) {\n  const s = new THREE.Shape(); const x = -w \/ 2, y = -h \/ 2;\n  s.moveTo(x + r, y); s.lineTo(x + w - r, y); s.quadraticCurveTo(x + w, y, x + w, y + r); s.lineTo(x + w, y + h - r);\n  s.quadraticCurveTo(x + w, y + h, x + w - r, y + h); s.lineTo(x + r, y + h); s.quadraticCurveTo(x, y + h, x, y + h - r);\n  s.lineTo(x, y + r); s.quadraticCurveTo(x, y, x + r, y);\n  const g = new THREE.ExtrudeGeometry(s, { depth, bevelEnabled: true, bevelThickness: bevel, bevelSize: bevel, bevelSegments: 4, curveSegments: 12 });\n  const m = new THREE.Mesh(g, mat); m.castShadow = true; return m;\n}\nfunction particles(n, mat) {\n  const g = new THREE.BufferGeometry(); g.setAttribute('position', new THREE.BufferAttribute(new Float32Array(n * 3), 3));\n  const p = new THREE.Points(g, mat); p.userData.seed = Array.from({ length: n }, () => Math.random()); return p;\n}\n\n\/* ---------- models ---------- *\/\nconst MODELS = {\n  ahu(M) {\n    const g = new THREE.Group(); const H = 1.6, D = 1.4, T = 0.055;\n    const secs = [['mix', 0.8, 'Mixing box'], ['filter', 0.62, 'Bag filters'], ['coil', 0.72, 'Cooling coil'], ['fan', 1.15, 'Plug fan'], ['atten', 0.8, 'Attenuator']];\n    const L = secs.reduce((a, s) => a + s[1], 0); let x0 = -L \/ 2; const doors = [], spin = [], labels = [];\n    \/\/ base frame: painted MS channel with lifting lugs\n    box(g, L + 0.08, 0.16, D + 0.08, M.base, 0, -H \/ 2 - 0.08, 0);\n    box(g, L + 0.1, 0.03, 0.04, M.red, 0, -H \/ 2 - 0.02, D \/ 2 + 0.045);\n    [-L \/ 2 + 0.25, L \/ 2 - 0.25].forEach(x => [1, -1].forEach(z => { const lug = box(g, 0.1, 0.12, 0.02, M.base, x, -H \/ 2 - 0.1, z * (D \/ 2 + 0.06)); const hole = cyl(g, 0.025, 0.025, 0.03, M.black, x, -H \/ 2 - 0.08, z * (D \/ 2 + 0.06), 16); hole.rotation.x = Math.PI \/ 2; }));\n    \/\/ casing: roof, floor, back, ends\n    box(g, L, 0.02, D, M.skin, 0, H \/ 2, 0); box(g, L, 0.02, D, M.skin, 0, -H \/ 2 + 0.01, 0);\n    box(g, L, H, 0.02, M.skin, 0, 0, -D \/ 2);\n    box(g, 0.02, H, D, M.skin, L \/ 2, 0, 0); box(g, 0.02, H, D, M.skin, -L \/ 2, 0, 0);\n    \/\/ aluminium frame profiles on every section joint + black nylon corners\n    const posts = [x0]; secs.forEach(s => posts.push(posts[posts.length - 1] + s[1]));\n    posts.forEach(px => { [D \/ 2, -D \/ 2].forEach(z => box(g, T, H, T, M.alu, px, 0, z)); [H \/ 2, -H \/ 2].forEach(y => box(g, T, T, D, M.alu, px, y, 0)); });\n    [H \/ 2, -H \/ 2].forEach(y => [D \/ 2, -D \/ 2].forEach(z => box(g, L, T, T, M.alu, 0, y, z)));\n    posts.forEach(px => [H \/ 2, -H \/ 2].forEach(y => [D \/ 2, -D \/ 2].forEach(z => { const c = new THREE.Mesh(new THREE.SphereGeometry(T * 0.72, 12, 8), M.black); c.position.set(px, y, z); g.add(c); })));\n    secs.forEach(([k, w, name], i) => {\n      const cx = x0 + w \/ 2; const dw = w - T - 0.01; const full = k !== 'coil'; const dh = full ? H - T - 0.01 : H * 0.7;\n      const dy = full ? 0 : H \/ 2 - T \/ 2 - dh \/ 2;\n      \/\/ hinged, removable door\n      const hinge = new THREE.Group(); hinge.position.set(x0 + T \/ 2 + 0.005, dy, D \/ 2 + 0.014); g.add(hinge);\n      box(hinge, dw, dh, 0.028, M.skin, dw \/ 2, 0, 0);\n      box(hinge, dw - 0.06, dh - 0.06, 0.004, M.skinEdge, dw \/ 2, 0, 0.016);\n      [dh \/ 2 - 0.15, -dh \/ 2 + 0.15].forEach(y => { const h = cyl(hinge, 0.014, 0.014, 0.1, M.steel, 0.0, y, 0.02, 12); });\n      const lever = (y) => { box(hinge, 0.05, 0.12, 0.012, M.dark, dw - 0.07, y, 0.02); box(hinge, 0.028, 0.16, 0.02, M.black, dw - 0.07, y - 0.02, 0.035); };\n      lever(dh \/ 2 - 0.3); if (dh > 1) lever(-dh \/ 2 + 0.3);\n      if (k === 'fan') { const vp = cyl(hinge, 0.085, 0.085, 0.03, M.glass, dw * 0.3, -0.35, 0.01, 32); vp.rotation.x = Math.PI \/ 2; const vr = new THREE.Mesh(new THREE.TorusGeometry(0.09, 0.012, 8, 32), M.steel); vr.position.set(dw * 0.3, -0.35, 0.02); hinge.add(vr); }\n      if (k === 'fan') { const lg = new THREE.Mesh(new THREE.PlaneGeometry(0.8, 0.67), M.logo); lg.position.set(dw \/ 2 + 0.02, 0.22, 0.03); hinge.add(lg); }\n      if (k === 'filter') { const gz = cyl(hinge, 0.07, 0.07, 0.03, M.gauge, dw \/ 2, 0.35, 0.03, 32); gz.rotation.x = Math.PI \/ 2; const gr = new THREE.Mesh(new THREE.TorusGeometry(0.072, 0.01, 8, 32), M.dark); gr.position.set(dw \/ 2, 0.35, 0.047); hinge.add(gr); }\n      if (k === 'mix') { const np = new THREE.Mesh(new THREE.PlaneGeometry(0.34, 0.12), M.plate); np.position.set(dw \/ 2, -0.35, 0.02); hinge.add(np); }\n      doors.push(hinge);\n      \/\/ label sprite (fades in when opened)\n      const sp = new THREE.Sprite(labelMat(name)); sp.scale.set(0.56, 0.14, 1); sp.position.set(cx, H \/ 2 + 0.22 + (i % 2) * 0.22 + (k === 'atten' ? 0.5 : 0), D \/ 2 - 0.1); sp.material.opacity = 0; g.add(sp); labels.push(sp);\n      \/\/ internals\n      const I = new THREE.Group(); I.position.x = cx; g.add(I);\n      if (k === 'mix') {\n        const dmp = (rot) => { const f = new THREE.Group(); frameRect(f, 0.9, 0.62, 0.045, 0.1, M.alu); for (let b = 0; b < 5; b++) { const bl = airfoil(0.12, 0.018, 0.82, M.galv); bl.rotation.y = Math.PI \/ 2; bl.rotation.z = 0.5 * (b % 2 ? 1 : -1); bl.position.y = -0.24 + b * 0.12; f.add(bl); } f.rotation.copy(rot); I.add(f); return f; };\n        const top = dmp(new THREE.Euler(-Math.PI \/ 2, 0, Math.PI \/ 2)); top.position.y = H \/ 2 + 0.06; top.scale.set(0.78, 1, 1);\n        const end = dmp(new THREE.Euler(0, Math.PI \/ 2, 0)); end.position.x = -w \/ 2 - 0.05;\n        const ac = box(I, 0.12, 0.1, 0.08, M.orange, -w \/ 2 - 0.08, 0.42, 0.35);\n      }\n      if (k === 'filter') {\n        box(I, 0.04, H - 0.1, D - 0.1, M.alu, -w \/ 2 + 0.08, 0, 0);\n        for (let r = 0; r < 3; r++) for (let c = 0; c < 3; c++) { const bag = new THREE.Mesh(new THREE.CylinderGeometry(0.03, 0.2, 0.44, 4, 1), M.media); bag.rotation.z = Math.PI \/ 2; bag.rotation.x = Math.PI \/ 4; bag.position.set(-w \/ 2 + 0.33, -0.48 + r * 0.48, -0.44 + c * 0.44); I.add(bag); }\n      }\n      if (k === 'coil') {\n        box(I, 0.28, H - 0.3, D - 0.14, M.fin, 0, 0.05, 0);\n        for (let p = 0; p < 2; p++) { cyl(I, 0.035, 0.035, H - 0.2, M.copper, -0.08 + p * 0.16, 0.05, D \/ 2 - 0.12); for (let s2 = 0; s2 < 10; s2++) { const t = cyl(I, 0.012, 0.012, 0.1, M.copper, -0.08 + p * 0.16, -0.6 + s2 * 0.13, D \/ 2 - 0.05, 8); t.rotation.x = Math.PI \/ 2; } }\n        box(I, 0.56, 0.05, D - 0.1, M.steel, 0, -H \/ 2 + 0.1, 0);\n        \/\/ fixed lower panel with pipe connections and drain\n        const lp = H - dh - T - 0.02; box(I, dw, lp, 0.028, M.skin, 0, -H \/ 2 + T \/ 2 + lp \/ 2 + 0.005, D \/ 2 + 0.014);\n        [[-0.12, M.blueV], [0.12, M.red]].forEach(([x, vm]) => { const pp = cyl(I, 0.04, 0.04, 0.3, M.copper, x, -H \/ 2 + 0.3, D \/ 2 + 0.15, 20); pp.rotation.x = Math.PI \/ 2; const fl = cyl(I, 0.06, 0.06, 0.02, M.steel, x, -H \/ 2 + 0.3, D \/ 2 + 0.3, 20); fl.rotation.x = Math.PI \/ 2; box(I, 0.14, 0.025, 0.03, vm, x, -H \/ 2 + 0.38, D \/ 2 + 0.2); cyl(I, 0.01, 0.01, 0.08, M.steel, x, -H \/ 2 + 0.34, D \/ 2 + 0.2, 8); });\n        const dr = cyl(I, 0.022, 0.022, 0.2, M.steel, 0.28, -H \/ 2 + 0.1, D \/ 2 + 0.1, 12); dr.rotation.x = Math.PI \/ 2;\n      }\n      if (k === 'fan') {\n        box(I, 0.04, H - 0.1, D - 0.1, M.galvDark, -w \/ 2 + 0.06, 0, 0);\n        const cone = new THREE.Mesh(new THREE.CylinderGeometry(0.26, 0.36, 0.14, 40, 1, true), M.galv); cone.rotation.z = Math.PI \/ 2; cone.position.set(-w \/ 2 + 0.14, 0, 0); I.add(cone);\n        const imp = new THREE.Group(); imp.position.set(-0.02, 0, 0); I.add(imp);\n        const back = cyl(imp, 0.5, 0.5, 0.02, M.dark, 0.12, 0, 0, 48); back.rotation.z = Math.PI \/ 2;\n        const shroud = new THREE.Mesh(new THREE.TorusGeometry(0.42, 0.03, 10, 48), M.dark); shroud.rotation.y = Math.PI \/ 2; shroud.position.x = -0.12; imp.add(shroud);\n        for (let b = 0; b < 9; b++) { const bl = box(imp, 0.24, 0.02, 0.26, M.alu, 0, 0, 0); const a = b \/ 9 * Math.PI * 2; bl.position.set(0, Math.cos(a) * 0.34, Math.sin(a) * 0.34); bl.rotation.x = -a; bl.rotation.y = 0.5; }\n        spin.push(imp);\n        const mot = cyl(I, 0.16, 0.16, 0.42, M.navy, 0.42, 0, 0); mot.rotation.z = Math.PI \/ 2;\n        box(I, 0.6, 0.06, 0.8, M.base, 0.25, -0.5, 0); box(I, 0.06, 0.44, 0.06, M.base, 0.3, -0.25, 0);\n        [[-0.1, 0.35], [0.5, 0.35], [-0.1, -0.35], [0.5, -0.35]].forEach(([x, z]) => cyl(I, 0.04, 0.04, 0.08, M.black, x, -0.57, z, 12));\n        box(I, 0.22, 0.28, 0.12, M.dark, w \/ 2 - 0.2, 0.45, -D \/ 2 + 0.1); \/\/ VFD\n      }\n      if (k === 'atten') {\n        for (let p = 0; p < 4; p++) box(I, w - 0.12, H - 0.12, 0.16, M.perf, 0, 0, -0.5 + p * 0.33);\n        const st = new THREE.Group(); st.position.set(0, H \/ 2 + 0.36, 0); I.add(st);\n        box(st, 0.6, 0.56, 0.02, M.galv, 0, 0.04, 0.45); box(st, 0.6, 0.56, 0.02, M.galv, 0, 0.04, -0.45);\n        box(st, 0.02, 0.56, 0.9, M.galv, 0.3, 0.04, 0); box(st, 0.02, 0.56, 0.9, M.galv, -0.3, 0.04, 0);\n        box(st, 0.64, 0.12, 0.94, M.canvas, 0, -0.29, 0); \/\/ flexible connector\n        const fl = new THREE.Group(); st.add(fl); fl.rotation.x = Math.PI \/ 2; fl.position.y = 0.32; frameRect(fl, 0.66, 0.96, 0.04, 0.03, M.dark);\n      }\n      x0 += w;\n    });\n    const doorMats = [];\n    doors.forEach(h => h.traverse(o => { if (o.isMesh) { o.castShadow = false; o.material = o.material.clone(); o.material.transparent = true; doorMats.push(o.material); } }));\n    g.userData.open = 0; g.userData.target = 0;\n    g.userData.tick = (dt) => {\n      const u = g.userData; u.open += (u.target - u.open) * Math.min(1, dt * 3);\n      doors.forEach(d => { d.rotation.y = -u.open * 0.35; d.position.z = D \/ 2 + 0.014 + u.open * 0.9; d.visible = u.open < 0.97; });\n      doorMats.forEach(m => { m.opacity = 1 - u.open; m.depthWrite = u.open < 0.4; });\n      labels.forEach(s => s.material.opacity = Math.max(0, u.open * 1.2 - 0.2));\n      spin.forEach(s => s.rotation.x += dt * (4 + u.open * 6));\n    };\n    g.userData.toggle = { label: ['Open the doors', 'Close the doors'], fn: () => { g.userData.target = g.userData.target ? 0 : 1; return g.userData.target; } };\n    return g;\n  },\n\n  rect(M) {\n    const g = new THREE.Group(); const L = 2.4, W = 1.0, H = 0.6, t = 0.012;\n    box(g, L, t, W, M.galv, 0, H \/ 2, 0); box(g, L, t, W, M.galv, 0, -H \/ 2, 0);\n    box(g, L, H, t, M.galv, 0, 0, W \/ 2); box(g, L, H, t, M.galv, 0, 0, -W \/ 2);\n    const lm = new THREE.LineBasicMaterial({ color: 0x6b7480 });\n    const cross = (pts) => { const geo = new THREE.BufferGeometry().setFromPoints(pts.map(p => new THREE.Vector3(...p))); g.add(new THREE.LineSegments(geo, lm)); };\n    const o = 0.008;\n    cross([[-L \/ 2, H \/ 2 + o, -W \/ 2], [L \/ 2, H \/ 2 + o, W \/ 2], [-L \/ 2, H \/ 2 + o, W \/ 2], [L \/ 2, H \/ 2 + o, -W \/ 2]]);\n    cross([[-L \/ 2, H \/ 2, W \/ 2 + o], [L \/ 2, -H \/ 2, W \/ 2 + o], [-L \/ 2, -H \/ 2, W \/ 2 + o], [L \/ 2, H \/ 2, W \/ 2 + o]]);\n    cross([[-L \/ 2, -H \/ 2 - o, -W \/ 2], [L \/ 2, -H \/ 2 - o, W \/ 2], [-L \/ 2, -H \/ 2 - o, W \/ 2], [L \/ 2, -H \/ 2 - o, -W \/ 2]]);\n    [-L \/ 2, L \/ 2].forEach(x => { \/\/ TDF flanges + corners + bolts\n      const f = new THREE.Group(); f.position.x = x; f.rotation.y = Math.PI \/ 2; g.add(f);\n      frameRect(f, W + 0.08, H + 0.08, 0.05, 0.04, M.galvDark);\n      [[1, 1], [1, -1], [-1, 1], [-1, -1]].forEach(([a, b]) => { box(f, 0.08, 0.08, 0.05, M.dark, a * (W \/ 2 + 0.01), b * (H \/ 2 + 0.01), 0); cyl(f, 0.012, 0.012, 0.08, M.alu, a * (W \/ 2 + 0.01), b * (H \/ 2 + 0.01), 0, 10).rotation.x = Math.PI \/ 2; });\n      box(f, W, 0.012, 0.045, M.black, 0, H \/ 2 + 0.03, 0); box(f, W, 0.012, 0.045, M.black, 0, -H \/ 2 - 0.03, 0);\n    });\n    \/\/ insulation band \/ red Truestar label\n    box(g, 0.34, 0.12, 0.004, M.red, -0.6, 0.12, W \/ 2 + 0.01);\n    return g;\n  },\n\n  spiral(M) {\n    const g = new THREE.Group(); const R = 0.42, L = 2.6;\n    const tube = cyl(g, R, R, L, M.galv, 0, 0, 0, 64, true); tube.rotation.z = Math.PI \/ 2;\n    const pts = []; const turns = L \/ 0.16;\n    for (let i = 0; i <= turns * 40; i++) { const a = i \/ 40 * Math.PI * 2; pts.push(new THREE.Vector3(-L \/ 2 + i \/ (turns * 40) * L, Math.cos(a) * (R + 0.004), Math.sin(a) * (R + 0.004))); }\n    const seam = new THREE.Mesh(new THREE.TubeGeometry(new THREE.CatmullRomCurve3(pts), 1200, 0.011, 6, false), M.galvDark); g.add(seam);\n    const cp = cyl(g, R + 0.02, R + 0.02, 0.18, M.galvDark, L \/ 2 - 0.09, 0, 0, 64, true); cp.rotation.z = Math.PI \/ 2;\n    const bead = new THREE.Mesh(new THREE.TorusGeometry(R + 0.025, 0.012, 8, 64), M.alu); bead.rotation.y = Math.PI \/ 2; bead.position.x = L \/ 2 - 0.09; g.add(bead);\n    \/\/ branch take-off\n    const br = cyl(g, 0.2, 0.2, 0.55, M.galv, -0.4, R + 0.2, 0, 48, true);\n    const sad = new THREE.Mesh(new THREE.TorusGeometry(0.205, 0.015, 8, 48), M.galvDark); sad.rotation.x = Math.PI \/ 2; sad.position.set(-0.4, R + 0.03, 0); g.add(sad);\n    return g;\n  },\n\n  fsd60(M) {\n    const g = new THREE.Group(); const S = 1.0, dep = 0.55; const blades = [];\n    \/\/ sleeve\n    box(g, S + 0.02, 0.012, dep, M.galv, 0, S \/ 2, 0); box(g, S + 0.02, 0.012, dep, M.galv, 0, -S \/ 2, 0);\n    box(g, 0.012, S, dep, M.galv, S \/ 2, 0, 0); box(g, 0.012, S, dep, M.galv, -S \/ 2, 0, 0);\n    frameRect(g, S - 0.02, S - 0.02, 0.07, 0.2, M.galvDark, 0);\n    for (let b = 0; b < 5; b++) { const bl = airfoil(0.2, 0.034, S - 0.16, M.galv); bl.rotation.y = Math.PI \/ 2; const piv = new THREE.Group(); piv.position.y = -0.34 + b * 0.17; piv.add(bl); g.add(piv); blades.push(piv);\n      const ax = cyl(g, 0.012, 0.012, S + 0.08, M.alu, 0, piv.position.y, 0, 10); ax.rotation.z = Math.PI \/ 2; }\n    \/\/ jamb seals\n    box(g, 0.01, S - 0.16, 0.18, M.alu, S \/ 2 - 0.075, 0, 0); box(g, 0.01, S - 0.16, 0.18, M.alu, -S \/ 2 + 0.075, 0, 0);\n    \/\/ actuator + linkage + heat release\n    const act = box(g, 0.14, 0.34, 0.16, M.dark, S \/ 2 + 0.09, 0.05, 0.08); box(g, 0.004, 0.1, 0.07, M.white, S \/ 2 + 0.162, 0.1, 0.08);\n    box(g, 0.06, 0.03, 0.02, M.ledRed, S \/ 2 + 0.16, -0.08, 0.08);\n    const link = box(g, 0.02, 0.72, 0.02, M.alu, S \/ 2 + 0.05, 0, -0.12);\n    cyl(g, 0.03, 0.03, 0.12, M.red, S \/ 2 + 0.07, -0.33, -0.12, 16);\n    box(g, 0.2, 0.12, 0.004, M.white, 0, S \/ 2 - 0.04, dep \/ 2 + 0.002).visible = false;\n    g.userData.ang = 0; g.userData.target = 0; g.userData.auto = true; g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; if (u.auto) { u.t += dt; u.target = (Math.floor(u.t \/ 3.2) % 2) ? 1 : 0; }\n      u.ang += (u.target - u.ang) * Math.min(1, dt * 4); blades.forEach((p, i) => p.rotation.x = u.ang * 1.35 * (i % 2 ? 1 : 1)); link.position.y = -u.ang * 0.05; };\n    g.userData.toggle = { label: ['Close the blades', 'Open the blades'], fn: () => { const u = g.userData; u.auto = false; u.target = u.target ? 0 : 1; return u.target; } };\n    g.rotation.y = 0.5; return g;\n  },\n\n  tfd80(M) {\n    const g = new THREE.Group(); const blades = []; const mw = 1.0, mh = 0.9, dep = 0.4;\n    frameRect(g, mw * 2 + 0.16, mh * 2 + 0.16, 0.1, dep, M.galvDark);\n    box(g, 0.1, mh * 2, dep, M.galvDark, 0, 0, 0); box(g, mw * 2, 0.1, dep, M.galvDark, 0, 0, 0);\n    [[-1, -1], [1, -1], [-1, 1], [1, 1]].forEach(([a, b]) => {\n      for (let i = 0; i < 4; i++) { const bl = airfoil(0.26, 0.05, mw - 0.14, M.galv); bl.rotation.y = Math.PI \/ 2; const piv = new THREE.Group(); piv.position.set(a * mw \/ 2, b * mh \/ 2 - 0.3 + i * 0.2, 0); piv.add(bl); g.add(piv); blades.push(piv); }\n    });\n    \/\/ jackshaft + actuators\n    const js = cyl(g, 0.025, 0.025, mh * 2 + 0.3, M.alu, mw + 0.18, 0, 0.1, 12);\n    box(g, 0.22, 0.36, 0.22, M.dark, mw + 0.3, 0.45, 0.12); box(g, 0.22, 0.36, 0.22, M.dark, mw + 0.3, -0.45, 0.12);\n    box(g, 0.005, 0.12, 0.1, M.white, mw + 0.412, 0.5, 0.12); box(g, 0.005, 0.12, 0.1, M.white, mw + 0.412, -0.4, 0.12);\n    \/\/ mounting flange\n    const fl = new THREE.Group(); fl.position.z = -dep \/ 2; g.add(fl); frameRect(fl, mw * 2 + 0.5, mh * 2 + 0.5, 0.18, 0.02, M.galvDark);\n    g.userData.ang = 0; g.userData.target = 0; g.userData.auto = true; g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; if (u.auto) { u.t += dt; u.target = (Math.floor(u.t \/ 3.6) % 2) ? 1 : 0; }\n      u.ang += (u.target - u.ang) * Math.min(1, dt * 2.5); blades.forEach(p => p.rotation.x = u.ang * 1.3); };\n    g.userData.toggle = { label: ['Close the blades', 'Open the blades'], fn: () => { const u = g.userData; u.auto = false; u.target = u.target ? 0 : 1; return u.target; } };\n    g.rotation.y = 0.45; return g;\n  },\n\n  vav(M) {\n    const g = new THREE.Group(); const L = 1.0, H = 0.4, W = 0.6;\n    box(g, L, 0.01, W, M.galv, 0, H \/ 2, 0); box(g, L, 0.01, W, M.galv, 0, -H \/ 2, 0);\n    box(g, L, H, 0.01, M.galv, 0, 0, W \/ 2); box(g, L, H, 0.01, M.galv, 0, 0, -W \/ 2);\n    box(g, 0.01, H, W, M.galv, -L \/ 2, 0, 0);\n    box(g, L - 0.02, H - 0.03, W - 0.03, M.insul, 0.005, 0, 0).material = M.insul;\n    \/\/ discharge flange\n    const fl = new THREE.Group(); fl.position.x = L \/ 2; fl.rotation.y = Math.PI \/ 2; g.add(fl); frameRect(fl, W + 0.05, H + 0.05, 0.035, 0.03, M.galvDark);\n    \/\/ inlet spigot + damper + sensor cross\n    const sp = cyl(g, 0.13, 0.13, 0.32, M.galv, -L \/ 2 - 0.16, 0, 0, 48, true); sp.rotation.z = Math.PI \/ 2;\n    const bead = new THREE.Mesh(new THREE.TorusGeometry(0.133, 0.008, 8, 48), M.alu); bead.rotation.y = Math.PI \/ 2; bead.position.x = -L \/ 2 - 0.25; g.add(bead);\n    const sx = new THREE.Group(); sx.position.x = -L \/ 2 - 0.22; g.add(sx);\n    box(sx, 0.02, 0.25, 0.02, M.alu); box(sx, 0.02, 0.02, 0.25, M.alu); box(sx, 0.03, 0.03, 0.03, M.alu);\n    const dp = new THREE.Group(); dp.position.x = -L \/ 2 - 0.08; g.add(dp); const disc = cyl(dp, 0.12, 0.12, 0.012, M.galvDark, 0, 0, 0, 40); disc.rotation.z = Math.PI \/ 2;\n    const shaft = cyl(g, 0.01, 0.01, W \/ 2 + 0.3, M.alu, -L \/ 2 - 0.08, 0, 0.18, 10); shaft.rotation.x = Math.PI \/ 2;\n    const tub = cyl(g, 0.006, 0.006, 0.4, M.navy, -L \/ 2 + 0.05, 0.12, 0.2, 8); tub.rotation.x = Math.PI \/ 2;\n    \/\/ control enclosure\n    box(g, 0.36, 0.3, 0.12, M.white, -L \/ 2 + 0.2, 0.02, W \/ 2 + 0.07);\n    box(g, 0.12, 0.12, 0.05, M.orange, -L \/ 2 + 0.05, 0.02, W \/ 2 + 0.16);\n    box(g, 0.14, 0.06, 0.004, M.navy, -L \/ 2 + 0.26, 0.08, W \/ 2 + 0.132);\n    box(g, 0.012, 0.012, 0.01, M.led, -L \/ 2 + 0.34, -0.06, W \/ 2 + 0.132);\n    const air = particles(160, M.air); g.add(air);\n    g.userData.ang = 0.2; g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; u.t += dt; const a = 0.25 + 0.55 * (0.5 + 0.5 * Math.sin(u.t * 0.8)); dp.rotation.y = a * 1.2;\n      const pos = air.geometry.attributes.position; const sd = air.userData.seed;\n      for (let i = 0; i < sd.length; i++) { const k = (sd[i] + u.t * (0.25 + a * 0.4)) % 1; const r = 0.1 * ((sd[(i * 7) % sd.length])); const th = sd[(i * 13) % sd.length] * 6.28;\n        pos.setXYZ(i, -L \/ 2 - 0.35 + k * (L + 0.7), Math.cos(th) * r * (k > 0.3 ? 2 : 1), Math.sin(th) * r * (k > 0.3 ? 2.6 : 1)); }\n      pos.needsUpdate = true; };\n    return g;\n  },\n\n  ambinode(M) {\n    const g = new THREE.Group(); const S = 1.5;\n    box(g, 1.1, 1.1, 0.03, M.steel, 0, 0, -0.13); \/\/ steel mounting bracket\n    const body = roundedPlate(S - 0.04, S - 0.04, 0.2, 0.12, M.white, 0.03); body.position.z = -0.1; g.add(body);\n    const face = new THREE.Mesh(new THREE.PlaneGeometry(S * 500 \/ 450, S * 500 \/ 450), M.ambFace); face.position.z = 0.056; g.add(face);\n    const led = new THREE.Mesh(new THREE.CircleGeometry(0.018, 16), M.led); led.position.set(0, S * 500 \/ 450 * (250 - 202) \/ 500, 0.058); g.add(led);\n    const waves = []; for (let i = 0; i < 3; i++) { const w = new THREE.Mesh(new THREE.RingGeometry(0.9, 0.93, 64, 1, -0.7, 1.4), M.wave.clone()); w.position.z = 0.02; g.add(w); waves.push(w);\n      const w2 = w.clone(); w2.material = w.material; w2.rotation.z = Math.PI; g.add(w2); waves.push(w2); }\n    g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; u.t += dt; led.visible = (u.t % 2) < 1.6;\n      waves.forEach((w, i) => { const k = ((u.t * 0.45) + Math.floor(i \/ 2) \/ 3) % 1; const s = 1 + k * 0.9; w.scale.set(s, s, 1); w.material.opacity = 0.55 * (1 - k); }); };\n    return g;\n  },\n\n  linear(M) {\n    const g = new THREE.Group(); const L = 2.2, slots = 3;\n    \/\/ ceiling slab\n    const ceil = box(g, 2.8, 0.03, 1.4, M.tile, 0, 0.02, 0); ceil.material = M.skin;\n    const face = new THREE.Group(); face.position.y = 0; g.add(face);\n    box(face, L, 0.03, 0.04, M.white, 0, -0.01, 0.17); box(face, L, 0.03, 0.04, M.white, 0, -0.01, -0.17);\n    for (let s = 0; s < slots; s++) { const z = -0.1 + s * 0.1; box(face, L, 0.2, 0.012, M.white, 0, 0.1, z - 0.045); box(face, L - 0.02, 0.012, 0.05, M.black, 0, 0.0, z); }\n    box(face, L, 0.2, 0.012, M.white, 0, 0.1, 0.155); box(face, 0.03, 0.03, 0.38, M.white, L \/ 2, -0.01, 0); box(face, 0.03, 0.03, 0.38, M.white, -L \/ 2, -0.01, 0);\n    \/\/ plenum box above\n    const pl = new THREE.Group(); pl.position.y = 0.32; g.add(pl);\n    box(pl, L, 0.01, 0.4, M.galv, 0, 0.2, 0); box(pl, L, 0.4, 0.01, M.galv, 0, 0, 0.2); box(pl, L, 0.4, 0.01, M.galv, 0, 0, -0.2);\n    box(pl, 0.01, 0.4, 0.4, M.galv, L \/ 2, 0, 0); box(pl, 0.01, 0.4, 0.4, M.galv, -L \/ 2, 0, 0);\n    const sp = cyl(pl, 0.12, 0.12, 0.25, M.galv, -0.5, 0.32, 0, 40, true);\n    const sp2 = cyl(pl, 0.12, 0.12, 0.25, M.galv, 0.5, 0.32, 0, 40, true);\n    const air = particles(420, M.air); g.add(air); g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; u.t += dt; const pos = air.geometry.attributes.position; const sd = air.userData.seed;\n      for (let i = 0; i < sd.length; i++) { const k = (sd[i] + u.t * 0.35) % 1; const side = i % 2 ? 1 : -1; const x = (sd[(i * 7) % sd.length] - 0.5) * L;\n        pos.setXYZ(i, x, -0.03 - k * 0.18 * k, side * (0.12 + k * 1.1)); }\n      pos.needsUpdate = true; };\n    return g;\n  },\n\n  ufad(M) {\n    const g = new THREE.Group(); const T = 0.6;\n    \/\/ raised floor tiles (3x3 with centre diffuser)\n    for (let i = -1; i <= 1; i++) for (let j = -1; j <= 1; j++) { const t = box(g, T - 0.01, 0.04, T - 0.01, M.tile, i * T, 0, j * T); if (!i && !j) t.visible = false; }\n    \/\/ centre tile with hole\n    const ct = new THREE.Mesh(new THREE.RingGeometry(0.2, 0.42, 48), M.tile); ct.rotation.x = -Math.PI \/ 2; ct.position.y = 0.021; ct.scale.set(1, 1, 1); g.add(ct);\n    box(g, T - 0.01, 0.04, 0.08, M.tile, 0, 0, 0.26); box(g, T - 0.01, 0.04, 0.08, M.tile, 0, 0, -0.26); box(g, 0.08, 0.04, T - 0.01, M.tile, 0.26, 0, 0); box(g, 0.08, 0.04, T - 0.01, M.tile, -0.26, 0, 0);\n    \/\/ diffuser\n    const rim = new THREE.Mesh(new THREE.TorusGeometry(0.2, 0.018, 10, 64), M.dark); rim.rotation.x = Math.PI \/ 2; rim.position.y = 0.03; g.add(rim);\n    const grille = new THREE.Group(); grille.position.y = 0.025; g.add(grille);\n    for (let r = 0; r < 12; r++) { const v = box(grille, 0.18, 0.012, 0.012, M.black, 0, 0, 0); const a = r \/ 12 * Math.PI; v.rotation.y = a; v.position.set(0, 0, 0); v.geometry.translate(0.09, 0, 0); v.rotation.y = r \/ 12 * Math.PI * 2 + 0.3; }\n    cyl(grille, 0.05, 0.05, 0.02, M.dark, 0, 0, 0, 24);\n    const bucket = cyl(g, 0.19, 0.16, 0.22, M.dark, 0, -0.12, 0, 40, true);\n    \/\/ pedestals\n    [[-1, -1], [1, -1], [-1, 1], [1, 1]].forEach(([a, b]) => { cyl(g, 0.018, 0.018, 0.45, M.alu, a * 0.3, -0.25, b * 0.3, 10); box(g, 0.1, 0.01, 0.1, M.alu, a * 0.3, -0.475, b * 0.3); });\n    box(g, 2.0, 0.01, 2.0, M.navy, 0, -0.485, 0);\n    const air = particles(360, M.air); g.add(air); g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; u.t += dt; grille.rotation.y += dt * 0.0; const pos = air.geometry.attributes.position; const sd = air.userData.seed;\n      for (let i = 0; i < sd.length; i++) { const k = (sd[i] + u.t * 0.22) % 1; const th = sd[(i * 11) % sd.length] * 6.28 + k * 7; const r = 0.05 + k * 0.55 * Math.sqrt(k);\n        pos.setXYZ(i, Math.cos(th) * r, 0.05 + k * 1.4, Math.sin(th) * r); }\n      pos.needsUpdate = true; };\n    return g;\n  },\n\n  nozzle(M) {\n    const g = new THREE.Group();\n    \/\/ wall panel\n    box(g, 1.8, 1.4, 0.04, M.skin, 0, 0, -0.2);\n    const flange = new THREE.Mesh(new THREE.TorusGeometry(0.34, 0.07, 16, 64), M.white); flange.position.z = -0.14; g.add(flange);\n    const ball = new THREE.Mesh(new THREE.SphereGeometry(0.3, 48, 32), M.white); ball.position.z = -0.08; g.add(ball);\n    const noz = new THREE.Group(); noz.position.z = -0.08; g.add(noz);\n    const cone = new THREE.Mesh(new THREE.CylinderGeometry(0.17, 0.23, 0.42, 48, 1, true), M.white); cone.rotation.x = Math.PI \/ 2; cone.position.z = 0.25; noz.add(cone);\n    const lip = new THREE.Mesh(new THREE.TorusGeometry(0.17, 0.02, 10, 48), M.white); lip.position.z = 0.46; noz.add(lip);\n    const inner = new THREE.Mesh(new THREE.CylinderGeometry(0.15, 0.15, 0.1, 48, 1, true), M.dark); inner.rotation.x = Math.PI \/ 2; inner.position.z = 0.42; noz.add(inner);\n    const air = particles(300, M.air); noz.add(air); g.userData.t = 0;\n    g.userData.tick = (dt) => { const u = g.userData; u.t += dt; noz.rotation.x = Math.sin(u.t * 0.5) * 0.25; noz.rotation.y = Math.cos(u.t * 0.4) * 0.3;\n      const pos = air.geometry.attributes.position; const sd = air.userData.seed;\n      for (let i = 0; i < sd.length; i++) { const k = (sd[i] + u.t * 0.4) % 1; const th = sd[(i * 7) % sd.length] * 6.28; const r = 0.12 * sd[(i * 3) % sd.length] + k * 0.25;\n        pos.setXYZ(i, Math.cos(th) * r, Math.sin(th) * r, 0.46 + k * 2.2); }\n      pos.needsUpdate = true; };\n    g.rotation.y = -0.6; return g;\n  }\n};\n\nconst VIEW = {\n  ahu: { yaw: 0.55, pitch: 0.26 }, rect: { yaw: 0.7, pitch: 0.35 }, spiral: { yaw: 0.8, pitch: 0.3 },\n  fsd60: { yaw: 0.2, pitch: 0.2 }, tfd80: { yaw: 0.2, pitch: 0.15 }, vav: { yaw: -0.75, pitch: 0.35 },\n  ambinode: { yaw: 0.25, pitch: 0.12, swing: 0.6 }, nozzle: { yaw: 0.9, pitch: 0.1, swing: 0.6 },\n  linear: { yaw: 0.5, pitch: -0.5, pmin: -1.1, pmax: -0.1, swing: 0.7 }, ufad: { yaw: 0.6, pitch: 0.42 }\n};\n\/* ---------- studio ---------- *\/\nfunction createStudio(host, { onToggleChange } = {}) {\n  const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, powerPreference: 'high-performance' });\n  renderer.setPixelRatio(Math.min(2, window.devicePixelRatio || 1));\n  renderer.outputColorSpace = THREE.SRGBColorSpace; renderer.toneMapping = THREE.ACESFilmicToneMapping; renderer.toneMappingExposure = 1.05;\n  renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap;\n  host.appendChild(renderer.domElement); renderer.domElement.style.cssText = 'width:100%;height:100%;display:block;touch-action:none;cursor:grab';\n  const scene = new THREE.Scene();\n  const pmrem = new THREE.PMREMGenerator(renderer); scene.environment = pmrem.fromScene(new RoomEnvironment(renderer), 0.04).texture;\n  const cam = new THREE.PerspectiveCamera(30, 1, 0.05, 100);\n  const key = new THREE.DirectionalLight(0xffffff, 1.6); key.position.set(3, 5, 4); key.castShadow = true; key.shadow.mapSize.set(1024, 1024);\n  Object.assign(key.shadow.camera, { left: -4, right: 4, top: 4, bottom: -4 }); scene.add(key);\n  scene.add(new THREE.HemisphereLight(0xdfe8ff, 0x1a2233, 0.5)); const rim = new THREE.DirectionalLight(0x9fb8ff, 0.6); rim.position.set(-4, 3, -4); scene.add(rim);\n  const floor = new THREE.Mesh(new THREE.CircleGeometry(6, 48), new THREE.ShadowMaterial({ opacity: 0.28 })); floor.rotation.x = -Math.PI \/ 2; floor.receiveShadow = true; scene.add(floor);\n  const M = makeMats();\n  const pivot = new THREE.Group(); scene.add(pivot);\n  let current = null, curKey = null, yaw = 0.6, pitch = 0.28, dist = 6, autoRot = true, lastUser = 0, visible = true, raf = 0, last = performance.now();\n  const cache = {}, dists = {}; let view = {}, base = 0, swingT = 0;\n  function fit(obj) {\n    const b = new THREE.Box3().setFromObject(obj); const s = b.getBoundingSphere(new THREE.Sphere());\n    obj.position.sub(s.center); obj.userData.floorY = b.min.y - s.center.y - 0.002;\n    return s.radius \/ Math.sin(THREE.MathUtils.degToRad(cam.fov \/ 2)) * 1.02;\n  }\n  function show(k) {\n    if (current) pivot.remove(current);\n    if (!cache[k]) { const m = MODELS[k](M); const wrap = new THREE.Group(); wrap.add(m); wrap.userData = m.userData; dists[k] = fit(wrap); cache[k] = wrap; }\n    view = VIEW[k] || {}; yaw = base = view.yaw ?? 0.6; pitch = view.pitch ?? 0.28; swingT = 0; dist = dists[k];\n    current = cache[k]; curKey = k; pivot.add(current); floor.position.y = current.userData.floorY; floor.visible = !(VIEW[k] && VIEW[k].pitch < 0);\n    onToggleChange && onToggleChange(current.userData.toggle ? current.userData.toggle.label[current.userData.target ? 1 : 0] : null);\n    kick();\n  }\n  function toggle() { const t = current && current.userData.toggle; if (!t) return null; const st = t.fn(); onToggleChange && onToggleChange(t.label[st ? 1 : 0]); kick(); return st; }\n  function resize() { const w = host.clientWidth || 1, h = host.clientHeight || 1; renderer.setSize(w, h, false); cam.aspect = w \/ h; cam.updateProjectionMatrix(); }\n  new ResizeObserver(() => { resize(); kick(); }).observe(host); resize();\n  \/\/ pointer rotate\n  let drag = null; const el = renderer.domElement;\n  el.addEventListener('pointerdown', e => { drag = { x: e.clientX, y: e.clientY, yaw, pitch }; el.setPointerCapture(e.pointerId); el.style.cursor = 'grabbing'; lastUser = performance.now(); kick(); });\n  el.addEventListener('pointermove', e => { if (!drag) return; yaw = drag.yaw + (e.clientX - drag.x) * 0.008; pitch = Math.max(view.pmin ?? -0.2, Math.min(view.pmax ?? 1.1, drag.pitch + (e.clientY - drag.y) * 0.006)); base = yaw; swingT = 0; lastUser = performance.now(); });\n  const end = () => { drag = null; el.style.cursor = 'grab'; lastUser = performance.now(); };\n  el.addEventListener('pointerup', end); el.addEventListener('pointercancel', end);\n  el.addEventListener('keydown', e => { if (e.key === 'ArrowLeft') yaw -= 0.2; if (e.key === 'ArrowRight') yaw += 0.2; if (e.key === 'ArrowUp') pitch = Math.max(-0.2, pitch - 0.1); if (e.key === 'ArrowDown') pitch = Math.min(1.1, pitch + 0.1); lastUser = performance.now(); kick(); });\n  el.tabIndex = 0;\n  new IntersectionObserver(es => { visible = es[0].isIntersecting; if (visible) kick(); }).observe(host);\n  document.addEventListener('visibilitychange', () => { if (!document.hidden) kick(); });\n  const reduce = matchMedia('(prefers-reduced-motion: reduce)').matches;\n  function frame(now) {\n    raf = 0; const dt = Math.min(0.05, (now - last) \/ 1000); last = now;\n    if (!drag && autoRot && !reduce && now - lastUser > 2500) { if (view.swing) { swingT += dt * 0.35; yaw = base + Math.sin(swingT) * view.swing; } else yaw += dt * 0.28; }\n    if (current && current.userData.tick && !reduce) current.userData.tick(dt);\n    const r = dist; cam.position.set(Math.sin(yaw) * Math.cos(pitch) * r, Math.sin(pitch) * r, Math.cos(yaw) * Math.cos(pitch) * r); cam.lookAt(0, 0, 0);\n    renderer.render(scene, cam);\n    if (visible && !document.hidden) raf = requestAnimationFrame(frame);\n  }\n  function kick() { if (!raf) { last = performance.now(); raf = requestAnimationFrame(frame); } }\n  return { show, toggle, get key() { return curKey; }, setAuto(v) { autoRot = v; } };\n}\nconst MODEL_KEYS = Object.keys(MODELS);\n\n  const $=s=>document.querySelector(s);\n  try {\n    \/\/ Featured studio\n    const tgl=$('#ftoggle');\n    const fs=createStudio($('#fgl'),{onToggleChange:l=>{ if(l){tgl.textContent=l;tgl.hidden=false;} else tgl.hidden=true; }});\n    window.feat3d=fs; window.featRender&&window.featRender();\n    \/\/ Hero: swap the CSS viewer for WebGL\n    const old=$('#stage'); const stage=old.cloneNode(false); old.replaceWith(stage); stage.style.cursor='default'; stage.style.position='relative';\n    const seg=$('.hero .seg'); const seg2=seg.cloneNode(true); seg.replaceWith(seg2);\n    const map={rect:'rect',round:'spiral',ahu:'ahu'}, hints={rect:'DRAG TO ROTATE \u00b7 GI RECTANGULAR DUCT, TDF FLANGES',spiral:'DRAG TO ROTATE \u00b7 SPIRAL-SEAM ROUND DUCT WITH TAKE-OFF',ahu:'DRAG TO ROTATE \u00b7 DOUBLE-SKIN AHU'};\n    const hb=document.createElement('button'); hb.type='button'; hb.className='fbtn'; hb.hidden=true; hb.style.cssText='position:absolute;right:14px;bottom:14px;z-index:2';\n    const host=document.createElement('div'); host.style.cssText='position:absolute;inset:0'; stage.append(host,hb);\n    const hs=createStudio(host,{onToggleChange:l=>{ if(l){hb.textContent=l;hb.hidden=false;} else hb.hidden=true; }});\n    hb.addEventListener('click',()=>hs.toggle());\n    const pick=m=>{ seg2.querySelectorAll('button').forEach(b=>b.classList.toggle('on',b.dataset.model===m)); hs.show(map[m]); $('#hint').textContent=hints[map[m]]; };\n    seg2.addEventListener('click',e=>{const b=e.target.closest('button'); if(b) pick(b.dataset.model);});\n    const first=seg2.querySelector('[data-model=\"ahu\"]'); seg2.prepend(first); pick('ahu');\n  } catch(err) { console.warn('3D unavailable', err); window.feat3d=null; window.featRender&&window.featRender(); }\n\n};\nconst go=()=>{ if(window.__ts3d) return; window.__ts3d=1; boot().catch(e=>{console.warn(\"3D unavailable\",e); window.feat3d=null; window.featRender&&window.featRender();}); };\nif(document.readyState==='complete') setTimeout(go,300); else addEventListener('load',()=>setTimeout(go,300));\n['pointerdown','scroll','keydown'].forEach(ev=>addEventListener(ev,go,{once:true,passive:true}));\n<\/script><!--\/noptimize-->\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Truestar Air Systems: factory-fabricated ductwork, air handling units, dampers, grilles and diffusers from plants in Valsad, Medak and Noida.<\/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":"set","ast-page-background-enabled":"default","ast-page-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":"","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-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":"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":""},"mobile":{"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":""}},"footnotes":""},"class_list":["post-7506","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Factory Fabricated Duct Manufacturer Truestar Air Systems<\/title>\n<meta name=\"description\" content=\"We are leading Manufacturer and Supplier of Factory Fabricated Ducts, Ventilation Duct, TDF Duct, Round Duct, Oval Duct from Noida India.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/truestarairsystems.com\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Factory Fabricated Duct Manufacturer Truestar Air Systems\" \/>\n<meta property=\"og:description\" content=\"We are leading Manufacturer and Supplier of Factory Fabricated Ducts, Ventilation Duct, TDF Duct, Round Duct, Oval Duct from Noida India.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/truestarairsystems.com\/\" \/>\n<meta property=\"og:site_name\" content=\"Truestar Air Systems\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-29T07:48:29+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@TruestarAir\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"14 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/\",\"url\":\"https:\\\/\\\/truestarairsystems.com\\\/\",\"name\":\"Factory Fabricated Duct Manufacturer Truestar Air Systems\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#website\"},\"datePublished\":\"2026-09-28T19:10:42+00:00\",\"dateModified\":\"2026-09-29T07:48:29+00:00\",\"description\":\"We are leading Manufacturer and Supplier of Factory Fabricated Ducts, Ventilation Duct, TDF Duct, Round Duct, Oval Duct from Noida India.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/truestarairsystems.com\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/truestarairsystems.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Home\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#website\",\"url\":\"https:\\\/\\\/truestarairsystems.com\\\/\",\"name\":\"Truestar Air System\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/truestarairsystems.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#organization\",\"name\":\"Truestar Air System\",\"url\":\"https:\\\/\\\/truestarairsystems.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/truestarairsystems.com\\\/wp-content\\\/uploads\\\/2025\\\/01\\\/2-scaled.png\",\"contentUrl\":\"https:\\\/\\\/truestarairsystems.com\\\/wp-content\\\/uploads\\\/2025\\\/01\\\/2-scaled.png\",\"width\":2560,\"height\":2560,\"caption\":\"Truestar Air System\"},\"image\":{\"@id\":\"https:\\\/\\\/truestarairsystems.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/x.com\\\/TruestarAir\",\"https:\\\/\\\/www.instagram.com\\\/truestarairsystems\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/truestarairsystems\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Factory Fabricated Duct Manufacturer Truestar Air Systems","description":"We are leading Manufacturer and Supplier of Factory Fabricated Ducts, Ventilation Duct, TDF Duct, Round Duct, Oval Duct from Noida India.","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:\/\/truestarairsystems.com\/","og_locale":"en_US","og_type":"article","og_title":"Factory Fabricated Duct Manufacturer Truestar Air Systems","og_description":"We are leading Manufacturer and Supplier of Factory Fabricated Ducts, Ventilation Duct, TDF Duct, Round Duct, Oval Duct from Noida India.","og_url":"https:\/\/truestarairsystems.com\/","og_site_name":"Truestar Air Systems","article_modified_time":"2026-09-29T07:48:29+00:00","twitter_card":"summary_large_image","twitter_site":"@TruestarAir","twitter_misc":{"Est. reading time":"14 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/truestarairsystems.com\/","url":"https:\/\/truestarairsystems.com\/","name":"Factory Fabricated Duct Manufacturer Truestar Air Systems","isPartOf":{"@id":"https:\/\/truestarairsystems.com\/#website"},"datePublished":"2026-09-28T19:10:42+00:00","dateModified":"2026-09-29T07:48:29+00:00","description":"We are leading Manufacturer and Supplier of Factory Fabricated Ducts, Ventilation Duct, TDF Duct, Round Duct, Oval Duct from Noida India.","breadcrumb":{"@id":"https:\/\/truestarairsystems.com\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/truestarairsystems.com\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/truestarairsystems.com\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/truestarairsystems.com\/"},{"@type":"ListItem","position":2,"name":"Home"}]},{"@type":"WebSite","@id":"https:\/\/truestarairsystems.com\/#website","url":"https:\/\/truestarairsystems.com\/","name":"Truestar Air System","description":"","publisher":{"@id":"https:\/\/truestarairsystems.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/truestarairsystems.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/truestarairsystems.com\/#organization","name":"Truestar Air System","url":"https:\/\/truestarairsystems.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/truestarairsystems.com\/#\/schema\/logo\/image\/","url":"https:\/\/truestarairsystems.com\/wp-content\/uploads\/2025\/01\/2-scaled.png","contentUrl":"https:\/\/truestarairsystems.com\/wp-content\/uploads\/2025\/01\/2-scaled.png","width":2560,"height":2560,"caption":"Truestar Air System"},"image":{"@id":"https:\/\/truestarairsystems.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/TruestarAir","https:\/\/www.instagram.com\/truestarairsystems\/","https:\/\/www.linkedin.com\/in\/truestarairsystems\/"]}]}},"_links":{"self":[{"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/pages\/7506","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/comments?post=7506"}],"version-history":[{"count":29,"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/pages\/7506\/revisions"}],"predecessor-version":[{"id":7555,"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/pages\/7506\/revisions\/7555"}],"wp:attachment":[{"href":"https:\/\/truestarairsystems.com\/index.php\/wp-json\/wp\/v2\/media?parent=7506"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}