PageSourceSearch

https://pinakkaa.com/services-pages/service-detail.js

js pinakkaa.com collected 2026-09-28 05:54:50 UTC 49,026 bytes, 987 lines download raw bytes

1// Service Detail Page Handler
2document.addEventListener('DOMContentLoaded', function() {
3    // Query (?service=) or clean SEO path (see seo-service-urls.js + .htaccess)
4    const serviceId = typeof serviceIdFromUrl === 'function'
5        ? serviceIdFromUrl()
6        : new URLSearchParams(window.location.search).get('service');
7    
8    if (!serviceId) {
9        // Redirect to services page if no service ID
10        window.location.href = 'services.html';
11        return;
12    }
13    
14    // Check if servicesData is available
15    if (typeof servicesData === 'undefined') {
16        console.error('servicesData is not defined. Make sure services-pages.js is loaded before service-detail.js');
17        return;
18    }
19    
20    // Find service data
21    const service = servicesData.find(s => s.id === serviceId);
22    
23    if (!service) {
24        console.error('Service not found:', serviceId);
25        // Redirect if service not found
26        window.location.href = 'services.html';
27        return;
28    }
29    
30    console.log('Service found:', service.title);
31    console.log('Features:', service.features);
32    console.log('Benefits:', service.benefits);
33    console.log('FAQs:', service.faqs);
34    
35    // SEO metadata for each service detail page
36    const serviceSeoMeta = {
37        'website-designing': {
38            title: 'Website Design and Development company in Bangalore | Pinakkaa',
39            description: 'Pinakkaa is a trusted website design and Development agency in Bangalore delivering creative, user-friendly websites that help businesses grow online. Let\'s build your digital success.'
40        },
41        'seo-digital-marketing': {
42            title: 'Best SEO Agency in Bangalore | SEO Company in Bangalore - Pinakkaa',
43            description: 'Pinakkaa is a Result oriented SEO company in Bangalore delivering real results. Improve SERP rankings, boost traffic, and grow your business with our expert team.'
44        },
45        'online-reputation-management': {
46            title: 'ORM Services in Bangalore | Online Reputation Management Company - Pinakkaa',
47            description: 'Protect your brand with Pinakkaa\'s Expert ORM services in Bangalore. We remove negative results, improve ratings, build trust, and help your business stand out with a strong online reputation.'
48        },
49        'social-media-optimization': {
50            title: 'SMO Company in Bangalore | Social Media Optimization Agency - Pinakkaa',
51            description: 'Pinakkaa is a trusted SMO company in Bangalore helping businesses increase reach, engagement, and leads through powerful social media strategies.'
52        },
53        'search-engine-marketing': {
54            title: 'SEM Services in Bangalore | Search Engine Marketing Agency - Pinakkaa',
55            description: 'Pinakkaa, a reliable search engine marketing company in Bangalore, offers performance-driven SEM services in Bangalore to generate leads, increase sales, and deliver strong ROI as a leading SEM agency.'
56        },
57        'social-media-marketing': {
58            title: 'Social Media Marketing agency in Bangalore | SMM Company in Bangalore | Pinakkaa',
59            description: 'As a trusted Social Media Marketing agency in Bangalore, Pinakkaa stands out as a reliable SMM company in Bangalore delivering measurable growth through effective social media campaigns.'
60        },
61        'branding-rebranding': {
62            title: 'Branding Agency in Bangalore | Pinakkaa Brand Identity Creators',
63            description: 'Why choose Pinakkaa? We go beyond visuals to build brands that stand out. Our branding and rebranding services in Bangalore focus on strategy, identity, and growth.'
64        },
65        'display-advertising': {
66            title: 'Best display advertising agency in Bangalore | Pinakkaa',
67            description: 'Pinakkaa offers display advertising services in Bangalore designed to reach the right audience, improve brand visibility, and generate higher engagement and measurable returns.'
68        },
69        'ecommerce-solutions': {
70            title: 'E-Commerce Website Development Agency in Bangalore | Pinakkaa',
71            description: 'Pinakkaa offers e-commerce website development Company in Bangalore, building scalable, user-friendly online stores with seamless design, secure systems, and performance-focused solutions.'
72        },
73        'pr-marketing-services': {
74            title: 'Strategic PR and Marketing Solutions in Bangalore | Pinakkaa',
75            description: 'Pinakkaa is a PR and marketing agency in Bangalore helping brands build credibility, gain media visibility, and connect with the right audience through targeted campaigns and storytelling.'
76        },
77        'software-development': {
78            title: 'Software Development Company in Bangalore | Pinakkaa Tech Solutions',
79            description: 'Get in touch with Pinakkaa, a custom softw
79are development company in Bangalore delivering tailored solutions for startups, SMEs, and enterprises, including applications, cloud, and system integration.'
80        },
81        'api-integration': {
82            title: 'API Integration Services in Bangalore | Pinakkaa Seamless System Connectivity',
83            description: 'Pinakkaa provides API integration services in Bangalore enabling smooth data flow between your apps, platforms, CRM, ERP and business systems for unified operations.'
84        },
85        'email-marketing': {
86            title: 'Email Marketing Services in Bangalore | Top Email marketing company Bangalore',
87            description: 'Pinakkaa Email Marketing Agency in Bangalore that offers result-driven email marketing services to achieve your goals. Hire the Best Email Marketing Company in Bangalore!'
88        },
89        'sms-marketing': {
90            title: 'SMS Marketing Company in Bangalore | Pinakkaa High-Conversion SMS Campaigns',
91            description: 'Pinakkaa , SMS Marketing agency in Bangalore creates high-impact SMS marketing campaigns for lead generation, customer retention and instant communication with measurable results.'
92        },
93        'whatsapp-marketing': {
94            title: 'WhatsApp Marketing Agency in Bangalore | Pinakkaa Direct Customer Engagement',
95            description: 'Pinakkaa offers WhatsApp marketing services in Bangalore to boost interaction, automate communication, deliver campaigns and increase conversion through personal outreach.'
96        },
97        'shopify-website-development': {
98            title: 'Shopify Website Development Services in Bangalore | Pinakkaa',
99            description: 'Pinakkaa offers Shopify website development services in Bangalore, creating scalable, user-friendly online stores designed to improve performance, conversions, and growth.'
100        }
101    };
102    const seoMeta = serviceSeoMeta[service.id] || {};
103    const pageTitle = seoMeta.title || `${service.title} in Bangalore | Pinakkaa`;
104    const pageDescription = seoMeta.description || (service.shortDescription || service.fullDescription || '')
105        .toString()
106        .trim()
107        .replace(/\s+/g, ' ')
108        .slice(0, 160);
109    const canonicalPath = typeof serviceDetailHref === 'function'
110        ? serviceDetailHref(service.id)
111        : '/service-detail.html?service=' + encodeURIComponent(service.id);
112    const canonicalUrl = new URL(canonicalPath, window.location.origin).toString();
113
114    // Update page title
115    document.title = pageTitle;
116
117    const setHeadTag = (selector, createTag, attrs) => {
118        let el = document.head.querySelector(selector);
119        if (!el) {
120            el = document.createElement(createTag);
121            document.head.appendChild(el);
122        }
123        Object.keys(attrs).forEach((key) => {
124            el.setAttribute(key, attrs[key]);
125        });
126    };
127
128    setHeadTag('meta[name="description"]', 'meta', {
129        name: 'description',
130        content: pageDescription
131    });
132    setHeadTag('meta[name="robots"]', 'meta', {
133        name: 'robots',
134        content: 'index,follow'
135    });
136    setHeadTag('link[rel="canonical"]', 'link', {
137        rel: 'canonical',
138        href: canonicalUrl
139    });
140    setHeadTag('meta[property="og:title"]', 'meta', {
141        property: 'og:title',
142        content: pageTitle
143    });
144    setHeadTag('meta[property="og:description"]', 'meta', {
145        property: 'og:description',
146        content: pageDescription
147    });
148    setHeadTag('meta[property="og:url"]', 'meta', {
149        property: 'og:url',
150        content: canonicalUrl
151    });
152    setHeadTag('meta[property="og:type"]', 'meta', {
153        property: 'og:type',
154        content: 'website'
155    });
156    
157    // Update hero section
158    const serviceTitleText = document.getElementById('serviceTitleText');
159    const serviceBreadcrumbName = document.getElementById('serviceBreadcrumbName');
160    const serviceDetailSubtitle = document.getElementById('serviceDetailSubtitle');
161    
162    if (serviceTitleText) {
163        serviceTitleText.textContent = service.title;
164    }
165    
166    if (serviceBreadcrumbName) {
167        serviceBreadcrumbName.textContent = service.title;
168    }
169    
170    if (serviceDetailSubtitle) {
171        serviceDetailSubtitle.textContent = service.shortDescription;
172    }
173
174    // Pinakkaa Advantage (dynamic per selected service)
175    const advantageTitleEl = document.getElementById('pinakkaaAdvantageTitle');
176    const advantageSubtitleEl = document.getElementById('pinakkaaAdvantageSubtitle');
177    const advantageDesc1 = document.getElementById('pinakkaaAdvantageDesc1');
178    const advantageDesc2 = document.getElementById('pinakkaaAdvantageDesc2');
179    const advantageDesc3 = document.getElementById('pinakkaaAdvantageDesc3');
180    const advantageDesc4 = document.getElementById('pinakkaaAdvantageDesc4');
181
182    const truncate = (text, max = 150) => {
183        const value = String(text || '').trim();
184        if (!value) return '';
185        return value.length > max ? value.slice(0, max - 3) + '...' : value;
186    };
187
188    const benefitPool = Array.isArray(service.benefits) ? service.benefits : [];
189    const featurePool = Array.isArray(service.features) ? service.features : [];
190
191    // Service-specific titles and micro-copy for Pinakkaa Advantage
192    const advantagePresets = {
193        'website-designing': {
194            heading: 'The Pinakkaa Advantage in Website Design',
195            items: [
196                'Pixel-Perfect Brand Presence',
197                'Experience-Led Journeys',
198                'Conversion-Ready Layouts',
199                'Analytics-Backed Iteration'
200            ],
201            descriptions: [
202                'Standout layouts that feel on-brand, modern, and consistent across every screen.',
203                'User journeys mapped to how people actually browse, not how wireframes look.',
204                'Page structures guided to enquiry, signup, or checkout with minimal friction.',
205                'Decisions driven by heatmaps, form analytics, and real behaviour data.'
206            ]
207        },
208        'seo-digital-marketing': {
209            heading: 'The Pinakkaa Advantage in SEO & Growth',
210            items: [
211                'Search Visibility that Compounds',
212                'Content that Earns Clicks',
213                'Funnels Built for Conversions',
214                'Always-On Measurement'
215            ],
216            descriptions: [
217                'Rankings built to last, not spike: technical, on-page, and authority working together.',
218                'Stories written for humans first and algorithms second, so clicks stay and explore.',
219                'Journeys tuned for demo, lead, or sale with clear paths from search term to action.',
220                'Dashboards you can actually read, focused on traffic quality and revenue.'
221            ]
222        },
223        'social-media-optimization': {
224            heading: 'The Pinakkaa Advantage in Social Media',
225            items: [
226                'Thumb‑Stopping Creatives',
227                'Communities, Not Just Followers',
228                'Campaigns that Convert',
229                'Real-Time Performance Insights'
230            ],
231            descriptions: [
232                'Posts and stories that pause the scroll with clear, on-brand visual language.',
233                'Comments and DMs turned into conversations that build real community.',
234                'Always-on and burst campaigns tied directly to signups, leads, or sales.',
235                'Live metrics instead of monthly surprises, so you can react in real time.'
236            ]
237        },
238        'online-reputation-management': {
239            heading: 'The Pinakkaa Advantage in Reputation',
240            items: [
241                'Proactive Brand Protection',
242                'Human, On-Point Responses',
243                'Trust that Converts',
244                'Always-On Monitoring'
245            ],
246            descriptions: [
247                'Issues spotted before they snowball through constant review and mention tracking.',
248                'Replies that sound like your brand, not a script, even in tough situations.',
249                'Reviews and testimonials shaped into proof and trust across key touchpoints.',
250                '24/7 eyes on review sites and socials, with clear playbooks for action.'
251            ]
252        },
253        'search-engine-marketing': {
254            heading: 'The Pinakkaa Advantage in SEM',
255            items: [
256                'Precision Targeting',
257                'Creative that Wins Auctions',
258                'ROI-First Optimisation',
259                'Transparent Reporting'
260            ],
261            descriptions: [
262                'Ads shown only to real prospects using intent, audience lists, and geos that matter.',
263                'Copy and creatives built to win more auctions without burning your budget.',
264                'Every rupee mapped to outcomes like leads, pipeline, or revenue, not just clicks.',
265                'Plain‑English performance breakdowns with clear keep/kill/scale decisions.'
266            ]
267        },
268        'social-media-marketing': {
269            heading: 'The Pinakkaa Advantage in Paid Social',
270            items: [
271                'Full-Funnel Ad Strategy',
272                'Audience Intelligence',
273                'Sales-Ready Campaigns',
274                'Continuous Experimentation'
275            ],
276            descriptions: [
277                'Cold, warm, and hot journeys aligned so each audience sees the right story.',
278                'Segments built from real behaviour, not guesses, and synced across platforms.',
279                'Offers and creatives written to move people from interest to actual revenue.',
280                'Always-on creative and audience tests so performance improves month after month.'
281            ]
282        }
283    };
284
285    const preset = advantagePresets[service.id] || {
286        heading: `The Pinakkaa Advantage in ${service.title}`,
287        items: [
288            'Better Brand Visibility',
289            'Stronger Audience Engagement',
290            'Higher Quality Conversions',
291            'Decisions Backed by Data'
292        ],
293        descriptions: [
294            'More of the right people seeing a clear, consistent message from your brand.',
295            'Interactions that feel genuinely useful instead of just adding to the noise.',
296            'Leads and customers that look like your ideal profile, not random clicks.',
297            'Next steps guided by numbers you understand, not just vanity metrics.'
298        ]
299    };
300
301    const itemTitleEls = document.querySelectorAll('.pinakkaa-advantage-item-title');
302    const iconImgs = document.querySelectorAll('.pinakkaa-advantage-icon-img');
303
304    const iconSets = {
305        'website-designing': [
306            'services-pages/icons/graphic_11183291.svg',
307            'services-pages/icons/idea_11331946.svg',
308            'services-pages/icons/view_14014506.svg',
309            'services-pages/icons/eye_4367508.svg'
310        ],
311        'seo-digital-marketing': [
312            'services-pages/icons/growth_12951171.svg',
313            'services-pages/icons/business-strategy_7897981.svg',
314            'services-pages/icons/objective_12209885.svg',
315            'services-pages/icons/strategic-plan_7897776.svg'
316        ],
317        'social-media-optimization': [
318            'services-pages/icons/speaker_17806860.png',
319            'services-pages/icons/respect_12198286.svg',
320            'services-pages/icons/handshake_8252396.svg',
321            'services-pages/icons/gmail_17844661.svg'
322        ],
323        'online-reputation-management': [
324            'services-pages/icons/eye_4367508.svg',
325            'services-pages/icons/respect_12198286.svg',
326            'services-pages/icons/handshake_8252396.svg',
327            'services-pages/icons/objective_12209885.svg'
328        ],
329        'search-engine-marketing': [
330            'services-pages/icons/profits_7895066.svg',
331            'services-pages/icons/growth_12951171.svg',
332            'services-pages/icons/business-strategy_7897981.svg',
333            'services-pages/icons/strategic-plan_7897776.svg'
334        ],
335        'social-media-marketing': [
336            'services-pages/icons/speaker_17806860.png',
337            'services-pages/icons/growth_12951171.svg',
338            'services-pages/icons/handshake_8252396.svg',
339            'services-pages/icons/gmail_17844661.svg'
340        ]
341    };
342
343    const fallbackIcons = [
344        'services-pages/icons/handshake_8252396.svg',
345        'services-pages/icons/growth_12951171.svg',
346        'services-pages/icons/profits_7895066.svg',
347        'services-pages/icons/business-strategy_7897981.svg'
348    ];
349    const iconSet = iconSets[service.id] || fallbackIcons;
350
351    if (advantageTitleEl) {
352        advantageTitleEl.textContent = preset.heading;
353    }
354
355    preset.items.forEach((label, index) => {
356        if (itemTitleEls[index]) {
357            itemTitleEls[index].textContent = label;
358        }
359    });
360
361    iconSet.forEach((src, index) => {
362        if (iconImgs[index]) {
363            iconImgs[index].src = src;
364            iconImgs[index].alt = preset.items[index] || 'Pinakkaa advantage';
365        }
366    });
367
368    if (advantageSubtitleEl) {
369        advantageSubtitleEl.textContent = `When you partner with Pinakkaa for ${service.title}, you don't just get a service, you get a growth partner.`;
370    }
371
372    const shortDescs = preset.descriptions || [];
373    if (advantageDesc1) advantageDesc1.textContent = truncate(shortDescs[0] || '');
374    if (advantageDesc2) advantageDesc2.textContent = truncate(shortDescs[1] || '');
375    if (advantageDesc3) advantageDesc3.textContent = truncate(shortDescs[2] || '');
376    if (advantageDesc4) advantageDesc4.textContent = truncate(shortDescs[3] || '');
377
378    // Why Choose Pinakkaa for [Service]
379    const whyChooseSection = document.getElementById('whyChooseService');
380    const whyChooseNameEl = document.getElementById('whyChooseServiceName');
381    const whyChooseSubtitleEl = document.getElementById('whyChooseSubtitle');
382    const whyChooseGrid = document.getElementById('whyChooseGrid');
383
384    const whyPresets = {
385        'website-designing': {
386            subtitle: 'Design, UX, and performance handled under one roof – from first wireframe to final launch.',
387            items: [
388                {
389                    icon: 'services-pages/New_icons/lamp_9935981.svg',
390                    title: 'Strategy Before Screens',
391                    desc: 'We start with brand, users, and outcomes, then design pages that each have a clear job.'
392                },
393                {
394                    icon: 'services-pages/New_icons/view_14014506.svg',
395                    title: 'Pixel-Level Craft',
396                    desc: 'Layouts, typography, and motion tuned to feel premium on desktop and mobile.'
397                },
398                {
399                    icon: 'services-pages/New_icons/sand-clock_11286687.svg',
400                    title: 'Fast, Stable Builds',
401                    desc: 'Clean code and fast load times so your site feels sharp, not sluggish.'
402                }
403            ]
404        },
405        'seo-digital-marketing': {
406            subtitle: 'Technical SEO, content, and authority rolled into one program focused on true business KPIs.',
407            items: [
408                {
409                    icon: 'services-pages/New_icons/achievement_7871901.svg',
410                    title: 'Proven Playbooks',
411                    desc: 'Battle‑tested SEO frameworks adapted to your domain, not copy‑pasted checklists.'
412                },
413                {
414                    icon: 'services-pages/New_icons/calendar_9642627.svg',
415                    title: 'Compounding Gains',
416                    desc: 'Roadmaps planned quarter by quarter so improvements stack instead of reset.'
417                },
418                {
419                    icon: 'services-pages/New_icons/eye_4367508.svg',
420                    title: 'Radical Transparency',
421                    desc: 'Clear tracking and reporting so you always know what moved the needle and why.'
422                }
423            ]
424        },
425        'social-media-optimization': {
426            subtitle: 'Content, cadence, and community management tuned to how your audience actually behaves.',
427            items: [
428                {
429                    icon: 'services-pages/New_icons/speaker_17806860.png',
430                    title: 'Distinct Brand Voice',
431                    desc: 'Posts and stories that sound like you, not like a generic social media template.'
432                },
433                {
434                    icon: 'services-pages/New_icons/heart_9548779.svg',
435                    title: 'Community Focus',
436                    desc: 'DMs and comments turned into real conversations that build loyalty over time.'
437                },
438                {
439                    icon: 'services-pages/New_icons/gmail_17844661.svg',
440                    title: 'Always-On Pipeline',
441                    desc: 'A steady stream of ideas and assets so your profiles never go silent.'
442                }
443            ]
444        },
445        'online-reputation-management': {
446            subtitle: 'Monitoring, response, and recovery plans that protect the trust you have already earned.',
447            items: [
448                {
449                    icon: 'services-pages/New_icons/eye_4367508.svg',
450                    title: 'Constant Monitoring',
451                    desc: 'Mentions and reviews tracked so small issues are caught long before they explode.'
452                },
453                {
454                    icon: 'services-pages/New_icons/respect_12198286.svg',
455                    title: 'Human Responses',
456                    desc: 'Reply frameworks that respect both your brand voice and the customer’s situation.'
457                },
458                {
459                    icon: 'services-pages/New_icons/flower_17891894.svg',
460                    title: 'Rebuild & Strengthen',
461                    desc: 'Positive content and review strategies that gradually shift sentiment in your favour.'
462                }
463            ]
464        },
465        'search-engine-marketing': {
466            subtitle: 'Hands-on campaign management built for profitable growth, not just higher spend.',
467            items: [
468                {
469                    icon: 'services-pages/New_icons/achievement_7871901.svg',
470                    title: 'Performance DNA',
471                    desc: 'Bids, audiences, and creatives tuned from live data, not set‑and‑forget rules.'
472                },
473                {
474                    icon: 'services-pages/New_icons/view_14014506.svg',
475                    title: 'Goal-Linked KPIs',
476                    desc: 'Every campaign wired to leads, pipeline, or revenue instead of surface‑level metrics.'
477                },
478                {
479                    icon: 'services-pages/New_icons/sand-clock_11286687.svg',
480                    title: 'Fast Test Cycles',
481                    desc: 'New angles tested quickly so winning ideas get budget and weak ones are cut.'
482                }
483            ]
484        },
485        'social-media-marketing': {
486            subtitle: 'Paid social designed as a full funnel – awareness, consideration, and conversion.',
487            items: [
488                {
489                    icon: 'services-pages/New_icons/speaker_17806860.png',
490                    title: 'Platform-Native Ads',
491                    desc: 'Creative built for reels, stories, and feeds instead of one resized master file.'
492                },
493                {
494                    icon: 'services-pages/New_icons/flower_18376638.svg',
495                    title: 'Deep Audience Maps',
496                    desc: 'Cold, warm, and hot segments mapped to messaging that matches intent.'
497                },
498                {
499                    icon: 'services-pages/New_icons/gift_9428742.svg',
500                    title: 'Offer Strategy',
501                    desc: 'Hooks, bundles, and promos crafted to turn attention into trackable revenue.'
502                }
503            ]
504        }
505    };
506
507    if (whyChooseSection && whyChooseGrid && whyChooseNameEl) {
508        const config = whyPresets[service.id];
509        whyChooseNameEl.textContent = `${service.title}?`;
510
511        if (!config) {
512            if (whyChooseSubtitleEl) {
513                whyChooseSubtitleEl.textContent = 'You get a team that thinks about strategy, execution, and reporting as one connected system.';
514            }
515            whyChooseGrid.innerHTML = `
516                <div class="why-choose-card">
517                    <div class="why-choose-icon"><img src="services-pages/New_icons/lamp_9935981.svg" alt=""></div>
518                    <h3 class="why-choose-card-title">Strategic Partner</h3>
519                    <p class="why-choose-card-desc">We learn your model first, then pick the mix of channels and tactics that actually fits.</p>
520                </div>
521                <div class="why-choose-card">
522                    <div class="why-choose-icon"><img src="services-pages/New_icons/achievement_7871901.svg" alt=""></div>
523                    <h3 class="why-choose-card-title">Execution Obsessed</h3>
524                    <p class="why-choose-card-desc">Clear plans, weekly movement, and campaigns that keep improving instead of stalling.</p>
525                </div>
526                <div class="why-choose-card">
527                    <div class="why-choose-icon"><img src="services-pages/New_icons/calendar_9642627.svg" alt=""></div>
528                    <h3 class="why-choose-card-title">Honest Reporting</h3>
529                    <p class="why-choose-card-desc">Simple dashboards and next‑step recommendations you can act on immediately.</p>
530                </div>
531            `;
532        } else {
533            if (whyChooseSubtitleEl) {
534                whyChooseSubtitleEl.textContent = config.subtitle;
535            }
536            whyChooseGrid.innerHTML = config.items.map(item => `
537                <div class="why-choose-card">
538                    <div class="why-choose-icon">
539                        <img src="${item.icon}" alt="">
540                    </div>
541                    <h3 class="why-choose-card-title">${item.title}</h3>
542                    <p class="why-choose-card-desc">${item.desc}</p>
543                </div>
544            `).join('');
545        }
546    }
547    
548    // Update service video/image
549    const serviceVideoSrc = document.getElementById('serviceVideoSrc');
550    const serviceImageSrc = document.getElementById('serviceImageSrc');
551    const serviceBannerSlogan = document.getElementById('serviceBannerSlogan');
552    
553    if (serviceVideoSrc && serviceImageSrc) {
554        if (service.video) {
555            // Use video if available
556            const source = serviceVideoSrc.querySelector('source');
557            if (source) {
558                source.src = service.video;
559                serviceVideoSrc.load();
560            }
561            serviceVideoSrc.setAttribute('aria-label', service.title);
562            serviceVideoSrc.style.display = 'block';
563            serviceImageSrc.style.display = 'none';
564        } else if (service.image) {
565            // Fallback to image if no video
566            serviceImageSrc.src = service.image;
567            serviceImageSrc.alt = service.title;
568            serviceImageSrc.style.display = 'block';
569            serviceVideoSrc.style.display = 'none';
570        }
571    }
572    
573    // Update banner slogan
574    if (serviceBannerSlogan && service.bannerSlogan) {
575        serviceBannerSlogan.textContent = service.bannerSlogan;
576        serviceBannerSlogan.style.display = 'block';
577    } else if (serviceBannerSlogan) {
578        serviceBannerSlogan.style.display = 'none';
579    }
580    
581    // Update service description
582    const serviceDetailDescription = document.getElementById('serviceDetailDescription');
583    if (serviceDetailDescription) {
584        serviceDetailDescription.innerHTML = `
585            <p>${service.fullDescription}</p>
586        `;
587    }
588    
589    // Helper function to check if feature/benefit is object or string
590    const isObject = (item) => typeof item === 'object' && item !== null && !Array.isArray(item) && item.hasOwnProperty('title');
591    
592    // Ensure minimum counts for sections
593    const ensureMinimumItems = (arr, min, type) => {
594        const list = Array.isArray(arr) ? arr.slice() : [];
595        const makeItem = (i) => {
596            if (type === 'feature') {
597                const fallbackFeatures = [
598                    { title: 'Advanced Targeting', description: 'Reach the right audience with precise filters, intent signals, and contextual placements.' },
599                    { title: 'Custom Reporting', description: 'Track KPIs in clear dashboards with weekly/monthly insights your team can act on.' },
600                    { title: 'A/B Testing Framework', description: 'Continuously test creatives, copy, and funnels to improve performance over time.' },
601                    { title: 'Automation Workflows', description: 'Automate routine steps like tagging, routing, and alerts to 
601save time.' },
602                    { title: 'Cross-Channel Integration', description: 'Unify data and messaging across web, search, social, and email for consistency.' },
603                    { title: 'Quality Assurance Review', description: 'Pre-launch and ongoing QA to maintain accuracy, speed, and reliability.' }
604                ];
605                return fallbackFeatures[(i - 1) % fallbackFeatures.length];
606            }
607            if (type === 'benefit') {
608                const fallbackBenefits = [
609                    { title: 'Lower Cost per Result', description: 'Reduce acquisition costs with better targeting, bids, and creative optimization.' },
610                    { title: 'Higher Conversion Rate', description: 'Improve on-site journeys and ad relevance to lift conversions.' },
611                    { title: 'Improved Lead Quality', description: 'Attract decision-makers and high-intent users more likely to buy.' },
612                    { title: 'Faster Time to Value', description: 'Launch quickly with proven playbooks and iterate based on data.' },
613                    { title: 'Scalable Growth', description: 'Build a foundation that supports higher budgets without performance drop.' },
614                    { title: 'Actionable Insights', description: 'Get clear recommendations backed by analytics and real user behavior.' }
615                ];
616                return fallbackBenefits[(i - 1) % fallbackBenefits.length];
617            }
618            const fallbackFaqs = [
619                { question: 'How long until I see meaningful results?', answer: 'Timelines vary by channel. Paid campaigns show movement in weeks; SEO takes 3–6 months for sustained gains.' },
620                { question: 'What budget should I start with?', answer: 'We propose an INR-based test budget aligned to goals and industry CPC/CPM, then scale with performance.' },
621                { question: 'Can you work with our in-house team?', answer: 'Yes. We collaborate with internal teams and share clear roadmaps, tasks, and reporting.' },
622                { question: 'Do you provide detailed reporting?', answer: 'Absolutely. Expect transparent dashboards and executive summaries with next-step actions.' },
623                { question: 'Will you sign NDAs and follow compliance?', answer: 'Yes. We adhere to brand, data, and legal guidelines and can sign NDAs on request.' },
624                { question: 'What makes your approach different?', answer: 'Precision targeting, creative excellence, and iterative optimization focused on measurable outcomes.' },
625                { question: 'Do you handle landing pages and creatives?', answer: 'We can support strategy, copy, design, and development as needed to improve performance.' },
626                { question: 'How do we get started?', answer: 'We begin with discovery, align on goals, set metrics, and launch a pilot to validate assumptions.' }
627            ];
628            return fallbackFaqs[(i - 1) % fallbackFaqs.length];
629        };
630        for (let i = list.length + 1; i <= min; i++) list.push(makeItem(i));
631        return list;
632    };
633    
634    // Update features (show all, ensure at least 6)
635    const serviceFeatures = document.getElementById('serviceFeatures');
636    const normalizedFeatures = ensureMinimumItems(service.features, 6, 'feature');
637    if (serviceFeatures && normalizedFeatures.length > 0) {
638        const firstFeature = normalizedFeatures[0];
639        const useGridLayout = isObject(firstFeature);
640        
641        const featuresHTML = normalizedFeatures.map((feature, index) => {
642            if (isObject(feature)) {
643                // Shorten description to max 100 characters
644                const shortDesc = feature.description.length > 100 
645                    ? feature.description.substring(0, 100) + '...' 
646                    : feature.description;
647                return `
648                    <div class="feature-item card fade-in" style="animation-delay: ${index * 0.1}s">
649                        <div class="feature-header">
650                            <h4 class="feature-title">${feature.title}</h4>
651                        </div>
652                        <p class="feature-description">${shortDesc}</p>
653                    </div>
654                `;
655            } else {
656                return `<li class="fade-in" style="animation-delay: ${index * 0.1}s">${feature}</li>`;
657            }
658        }).join('');
659        
660        serviceFeatures.innerHTML = `
661            <h3><span class="text-purple">Key</span> Features</h3>
662            ${useGridLayout ? `<div class="features-hscroll hscroll">${featuresHTML}</div>` : `<ul>${featuresHTML}</ul>`}
663        `;
664        
665        // Make sure it's visible
666        serviceFeatures.style.display = 'block';
667        serviceFeatures.style.opacity = '1';
668    } else if (serviceFeatures) {
669        serviceFeatures.innerHTML = '<p>Features information coming soon.</p>';
670    }
671    
672    // Update benefits (show all, ensure at least 6)
673    const serviceBenefits = document.getElementById('serviceBenefits');
674    const normalizedBenefits = ensureMinimumItems(service.benefits, 6, 'benefit');
675    if (serviceBenefits && normalizedBenefits.length > 0) {
676        const firstBenefit = normalizedBenefits[0];
677        const useGridLayout = isObject(firstBenefit);
678        
679        const benefitsHTML = normalizedBenefits.map((benefit, index) => {
680            if (isObject(benefit)) {
681                // Shorten description to max 100 characters
682                const shortDesc = benefit.description.length > 100 
683                    ? benefit.description.substring(0, 100) + '...' 
684                    : benefit.description;
685                return `
686                    <div class="benefit-item card fade-in" style="animation-delay: ${index * 0.1}s">
687                        <div class="benefit-header">
688                            <h4 class="benefit-title">${benefit.title}</h4>
689                        </div>
690                        <p class="benefit-description">${shortDesc}</p>
691                    </div>
692                `;
693            } else {
694                return `<li class="fade-in" style="animation-delay: ${index * 0.1}s">${benefit}</li>`;
695            }
696        }).join('');
697        
698        serviceBenefits.innerHTML = `
699            <h3><span class="text-purple">Key</span> Benefits</h3>
700            ${useGridLayout ? `<div class="benefits-hscroll hscroll">${benefitsHTML}</div>` : `<ul>${benefitsHTML}</ul>`}
701        `;
702        
703        // Make sure it's visible
704        serviceBenefits.style.display = 'block';
705        serviceBenefits.style.opacity = '1';
706    } else if (serviceBenefits) {
707        serviceBenefits.innerHTML = '<p>Benefits information coming soon.</p>';
708    }
709    
710    // Update FAQ (show all, ensure at least 8)
711    const serviceFAQ = document.getElementById('serviceFAQ');
712    const normalizedFaqs = ensureMinimumItems(service.faqs, 8, 'faq');
713    if (serviceFAQ && normalizedFaqs.length > 0) {
714        // Expand short FAQ answers with clearer guidance
715        const expandAnswer = (question, answer, serviceName) => {
716            const base = String(answer || '').trim();
717            if (base.length >= 220) return base;
718            
719            const q = String(question || '').toLowerCase();
720            const extra = [];
721            
722            if (/(cost|price|pricing|budget|charge)/i.test(q)) {
723                extra.push('We provide a phased estimate in INR that separates media spend from our service fees, with options for monthly retainers or project-based engagements.');
724            }
725            if (/(how long|result|when|timeline|timeframe|roi)/i.test(q)) {
726                extra.push('For paid channels you will typically see directional results within 2–4 weeks; SEO and organic programs usually take 3–6 months to compound and show strong lift.');
727            }
728            if (/(report|tracking|analytics|measure|kpi|dashboard)/i.test(q)) {
729                extra.push('You receive a simple dashboard plus a monthly summary highlighting KPIs, insights, and recommended next steps, so decisions are always data‑driven.');
730            }
731            if (/(industry|domain|sector|niche)/i.test(q)) {
732                extra.push('Our approach is adaptable across industries; we start with discovery, map target personas, benchmark competitors, and tailor creatives and keywords accordingly.');
733            }
734            if (/(contract|lock|term|commitment|cancellation)/i.test(q)) {
735                extra.push('Engagements are flexible. Most clients start with a 3‑month plan to validate impact, then extend based on performance and roadmap.');
736            }
737            if (/(team|in‑house|collaborate|work with us|handoff)/i.test(q)) {
738                extra.push('We collaborate seamlessly with in‑house teams, sharing roadmaps, tasks, and clear ownership to avoid duplication and accelerate delivery.');
739            }
740            if (/(creative|asset|landing|page|copy|design)/i.test(q)) {
741                extra.push('We can support copy, design, and landing pages. Where you have existing assets, we iterate through structured A/B tests to find winners faster.');
742            }
743            if (/(start|onboard|next step|how do i)/i.test(q)) {
744                extra.push(`Getting started is simple: book a discovery call, align on goals and KPIs for ${serviceName}, approve the plan and INR budget, and we launch a pilot within days.`);
745            }
746            if (extra.length === 0) {
747                extra.push('We follow a clear process: discovery, strategy, execution, and continuous optimization with transparent communication and measurable outcomes.');
748            }
749            
750            const expanded = `${base} ${extra.join(' ')}`.trim();
751            return expanded.length > 800 ? expanded.slice(0, 780) + '...' : expanded;
752        };
753        
754        const expandedFaqs = normalizedFaqs.map(f => ({
755            question: f.question,
756            answer: expandAnswer(f.question, f.answer, service.title)
757        }));
758        
759        serviceFAQ.innerHTML = `
760            <h3><span class="text-purple">Frequently Asked</span> Questions</h3>
761            <div class="faq-container">
762                ${expandedFaqs.map((faq, index) => `
763                    <div class="faq-item fade-in" style="animation-delay: ${index * 0.1}s">
764                        <div class="faq-question">
765                            <h4>${faq.question}</h4>
766                            <span class="faq-icon">+</span>
767                        </div>
768                        <div class="faq-answer">
769                            <p>${faq.answer}</p>
770                        </div>
771                    </div>
772                `).join('')}
773            </div>
774        `;
775        
776        // Make sure it's visible
777        serviceFAQ.style.display = 'block';
778        serviceFAQ.style.opacity = '1';
779        
780        // Initialize FAQ accordion after a short delay to ensure DOM is ready
781        setTimeout(() => {
782            initializeFAQ();
783        }, 100);
784    } else if (serviceFAQ) {
785        serviceFAQ.innerHTML = '<p>FAQ information coming soon.</p>';
786    }
787    
788    // Update sidebar services list
789    const sidebarServicesList = document.getElementById('sidebarServicesList');
790    if (sidebarServicesList) {
791        // Get other services (exclude current)
792        const otherServices = servicesData.filter(s => s.id !== serviceId).slice(0, 5);
793        
794        sidebarServicesList.innerHTML = otherServices.map(s => 
795            `<li><a href="${typeof serviceDetailHref === 'function' ? serviceDetailHref(s.id) : 'service-detail.html?service=' + encodeURIComponent(s.id)}">${s.title}</a></li>`
796        ).join('');
797    }
798    
799    // Load related services section
800    loadRelatedServices(service);
801    
802    // Ensure content sections are visible
803    const contentSections = document.querySelectorAll('.service-features, .service-benefits, .service-faq');
804    contentSections.forEach(section => {
805        section.style.display = 'block';
806        section.style.opacity = '1';
807        section.style.visibility = 'visible';
808    });
809    
810    // Add fade-in animation with scroll observer
811    const elements = document.querySelectorAll('.service-detail-main, .service-detail-sidebar');
812    elements.forEach((el, index) => {
813        el.classList.add('fade-in');
814        el.style.animationDelay = `${index * 0.2}s`;
815        el.style.opacity = '1';
816    });
817    
818    // Initialize scroll observer for animations (but don't hide content)
819    const observerOptions = {
820        threshold: 0.1,
821        rootMargin: '0px 0px -50px 0px'
822    };
823
824    const observer = new IntersectionObserver((entries) => {
825        entries.forEach(entry => {
826            if (entry.isIntersecting) {
827                entry.target.classList.add('visible');
828                entry.target.style.opacity = '1';
829                observer.unobserve(entry.target);
830            }
831        });
832    }, observerOptions);
833
834    elements.forEach(el => observer.observe(el));
835    
836    // Add interactive features to features and benefits lists
837    const listItems = document.querySelectorAll('.service-features li, .service-benefits li');
838    listItems.forEach((item, index) => {
839        item.style.opacity = '0';
840        item.style.transform = 'translateX(-20px)';
841        setTimeout(() => {
842            item.style.transition = 'all 0.4s ease';
843            item.style.opacity = '1';
844            item.style.transform = 'translateX(0)';
845        }, index * 50);
846        
847        // Add click interaction
848        item.addEventListener('click', function() {
849            this.style.transform = 'translateX(10px) scale(1.05)';
850            setTimeout(() => {
851                this.style.transform = 'translateX(0) scale(1)';
852            }, 200);
853        });
854    });
855    
856    // Add image zoom effect
857    const serviceImage = document.getElementById('serviceImageSrc');
858    if (serviceImage) {
859        serviceImage.addEventListener('mouseenter', function() {
860            this.style.transform = 'scale(1.1)';
861            this.style.transition = 'transform 0.5s ease';
862        });
863        
864        serviceImage.addEventListener('mouseleave', function() {
865            this.style.transform = 'scale(1)';
866        });
867    }
868    
869    // Add sidebar card animations
870    const sidebarCards = document.querySelectorAll('.service-sidebar-card');
871    sidebarCards.forEach((card, index) => {
872        card.classList.add('scale-in');
873        card.style.animationDelay = `${index * 0.2}s`;
874        observer.observe(card);
875    });
876    
877    // Initialize scroll progress
878    const addScrollProgress = () => {
879        const progressBar = document.querySelector('.scroll-progress');
880        if (!progressBar) return;
881        
882        window.addEventListener('scroll', () => {
883            const windowHeight = document.documentElement.scrollHeight - document.documentElement.clientHeight;
884            const scrolled = (window.pageYOffset / windowHeight) * 100;
885            progressBar.style.width = scrolled + '%';
886        });
887    };
888    
889    addScrollProgress();
890});
891
892// Load Related Services Section
893function loadRelatedServices(currentService) {
894    const relatedServicesSection = document.getElementById('relatedServicesSection');
895    if (!relatedServicesSection) return;
896    
897    // Get other services with videos only (exclude current) and limit to 6
898    const otherServices = servicesData
899        .filter(s => s.id !== currentService.id && s.video)
900        .slice(0, 6);
901    
902    if (otherServices.length === 0) {
903        relatedServicesSection.style.display = 'none';
904        return;
905    }
906    
907    relatedServicesSection.innerHTML = `
908        <h3 class="related-services-title">
909            <span class="text-purple">Explore</span> Other Services
910        </h3>
911        <div class="related-services-grid">
912            ${otherServices.map((service, index) => `
913                <a href="${typeof serviceDetailHref === 'function' ? serviceDetailHref(service.id) : 'service-detail.html?service=' + encodeURIComponent(service.id)}" class="related-service-card fade-in" style="animation-delay: ${index * 0.1}s">
914                    <div class="related-service-image">
915                        ${service.video ? `
916                            <video autoplay loop muted playsinline>
917                                <source src="${service.video}" type="video/mp4">
918                            </video>
919                        ` : service.image ? `
920                            <img src="${service.image}" alt="${service.title}">
921                        ` : ''}
922                    </div>
923                    <div class="related-service-content">
924                        <h4 class="related-service-name">${service.title}</h4>
925                        <p class="related-service-description">${service.shortDescription}</p>
926                        <span class="related-service-link">Learn More →</span>
927                    </div>
928                </a>
929            `).join('')}
930        </div>
931        <div class="services-cta-actions" style="margin-top: 28px;">
932            <a href="services.html" class="services-cta-button">Explore more services</a>
933        </div>
934    `;
935    
936    // Make sure it's visible
937    relatedServicesSection.style.display = 'block';
938    relatedServicesSection.style.opacity = '1';
939}
940
941// FAQ Accordion Functionality
942function initializeFAQ() {
943    const faqItems = document.querySelectorAll('.faq-item');
944    
945    faqItems.forEach(item => {
946        const question = item.querySelector('.faq-question');
947        const answer = item.querySelector('.faq-answer');
948        const icon = item.querySelector('.faq-icon');
949        
950        // Set initial state
951        answer.style.maxHeight = '0';
952        answer.style.opacity = '0';
953        item.classList.remove('active');
954        
955        question.addEventListener('click', () => {
956            const isActive = item.classList.contains('active');
957            
958            // Close all other FAQs
959            faqItems.forEach(otherItem => {
960                if (otherItem !== item) {
961                    otherItem.classList.remove('active');
962                    const otherAnswer = otherItem.querySelector('.faq-answer');
963                    const otherIcon = otherItem.querySelector('.faq-icon');
964                    otherAnswer.style.maxHeight = '0';
965                    otherAnswer.style.opacity = '0';
966                    otherIcon.textContent = '+';
967                    otherIcon.style.transform = 'rotate(0deg)';
968                }
969            });
970            
971            // Toggle current FAQ
972            if (isActive) {
973                item.classList.remove('active');
974                answer.style.maxHeight = '0';
975                answer.style.opacity = '0';
976                icon.textContent = '+';
977                icon.style.transform = 'rotate(0deg)';
978            } else {
979                item.classList.add('active');
980                answer.style.maxHeight = answer.scrollHeight + 'px';
981                answer.style.opacity = '1';
982                icon.textContent = '−';
983                icon.style.transform = 'rotate(180deg)';
984            }
985        });
986    });
987}

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.