टेम्पलेट के प्रोसेसिंग के समय त्रुटि हुई है.
The following has evaluated to null or missing:
==> document.selectSingleNode(
            "//dynamic-element[@field-reference='name']/dynamic-content[@language-id='${languageId}']"
        )  [in template "20662264241477#20120#102636" at line 300, column 25]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign nameNode = document.selectSin...  [in template "20662264241477#20120#102636" at line 300, column 5]
----
1<div class="gallery-wrapper"> 
2 
3    <!-- ========================= 
4         HEADER 
5    ========================== --> 
6 
7    <div class="gallery-header"> 
8 
9        <h1> 
10            <i class="bi bi-camera-fill"></i> 
11${languageUtil.get(locale, "photo_gallery")} 
12        </h1> 
13 
14     
15        
16 
17    </div> 
18 
19 
20     
21<!-- ========================= 
22     TOOLBAR 
23========================== --> 
24 
25<div class="gallery-toolbar"> 
26 
27    <div class="gallery-filter-row"> 
28 
29        <!-- CATEGORY --> 
30        <div class="filter-group category-group"> 
31 
32            <label for="categoryFilter"> 
33                <i class="bi bi-grid-3x3-gap-fill"></i> 
34                Category 
35            </label> 
36 
37            <div class="select-wrapper"> 
38 
39                <select 
40                    id="categoryFilter" 
41                    class="gallery-select"> 
42 
43                    <option value="all"> 
44                        All Categories 
45                    </option> 
46 
47                </select> 
48 
49                <i class="bi bi-chevron-down select-icon"></i> 
50 
51            </div> 
52 
53        </div> 
54 
55 
56        <!-- SEARCH --> 
57        <div class="filter-group search-group"> 
58 
59            <label for="searchInput"> 
60                <i class="bi bi-search"></i> 
61                Search 
62            </label> 
63 
64            <div class="search-wrapper"> 
65 
66                <i class="bi bi-search search-icon"></i> 
67 
68                <input 
69                    type="text" 
70                    id="searchInput" 
71                    class="gallery-search" 
72                    placeholder="Search photos..." 
73                    autocomplete="off" 
74                /> 
75 
76                <button 
77                    type="button" 
78                    id="clearSearch" 
79                    class="clear-search" 
80                    title="Clear search"> 
81 
82                    <i class="bi bi-x"></i> 
83 
84                </button> 
85 
86            </div> 
87 
88        </div> 
89 
90 
91        <!-- TOTAL --> 
92        <div class="photo-count-box"> 
93 
94            <div class="count-icon"> 
95 
96                <i class="bi bi-images"></i> 
97 
98            </div> 
99 
100            <div class="count-content"> 
101 
102                <span class="count-label"> 
103                    Total Photos 
104                </span> 
105 
106                <strong id="totalPhotos"> 
107                    0 
108                </strong> 
109 
110            </div> 
111 
112        </div> 
113 
114    </div> 
115 
116</div> 
117 
118	<!-- ========================= 
119     GALLERY GRID 
120========================== --> 
121 
122<div class="gallery-grid"> 
123 
124    <div 
125        id="galleryContainer" 
126        class="row g-4"> 
127 
128    </div> 
129 
130</div> 
131 
132    <!-- ========================= 
133         PAGINATION 
134    ========================== --> 
135 
136    <div class="pagination-wrapper"> 
137 
138        <nav aria-label="Photo pagination"> 
139 
140            <ul 
141                id="pagination" 
142                class="pagination justify-content-center mb-0" 
143            > 
144            </ul> 
145 
146        </nav> 
147 
148    </div> 
149 
150</div> 
151 
152 
153 
154<!-- ========================= 
155     LIGHTBOX 
156========================== --> 
157 
158<div 
159    id="lightbox" 
160    class="lightbox" 
161> 
162 
163    <div class="lightbox-content"> 
164 
165 
166        <!-- CLOSE --> 
167 
168        <button 
169            class="lightbox-close" 
170            id="closeLightbox" 
171            title="Close" 
172        > 
173            <i class="bi bi-x-lg"></i> 
174        </button> 
175 
176 
177        <!-- IMAGE AREA --> 
178 
179        <div class="lightbox-image-container"> 
180 
181            <!-- PREVIOUS --> 
182 
183            <button 
184                id="prevPhoto" 
185                class="lightbox-prev" 
186            > 
187                <i class="bi bi-chevron-left"></i> 
188            </button> 
189 
190 
191            <!-- IMAGE --> 
192 
193            <img 
194                id="lightboxImage" 
195                src="" 
196                alt="Photo" 
197            > 
198 
199 
200            <!-- NEXT --> 
201 
202            <button 
203                id="nextPhoto" 
204                class="lightbox-next" 
205            > 
206                <i class="bi bi-chevron-right"></i> 
207            </button> 
208 
209        </div> 
210 
211 
212        <!-- FOOTER --> 
213 
214        <div class="lightbox-footer"> 
215 
216            <div> 
217 
218                <div 
219                    id="lightboxTitle" 
220                    class="lightbox-title" 
221                > 
222                    Photo 
223                </div> 
224 
225                <div 
226                    id="lightboxCounter" 
227                    class="lightbox-counter" 
228                > 
229                    1 / 1 
230                </div> 
231 
232            </div> 
233 
234 
235            <!-- ACTION BUTTONS --> 
236 
237            <div class="lightbox-actions"> 
238 
239                <button 
240                    id="zoomOut" 
241                    title="Zoom Out" 
242                > 
243                    <i class="bi bi-zoom-out"></i> 
244                </button> 
245 
246                <button 
247                    id="zoomIn" 
248                    title="Zoom In" 
249                > 
250                    <i class="bi bi-zoom-in"></i> 
251                </button> 
252 
253                <button 
254                    id="resetZoom" 
255                    title="Reset Zoom" 
256                > 
257                    <i class="bi bi-arrow-counterclockwise"></i> 
258                </button> 
259 
260                <button 
261                    id="downloadPhoto" 
262                    title="Download" 
263                > 
264                    <i class="bi bi-download"></i> 
265                </button> 
266 
267            </div> 
268 
269        </div> 
270 
271    </div> 
272 
273</div> 
274 
275 
276 
277<!-- ========================= 
278     JAVASCRIPT 
279========================== --> 
280 
281<script> 
282 
283    /* ===================================== 
284       PHOTO DATA 
285    ====================================== */ 
286 
287   const photos = [ 
288 
289<#list entries as entry> 
290 
291    <#assign 
292        renderer = entry.getAssetRenderer() 
293        article = renderer.getArticle() 
294        document = saxReaderUtil.read(article.getContent()) 
295        languageId = locale.toString() 
296        srNo = entry?index + 1 
297    /> 
298 
299    <#-- NAME --> 
300    <#assign nameNode = document.selectSingleNode( 
301        "//dynamic-element[@field-reference='name']/dynamic-content[@language-id='${languageId}']" 
302    ) /> 
303 
304    <#assign photoName = "" /> 
305 
306    <#if nameNode??> 
307        <#assign photoName = nameNode.getText() /> 
308    </#if> 
309 
310 
311    <#-- CATEGORY --> 
312    <#assign categoryNode = document.selectSingleNode( 
313        "//dynamic-element[@field-reference='category']/dynamic-content[@language-id='${languageId}']" 
314    ) /> 
315 
316    <#assign photoCategory = "" /> 
317 
318    <#if categoryNode??> 
319        <#assign photoCategory = categoryNode.getText() /> 
320					 
321    </#if> 
322 
323 
324    <#-- IMAGE --> 
325    <#assign imageNode = document.selectSingleNode( 
326        "//dynamic-element[@field-reference='image']/dynamic-content[@language-id='${languageId}']" 
327    ) /> 
328 
329    <#assign imageUrl = "" /> 
330 
331    <#if imageNode??> 
332 
333        <#assign imageData = imageNode.getText() /> 
334 
335        <#if imageData?has_content> 
336 
337            <#assign imageJson = jsonFactoryUtil.createJSONObject(imageData) /> 
338 
339            <#if imageJson.has("url")> 
340                <#assign imageUrl = imageJson.getString("url") /> 
341            </#if> 
342 
343        </#if> 
344 
345    </#if> 
346 
347 
348    { 
349        id: ${srNo}, 
350        title: "${photoName?js_string}", 
351        category: "${photoCategory?js_string}", 
352        image: "${imageUrl?js_string}" 
353    }<#if entry?has_next>,</#if> 
354 
355</#list> 
356 
357]; 
358 
359 
360    /* ===================================== 
361       VARIABLES 
362    ====================================== */ 
363 
364    const photosPerPage = 6; 
365 
366    let currentPage = 1; 
367 
368    let filteredPhotos = [...photos]; 
369 
370    let currentLightboxIndex = 0; 
371 
372    let zoomLevel = 1; 
373 
374 
375    /* ===================================== 
376       DOM ELEMENTS 
377    ====================================== */ 
378 
379    const galleryContainer = 
380        document.getElementById("galleryContainer"); 
381 
382    const pagination = 
383        document.getElementById("pagination"); 
384 
385    const totalPhotos = 
386        document.getElementById("totalPhotos"); 
387 
388    const categoryFilter = 
389        document.getElementById("categoryFilter"); 
390 
391    const searchInput = 
392        document.getElementById("searchInput"); 
393 
394    const lightbox = 
395        document.getElementById("lightbox"); 
396 
397    const lightboxImage = 
398        document.getElementById("lightboxImage"); 
399 
400    const lightboxTitle = 
401        document.getElementById("lightboxTitle"); 
402 
403    const lightboxCounter = 
404        document.getElementById("lightboxCounter"); 
405/* ===================================== 
406   LOAD DYNAMIC CATEGORIES 
407====================================== */ 
408 
409function loadCategories() { 
410 
411    const categorySet = new Set(); 
412 
413    photos.forEach(function(photo) { 
414 
415        if ( 
416            photo.category && 
417            photo.category.trim() !== "" 
418        ) { 
419 
420            categorySet.add( 
421                photo.category.trim() 
422            ); 
423 
424        } 
425 
426    }); 
427 
428 
429    const categories = 
430        Array.from(categorySet).sort(); 
431 
432 
433    console.log( 
434        "Dynamic Categories:", 
435        categories 
436    ); 
437 
438 
439    categoryFilter.innerHTML = 
440        '<option value="all">' + 
441        'All Categories' + 
442        '</option>'; 
443 
444 
445    categories.forEach(function(category) { 
446 
447        const option = 
448            document.createElement("option"); 
449 
450 
451        option.value = 
452            category; 
453 
454 
455        option.textContent = 
456            category; 
457 
458 
459        categoryFilter.appendChild( 
460            option 
461        ); 
462 
463    }); 
464 
465} 
466 
467    /* ===================================== 
468       DISPLAY GALLERY 
469    ====================================== */ 
470 
471    function displayGallery() { 
472 
473        galleryContainer.innerHTML = ""; 
474 
475        const start = 
476            (currentPage - 1) * photosPerPage; 
477 
478        const end = 
479            start + photosPerPage; 
480 
481        const pagePhotos = 
482            filteredPhotos.slice(start, end); 
483 
484 
485        if (pagePhotos.length === 0) { 
486 
487            galleryContainer.innerHTML = ` 
488                <div class="col-12 text-center py-5"> 
489                    <i class="bi bi-image fs-1 text-muted"></i> 
490                    <h5 class="mt-3 text-muted"> 
491                        No photos found 
492                    </h5> 
493                </div> 
494            `; 
495 
496            return; 
497        } 
498 
499 
500        pagePhotos.forEach((photo) => { 
501 
502            const originalIndex = filteredPhotos.indexOf(photo); 
503 
504 
505            const column = document.createElement("div"); 
506 
507                
508            column.className = "col-12 col-sm-6 col-md-4 col-lg-4 mt-3"; 
509                
510 
511 
512           column.innerHTML = 
513    '<div class="photo-card mt-3">' + 
514 
515        '<div ' + 
516            'class="photo-image-wrapper" ' + 
517            'onclick="openLightbox(' + originalIndex + ')">' + 
518 
519            '<img ' + 
520                'src="' + photo.image + '" ' + 
521                'alt="' + photo.title + '" ' + 
522                'class="photo-image" ' + 
523                'loading="lazy">' + 
524 
525            '<span class="zoom-icon">' + 
526                '<i class="bi bi-search"></i>' + 
527            '</span>' + 
528 
529        '</div>' + 
530 
531        '<div class="photo-title">' + 
532            photo.title + 
533        '</div>' + 
534 
535    '</div>'; 
536 
537 
538            galleryContainer.appendChild(column); 
539 
540        }); 
541 
542 
543        totalPhotos.textContent = filteredPhotos.length; 
544 
545    } 
546 
547 
548    /* ===================================== 
549       PAGINATION 
550    ====================================== */ 
551 
552    function createPagination() { 
553 
554        pagination.innerHTML = ""; 
555			const totalPages =  Math.ceil( 
556                filteredPhotos.length / photosPerPage 
557            ); 
558 
559 
560        if (totalPages <= 1) { 
561            return; 
562        } 
563 
564 
565        /* PREVIOUS */ 
566 
567        const previous = document.createElement("li"); 
568 
569        
570			previous.className = 
571    "page-item " + (currentPage === 1 ? "disabled" : ""); 
572 
573        previous.innerHTML = ` 
574            <a class="page-link" href="#"> 
575                Previous 
576            </a> 
577        `; 
578 
579        previous.onclick = function(e) { 
580 
581            e.preventDefault(); 
582 
583            if (currentPage > 1) { 
584 
585                currentPage--; 
586							 
587 
588                displayGallery(); 
589 
590                createPagination(); 
591 
592                window.scrollTo({ 
593                    top: 0, 
594                    behavior: "smooth" 
595                }); 
596            } 
597 
598        }; 
599 
600        pagination.appendChild(previous); 
601 
602 
603        /* PAGE NUMBERS */ 
604 
605        for ( 
606            let i = 1; 
607            i <= totalPages; 
608            i++ 
609        ) { 
610 
611            const page = 
612                document.createElement("li"); 
613 
614           page.className = 
615    "page-item " + (i === currentPage ? "active" : ""); 
616 
617            page.innerHTML = 
618    '<a class="page-link" href="#">' + 
619        i + 
620    '</a>'; 
621 
622 
623            page.onclick = function(e) { 
624 
625                e.preventDefault(); 
626 
627                currentPage = i; 
628						 
629 
630                displayGallery(); 
631 
632                createPagination(); 
633 
634                window.scrollTo({ 
635                    top: 0, 
636                    behavior: "smooth" 
637                }); 
638 
639            }; 
640 
641 
642            pagination.appendChild(page); 
643 
644        } 
645 
646 
647        /* NEXT */ 
648 
649        const next = 
650            document.createElement("li"); 
651 
652        next.className = 
653    "page-item " + (currentPage === totalPages ? "disabled" : ""); 
654 
655        next.innerHTML = ` 
656            <a class="page-link" href="#"> 
657                Next 
658            </a> 
659        `; 
660 
661 
662        next.onclick = function(e) { 
663 
664            e.preventDefault(); 
665 
666            if (currentPage < totalPages) { 
667 
668                currentPage++; 
669							 
670 
671                displayGallery(); 
672 
673                createPagination(); 
674 
675                window.scrollTo({ 
676                    top: 0, 
677                    behavior: "smooth" 
678                }); 
679 
680            } 
681 
682        }; 
683 
684 
685        pagination.appendChild(next); 
686 
687    } 
688 
689 
690    
691/* ===================================== 
692   FILTER PHOTOS 
693====================================== */ 
694 
695function filterPhotos() { 
696 
697    const selectedCategory = 
698        categoryFilter.value.trim(); 
699 
700 
701    const searchText = 
702        searchInput.value 
703            .toLowerCase() 
704            .trim(); 
705 
706 
707    console.log( 
708        "Selected Category:", 
709        selectedCategory 
710    ); 
711 
712 
713    filteredPhotos = 
714        photos.filter(function(photo) { 
715 
716 
717            const photoCategory = 
718                ( 
719                    photo.category || "" 
720                ).trim(); 
721 
722 
723            const photoTitle = 
724                ( 
725                    photo.title || "" 
726                ) 
727                .toLowerCase(); 
728 
729 
730            /* 
731             * CATEGORY FILTER 
732             */ 
733 
734            const categoryMatch = 
735 
736                selectedCategory === "all" || 
737 
738                photoCategory === 
739                    selectedCategory; 
740 
741 
742            /* 
743             * SEARCH FILTER 
744             */ 
745 
746            const searchMatch = 
747 
748                photoTitle.includes( 
749                    searchText 
750                ); 
751 
752 
753            return ( 
754                categoryMatch && 
755                searchMatch 
756            ); 
757 
758        }); 
759 
760 
761    console.log( 
762        "Filtered Photos:", 
763        filteredPhotos 
764    ); 
765 
766 
767    currentPage = 1; 
768 
769 
770    displayGallery(); 
771 
772    createPagination(); 
773 
774} 
775 
776 
777    categoryFilter.addEventListener( 
778        "change", 
779        filterPhotos 
780    ); 
781 
782 
783   searchInput.addEventListener( 
784        "input", 
785        filterPhotos 
786    ); 
787	const clearSearch = 
788    document.getElementById("clearSearch"); 
789 
790 
791searchInput.addEventListener( 
792    "input", 
793    function() { 
794 
795        if (searchInput.value.trim() !== "") { 
796 
797            clearSearch.style.display = 
798                "flex"; 
799 
800        } else { 
801 
802            clearSearch.style.display = 
803                "none"; 
804 
805        } 
806 
807    } 
808); 
809 
810 
811clearSearch.addEventListener( 
812    "click", 
813    function() { 
814 
815        searchInput.value = ""; 
816 
817        clearSearch.style.display = 
818            "none"; 
819 
820        filterPhotos(); 
821 
822        searchInput.focus(); 
823 
824    } 
825); 
826 
827 
828    /* ===================================== 
829       OPEN LIGHTBOX 
830    ====================================== */ 
831 
832    function openLightbox(index) { 
833 
834        currentLightboxIndex = index; 
835 
836        zoomLevel = 1; 
837 
838        updateLightbox(); 
839 
840        lightbox.classList.add("show"); 
841 
842        document.body.style.overflow = "hidden"; 
843 
844    } 
845 
846 
847    /* ===================================== 
848       UPDATE LIGHTBOX 
849    ====================================== */ 
850 
851    function updateLightbox() { 
852 
853        const photo = 
854            filteredPhotos[currentLightboxIndex]; 
855 
856 
857        if (!photo) { 
858            return; 
859        } 
860 
861 
862        lightboxImage.src = 
863            photo.image; 
864 
865        lightboxImage.alt = 
866            photo.title; 
867 
868        lightboxTitle.textContent = 
869            photo.title; 
870 
871        lightboxCounter.textContent = 
872            (currentLightboxIndex + 1) + " / " + filteredPhotos.length; 
873 
874        applyZoom(); 
875 
876    } 
877 
878 
879    /* ===================================== 
880       CLOSE LIGHTBOX 
881    ====================================== */ 
882 
883    function closeLightbox() { 
884 
885        lightbox.classList.remove("show"); 
886 
887        document.body.style.overflow = ""; 
888 
889    } 
890 
891 
892    document 
893        .getElementById("closeLightbox") 
894        .addEventListener( 
895            "click", 
896            closeLightbox 
897        ); 
898 
899 
900    /* ===================================== 
901       NEXT PHOTO 
902    ====================================== */ 
903 
904    function nextPhoto() { 
905 
906        if ( 
907            currentLightboxIndex < 
908            filteredPhotos.length - 1 
909        ) { 
910 
911            currentLightboxIndex++; 
912 
913        } else { 
914 
915            currentLightboxIndex = 0; 
916 
917        } 
918 
919 
920        zoomLevel = 1; 
921 
922        updateLightbox(); 
923 
924    } 
925 
926 
927    document 
928        .getElementById("nextPhoto") 
929        .addEventListener( 
930            "click", 
931            nextPhoto 
932        ); 
933 
934 
935    /* ===================================== 
936       PREVIOUS PHOTO 
937    ====================================== */ 
938 
939    function previousPhoto() { 
940 
941        if ( 
942            currentLightboxIndex > 0 
943        ) { 
944 
945            currentLightboxIndex--; 
946 
947        } else { 
948 
949            currentLightboxIndex = 
950                filteredPhotos.length - 1; 
951 
952        } 
953 
954 
955        zoomLevel = 1; 
956 
957        updateLightbox(); 
958 
959    } 
960 
961 
962    document 
963        .getElementById("prevPhoto") 
964        .addEventListener( 
965            "click", 
966            previousPhoto 
967        ); 
968 
969 
970    /* ===================================== 
971       ZOOM 
972    ====================================== */ 
973 
974    function applyZoom() { 
975 
976    lightboxImage.style.transform = 
977        "scale(" + zoomLevel + ")"; 
978 
979} 
980 
981 
982    document 
983        .getElementById("zoomIn") 
984        .addEventListener( 
985            "click", 
986            function() { 
987 
988                zoomLevel += 0.2; 
989 
990                if (zoomLevel > 3) { 
991                    zoomLevel = 3; 
992                } 
993 
994                applyZoom(); 
995 
996            } 
997        ); 
998 
999 
1000    document 
1001        .getElementById("zoomOut") 
1002        .addEventListener( 
1003            "click", 
1004            function() { 
1005 
1006                zoomLevel -= 0.2; 
1007 
1008                if (zoomLevel < 0.5) { 
1009                    zoomLevel = 0.5; 
1010                } 
1011 
1012                applyZoom(); 
1013 
1014            } 
1015        ); 
1016 
1017 
1018    document 
1019        .getElementById("resetZoom") 
1020        .addEventListener( 
1021            "click", 
1022            function() { 
1023 
1024                zoomLevel = 1; 
1025 
1026                applyZoom(); 
1027 
1028            } 
1029        ); 
1030 
1031 
1032    /* ===================================== 
1033       DOWNLOAD 
1034    ====================================== */ 
1035 
1036    document 
1037        .getElementById("downloadPhoto") 
1038        .addEventListener( 
1039            "click", 
1040            function() { 
1041 
1042                const photo = 
1043                    filteredPhotos[currentLightboxIndex]; 
1044 
1045 
1046                const link = 
1047                    document.createElement("a"); 
1048 
1049                link.href = 
1050                    photo.image; 
1051 
1052                link.download = 
1053                    photo.title + ".jpg"; 
1054 
1055                link.target = 
1056                    "_blank"; 
1057 
1058                document.body.appendChild(link); 
1059 
1060                link.click(); 
1061 
1062                document.body.removeChild(link); 
1063 
1064            } 
1065        ); 
1066 
1067 
1068    /* ===================================== 
1069       KEYBOARD CONTROLS 
1070    ====================================== */ 
1071 
1072    document.addEventListener( 
1073        "keydown", 
1074        function(e) { 
1075 
1076            if (!lightbox.classList.contains("show")) { 
1077                return; 
1078            } 
1079 
1080 
1081            if (e.key === "Escape") { 
1082 
1083                closeLightbox(); 
1084 
1085            } 
1086 
1087 
1088            if (e.key === "ArrowRight") { 
1089 
1090                nextPhoto(); 
1091 
1092            } 
1093 
1094 
1095            if (e.key === "ArrowLeft") { 
1096 
1097                previousPhoto(); 
1098 
1099            } 
1100 
1101 
1102            if (e.key === "+") { 
1103 
1104                zoomLevel += 0.2; 
1105 
1106                if (zoomLevel > 3) { 
1107                    zoomLevel = 3; 
1108                } 
1109 
1110                applyZoom(); 
1111 
1112            } 
1113 
1114 
1115            if (e.key === "-") { 
1116 
1117                zoomLevel -= 0.2; 
1118 
1119                if (zoomLevel < 0.5) { 
1120                    zoomLevel = 0.5; 
1121                } 
1122 
1123                applyZoom(); 
1124 
1125            } 
1126 
1127        } 
1128    ); 
1129 
1130 
1131    /* ===================================== 
1132       CLICK OUTSIDE IMAGE 
1133    ====================================== */ 
1134 
1135    lightbox.addEventListener( 
1136        "click", 
1137        function(e) { 
1138 
1139            if (e.target === lightbox) { 
1140 
1141                closeLightbox(); 
1142 
1143            } 
1144 
1145        } 
1146    ); 
1147 
1148 
1149    /* ===================================== 
1150       INITIAL LOAD 
1151    ====================================== */ 
1152loadCategories(); 
1153    displayGallery(); 
1154 
1155    createPagination(); 
1156 
1157</script> 
1158 
1159<link 
1160        rel="stylesheet" 
1161        href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" 
1162    > 
1163 
1164    <style> 
1165 
1166        /* ========================= 
1167           GENERAL 
1168        ========================= */ 
1169 
1170        body { 
1171            background: #f5f7fa; 
1172            font-family: Arial, Helvetica, sans-serif; 
1173        } 
1174 
1175        .gallery-wrapper { 
1176            max-width: 1400px; 
1177            margin: 40px auto; 
1178            padding: 0 20px; 
1179        } 
1180 
1181 
1182        /* ========================= 
1183           HEADER 
1184        ========================= */ 
1185 
1186        .gallery-header { 
1187            background: linear-gradient(135deg, #073b70, #0d5ca8); 
1188            color: #ffffff; 
1189            padding: 30px 20px; 
1190            border-radius: 10px 10px 0 0; 
1191            text-align: center; 
1192        } 
1193 
1194        .gallery-header h1 { 
1195            font-size: 32px; 
1196            font-weight: 700; 
1197            margin-bottom: 8px; 
1198        } 
1199 
1200        .gallery-header p { 
1201            margin: 0; 
1202            font-size: 16px; 
1203            opacity: 0.9; 
1204        } 
1205 
1206 
1207        /* ========================= 
1208           FILTER BAR 
1209        ========================= */ 
1210 
1211        .gallery-toolbar { 
1212            background: #ffffff; 
1213            padding: 20px; 
1214            border-left: 1px solid #ddd; 
1215            border-right: 1px solid #ddd; 
1216        } 
1217 
1218        .photo-count { 
1219            font-weight: 600; 
1220            color: #555; 
1221        } 
1222 
1223 
1224        /* ========================= 
1225           GALLERY 
1226        ========================= */ 
1227 
1228        .gallery-grid { 
1229            background: #ffffff; 
1230            padding: 20px; 
1231            border-left: 1px solid #ddd; 
1232            border-right: 1px solid #ddd; 
1233        } 
1234 
1235        .photo-card { 
1236            background: #ffffff; 
1237            border: 1px solid #dee2e6; 
1238            border-radius: 8px; 
1239            overflow: hidden; 
1240            height: 100%; 
1241            transition: all 0.3s ease; 
1242        } 
1243 
1244        .photo-card:hover { 
1245            transform: translateY(-5px); 
1246            box-shadow: 0 8px 20px rgba(0,0,0,0.12); 
1247        } 
1248 
1249        .photo-image-wrapper { 
1250            position: relative; 
1251            height: 220px; 
1252            overflow: hidden; 
1253            cursor: pointer; 
1254            background: #eee; 
1255        } 
1256 
1257        .photo-image { 
1258            width: 100%; 
1259            height: 100%; 
1260            object-fit: cover; 
1261            transition: transform 0.4s ease; 
1262        } 
1263 
1264        .photo-card:hover .photo-image { 
1265            transform: scale(1.06); 
1266        } 
1267 
1268        .zoom-icon { 
1269            position: absolute; 
1270            right: 10px; 
1271            top: 10px; 
1272 
1273            width: 38px; 
1274            height: 38px; 
1275 
1276            border-radius: 50%; 
1277 
1278            display: flex; 
1279            align-items: center; 
1280            justify-content: center; 
1281 
1282            background: rgba(0,0,0,0.65); 
1283            color: white; 
1284 
1285            font-size: 18px; 
1286        } 
1287 
1288        .photo-title { 
1289            padding: 14px; 
1290            text-align: center; 
1291            font-size: 16px; 
1292            font-weight: 600; 
1293            color: #333; 
1294        } 
1295 
1296 
1297        /* ========================= 
1298           PAGINATION 
1299        ========================= */ 
1300 
1301        .pagination-wrapper { 
1302            background: #ffffff; 
1303            padding: 20px; 
1304            border: 1px solid #ddd; 
1305            border-top: 0; 
1306            border-radius: 0 0 10px 10px; 
1307        } 
1308 
1309        .pagination .page-link { 
1310            color: #0d5ca8; 
1311            margin: 0 3px; 
1312            border-radius: 6px; 
1313        } 
1314 
1315        .pagination .page-item.active .page-link { 
1316            background: #0d5ca8; 
1317            border-color: #0d5ca8; 
1318            color: white; 
1319        } 
1320 
1321 
1322        /* ========================= 
1323           LIGHTBOX 
1324        ========================= */ 
1325 
1326        .lightbox { 
1327            position: fixed; 
1328            inset: 0; 
1329 
1330            background: rgba(0,0,0,0.92); 
1331 
1332            z-index: 9999; 
1333 
1334            display: none; 
1335 
1336            align-items: center; 
1337            justify-content: center; 
1338 
1339            padding: 20px; 
1340        } 
1341 
1342        .lightbox.show { 
1343            display: flex; 
1344        } 
1345 
1346        .lightbox-content { 
1347            position: relative; 
1348 
1349            width: 100%; 
1350            max-width: 1100px; 
1351 
1352            max-height: 95vh; 
1353 
1354            display: flex; 
1355            flex-direction: column; 
1356 
1357            background: #111; 
1358 
1359            border-radius: 8px; 
1360 
1361            overflow: hidden; 
1362        } 
1363 
1364 
1365        /* ========================= 
1366           LIGHTBOX IMAGE 
1367        ========================= */ 
1368 
1369        .lightbox-image-container { 
1370            position: relative; 
1371 
1372            width: 100%; 
1373            height: 75vh; 
1374 
1375            display: flex; 
1376            align-items: center; 
1377            justify-content: center; 
1378 
1379            background: #000; 
1380 
1381            overflow: hidden; 
1382        } 
1383 
1384        #lightboxImage { 
1385            max-width: 100%; 
1386            max-height: 100%; 
1387 
1388            object-fit: contain; 
1389 
1390            transition: transform 0.3s ease; 
1391        } 
1392 
1393 
1394        /* ========================= 
1395           CLOSE BUTTON 
1396        ========================= */ 
1397 
1398        .lightbox-close { 
1399            position: absolute; 
1400 
1401            top: 15px; 
1402            right: 15px; 
1403 
1404            width: 42px; 
1405            height: 42px; 
1406 
1407            border: 0; 
1408            border-radius: 50%; 
1409 
1410            background: rgba(0,0,0,0.65); 
1411            color: white; 
1412 
1413            font-size: 25px; 
1414 
1415            z-index: 10; 
1416        } 
1417 
1418        .lightbox-close:hover { 
1419            background: rgba(255,255,255,0.25); 
1420        } 
1421 
1422 
1423        /* ========================= 
1424           PREVIOUS / NEXT 
1425        ========================= */ 
1426 
1427        .lightbox-prev, 
1428        .lightbox-next { 
1429            position: absolute; 
1430 
1431            top: 50%; 
1432            transform: translateY(-50%); 
1433 
1434            width: 50px; 
1435            height: 60px; 
1436 
1437            border: none; 
1438 
1439            background: rgba(0,0,0,0.65); 
1440            color: white; 
1441 
1442            font-size: 30px; 
1443 
1444            z-index: 5; 
1445        } 
1446 
1447        .lightbox-prev { 
1448            left: 15px; 
1449            border-radius: 8px; 
1450        } 
1451 
1452        .lightbox-next { 
1453            right: 15px; 
1454            border-radius: 8px; 
1455        } 
1456 
1457        .lightbox-prev:hover, 
1458        .lightbox-next:hover { 
1459            background: rgba(255,255,255,0.2); 
1460        } 
1461 
1462 
1463        /* ========================= 
1464           LIGHTBOX FOOTER 
1465        ========================= */ 
1466 
1467        .lightbox-footer { 
1468            min-height: 65px; 
1469 
1470            padding: 12px 20px; 
1471 
1472            display: flex; 
1473 
1474            align-items: center; 
1475 
1476            justify-content: space-between; 
1477 
1478            color: white; 
1479 
1480            background: #151515; 
1481        } 
1482 
1483        .lightbox-title { 
1484            font-weight: 600; 
1485            font-size: 17px; 
1486        } 
1487 
1488        .lightbox-counter { 
1489            font-size: 14px; 
1490            color: #ccc; 
1491        } 
1492 
1493        .lightbox-actions { 
1494            display: flex; 
1495            gap: 8px; 
1496        } 
1497 
1498        .lightbox-actions button { 
1499            width: 38px; 
1500            height: 38px; 
1501 
1502            border: 1px solid #555; 
1503 
1504            border-radius: 5px; 
1505 
1506            background: #222; 
1507            color: white; 
1508        } 
1509 
1510        .lightbox-actions button:hover { 
1511            background: #444; 
1512        } 
1513 
1514 
1515        /* ========================= 
1516           RESPONSIVE 
1517        ========================= */ 
1518 
1519        @media (max-width: 768px) { 
1520 
1521            .gallery-wrapper { 
1522                margin: 15px auto; 
1523                padding: 0 10px; 
1524            } 
1525 
1526            .gallery-header h1 { 
1527                font-size: 24px; 
1528            } 
1529 
1530            .photo-image-wrapper { 
1531                height: 180px; 
1532            } 
1533 
1534            .lightbox { 
1535                padding: 5px; 
1536            } 
1537 
1538            .lightbox-image-container { 
1539                height: 75vh; 
1540            } 
1541 
1542            .lightbox-footer { 
1543                flex-wrap: wrap; 
1544                gap: 10px; 
1545            } 
1546 
1547            .lightbox-prev, 
1548            .lightbox-next { 
1549                width: 40px; 
1550                height: 50px; 
1551                font-size: 24px; 
1552            } 
1553 
1554            .lightbox-prev { 
1555                left: 5px; 
1556            } 
1557 
1558            .lightbox-next { 
1559                right: 5px; 
1560            } 
1561        } 
1562			 
1563			 
1564		 
1565			 
1566			 
1567			 
1568			/* ===================================== 
1569   MODERN GALLERY TOOLBAR 
1570===================================== */ 
1571 
1572.gallery-toolbar { 
1573 
1574    background: #ffffff; 
1575 
1576    padding: 24px 30px; 
1577 
1578    border-left: 1px solid #e1e5eb; 
1579 
1580    border-right: 1px solid #e1e5eb; 
1581 
1582    border-bottom: 1px solid #e1e5eb; 
1583 
1584} 
1585 
1586 
1587/* ===================================== 
1588   FILTER ROW 
1589===================================== */ 
1590 
1591.gallery-filter-row { 
1592 
1593    display: flex; 
1594 
1595    align-items: flex-end; 
1596 
1597    gap: 24px; 
1598 
1599} 
1600 
1601 
1602/* ===================================== 
1603   FILTER GROUP 
1604===================================== */ 
1605 
1606.filter-group { 
1607 
1608    display: flex; 
1609 
1610    flex-direction: column; 
1611 
1612    gap: 8px; 
1613 
1614} 
1615 
1616 
1617.filter-group label { 
1618 
1619    font-size: 13px; 
1620 
1621    font-weight: 600; 
1622 
1623    color: #344054; 
1624 
1625    margin: 0; 
1626 
1627} 
1628 
1629 
1630.filter-group label i { 
1631 
1632    margin-right: 5px; 
1633 
1634    color: #145a96; 
1635 
1636} 
1637 
1638 
1639/* ===================================== 
1640   CATEGORY 
1641===================================== */ 
1642 
1643.category-group { 
1644 
1645    width: 250px; 
1646 
1647} 
1648 
1649 
1650.select-wrapper { 
1651 
1652    position: relative; 
1653 
1654} 
1655 
1656 
1657.gallery-select { 
1658 
1659    width: 100%; 
1660 
1661    height: 48px; 
1662 
1663    padding: 0 42px 0 15px; 
1664 
1665    border: 1px solid #d0d5dd; 
1666 
1667    border-radius: 8px; 
1668 
1669    background: #ffffff; 
1670 
1671    color: #344054; 
1672 
1673    font-size: 15px; 
1674 
1675    cursor: pointer; 
1676 
1677    appearance: none; 
1678 
1679    -webkit-appearance: none; 
1680 
1681    transition: all 0.2s ease; 
1682 
1683} 
1684 
1685 
1686.gallery-select:hover { 
1687 
1688    border-color: #145a96; 
1689 
1690} 
1691 
1692 
1693.gallery-select:focus { 
1694 
1695    outline: none; 
1696 
1697    border-color: #145a96; 
1698 
1699    box-shadow: 
1700        0 0 0 3px 
1701        rgba(20, 90, 150, 0.12); 
1702 
1703} 
1704 
1705 
1706.select-icon { 
1707 
1708    position: absolute; 
1709 
1710    right: 15px; 
1711 
1712    top: 50%; 
1713 
1714    transform: translateY(-50%); 
1715 
1716    pointer-events: none; 
1717 
1718    color: #667085; 
1719 
1720} 
1721 
1722 
1723/* ===================================== 
1724   SEARCH 
1725===================================== */ 
1726 
1727.search-group { 
1728 
1729    flex: 1; 
1730 
1731    max-width: 500px; 
1732 
1733} 
1734 
1735 
1736.search-wrapper { 
1737 
1738    position: relative; 
1739 
1740} 
1741 
1742 
1743.gallery-search { 
1744 
1745    width: 100%; 
1746 
1747    height: 48px; 
1748 
1749    padding: 
1750        0 45px 
1751        0 42px; 
1752 
1753    border: 1px solid #d0d5dd; 
1754 
1755    border-radius: 8px; 
1756 
1757    background: #ffffff; 
1758 
1759    font-size: 15px; 
1760 
1761    color: #344054; 
1762 
1763    transition: all 0.2s ease; 
1764 
1765} 
1766 
1767 
1768.gallery-search::placeholder { 
1769 
1770    color: #98a2b3; 
1771 
1772} 
1773 
1774 
1775.gallery-search:hover { 
1776 
1777    border-color: #145a96; 
1778 
1779} 
1780 
1781 
1782.gallery-search:focus { 
1783 
1784    outline: none; 
1785 
1786    border-color: #145a96; 
1787 
1788    box-shadow: 
1789        0 0 0 3px 
1790        rgba(20, 90, 150, 0.12); 
1791 
1792} 
1793 
1794 
1795.search-icon { 
1796 
1797    position: absolute; 
1798 
1799    left: 15px; 
1800 
1801    top: 50%; 
1802 
1803    transform: translateY(-50%); 
1804 
1805    color: #667085; 
1806 
1807    pointer-events: none; 
1808 
1809} 
1810 
1811 
1812.clear-search { 
1813 
1814    position: absolute; 
1815 
1816    right: 8px; 
1817 
1818    top: 50%; 
1819 
1820    transform: translateY(-50%); 
1821 
1822    width: 32px; 
1823 
1824    height: 32px; 
1825 
1826    border: none; 
1827 
1828    border-radius: 6px; 
1829 
1830    background: transparent; 
1831 
1832    color: #667085; 
1833 
1834    display: none; 
1835 
1836    align-items: center; 
1837 
1838    justify-content: center; 
1839 
1840    cursor: pointer; 
1841 
1842} 
1843 
1844 
1845.clear-search:hover { 
1846 
1847    background: #f2f4f7; 
1848 
1849    color: #344054; 
1850 
1851} 
1852 
1853 
1854/* ===================================== 
1855   PHOTO COUNT 
1856===================================== */ 
1857 
1858.photo-count-box { 
1859 
1860    min-width: 190px; 
1861 
1862    height: 48px; 
1863 
1864    padding: 6px 14px; 
1865 
1866    border-radius: 8px; 
1867 
1868    background: #f4f8fc; 
1869 
1870    border: 1px solid #dce8f3; 
1871 
1872    display: flex; 
1873 
1874    align-items: center; 
1875 
1876    gap: 11px; 
1877 
1878} 
1879 
1880 
1881.count-icon { 
1882 
1883    width: 36px; 
1884 
1885    height: 36px; 
1886 
1887    border-radius: 7px; 
1888 
1889    display: flex; 
1890 
1891    align-items: center; 
1892 
1893    justify-content: center; 
1894 
1895    background: #145a96; 
1896 
1897    color: #ffffff; 
1898 
1899    font-size: 17px; 
1900 
1901} 
1902 
1903 
1904.count-content { 
1905 
1906    display: flex; 
1907 
1908    align-items: center; 
1909 
1910    gap: 8px; 
1911 
1912} 
1913 
1914 
1915.count-label { 
1916 
1917    font-size: 13px; 
1918 
1919    color: #667085; 
1920 
1921    white-space: nowrap; 
1922 
1923} 
1924 
1925 
1926.count-content strong { 
1927 
1928    font-size: 20px; 
1929 
1930    color: #145a96; 
1931 
1932    line-height: 1; 
1933 
1934} 
1935 
1936 
1937/* ===================================== 
1938   RESPONSIVE 
1939===================================== */ 
1940 
1941@media (max-width: 900px) { 
1942 
1943    .gallery-filter-row { 
1944 
1945        flex-wrap: wrap; 
1946 
1947    } 
1948 
1949    .category-group { 
1950 
1951        flex: 1; 
1952 
1953        min-width: 220px; 
1954 
1955    } 
1956 
1957    .search-group { 
1958 
1959        min-width: 280px; 
1960 
1961    } 
1962 
1963    .photo-count-box { 
1964 
1965        min-width: 180px; 
1966 
1967    } 
1968 
1969} 
1970 
1971 
1972@media (max-width: 600px) { 
1973 
1974    .gallery-toolbar { 
1975 
1976        padding: 18px; 
1977 
1978    } 
1979 
1980    .gallery-filter-row { 
1981 
1982        flex-direction: column; 
1983 
1984        align-items: stretch; 
1985 
1986        gap: 16px; 
1987 
1988    } 
1989 
1990    .category-group, 
1991    .search-group { 
1992 
1993        width: 100%; 
1994 
1995        max-width: none; 
1996 
1997    } 
1998 
1999    .photo-count-box { 
2000 
2001        width: 100%; 
2002 
2003    } 
2004 
2005} 
2006			 
2007			 
2008 
2009    </style>