PageSourceSearch

https://napa-canvas-website.webflow.io/solutions

html napa-canvas-website.webflow.io collected 2026-10-03 13:30:50 UTC 70,046 bytes, 1,378 lines download raw bytes

1<!DOCTYPE html><!-- This site was created in Webflow. https://webflow.com --><!-- Last Published: Wed May 13 2026 06:48:54 GMT+0000 (Coordinated Universal Time) --><html data-wf-domain="napa-canvas-website.webflow.io" data-wf-page="69ba6291152cc9f0778e4cb8" data-wf-site="69ab2b3b80f48170ba7e0b8f" lang="en"><head><meta charset="utf-8"/><link href="https://cdn.prod.website-files.com" rel="preconnect" crossorigin="anonymous"/><title>Solutions</title><meta content="Solutions" property="og:title"/><meta content="Solutions" name="twitter:title"/><meta content="width=device-width, initial-scale=1" name="viewport"/><meta content="Webflow" name="generator"/><link href="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/css/napa-canvas-website.webflow.shared.7f37e9e79.css" rel="stylesheet" type="text/css" integrity="sha384-fzfp555nmJrY98IbqElK1Y5kLZFhRa+Ft58zih4i49bN5nr/ZpfYxTuplJjJ8Eyi" crossorigin="anonymous"/><style>html.w-mod-js:not(.w-mod-ix3) :is(.div-block-3) {visibility: hidden !important;}</style><link href="https://fonts.googleapis.com" rel="preconnect"/><link href="https://fonts.gstatic.com" rel="preconnect" crossorigin="anonymous"/>
1<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js" type="text/javascript"></script>
1<script type="text/javascript">WebFont.load({  google: {    families: ["Montserrat:100,100italic,200,200italic,300,300italic,400,400italic,500,500italic,600,600italic,700,700italic,800,800italic,900,900italic","Inter:300,400,500,600,700","Tenor Sans:300,400,500,600,700"]  }});</script>
1<script type="text/javascript">!function(o,c){var n=c.documentElement,t=" w-mod-";n.className+=t+"js",("ontouchstart"in o||o.DocumentTouch&&c instanceof DocumentTouch)&&(n.className+=t+"touch")}(window,document);</script>
1<link href="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69afb9f6a01fa3d13b429153_favicon-32x32.png" rel="shortcut icon" type="image/x-icon"/><link href="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69afba07c8531cd9d5f8aa0f_favicon-256x256.png" rel="apple-touch-icon"/><!-- 1. Paste this code as high in the <head> of the page as possible: -->
2<!-- Google Tag Manager -->
3<script>
vendor: 327 bytes, lines 3-7
3(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
4new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
5j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
6'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
7})(window,document,'script','dataLayer','
7GTM-NTQ5SPMC
vendor: 3 bytes, line 7
7');
7</script>
7
8<!-- End Google Tag Manager -->
9
10
11
12<style>
13  .product-total-price:before {
14    content: '$';
15  }
16  .product-total-price:after {
17    content: '.00';
18  }
19  /*a.footer-menu-link.w--current .footer-menu-text,
20  a.footer-menu-link.w--current .footer-menu-text {
21      color: #dfa961 !important;
22  }*/
23  .footer-menu-icon-link:hover .footer-menu-icon-text {
24    color: #dfa961 !important;
25    text-decoration-color: #dfa961 !important;
26  }
27  /* Solution Page Css Start */
28  .solution-collection-list::before,
29  .solution-collection-list::after {
30    content: none !important;
31    display: none !important;
32  }
33  .solution-collection-list {
34    margin-left: auto !important;
35    margin-right: auto !important;
36  }
37  .marquee-wrapper {
38    overflow: hidden;
39    width: 100%;
40  }
41  .marquee-track {
42    display: flex;
43    width: max-content;
44    will-change: transform;
45  }
46
47  .clients-wrapper-three {
48    display: flex;
49    gap: 32px;
50    flex-shrink: 0;
51
52    /* 🔥 THIS IS THE FIX */
53    padding-left: 32px;
54  }
55  /* FAQ section css start */
56
57  .faq-answer {
58    height: 0;
59    overflow: hidden;
60    transition: height 0.35s ease;
61  }
62
63  .faq-item.active .faq-answer {
64    height: auto;
65  }
66  .faq-icon {
67    transition: transform 0.4s ease;
68  }
69  .faq-answer a {
70    color: #1e1e1e;
71    transition: color 0.2s ease;
72  }
73
74  .faq-answer a:hover {
75    color: #dfa961;
76  }
77  /* Solution Page Css End */
78  /* Privacy Policy css start */
79  .p-tag a {
80    color: #1e1e1e;
81    transition: color 0.2s ease;
82  }
83
84  .p-tag a:hover {
85    color: #dfa961;
86  }
87  /* Privacy policy css end */
88
89  .home-body {
90    overflow-x: hidden;
91  }
92
93  .w-layout-blockcontainer.horizantal-container.w-container {
94    margin-left: auto !important;
95    margin-right: 0;
96    max-width: calc((100% - 1320px) / 2 + 1320px) !important;
97  }
98  .collection-item img.image-40 {
99    transition: transform 0.5s;
100  }
101  .collection-item:hover img.image-40 {
102    transform: scale(1.1) !important;
103  }
104  /* TEXT COLOR CHANGE */
105  .collection-item .related-projects {
106    transition: color 0.3s ease;
107  }
108
109  .collection-item:hover .related-projects {
110    /* color: #dfa961; */
111  }
112  a.nav-link.w-nav-link.w--current,
113  a.nav-link:hover {
114    color: var(--_napa-canvas-colors---muted-gold) !important;
115  }
116  .horizontal-section {
117    position: relative;
118  }
119  .horizantal-scroll-track {
120    display: flex;
121    position: sticky;
122    top: 0;
123    will-change: transform;
124  }
125  @media screen and (max-width: 991px) {
126    .nav-link.white-text:active,
127    .nav-link.white-text:visited {
128      color: initial;
129    }
130  }
131
132  /* filter radio styling start*/
133  /* Base radio wrapper → button */
134  .w-radio {
135    display: inline-flex;
136    align-items: center;
137    justify-content: center;
138    padding: 14px 18px;
139    background-color: rgba(42, 79, 139, 0.08);
140    cursor: pointer;
141    /* transition: all 0.25s ease; */
142  }
143
144  /* Hide native radio */
145  .w-radio-input {
146    display: none;
147  }
148
149  /* Label text */
150  .w-radio .w-form-label {
151    margin: 0;
152    font-size: 14px;
153    font-weight: 400;
154    color: #1e1e1e;
155    cursor: pointer;
156    font-family: Satoshi, Arial, sans-serif;
157    line-height: initial;
158    letter-spacing: 0;
159  }
160  /* Hover state */
161  .w-radio:hover {
162    border-color: #000;
163  }
164  /* Active text */
165  .w-radio-input:checked + .w-form-label,
166  .w-radio:hover .w-form-label {
167    color: #fff;
168  }
169  /* Active button (modern browsers) */
170  .w-radio:has(.w-radio-input:checked),
171  .w-radio:hover {
172    background-color: #dfa961;
173    border-color: #fff;
174  }
175  /* Optional press effect */
176  .w-radio:active {
177    transform: scale(0.97);
178  }
179  /* filter radio styling end*/
180
181  a.page-number.w--current,
182  a.pagination-previous.w--current {
183    background-color: #dfa961;
184    color: #fff;
185  }
186  a.pagination-previous.is-list-pagination-disabled path,
187  a.pagination-next.is-list-pagination-disabled path {
188    color: rgba(30, 30, 30, 0.3);
189  }
190
191  .filter-tab-row.w-dyn-items,
192  .w-form-label {
193    white-space: nowrap;
194  }
195  
196  /* .pagination-row {
197    display: none;
198} */
199
200/* detail page gallery */
201.detail-gallery-list {
202    display: flex;
203    gap: 24px;
204    flex-wrap: wrap;
205}
206
207.detail-gallery-list .w-dyn-item {
208    box-sizing: border-box;
209}
210.detail-gallery-list img {
211    width: 100%;
212    height: 100%;
213    object-fit: cover !important;
214}
215/* 1st */
216.detail-gallery-list .w-dyn-item:nth-child(5n + 1) {
217    width: calc(61.67% - 12px);
218    height: 678px;
219}
220
221/* 2nd */
222.detail-gallery-list .w-dyn-item:nth-child(5n + 2) {
223    width: calc(38.33% - 12px);
224    height: 678px;
225}
226
227/* 3rd */
228.detail-gallery-list .w-dyn-item:nth-child(5n + 3) {
229    width: calc(41.52% - 12px);
230    height: 545px;
231}
232
233/* 4th */
234.detail-gallery-list .w-dyn-item:nth-child(5n + 4) {
235    width: calc(58.48% - 12px);
236    height: 545px;
237}
238
239/* 5th (FULL WIDTH) */
240.detail-gallery-list .w-dyn-item:nth-child(5n + 5) {
241    width: 100%;
242    height: 793px;
243}
244.collection-list.solution-collection-list.portfolio-listing-sec {
245    grid-template-rows: initial !important;
246}
247/* tab horizantal scroll bar styling */
248/* .collection-item:hover .detail-page-category{
249    color: #1e1e1e !important;
250}
251.detail-page-category {
252    transition: initial !important;
253} */
254@media screen and (max-width: 930px) {
255  .filter-tabs-scroll {
256  	overflow-x: scroll;
257  }
258  .filter-tabs-scroll::-webkit-scrollbar {
259  	height: 2px;
260  }
261  .filter-tabs-scroll::-webkit-scrollbar-track {
262    background: #2a4f8b50;
263  }
264  .filter-tabs-scroll::-webkit-scrollbar-thumb {
265    background-color: #dfa961;
266    border-radius: 10px;
267  }
268  .filter-tabs-scroll::-webkit-scrollbar-thumb:hover {
269    background-color: #dfa961;
270  }
271}
272  @media (max-width: 767px) {
273    .detail-gallery-list {
274        flex-direction: column;
275        gap: 16px; /* optional */
276    }
277
278    .detail-gallery-list .w-dyn-item {
279        width: 100% !important;
280        height: 400px !important;
281    }
282}
283</style></head><body class="body"><div class="div-block-2"><section class="header-sec black-header"><div class="w-layout-blockcontainer container w-container"><div data-animation="default" data-collapse="medium" data-duration="400" data-easing="ease-in-quart" data-easing2="ease" role="banner" class="navbar w-nav"><div class="navbar-row"><div><a href="https://napa-canvas-website.webflow.io" class="w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69afbcf7e3d2db41ba5c2b0b_Logo.svg" alt="" class="logo-img"/></a></div><div class="header-menu-column"><div class="header-menu-inline"><nav role="navigation" class="nav-menu-3 w-nav-menu"><a href="/" class="nav-link w-nav-link">Home</a><a href="/solutions" aria-current="page" class="nav-link w-nav-link w--current">Solutions</a><a href="/portfolio" class="nav-link w-nav-link">Portfolio</a><a href="/about" class="nav-link w-nav-link">About</a><a href="/faq" class="nav-link w-nav-link">FAQ</a><a href="/pricing" class="nav-link w-nav-link">Pricing</a><a href="/contact" class="blue-button-icon hide-for-desktop w-inline-block"><div class="btn-text-white">Get in Touch</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c24a519c2a0d913bc4c45d_orange-right-icon.svg" loading="lazy" alt="" class="btn-icon"/></a></nav><a href="/contact" class="blue-button-icon hide-for-mobile w-inline-block"><div class="btn-text-white">Get in Touch</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c24a519c2a0d913bc4c45d_orange-right-icon.svg" loading="lazy" alt="" class="btn-icon"/></a></div><div class="menu-button-3 mobile-menu-bar w-nav-button"><div class="icon w-icon-nav-menu"></div></div></div></div></div></div></section></div><section class="section-8 banner-overlay"><div class="w-layout-blockcontainer container w-container"><div class="div-block-3"><div class="w-layout-blockcontainer container-36 w-container"><div class="text-satoshi-white-18">Solutions</div><h1 class="heading-tenor-white-42">Custom Shade Solutions, Designed Around You</h1></div><div class="w-layout-blockcontainer container-37 w-container"><div class="text-satoshi-white-18 solution-banner-content">Every Napa Canvas project begins with your space, your vision, and 
283your needs. We bring your design to life with clarity, intention and precision.</div><div class="w-layout-hflex flex-block"><div class="w-layout-vflex"><a href="#explore-our-solution" class="link-block-9 w-inline-block"><div class="text-block-11 explore-product">Explore Our Solutions</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c24df7f83d4d963305f414_Explore%20Solution%20Icon.svg" alt="" class="image-32"/></a></div></div></div></div></div></section><section class="section-9"><div class="w-layout-blockcontainer container w-container"><div class="div-block-4"><div class="white-heading-tenor-52">Enhance your outdoor living space and create functional shade, we guide you every step of the way.</div></div><div id="explore-our-solution" class="div-block-16"><div class="collection-list-wrapper w-dyn-list"><div role="list" class="collection-list solution-collection-list w-dyn-items"><div role="listitem" class="collection-item w-dyn-item"><a href="/portfolio?sun-shades" class="link-block-12 w-inline-block"><div class="collection-img-box"><img src="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfa80c6ed7508bf44ce86e_sunshades%20img.jpg" loading="lazy" alt="" sizes="(max-width: 767px) 100vw, (max-width: 991px) 95vw, 848px" srcset="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfa80c6ed7508bf44ce86e_sunshades%20img-p-500.jpg 500w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfa80c6ed7508bf44ce86e_sunshades%20img-p-800.jpg 800w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfa80c6ed7508bf44ce86e_sunshades%20img.jpg 848w" class="image-40"/></div><div class="div-block-12"><h3 class="heading-18">Sun Shades</h3><div class="div-block-6"><div class="text-block-7 related-projects">See Related Projects</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69b1148ce4791c8169422443_Vector%201.svg" alt="" class="image-34"/></div></div></a></div><div role="listitem" class="collection-item w-dyn-item"><a href="/portfolio?cat=traditional-awnings-commercial" class="link-block-12 w-inline-block"><div class="collection-img-box"><img src="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/6a02e1a5894cc41cd1547bfb_Traditional%20Awnings%20(Commercial)%20cat%20img.jpg" loading="lazy" alt="" sizes="(max-width: 767px) 100vw, (max-width: 991px) 95vw, 848px" srcset="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/6a02e1a5894cc41cd1547bfb_Traditional%20Awnings%20(Commercial)%20cat%20img-p-500.jpg 500w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/6a02e1a5894cc41cd1547bfb_Traditional%20Awnings%20(Commercial)%20cat%20img-p-800.jpg 800w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/6a02e1a5894cc41cd1547bfb_Traditional%20Awnings%20(Commercial)%20cat%20img.jpg 848w" class="image-40"/></div><div class="div-block-12"><h3 class="heading-18">Traditional Awnings (Commercial)</h3><div class="div-block-6"><div class="text-block-7 related-projects">See Related Projects</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69b1148ce4791c8169422443_Vector%201.svg" alt="" class="image-34"/></div></div></a></div><div role="listitem" class="collection-item w-dyn-item"><a href="/portfolio?cat=sail-shades" class="link-block-12 w-inline-block"><div class="collection-img-box"><img src="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69e7203f8ea4cd4374d0c7a0_Sails%20Shades.jpg" loading="lazy" alt="" sizes="(max-width: 767px) 100vw, (max-width: 991px) 95vw, 848px" srcset="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69e7203f8ea4cd4374d0c7a0_Sails%20Shades-p-500.jpg 500w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69e7203f8ea4cd4374d0c7a0_Sails%20Shades-p-800.jpg 800w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69e7203f8ea4cd4374d0c7a0_Sails%20Shades.jpg 848w" class="image-40"/></div><div class="div-block-12"><h3 class="heading-18">Sail Shades</h3><div class="div-block-6"><div class="text-block-7 related-projects">See Related Projects</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69b1148ce4791c8169422443_Vector%201.svg" alt="" class="image-34"/></div></div></a></div><div role="listitem" class="collection-item w-dyn-item"><a href="/portfolio?traditional-awnings" class="link-block-12 w-inline-block"><div class="collection-img-box"><img src="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfac8ced3be7bbd72cf1d4_Traditional%20awing%20img.jpg" loading="lazy" alt="" sizes="(max-width: 767px) 100v
283w, (max-width: 991px) 95vw, 848px" srcset="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfac8ced3be7bbd72cf1d4_Traditional%20awing%20img-p-500.jpg 500w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfac8ced3be7bbd72cf1d4_Traditional%20awing%20img-p-800.jpg 800w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cfac8ced3be7bbd72cf1d4_Traditional%20awing%20img.jpg 848w" class="image-40"/></div><div class="div-block-12"><h3 class="heading-18">Traditional Awnings</h3><div class="div-block-6"><div class="text-block-7 related-projects">See Related Projects</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69b1148ce4791c8169422443_Vector%201.svg" alt="" class="image-34"/></div></div></a></div><div role="listitem" class="collection-item w-dyn-item"><a href="/portfolio?retractable-awnings" class="link-block-12 w-inline-block"><div class="collection-img-box"><img src="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cface6025a5122e756e1a5_Retractable%20img.jpg" loading="lazy" alt="" sizes="(max-width: 767px) 100vw, (max-width: 991px) 95vw, 848px" srcset="https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cface6025a5122e756e1a5_Retractable%20img-p-500.jpg 500w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cface6025a5122e756e1a5_Retractable%20img-p-800.jpg 800w, https://cdn.prod.website-files.com/69c27323fcf6b36fe968f58a/69cface6025a5122e756e1a5_Retractable%20img.jpg 848w" class="image-40"/></div><div class="div-block-12"><h3 class="heading-18">Retractable Awnings</h3><div class="div-block-6"><div class="text-block-7 related-projects">See Related Projects</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69b1148ce4791c8169422443_Vector%201.svg" alt="" class="image-34"/></div></div></a></div></div></div></div><div class="w-layout-vflex flex-block-2 portfolio-cta"><a href="/portfolio" class="link-block-9 w-inline-block"><div class="text-block-11 explore-product">See All Portfolio</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c272ec836112f98196d1fe_See%20all%20Portfolio.svg" alt="" class="image-32"/></a></div></div></section><section class="logos-title-small blue-bg blue-marquee"><div class="marquee-wrapper"><div class="marquee-track"><div class="clients-wrapper-three"><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e06540daf399a681713_Napa%20Canvas%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e06540daf399a681713_Napa%20Canvas%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e06540daf399a681713_Napa%20Canvas%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e06540daf399a681713_Napa%20Canvas%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e06540daf399a681713_Napa%20Canvas%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/></div></div></div></section><section class="section-10"><div class="w-layout-blockcontainer container w-container"><div class="div-block-9"><div id="w-node-_2805fdaf-764c-fec1-f4b0-4e0fff2e147d-778e4cb8" class="div-block-10"><h1 class="heading-tenor-white-42">Frequently Asked Questions</h1><div class="text-block-13 text-satoshi-white-18">Clear answers to common questions about implementation, integrations, and how our solution fits your business. Still have questions? Feel free to contact our support.</div><div class="w-layout-hflex flex-block"><div class="w-layout-vflex"><a href="/contact" class="link-block-9 get-in-touch-cta w-inline-block"><div class="text-block-11 get-in-touch">Get in Touch</div><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c24a519c2a0d913bc4c45d_orange-right-icon.svg" alt="" class="get-touch-icon"/></a></div></div></div><div class="div-block-11 faq-wrapper"><div class="faq-list"><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">What types of projects do you work on?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>We design and fabricate custom awnings, shade structures, and fabric solutions for residential homes, wineries, hospital
283ity spaces, and commercial properties. Every project is made to order to suit the specific space and requirements.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">Do you work on both residential and commercial projects?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>Yes, We work with homeowners as well as commercial clients, including wineries, restaurants, retail spaces, and other businesses that need durable, professionally installed shade solutions.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">How much does a custom awning cost?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>
283Pricing varies depending on size, materials, structural requirements, and installation complexity. Once we review your space and project goals, we provide a detailed proposal tailored to your project.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">How long does a project take?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>Most projects have an average lead time of about <strong>6 weeks</strong>.<br/>The process typically includes:</p><ul role="list"><li>Consultation and measurements</li><li>Design and material selection</li><li>Fabrication</li><li>Installation</li></ul><p>We provide a more specific timeline during the consultation phase.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">What materials do you use?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>We use high-quality performance fabrics and materials designed for outdoor environments, including:<br/></p><ul role="list"><li>Sunbrella fabrics</li><li>Commercial-grade vinyl materials</li><li>Screen fabrics</li></ul><p><strong>‍</strong>These materials are selected for durability, weather resistance, and long-term outdoor performance.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">How long do your awnings last?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>Lifespan depends on the material, environmental exposure, and maintenance. With proper care, many installations last for many years. We select materials specifically for durability and long-term performance.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">What warranties do you offer?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>
283Warranty coverage varies depending on the materials used.</p><ul role="list"><li>Sunbrella fabrics include a 10-year manufacturer warranty</li><li>All stitching completed in-house carries a 10-year workmanship warranty</li></ul><p>Additional components may carry manufacturer warranties depending on the product.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">Do you offer custom logos or branding for commercial projects?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>Yes, We can incorporate logos, lettering, and branding elements into commercial awnings and fabric installations when required.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">Do you handle installation?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>Yes, Our team manages installation to ensure proper fit, safety, and long-term performance.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">How do I maintain or clean my awning?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>
283Maintenance varies depending on the fabric type. In general, periodic cleaning and basic care will extend the life of your awning.</p><p>For manufacturer-recommended cleaning methods, see: <a href="/cleaning-guide"><strong>Cleaning Guide</strong></a></p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">Can existing awnings be repaired or re-covered?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>In many cases, existing structures can be repaired or re-covered with new fabric. We can evaluate the condition of the frame and recommend the best approach.</p></div></div></div><div class="faq-item"><div class="faq-question solution-faq-question"><div class="text-block-14">What is the first step to start a project?</div><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3ddf88aeec579eab6e9d9_Chevron.svg" loading="lazy" alt="" class="faq-icon"/></div><div class="faq-answer"><div class="rich-text-block paragraph w-richtext"><p>The first step is to request an estimate and share details about your space.</p><p><a href="/contact">‍<strong>Start Here</strong></a></p><p><strong>‍</strong>We will review your project information, discuss your goals, and guide you through the next steps.</p></div></div></div></div></div></div></div></section><section><div class="w-layout-blockcontainer w-container"><div class="div-block-13"><div class="div-block-14"></div><div class="div-block-15"></div></div></div></section><section class="section-12 carfted-in-house-copy"><div class="w-layout-blockcontainer container w-container"><div class="div-block-30 craft-block"><div class="w-layout-blockcontainer container-43 col1 w-container"><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c279543cf3cde35525babd_Line%201.png" loading="lazy" alt="" class="image-49"/><h1 class="heading-22">Crafted In-House in Napa Valley</h1></div><div class="w-layout-blockcontainer container-42 col2 w-container"><div class="text-block-19 craft-text">Unlike mass-produced alternatives, our products are made to order by skilled fabricators using proven materials and construction methods.</div></div></div></div></section><section class="footer-sec"><section class="logos-title-small"><div class="marquee-wrapper"><div class="marquee-track"><div class="clients-wrapper-three"><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3982967a280eb9dd40115_Napa%20blue%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3982967a280eb9dd40115_Napa%20blue%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3982967a280eb9dd40115_Napa%20blue%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3982967a280eb9dd40115_Napa%20blue%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c3982967a280eb9dd40115_Napa%20blue%20logo.svg" loading="lazy" alt="AriseHealth logo" class="clients-image-three"/><img src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c38e611bf0e61113fc3e79_Marquee%20Icon.svg" loading="lazy" alt="OE logo" class="clients-image-three"/></div></div></div></section><div class="w-layout-blockcontainer container-1298 w-container"><div class="footer-row"><div class="footer-logo-col"><div class="footer-logo-col-box-1"><a href="https://napa-canvas-website.webflow.io" class="link-block-14 w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c2845d01fe0eadab771757_logo%20whtie%20footer.svg" alt=""/></a><div class="footer-logo-col-box-2"><div class="text-white-14">Bespoke shade solutions designed for residential estates and commercial properties, combining craftsmanship, premium materials, and lasting performance.</div><div class="footer-logo-col-box-3"><div class="social-icon-row"><a href="https://www.facebook.com/profile.php?id=61588848756028" target="_blank" class="social-icon-box w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c2880793e696dea039c7c3_facebook%20icon.svg" alt="" class="social-icon"/></a><a href="https://www.instagram.com/napacanvas/" target="_blank" class="social-icon-box w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c2888d9c267c37f24d5d63_insagram%20icon.svg" alt="" class="social-icon"/></a><a href="https://www.linkedin.com/company/napa-canvas" target="_blank" class="social-icon-box w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c288078b35dd5c81d144dd_linkedin%20icon.svg" alt="" class="social-icon"/></a></div><div class="text-gray-14">Copyright © 2026 Napa Canvas. All right reserved.</div></div></div></div></div><div class="footer-menus-col"><div class="footer-menus-row"><div class="footer-menus-column"><h3 class="orange-heading-24-tenor">Portfolio</h3><div class="footer-menu-box"><a href="/portfolio" class="footer-menu-link w-inline-block"><div class="footer-menu-text">All Projects</div></a><a href="/portfolio?sun-shades" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Sun Shades</div></a><a href="/portfolio?traditional-awnings-commercial" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Traditional Awnings (Commercial)</div></a><a href="/portfolio?cat=sail-shades" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Sail Shades</div></a><a href="/portfolio?traditional-awnings" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Traditional Awnings</div></a><a href="/portfolio?retractable-awnings" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Retractable Awnings</div></a></div></div><div class="footer-menus-column"><h3 class="orange-heading-24-tenor">Explore</h3><div class="footer-menu-box"><a href="/" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Home</div></a><a href="/solutions" aria-current="page" class="footer-menu-link w-inline-block w--current"><div class="footer-menu-text">Solutions</div></a><a href="/portfolio" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Portfolio</div></a><a href="/about" class="footer-menu-link w-inline-block"><div class="footer-menu-text">About</div></a><a href="/faq" class="footer-menu-link w-inline-block"><div class="footer-menu-text">FAQ</div></a><a href="/pricing" class="footer-menu-link w-inline-block"><div class="footer-menu-text">
283Pricing</div></a><a href="/contact" class="footer-menu-link w-inline-block"><div class="footer-menu-text">Contact</div></a></div></div><div class="footer-menus-column"><h3 class="orange-heading-24-tenor">Contact</h3><div class="footer-menu-icon-box"><div class="text-white-14">Request a Consultation</div><a href="tel:7072582903" class="footer-menu-icon-link w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c382dc3efc8e2a01e4ba86_phone%20icon.svg" alt="" class="image-41"/><div class="footer-menu-icon-text">707-258-2903</div></a><a href="mailto:[email protected]" target="_blank" class="footer-menu-icon-link w-inline-block"><img loading="lazy" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c382dc0c92a90bdb9e7717_email%20icon.svg" alt="" class="image-42"/><div class="footer-menu-icon-text">[email protected]</div></a></div></div></div><div><div class="footer-horizantal-menu-box"><a href="/terms-of-service" class="footer-menu-link w-inline-block"><div class="footer-horizantal-menu-text">Terms of Service</div></a><div class="divider-vertical"><div class="divider-vertical-inner"></div></div><a href="/privacy-policy" class="footer-horizantal-menu-text w-inline-block"><div class="footer-horizantal-menu-text">Privacy Policy</div></a></div></div></div></div></div><div class="divider"></div><div class="w-layout-blockcontainer container w-container"><img data-w-id="6137622c-4b15-8b4e-f10c-710ed8b40619" loading="lazy" alt="" src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/69c26287d2bd5067873373a2_logo%20large.svg" class="footer-logo-large"/></div></section>
283<script src="https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js?site=69ab2b3b80f48170ba7e0b8f" type="text/javascript" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
283<script src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/js/webflow.schunk.36b8fb49256177c8.js" type="text/javascript" integrity="sha384-4abIlA5/v7XaW1HMXKBgnUuhnjBYJ/Z9C1OSg4OhmVw9O3QeHJ/qJqFBERCDPv7G" crossorigin="anonymous"></script>
283<script src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/js/webflow.schunk.2c12a0068e137466.js" type="text/javascript" integrity="sha384-De7Y0vcCatHoz1HskSkcKlTN/SUvf32Nf/NTi+cASpDCqjsQNOXViYXX4h7RDIm+" crossorigin="anonymous"></script>
283<script src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/js/webflow.schunk.ba232ca75e256be3.js" type="text/javascript" integrity="sha384-t+4fkOWj47jTfCjx5I9dTEE2IaxF+elImimFk66qJvV8OEZKPaMAPXqpeyKRbCvt" crossorigin="anonymous"></script>
283<script src="https://cdn.prod.website-files.com/69ab2b3b80f48170ba7e0b8f/js/webflow.e32610a6.b5d2e649526db97f.js" type="text/javascript" integrity="sha384-pUeFEwf8c37xXyTQ39Ct8Dy4iuxCMswCOCfoCGw5BEmbIWrWhywlMokadFLZtLnG" crossorigin="anonymous"></script>
283<script src="https://cdn.prod.website-files.com/gsap/3.15.0/gsap.min.js" type="text/javascript"></script>
283<!-- 2. Paste this code immediately after the opening <body> tag: -->
284<!-- Google Tag Manager (noscript) -->
vendor: 68 bytes, lines 284-285
284
285<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
285GTM-NTQ5SPMC
vendor: 83 bytes, lines 285-286
285"
286height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
287<!-- End Google Tag Manager (noscript) -->
288
289<script>
290document.addEventListener("DOMContentLoaded", function () {
291
292  // CENTRAL STATE
293  const state = {
294    productType: { price: 0, label: "" },
295    productMaterial: { price: 0, label: "" },
296    productSize: { price: 0, label: "" }
297  };
298
299  // TOTAL + UI UPDATE
300  function updateTotal() {
301    const total =
302      state.productType.price +
303      state.productMaterial.price +
304      state.productSize.price;
305
306    console.log("Total:", total);
307
308    // TOTAL UI
309    const totalEl = document.querySelector(".product-total-price");
310    if (totalEl) {
311      totalEl.textContent = total;
312    }
313
314    // TYPE UI (only update if selected)
315    const typeEl = document.querySelector(".product-result-type");
316    if (typeEl && state.productType.label) {
317      typeEl.textContent = state.productType.label;
318    }
319
320    // MATERIAL UI
321    const materialEl = document.querySelector(".product-result-material");
322    if (materialEl && state.productMaterial.label) {
323      materialEl.textContent = state.productMaterial.label;
324    }
325
326    // SIZE UI
327    const sizeEl = document.querySelector(".product-result-size");
328    if (sizeEl && state.productSize.label) {
329      sizeEl.textContent = state.productSize.label;
330    }
331  }
332
333  // GET CORRECT LABEL (Webflow-safe)
334  function getLabel(input) {
335    return (
336      input.closest("label") ||
337      document.querySelector(`label[for="${input.id}"]`)
338    );
339  }
340
341  // GENERIC HANDLER
342  function handleRadioChange(selector, stateKey) {
343
344    const inputs = document.querySelectorAll(selector + " input[type='radio']");
345
346    inputs.forEach(input => {
347
348      input.addEventListener("change", function () {
349
350        const label = getLabel(input);
351        if (!label) return;
352
353        // PRICE
354        const priceEl = label.querySelector(".canvas-price");
355        const price = priceEl
356          ? parseFloat(priceEl.textContent.replace(/[^\d.]/g, "")) || 0
357          : 0;
358
359        // LABEL TEXT
360        const labelEl = label.querySelector(".radio-lablel-backend");
361        const labelValue = labelEl
362          ? labelEl.textContent.trim()
363          : "";
364
365        // UPDATE STATE
366        state[stateKey].price = price;
367        state[stateKey].label = labelValue;
368
369        console.log(stateKey + ":", state[stateKey]);
370        console.log("Full State:", state);
371
372        // UPDATE TOTAL + UI
373        updateTotal();
374
375      });
376
377    });
378  }
379
380  // INITIALIZE ALL GROUPS
381  handleRadioChange(
382    ".calculator-form .form-radio-product-row label.product-type",
383    "productType"
384  );
385
386  handleRadioChange(
387    ".calculator-form .form-radio-product-row label.product-material",
388    "productMaterial"
389  );
390
391  handleRadioChange(
392    ".calculator-form .form-radio-product-row label.product-size",
393    "productSize"
394  );
395
396  // INITIAL LOAD (only total, labels won't overwrite default HTML)
397  updateTotal();
398
399});
400</script>
vendor: 1 bytes, line 400
400
401<script>
402window.addEventListener("load", () => {
403
404  const tracks = document.querySelectorAll('.marquee-track');
405
406  tracks.forEach(track => {
407
408    const content = track.innerHTML;
409
410    // duplicate until enough width
411    while (track.scrollWidth < window.innerWidth * 2) {
412      track.innerHTML += content;
413    }
414
415    const singleWidth = track.scrollWidth / 2; // 🔥 important fix
416
417    let position = 0;
418
419    function animate() {
420      position -= 0.5;
421
422      track.style.transform = `translateX(${position}px)`;
423
424      // 🔥 FIXED RESET (no gap / no mismatch)
425      if (Math.abs(position) >= singleWidth) {
426        position = 0;
427      }
428
429      requestAnimationFrame(animate);
430    }
431
432    animate();
433
434  });
435
436});
437</script>
vendor: 1 bytes, line 437
437
438<script>
439document.querySelectorAll('.faq-question').forEach((question) => {
440  question.addEventListener('click', () => {
441    const item = question.closest('.faq-item');
442    const answer = item.querySelector('.faq-answer');
443    const icon = item.querySelector('.faq-icon');
444
445    // close others
446    document.querySelectorAll('.faq-item').forEach((i) => {
447      if (i !== item) {
448        i.classList.remove('active');
449        i.querySelector('.faq-answer').style.height = "0px";
450        const otherIcon = i.querySelector('.faq-icon');
451        if (otherIcon) otherIcon.style.transform = "rotate(0deg)";
452      }
453    });
454
455    // toggle current
456    if (item.classList.contains('active')) {
457      item.classList.remove('active');
458      answer.style.height = "0px";
459      icon.style.transform = "rotate(0deg)";
460    } else {
461      item.classList.add('active');
462      answer.style.height = answer.scrollHeight + "px";
463      icon.style.transform = "rotate(180deg)";
464    }
465  });
466});
467
468
469// ✅ OPEN FIRST FAQ ON LOAD
470window.addEventListener('load', () => {
471  const firstItem = document.querySelector('.faq-item');
472  if (firstItem) {
473    const answer = firstItem.querySelector('.faq-answer');
474    const icon = firstItem.querySelector('.faq-icon');
475
476    firstItem.classList.add('active');
477    answer.style.height = answer.scrollHeight + "px";
478    if (icon) icon.style.transform = "rotate(180deg)";
479  }
480});
481
482
483
484  
485// horizantal scrolling section fixation start
486document.addEventListener("DOMContentLoaded", () => {
487  const track = document.querySelector(".horizantal-scroll-track");
488  const section = track.closest("section");
489
490  let maxTranslate = 0;
491  let sectionTop = 0;
492  let scrollDistance = 0;
493  let isActive = false;
494
495  const BREAKPOINT = 990;
496
497  function calculate() {
498    const viewportWidth = window.innerWidth;
499    const viewportHeight = window.innerHeight;
500
501    // base horizontal distance
502    maxTranslate = track.scrollWidth - viewportWidth;
503
504    // gap
505    const styles = window.getComputedStyle(track);
506    const gap = parseFloat(styles.columnGap) || 0;
507
508    // container offset
509    const trackRect = track.getBoundingClientRect();
510    const offsetLeft = trackRect.left;
511
512    maxTranslate = maxTranslate + gap + offsetLeft;
513
514    // section position
515    const rect = section.getBoundingClientRect();
516    sectionTop = window.scrollY + rect.top;
517
518    // same speed logic
519    scrollDistance = maxTranslate * 1.2;
520
521    section.style.height = `${scrollDistance + viewportHeight}px`;
522  }
523
524  function update() {
525    const scrollY = window.scrollY;
526
527    let progress = (scrollY - sectionTop) / scrollDistance;
528    progress = Math.max(0, Math.min(1, progress));
529
530    const translateX = -maxTranslate * progress;
531    track.style.transform = `translate3d(${translateX}px, 0, 0)`;
532  }
533
534  function enable() {
535    if (isActive) return;
536    isActive = true;
537
538    calculate();
539    update();
540
541    window.addEventListener("scroll", onScroll);
542  }
543
544  function disable() {
545    if (!isActive) return;
546    isActive = false;
547
548    window.removeEventListener("scroll", onScroll);
549
550    // ✅ reset styles (VERY IMPORTANT)
551    track.style.transform = "none";
552    section.style.height = "auto";
553  }
554
555  let ticking = false;
556
557  function onScroll() {
558    if (!ticking) {
559      requestAnimationFrame(() => {
560        update();
561        ticking = false;
562      });
563      ticking = true;
564    }
565  }
566
567  function handleResize() {
568    if (window.innerWidth >= BREAKPOINT) {
569      enable();
570      calculate();
571      update();
572    } else {
573      disable();
574    }
575  }
576
577  // init
578  handleResize();
579
580  window.addEventListener("resize", handleResize);
581  
582  // ✅ FIX: Force re-calculation after fonts/images load to ensure sticky works first time
583  window.addEventListener("load", function() {
584    if (window.innerWidth >= BREAKPOINT) {
585      calculate();
586      update();
587    }
588  });
589});
590// horizantal scrolling section fixation end
591
592
593
594// Portfolio Tab Filter ---------------------------------------------------------------------------------------------------------
595// Portfolio Tab Filter active on page load and on click
596let categoryMatched = false;
597let activeCategory = null;
598let currentPageNumber = 1;
599let pageRestoreAttempts = 0;
600let categoryRestored = false;
601
602window.addEventListener("load", function () {
603  initCategoryFilter();
604  initRadioUI();
605  restoreFromURL();
606  
607  // Auto double-click on All Project if it has is-list-active class
608  setTimeout(function() {
609    autoTriggerAllProjectIfActive();
610  }, 500);
611});
612
613function autoTriggerAllProjectIfActive() {
614  const clearAllButton = document.querySelector(".clear-all-filter.w-radio.is-list-active");
615  
616  if (clearAllButton) {
617    const label = clearAllButton.querySelector(".w-form-label");
618    if (label && label.textContent.trim() === "All Project") {
619      console.log("Auto-triggering All Project filter");
620      
621      // First click
622      clearAllButton.click();
623      
624      // Double click with small delay
625      setTimeout(() => {
626        clearAllButton.click();
627        console.log("Double click triggered on All Project");
628        
629        // Force Finsweet filter refresh after double click
630        setTimeout(() => {
631          triggerFinsweetFilterRefresh();
632        }, 100);
633      }, 150);
634    }
635  }
636}
637
638function initCategoryFilter() {
639  // Check URL query parameters first
640  const urlParams = new URLSearchParams(window.location.search);
641  let categoryFromURL = null;
642  
643  // Check for 'cat' parameter first
644  if (urlParams.has('cat')) {
645    categoryFromURL = urlParams.get('cat');
646  } else {
647    // Check for old format (direct parameter like ?sun-shades)
648    for (let [key, value] of urlParams.entries()) {
649      if (key !== 'page' && !value) {
650        categoryFromURL = key;
651        break;
652      }
653    }
654  }
655  
656  if (categoryFromURL) {
657    // URL parameter takes precedence
658    const categoryText = paramToCategoryText(categoryFromURL);
659    if (categoryText) {
660      categoryRestored = true;
661      setTimeout(() => {
662        activateCategoryByText(categoryText);
663      }, 200);
664      return;
665    }
666  }
667  
668  // No category in URL, activate All Project after a short delay
669  setTimeout(() => {
670    const clearAll = document.querySelector(".clear-all-filter.w-radio");
671    if (clearAll && !clearAll.classList.contains('is-list-active')) {
672      clearAll.click();
673      saveActiveCategory('All Project');
674    }
675  }, 300);
676}
677
678function initRadioUI() {
679  const radios = document.querySelectorAll(".w-radio");
680  const clearAll = document.querySelector(".clear-all-filter.w-radio");
681
682  // UI active state sync
683  radios.forEach((radio) => {
684    const input = radio.querySelector("input[type='radio']");
685    if (!input) return;
686
687    input.addEventListener("change", () => {
688      radios.forEach(r => r.classList.remove("is-list-active"));
689
690      if (input.checked) {
691        radio.classList.add("is-list-active");
692        const categoryText = getCategoryText(radio);
693        saveActiveCategory(categoryText);
694        activeCategory = categoryText;
695        
696        // Reset to page 1 when changing category
697        currentPageNumber = 1;
698        
699        // Update URL based on selected category (except for All Project)
700        updateFullURL(categoryText, 1);
701      }
702    });
703  });
704
705  // Clear-all click fix (single-click UI sync)
706  if (clearAll) {
707    clearAll.addEventListener("click", () => {
708      const input = clearAll.querySelector("input[type='radio']");
709
710      radios.forEach(r => r.classList.remove("is-list-active"));
711
712      clearAll.classList.add("is-list-active");
713      
714      // Save Clear All as active category
715      saveActiveCategory('All Project');
716      activeCategory = 'All Project';
717      
718      // Reset to page 1
719      currentPageNumber = 1;
720      
721      // Update URL to base portfolio page (remove all query params)
722      updateFullURL(null, 1);
723
724      if (input && !input.checked) {
725        input.checked = true;
726        input.dispatchEvent(new Event("change", { bubbles: true }));
727      }
728      
729      // Force trigger Finsweet filter refresh for Clear All
730      setTimeout(() => {
731        triggerFinsweetFilterRefresh();
732      }, 100);
733    });
734  }
735  
736  // Setup pagination click handlers after a delay (wait for Finsweet)
737  setTimeout(() => {
738    setupPaginationHandlers();
739  }, 1000);
740}
741
742// Setup pagination click handlers
743function setupPaginationHandlers() {
744  // Function to handle pagination clicks
745  function handlePaginationClick(e) {
746    // Get the current active page after click
747    setTimeout(() => {
748      const activePage = document.querySelector('.page-number.w--current');
749      if (activePage) {
750        currentPageNumber = parseInt(activePage.textContent);
751        const currentCategory = getCurrentCategory();
752        updateFullURL(currentCategory, currentPageNumber);
753        console.log('Page updated to:', currentPageNumber);
754      }
755    }, 200);
756  }
757  
758  // Watch for clicks on page buttons
759  const pageButtons = document.querySelectorAll('[fs-list-element="page-button"]');
760  pageButtons.forEach(button => {
761    button.removeEventListener('click', handlePaginationClick);
762    button.addEventListener('click', handlePaginationClick);
763  });
764  
765  // Watch for clicks on next/prev buttons
766  const nextButton = document.querySelector('.pagination-next');
767  const prevButton = document.querySelector('.pagination-previous');
768  
769  if (nextButton) {
770    nextButton.removeEventListener('click', handlePaginationClick);
771    nextButton.addEventListener('click', handlePaginationClick);
772  }
773  
774  if (prevButton) {
775    prevButton.removeEventListener('click', handlePaginationClick);
776    prevButton.addEventListener('click', handlePaginationClick);
777  }
778}
779
780// Get current active category
781function getCurrentCategory() {
782  const activeRadio = document.querySelector('.w-radio.is-list-active');
783  if (activeRadio) {
784    const label = activeRadio.querySelector('.w-form-label');
785    if (label && label.textContent.trim() !== 'All Project') {
786      return label.textContent.trim();
787    }
788  }
789  return null; // All Project
790}
791
792// Update full URL with both category and page - IMPROVED VERSION
793function updateFullURL(categoryText, pageNumber) {
794  const baseUrl = window.location.origin + window.location.pathname;
795  const params = new URLSearchParams();
796  
797  // Add category parameter if not All Project
798  if (categoryText && categoryText !== 'All Project') {
799    const param = categoryToParam(categoryText);
800    params.set('cat', param);
801  }
802  
803  // Add page parameter if greater than 1
804  if (pageNumber && pageNumber > 1) {
805    params.set('page', pageNumber);
806  }
807  
808  // Build new URL
809  let newUrl = baseUrl;
810  const paramString = params.toString();
811  if (paramString) {
812    newUrl = baseUrl + '?' + paramString;
813  }
814  
815  // Only update if URL has changed
816  if (window.location.href !== newUrl) {
817    // Check if we're just normalizing the URL format
818    const currentParams = new URLSearchParams(window.location.search);
819    const hasOldFormat = Array.from(currentParams.keys()).some(key => key !== 'page' && key !== 'cat' && currentParams.get(key) === '');
820    
821    if (hasOldFormat && params.has('cat')) {
822      // If we're converting from old format to new format, use replaceState
823      window.history.replaceState({ category: categoryText, page: pageNumber }, "", newUrl);
824    } else {
825      // Normal navigation - use pushState
826      window.history.pushState({ category: categoryText, page: pageNumber }, "", newUrl);
827    }
828    console.log('URL updated to:', newUrl);
829  }
830}
831
832// Restore from URL on page load - IMPROVED VERSION
833function restoreFromURL() {
834  const urlParams = new URLSearchParams(window.location.search);
835  
836  // Check and normalize URL format
837  let needsNormalization = false;
838  let oldFormatCategory = null;
839  
840  // Check for old format (direct parameter without 'cat')
841  for (let [key, value] of urlParams.entries()) {
842    if (key !== 'page' && key !== 'cat' && !value) {
843      oldFormatCategory = key;
844      needsNormalization = true;
845      break;
846    }
847  }
848  
849  // If old format detected, update to new format without page reload
850  if (needsNormalization && oldFormatCategory) {
851    const normalizedCategory = oldFormatCategory.replace(/-/g, ' ');
852    const param = categoryToParam(normalizedCategory);
853    const newUrl = window.location.origin + window.location.pathname + '?cat=' + param;
854    // Use replaceState to fix the URL without reload
855    window.history.replaceState({ category: normalizedCategory, page: 1 }, "", newUrl);
856    console.log('Normalized URL from old format to:', newUrl);
857  }
858  
859  // Get category from URL
860  let categoryFromURL = null;
861  if (urlParams.has('cat')) {
862    categoryFromURL = urlParams.get('cat');
863  } else {
864    // Check for old format
865    for (let [key, value] of urlParams.entries()) {
866      if (key !== 'page' && !value) {
867        categoryFromURL = key;
868        break;
869      }
870    }
871  }
872  
873  // Get page from URL
874  const pageFromURL = urlParams.get('page');
875  let targetPage = 1;
876  if (pageFromURL && !isNaN(parseInt(pageFromURL))) {
877    targetPage = parseInt(pageFromURL);
878    currentPageNumber = targetPage;
879    console.log('Target page from URL:', targetPage);
880  }
881  
882  // Restore category first, then page
883  if (categoryFromURL) {
884    const categoryText = paramToCategoryText(categoryFromURL);
885    if (categoryText) {
886      setTimeout(() => {
887        activateCategoryByText(categoryText);
888        // Wait for category filter to apply, then restore page
889        waitForPaginationAndRestorePage(targetPage);
890      }, 300);
891      return;
892    }
893  }
894  
895  // No category, restore page for All Project
896  if (targetPage > 1) {
897    waitForPaginationAndRestorePage(targetPage);
898  }
899}
900
901// Wait for pagination to be ready before restoring page
902function waitForPaginationAndRestorePage(targetPage, attempt = 0) {
903  if (attempt > 20) {
904    console.log('Max attempts reached, could not restore page');
905    return;
906  }
907  
908  const paginationWrapper = document.querySelector('[fs-list-element="pagination-wrapper"]');
909  const pageButtons = document.querySelectorAll('[fs-list-element="page-button"]');
910  
911  if (paginationWrapper && pageButtons.length > 0) {
912    console.log('Pagination found, restoring page:', targetPage);
913    setTimeout(() => {
914      restorePageNumber(targetPage);
915    }, 500);
916  } else {
917    console.log('Waiting for pagination... attempt:', attempt + 1);
918    setTimeout(() => {
919      waitForPaginationAndRestorePage(targetPage, attempt + 1);
920    }, 300);
921  }
922}
923
924// Restore page number
925function restorePageNumber(targetPage) {
926  if (!targetPage || targetPage === 1) {
927    console.log('No need to restore, page 1 is default');
928    return;
929  }
930  
931  console.log('Attempting to restore to page:', targetPage);
932  
933  // Try multiple times with increasing delays
934  let restoreAttempt = 0;
935  
936  function attemptRestore() {
937    restoreAttempt++;
938    
939    // Find the target page button
940    const pageButtons = document.querySelectorAll('[fs-list-element="page-button"]');
941    let targetButton = null;
942    
943    for (let button of pageButtons) {
944      const pageNum = parseInt(button.textContent);
945      if (pageNum === targetPage) {
946        targetButton = button;
947        break;
948      }
949    }
950    
951    if (targetButton && !targetButton.classList.contains('w--current')) {
952      targetButton.click();
953      console.log('Restored to page:', targetPage);
954      return true;
955    } else if (targetButton && targetButton.classList.contains('w--current')) {
956      console.log('Already on correct page:', targetPage);
957      return true;
958    } else if (restoreAttempt < 5) {
959      // Try again with longer delay
960      console.log('Retry restore attempt:', restoreAttempt);
961      setTimeout(attemptRestore, 500);
962      return false;
963    } else {
964      console.log('Could not restore page after multiple attempts');
965      return false;
966    }
967  }
968  
969  // Start restore attempts with initial delay
970  setTimeout(attemptRestore, 300);
971}
972
973// Helper function to get category text from radio element
974function getCategoryText(radio) {
975  const label = radio.querySelector(".w-form-label");
976  if (label) {
977    return label.textContent.trim();
978  }
979  return null;
980}
981
982// Save active category to sessionStorage (backup)
983function saveActiveCategory(categoryText) {
984  if (categoryText) {
985    sessionStorage.setItem('activePortfolioCategory', categoryText);
986    sessionStorage.setItem('activePortfolioCategoryTimestamp', Date.now());
987  }
988}
989
990// Convert category text to URL parameter
991function categoryToParam(categoryText) {
992  return categoryText
993    .toLowerCase()
994    .replace(/[()]/g, "") // remove brackets
995    .replace(/&/g, "and") // replace & with 'and'
996    .replace(/\s+/g, "-") // replace spaces with hyphens
997    .replace(/[^a-z0-9-]/g, ""); // remove special characters
998}
999
1000// Convert URL parameter back to category text
1001function paramToCategoryText(param) {
1002  const radios = document.querySelectorAll(".w-radio");
1003  
1004  // Decode the parameter (replace hyphens with spaces)
1005  const decodedParam = param.replace(/-/g, " ");
1006  
1007  // First try exact match (case insensitive)
1008  for (let radio of radios) {
1009    const label = radio.querySelector(".w-form-label");
1010    if (label) {
1011      const labelText = label.textContent.trim();
1012      if (labelText.toLowerCase() === decodedParam.toLowerCase()) {
1013        return labelText;
1014      }
1015    }
1016  }
1017  
1018  // Then try slug match
1019  for (let radio of radios) {
1020    const label = radio.querySelector(".w-form-label");
1021    if (label) {
1022      const labelText = label.textContent.trim();
1023      const labelParam = categoryToParam(labelText);
1024      if (labelParam === param) {
1025        return labelText;
1026      }
1027    }
1028  }
1029  
1030  return null;
1031}
1032
1033// Handle browser back/forward buttons - FIXED VERSION
1034window.addEventListener("popstate", function(event) {
1035  // Don't reload the page - let the browser handle navigation naturally
1036  
1037  if (event.state) {
1038    // If we have state data, use it to restore category and page
1039    const category = event.state.category;
1040    const page = event.state.page || 1;
1041    
1042    if (category && category !== 'All Project') {
1043      setTimeout(() => {
1044        activateCategoryByText(category);
1045        if (page > 1) {
1046          waitForPaginationAndRestorePage(page);
1047        } else {
1048          currentPageNumber = 1;
1049        }
1050      }, 100);
1051    } else {
1052      // Activate All Project
1053      const clearAll = document.querySelector(".clear-all-filter.w-radio");
1054      if (clearAll && !clearAll.classList.contains('is-list-active')) {
1055        clearAll.click();
1056        if (page > 1) {
1057          waitForPaginationAndRestorePage(page);
1058        }
1059      }
1060    }
1061  } else {
1062    // No state available, check URL parameters
1063    const urlParams = new URLSearchParams(window.location.search);
1064    let categoryFromURL = null;
1065    
1066    if (urlParams.has('cat')) {
1067      categoryFromURL = urlParams.get('cat');
1068    } else {
1069      for (let [key, value] of urlParams.entries()) {
1070        if (key !== 'page' && !value) {
1071          categoryFromURL = key;
1072          break;
1073        }
1074      }
1075    }
1076    
1077    if (categoryFromURL) {
1078      const categoryText = paramToCategoryText(categoryFromURL);
1079      if (categoryText) {
1080        setTimeout(() => {
1081          activateCategoryByText(categoryText);
1082        }, 100);
1083      }
1084    } else {
1085      // No category in URL, activate All Project
1086      setTimeout(() => {
1087        const clearAll = document.querySelector(".clear-all-filter.w-radio");
1088        if (clearAll && !clearAll.classList.contains('is-list-active')) {
1089          clearAll.click();
1090        }
1091      }, 100);
1092    }
1093  }
1094});
1095
1096// Force trigger Finsweet filter refresh
1097function triggerFinsweetFilterRefresh() {
1098  const filterInputs = document.querySelectorAll('[fs-cmsfilter-element="filter"] input, [fs-cmsfilter-element="filter"] select');
1099  
1100  if (filterInputs.length > 0) {
1101    filterInputs.forEach(input => {
1102      input.dispatchEvent(new Event('change', { bubbles: true }));
1103      input.dispatchEvent(new Event('input', { bubbles: true }));
1104    });
1105  }
1106  
1107  const filterForm = document.querySelector('[fs-cmsfilter-element="filters"]');
1108  if (filterForm) {
1109    filterForm.dispatchEvent(new Event('change', { bubbles: true }));
1110  }
1111}
1112
1113// Activate category by its text label
1114function activateCategoryByText(categoryText) {
1115  const radios = document.querySelectorAll(".w-radio");
1116  let found = false;
1117  
1118  for (let radio of radios) {
1119    const label = radio.querySelector(".w-form-label");
1120    if (label && label.textContent.trim() === categoryText) {
1121      const input = radio.querySelector("input[type='radio']");
1122      if (input && !input.checked) {
1123        found = true;
1124        setTimeout(() => {
1125          radio.click();
1126        }, 100);
1127        break;
1128      } else if (input && input.checked) {
1129        found = true;
1130        radios.forEach(r => r.classList.remove("is-list-active"));
1131        radio.classList.add("is-list-active");
1132        break;
1133      }
1134    }
1135  }
1136  
1137  return found;
1138}
1139// Category tabs and pagination state back from detail page should be active end ---------------------------------------------------------------
1140</script>
1140
1141
1142
1143<script>
1144const fixImages = () => {
1145  document.querySelectorAll(
1146    ".detail-images-sec img, .portfolio-listing-sec img"
1147  ).forEach(img => {
1148    if (img.srcset) {
1149      img.removeAttribute("srcset");
1150      img.removeAttribute("sizes");
1151    }
1152  });
1153};
1154
1155window.addEventListener("load", fixImages);
1156
1157// CMS / dynamic content ke liye
1158const observer = new MutationObserver(fixImages);
1159observer.observe(document.body, { childList: true, subtree: true });
1160
1161  
1162</script>
1162
1163
1164<script>
1165// PDF file download on pricing page - Multiple PDFs support start
1166// document.addEventListener("DOMContentLoaded", function() {
1167//     const links = document.querySelectorAll('.see-pricing'); // Sabhi elements select honge
1168    
1169//     links.forEach(link => {
1170//         link.addEventListener('click', function(e) {
1171//             e.preventDefault(); // Default behavior rokein
1172//             const pdfUrl = this.getAttribute('href');
1173            
1174//             // Extract filename from URL
1175//             const fileName = pdfUrl.split('/').pop();
1176            
1177//             // 1. PDF download karein
1178//             fetch(pdfUrl)
1179//                 .then(response => response.blob())
1180//                 .then(blob => {
1181//                     const blobUrl = window.URL.createObjectURL(blob);
1182//                     const downloadLink = document.createElement('a');
1183//                     downloadLink.href = blobUrl;
1184//                     downloadLink.download = fileName; // Dynamic filename
1185//                     document.body.appendChild(downloadLink);
1186//                     downloadLink.click();
1187//                     document.body.removeChild(downloadLink);
1188//                     window.URL.revokeObjectURL(blobUrl);
1189//                 })
1190//                 .catch(error => console.error('Download failed:', error));
1191            
1192//             // 2. New tab mein bhi open karein
1193//             // window.open(pdfUrl, '_blank');
1194//             window.open(pdfUrl, '_blank');
1195//         });
1196//     });
1197// });
1198
1199// document.addEventListener("DOMContentLoaded", function() {
1200//     const links = document.querySelectorAll('.see-pricing');
1201    
1202//     links.forEach(link => {
1203//         link.addEventListener('click', function(e) {
1204//             e.preventDefault();
1205//             const pdfUrl = this.getAttribute('href');
1206
1207//             // Download (optional)
1208//             fetch(pdfUrl)
1209//                 .then(response => response.blob())
1210//                 .then(blob => {
1211//                     const blobUrl = window.URL.createObjectURL(blob);
1212//                     const downloadLink = document.createElement('a');
1213//                     downloadLink.href = blobUrl;
1214//                     downloadLink.download = pdfUrl.split('/').pop();
1215//                     document.body.appendChild(downloadLink);
1216//                     downloadLink.click();
1217//                     document.body.removeChild(downloadLink);
1218//                     window.URL.revokeObjectURL(blobUrl);
1219//                 })
1220//                 .catch(error => console.error('Download failed:', error));
1221
1222//             // Open in SAME TAB
1223//             window.location.href = pdfUrl;
1224//         });
1225//     });
1226// });
1227
1228document.addEventListener("DOMContentLoaded", function () {
1229    const links = document.querySelectorAll('.see-pricing');
1230    const modal = document.getElementById('pdf-modal');
1231    const iframe = document.getElementById('pdf-frame');
1232    const closeBtn = document.querySelector('.pdf-close');
1233    const overlay = document.querySelector('.pdf-modal-overlay');
1234
1235    function isMobile() {
1236        return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
1237    }
1238
1239    links.forEach(link => {
1240        link.addEventListener('click', function (e) {
1241            e.preventDefault();
1242            
1243            const pdfUrl = this.getAttribute('href');
1244
1245            // For mobile/tablet - open directly in new tab/window
1246            if (isMobile()) {
1247                window.open(pdfUrl, '_blank');
1248            } else {
1249                // Desktop - show in modal
1250                iframe.src = pdfUrl;
1251                modal.classList.add('active');
1252            }
1253        });
1254    });
1255
1256    function closeModal() {
1257        modal.classList.remove('active');
1258        iframe.src = ""; // stop loading
1259    }
1260
1261    if (closeBtn) closeBtn.addEventListener('click', closeModal);
1262    if (overlay) overlay.addEventListener('click', closeModal);
1263});
1264// PDF file download on pricing page - Multiple PDFs support end
1265</script>
1265
1266
1267<!-- clicking on pagination redirect move to tabs section start-->
1268<script>
1269document.addEventListener("DOMContentLoaded", function () {
1270  const paginationWrapper = document.querySelector('.w-pagination-wrapper.pagination-row');
1271  const targetSection = document.querySelector('#tab-filters');
1272
1273  if (paginationWrapper && targetSection) {
1274    paginationWrapper.addEventListener('click', function () {
1275      targetSection.scrollIntoView({
1276        behavior: 'smooth',
1277        block: 'start'
1278      });
1279    });
1280  }
1281});
1282</script>
1282
1283<!-- clicking on pagination redirect move to tabs section end-->
1284
1285<!-- make portiflio active header menu once category page open start -->
1286<script>
1287document.addEventListener("DOMContentLoaded", function () {
1288  if (window.location.pathname.startsWith('/category')) {
1289
1290    setTimeout(() => {
1291      const portfolioLink = document.querySelector(
1292        '.header-menu-inline a.nav-link[href="/portfolio"]'
1293      );
1294
1295      if (portfolioLink) {
1296        portfolioLink.classList.add('w--current');
1297      }
1298    }, 300); // adjust 200–500ms if needed
1299  }
1300});
1301</script>
1301
1302<!-- make portiflio active header menu once category page open end -->
1303
1304
1305<script>
1306(function() {
1307  function hideMatches() {
1308    console.log("Hiding matches..."); // Optional: for debugging
1309    document.querySelectorAll(".collection-item").forEach(function(item) {
1310      var project = item.querySelector(".listing-project-name");
1311      var category = item.querySelector(".related-projects");
1312      if (project && category) {
1313        if (project.innerText.trim().toLowerCase() === category.innerText.trim().toLowerCase()) {
1314          category.style.display = "none";
1315        } else {
1316          // Ensure items that don't match remain visible (important for when DOM changes)
1317          category.style.display = "";
1318        }
1319      }
1320    });
1321  }
1322  
1323  // Run immediately
1324  hideMatches();
1325  
1326  // Wait for full page load
1327  window.addEventListener("load", hideMatches);
1328  
1329  // Handle clicks (existing functionality)
1330  document.addEventListener("click", function() {
1331    setTimeout(hideMatches, 50);
1332  });
1333  
1334  // CRITICAL: Handle back/forward navigation (pageshow event)
1335  window.addEventListener("pageshow", function(event) {
1336    // pageshot fires on back/forward navigation
1337    // persisted is true when page is loaded from cache
1338    if (event.persisted) {
1339      hideMatches();
1340    }
1341    setTimeout(hideMatches, 100); // Extra delay for safety
1342  });
1343  
1344  // For Webflow's native navigation
1345  if (typeof Webflow !== "undefined") {
1346    Webflow.push(hideMatches);
1347    
1348    // Also listen for Webflow page transitions
1349    $(document).on('wf-page-ready', function() {
1350      setTimeout(hideMatches, 100);
1351    });
1352  }
1353  
1354  // Use MutationObserver as a backup (detects DOM changes)
1355  if (typeof MutationObserver !== "undefined") {
1356    var observer = new MutationObserver(function(mutations) {
1357      // Only run if we see significant DOM changes
1358      var shouldRun = mutations.some(function(mutation) {
1359        return mutation.target.matches && 
1360               (mutation.target.matches('.collection-item, .collection-list') ||
1361                mutation.target.querySelector && mutation.target.querySelector('.collection-item'));
1362      });
1363      
1364      if (shouldRun) {
1365        setTimeout(hideMatches, 50);
1366      }
1367    });
1368    
1369    // Start observing when DOM is ready
1370    document.addEventListener("DOMContentLoaded", function() {
1371      observer.observe(document.body, {
1372        childList: true,
1373        subtree: true
1374      });
1375    });
1376  }
1377})();
1378</script>
1378</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.