PageSourceSearch

https://education.gov.pg/news

html education.gov.pg collected 2026-10-02 17:40:53 UTC 57,881 bytes, 1,002 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3
4<head>
5    <base href="/">
6    <meta charset="UTF-8">
7    <meta name="viewport" content="width=device-width, initial-scale=1.0">
8    
9    <!-- Security Headers -->
10    <meta http-equiv="X-XSS-Protection" content="1; mode=block">
11    <meta http-equiv="X-Content-Type-Options" content="nosniff">
12    <meta name="referrer" content="strict-origin-when-cross-origin">
13    <meta http-equiv="Content-Security-Policy" content="default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval'; object-src 'none'; base-uri 'self';">
14
15    <title>Department of Education | Papua New Guinea</title>
16    
17    <!-- DOMPurify for XSS Protection -->
18    
18<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.6/purify.min.js"></script>
18
19
20    <!-- Site Health & Error Tracker -->
21    
21<script>
22        window.addEventListener('error', function (e) {
23            const errorMsg = e.message || 'Unknown JS Error';
24            const stack = e.error && e.error.stack ? e.error.stack.split('\n')[1] || '' : '';
25
26            fetch('api/error_logger.php?action=log', {
27                method: 'POST',
28                headers: { 'Content-Type': 'application/json' },
29                body: JSON.stringify({
30                    type: 'FRONTEND',
31                    message: errorMsg + ' ' + stack,
32                    url: window.location.href,
33                    line_number: e.lineno ? (e.lineno + ':' + e.colno) : 'N/A'
34                })
35            }).catch(err => console.error('Error logging failed', err));
36        });
37
38        window.addEventListener('unhandledrejection', function (e) {
39            const errorMsg = e.reason ? (e.reason.message || e.reason) : 'Unhandled Promise Rejection';
40            fetch('api/error_logger.php?action=log', {
41                method: 'POST',
42                headers: { 'Content-Type': 'application/json' },
43                body: JSON.stringify({
44                    type: 'FRONTEND',
45                    message: 'Promise Rejection: ' + errorMsg,
46                    url: window.location.href,
47                    line_number: 'N/A'
48                })
49            }).catch(err => console.error('Error logging failed', err));
50        });
51    </script>
51
52    <meta name="description"
53        content="National Department of Education Papua Guinea - Providing quality education, curriculum resources, and administrative services for all PNG citizens.">
54    <meta name="keywords"
55        content="Education PNG, Papua New Guinea Schools, DoE PNG, Curriculum Resources, Teacher Resources, PNG Education Portal">
56    <link rel="canonical" href="https://education.gov.pg">
57
58    <!-- Cache Control: Force browser to always check for the newest index.html -->
59    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
60    <meta http-equiv="Pragma" content="no-cache">
61    <meta http-equiv="Expires" content="0">
62
63    <!-- Open Graph / Facebook -->
64    <meta property="og:type" content="website">
65    <meta property="og:url" content="https://education.gov.pg/">
66    <meta property="og:title" content="Department of Education | Papua New Guinea">
67    <meta property="og:description"
68        content="Providing quality education and resources for all citizens of Papua New Guinea.">
69    <meta property="og:image" content="https://education.gov.pg/assets/images/logo/DoE-Logo.png">
70
71    <!-- Twitter -->
72    <meta property="twitter:card" content="summary_large_image">
73    <meta property="twitter:url" content="https://education.gov.pg/">
74    <meta property="twitter:title" content="Department of Education | Papua New Guinea">
75    <meta property="twitter:description"
76        content="Providing quality education and resources for all citizens of Papua New Guinea.">
77    <meta property="twitter:image" content="https://education.gov.pg/assets/images/logo/DoE-Logo.png">
78
79    <!-- Styles & Fonts -->
80    <link rel="preconnect" href="https://fonts.googleapis.com">
81    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
82    <link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=Outfit:wght@300;400;500;600;700;800&display=swap"
83        rel="stylesheet">
84    <link rel="icon" id="favicon" type="image/png" href="assets/images/fav-icon/android-chrome-192x192.png">
85    <link rel="stylesheet" href="styles.css?v=2026.22">
86
87    <!-- Lucide Icons -->
88    
88<script src="https://unpkg.com/lucide@latest" defer></script>
88
89
90    <!-- Preload Critical Assets -->
91    <link rel="preload" href="components/api.js?v=2026.20" as="script">
92    <link rel="preload" href="router.js?v=2026.20" as="script">
93    <link rel="preload" href="components/home.js?v=2026.20" as="script">
94
95    <meta name="theme-color" content="#0a0d14">
96</head>
97
98<body>
99    <!-- Loading Animation Overlay -->
100    <div id="loading-overlay">
101        <div class="loader-content">
102            <div class="crest-container">
103                <img src="assets/images/logo/DoE-Logo.png?v=2" alt="Department Crest" class="loader-crest">
104                <div class="loader-ripple"></div>
105                <div class="loader-spinner"></div>
106            </div>
107            <h2 class="loader-title">Department of Education</h2>
108            <p class="loader-subtitle">Papua New Guinea</p>
109            <div class="loader-progress-bar">
110                <div class="loader-progress-line"></div>
111            </div>
112        </div>
113    </div>
114
115    <div id="toast-container" class="toast-container"></div>
116    <div id="glow-blob"></div>
117
118    <header class="glass-header">
119        <!-- Top Branding Banner (Teaching Service Commission Style) -->
120        <div class="top-branding-banner">
121            <div class="banner-inner">
122                <!-- Left Emblem: Papua New Guinea Coat of Arms -->
123                <div class="banner-logo-container left-logo">
124                    <img id="top-brand-logo-left" src="assets/images/logo/logo-2.png" alt="Papua New Guinea National Emblem" class="banner-logo">
125                </div>
126                
127                <!-- Center Content: Title, Country, and Tagline -->
128                <div class="banner-text-center">
129                    <div class="banner-country-wrapper">
130                        <span class="banner-line"></span>
131                        <span class="banner-country">PAPUA NEW GUINEA</span>
132                        <span class="banner-line right"></span>
133                    </div>
134                    <h1 class="banner-title">DEPARTMENT OF EDUCATION</h1>
135                    <div class="banner-divider">
136                        <span class="divider-line"></span>
137                        <span class="divider-diamond"></span>
138                        <span class="divider-line right"></span>
139                    </div>
140                    <p class="banner-tagline">"QUALITY EDUCATION FOR ALL"</p>
141                </div>
142                
143                <!-- Right Emblem: Department of Education Crest -->
144                <div class="banner-logo-container right-logo">
145                    <img id="top-brand-logo-right" src="assets/images/logo/DoE-Logo.png" alt="Department of Education Crest" class="banner-logo">
146                </div>
147            </div>
148        </div>
149
150        <div class="header-container">
151            <a href="/home" class="logo">
152                <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
153                    alt="Department Logo" id="header-logo" class="logo-img-placeholder">
154                <div class="logo-text">
155                    <h1 id="header-title">Department of Education</h1>
156                    <span id="header-subtitle">Papua New Guinea</span>
157                </div>
158            </a>
159
160            <nav class="main-nav">
161                <!-- Mobile Menu Header (logo + close btn) -->
162                <div class="mobile-nav-header">
163                    <a href="/home" class="mobile-nav-logo">
164                        <img id="mobile-nav-logo-img" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" alt="DoE Logo">
165                        <div class="mobile-nav-logo-text">
166                            <span class="mobile-nav-title">Department of Education</span>
167                            <span class="mobile-nav-subtitle">Papua New Guinea</span>
168                        </div>
169                    </a>
170                <button class="mobile-nav-close" id="mobile-nav-close-btn" aria-label="Close Menu">&times;</button>
171                </div>
172
173                <!-- Nav Links -->
174                <div class="mobile-nav-links">
175                    <!-- Home -->
176                    <a href="/home" class="nav-link">Home</a>
177
178                    <!-- About -->
179                    <div class="dropdown">
180                        <a href="/about" class="nav-link">About <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
181                                fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
182                                stroke-linejoin="round" class="lucide lucide-chevron-down nav-icon-sm arrow">
183                                <path d="m6 9 6 6 6-6" />
184                            </svg></a>
185                        <div class="dropdown-content glass-panel">
186                            <a href="/about" class="dropdown-item">Mission & Vision</a>
187                            <a href="/activities" class="dropdown-item">Programs & Activities</a>
188                            <a href="/careers" class="dropdown-item">Job Opportunities</a>
189                            <a href="/pngetv75" class="dropdown-item highlight-primary">Vision 2075</a>
190                            <a href="/leap" class="dropdown-item highlight-primary">PNG LEAP</a>
191                            <a href="/gesi" class="dropdown-item highlight-primary">GESI</a>
192                            <a href="/faq" class="dropdown-item highlight-primary">FAQ (Help Center)</a>
193                            <a href="http://eduportal.educationpng.gov.pg/" target="_blank" rel="noopener" class="dropdown-item highlight-primary">DoE Portal</a>
194                        </div>
195                    </div>
196
197                    <!-- Schools -->
198                    <div class="dropdown">
199                        <a href="javascript:void(0)" class="nav-link">Schools <svg xmlns="http://www.w3.org/2000/svg"
200                                viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
201                                stroke-linecap="round" stroke-linejoin="round"
202                                class="lucide lucide-chevron-down nav-icon-sm arrow">
203                                <path d="m6 9 6 6 6-6" />
204                            </svg></a>
205                        <div class="dropdown-content glass-panel">
206                            <a href="http://apps.education.gov.pg:8080/ords/f?p=2024:LOGIN_DESKTOP" target="_blank"
207                                rel="noopener" class="dropdown-item">EMIS System</a>
208                            <a href="http://mypng.school/" target="_blank" rel="noopener"
209                                class="dropdown-item">MyPNGSchool</a>
210                            <a href="/gfep" class="dropdown-item highlight-primary">GFEP</a>
211                        </div>
212                    </div>
213
214                    <!-- Curriculum -->
215                    <div class="dropdown">
216                        <a href="javascript:void(0)" class="nav-link">Curriculum <svg xmlns="http://www.w3.org/2000/svg"
217                                viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
218                                stroke-linecap="round" stroke-linejoin="round"
219                                class="lucide lucide-chevron-down nav-icon-sm arrow">
220                                <path d="m6 9 6 6 6-6" />
221                            </svg></a>
222                        <div class="dropdown-content glass-panel">
223                            <a href="/elementary" class="dropdown-item">Prep</a>
224                            <a href="/primary" class="dropdown-item">Primary</a>
225                            <a href="/secondary" class="dropdown-item">Secondary</a>
226                            <a href="/textbooks" class="dropdown-item">Textbooks & Teacher Guides</a>
227                        </div>
228                    </div>
229
230                    <!-- Services -->
231                    <div class="dropdown">
232                        <a href="javascript:void(0)" class="nav-link">Services <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
233                                fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
234                                stroke-linejoin="round" class="lucide lucide-chevron-down nav-icon-sm arrow">
235                                <path d="m6 9 6 6 6-6" />
236                            </svg></a>
237                        <div class="dropdown-content glass-panel">
238                            <!-- For Teachers -->
239                            <div class="nested-dropdown" id="services-teachers-nested">
240                                <div class="dropdown-item nested-trigger" onclick="toggleNested(event)">
241                                    For Teachers <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
242                                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
243                                        stroke-linejoin="round" class="lucide lucide-chevron-right nav-icon-sm arrow">
244                                        <path d="m9 18 6-6-6-6" />
245                                    </svg>
246                                </div>
247                                <div class="nested-content">
248                                    <a href="http://apps.education.gov.pg:8081/ords/f?p=144" target="_blank" class="dropdown-item sub-item">MyPaySlip Portal</a>
249                                    <a href="/contact" class="dropdown-item sub-item">Pay & Allowance Enquiries</a>
250                                    <a href="/teachers" class="dropdown-item sub-item">Teacher Postings & TSC Appts</a>
251                                    <a href="/teachers" class="dropdown-item sub-item">Professional Training</a>
252                                    <a href="/teachers" class="dropdown-item sub-item">Teacher Information</a>
253                                </div>
254                            </div>
255                            
256                            <!-- For Students & Parents -->
257                            <div class="nested-dropdown" id="services-students-nested">
258                                <div class="dropdown-item nested-trigger" onclick="toggleNested(event)">
259                                    For Students & Parents <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
260                                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
261                                        stroke-linejoin="round" class="lucide lucide-chevron-right nav-icon-sm arrow">
262                                        <path d="m9 18 6-6-6-6" />
263                                    </svg>
264                                </div>
265                                <div class="nested-content">
266                                    <a href="/elementary" class="dropdown-item sub-item">FODE Distance Education</a>
267                                    <a href="/elementary" class="dropdown-item sub-item">e-Learning Hub</a>
268                                    <a href="http://apps.education.gov.pg:8081/ords/f?p=103" target="_blank" class="dropdown-item sub-item">Grade 11 Online Selection</a>
269                                    <a href="/publications" class="dropdown-item sub-item">Replacement Certificates (MSD)</a>
270                                    <a href="/careers" class="dropdown-item sub-item">Scholarships</a>
271                                </div>
272                            </div>
273
274                            <!-- For School Administration -->
275                            <div class="nested-dropdown" id="services-admin-nested">
276                                <div class="dropdown-item nested-trigger" onclick="toggleNested(event)">
277                                    For School Administration <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
278                                        fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
279                                        stroke-linejoin="round" class="lucide lucide-chevron-right nav-icon-sm arrow">
280                                        <path d="m9 18 6-6-6-6" />
281                                    </svg>
282                                </div>
283                                <div class="nested-content">
284                                    <a href="http://apps.education.gov.pg:8080/ords/f?p=2024
284:LOGIN_DESKTOP" target="_blank" class="dropdown-item sub-item">EMIS & School Census</a>
285                                    <a href="/forms" class="dropdown-item sub-item">School Registration Guide</a>
286                                    <a href="/about" class="dropdown-item sub-item">Inspections & Quality Standards</a>
287                                    <a href="/provincial-sites" class="dropdown-item sub-item">Provincial Sites</a>
288                                </div>
289                            </div>
290                        </div>
291                    </div>
292
293                    <!-- News -->
294                    <div class="dropdown">
295                        <a href="/news" class="nav-link">News <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
296                                fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
297                                stroke-linejoin="round" class="lucide lucide-chevron-down nav-icon-sm arrow">
298                                <path d="m6 9 6 6 6-6" />
299                            </svg></a>
300                        <div class="dropdown-content glass-panel">
301                            <a href="/news" class="dropdown-item">Latest News</a>
302                            <a href="/press-release" class="dropdown-item">Press Releases</a>
303                            <a href="/gallery" class="dropdown-item">Event Gallery</a>
304                            <a href="/calendars" class="dropdown-item">Term Dates & Calendars</a>
305                        </div>
306                    </div>
307
308                    <!-- Resources -->
309                    <div class="dropdown">
310                        <a href="javascript:void(0)" class="nav-link">Resources <svg xmlns="http://www.w3.org/2000/svg"
311                                viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
312                                stroke-linecap="round" stroke-linejoin="round"
313                                class="lucide lucide-chevron-down nav-icon-sm arrow">
314                                <path d="m6 9 6 6 6-6" />
315                            </svg></a>
316                        <div class="dropdown-content glass-panel">
317                            <a href="/publications" class="dropdown-item">Publications & Reports</a>
318                            <a href="/open-data" class="dropdown-item highlight-accent">Open Data</a>
319                            <a href="/app-gallery" class="dropdown-item highlight-accent">Digital Applications</a>
320                            <a href="/forms" class="dropdown-item">Forms & Downloads</a>
321                            <a href="https://fode.education.gov.pg/" class="dropdown-item" target="_blank" rel="noopener noreferrer">FODE Website</a>
322                        </div>
323                    </div>
324
325                    <!-- Contact -->
326                    <a href="/contact" class="nav-link">Contact</a>
327
328                    <span class="desktop-search-divider hide-on-mobile" style="color: rgba(255,255,255,0.3); margin: 0 0.5rem; display: flex; align-items: center; cursor: default; user-select: none;">|</span>
329                    
330                    <!-- Search Icon (Desktop) -->
331                    <a href="javascript:void(0)" id="header-search-icon" class="nav-link hide-on-mobile" aria-label="Search" style="gap: 0.4rem; padding-left: 0.5rem;">
332                        <svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
333                            stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
334                            class="lucide lucide-search">
335                            <circle cx="11" cy="11" r="8"></circle>
336                            <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
337                        </svg>
338                        <span style="font-weight: 500;">Search</span>
339                    </a>
340                </div>
341
342            </nav>
343
344            <div class="header-actions">
345                <button class="mobile-toggle" id="hamburger-toggle" aria-label="Toggle Menu">
346                    <span></span><span></span><span></span>
347                </button>
348            </div>
349        </div>
350    </header>
351
352    <!-- Search Overlay -->
353    <div class="search-overlay" id="search-overlay">
354        <!-- Close button is a direct child of overlay, NOT inner - prevents transform breaking position:fixed -->
355        <button class="search-close-btn" id="search-close-btn" aria-label="Close Search">&times;</button>
356        <div class="search-overlay-inner">
357            <h2 class="search-overlay-title">Search the Department of Education</h2>
358            <div class="search-input-wrapper">
359                <svg class="search-input-icon" viewBox="0 0 24 24" width="22" height="22" fill="none"
360                    stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
361                    <circle cx="11" cy="11" r="8" />
362                    <line x1="21" y1="21" x2="16.65" y2="16.65" />
363                </svg>
364                <input type="text" id="site-search-input" class="search-input"
365                    placeholder="Type to search pages, news, publications..." autocomplete="off">
366            </div>
367            <div class="search-results" id="search-results">
368                <div class="search-placeholder-text">Start typing to find pages, news articles, forms, and more...</div>
369            </div>
370        </div>
371    </div>
372
373    <!-- Gallery Modal (Album/Category View) -->
374    <div class="gallery-modal" id="gallery-modal">
375        <div class="gallery-modal-inner">
376            <span class="gallery-modal-close" id="gallery-modal-close">&times;</span>
377            <div id="gallery-album-header" class="gallery-album-header">
378                <h2 id="gallery-album-title" class="gallery-album-title"></h2>
379                <p id="gallery-album-desc" class="gallery-album-desc"></p>
380            </div>
381            <div class="gallery-modal-grid" id="gallery-modal-grid">
382                <!-- Category images will be injected here -->
383            </div>
384        </div>
385    </div>
386
387    <div class="detail-modal" id="detail-modal">
388        <span class="detail-modal-close" id="detail-modal-close">&times;</span>
389        <img class="detail-modal-content" id="detail-modal-img" alt="Detailed event image view">
390    </div>
391
392    <main id="app-content">
393        <!-- SPA Content injected here by router.js -->
394    </main>
395
396    <footer class="solid-footer">
397        <div class="footer-container">
398            <div class="footer-col col-brand">
399                <div class="footer-brand" id="footer-brand-container">
400                    <img src="assets/images/logo/DoE-Logo.png" alt="Department Logo" class="footer-logo">
401                </div>
402                <div class="footer-brand-text">
403                    <h3 id="footer-brand-title">Department of Education</h3>
404                    <span id="footer-brand-subtitle">Papua New Guinea</span>
405                </div>
406                <div class="footer-brand-divider"></div>
407                <p id="footer-brand-desc">Ensuring quality education for all children in Papua New Guinea to promote
408                    national growth and opportunities.</p>
409            </div>
410
411            <div class="footer-col col-links">
412                <h3 class="footer-col-header">
413                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
414                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
415                        class="lucide lucide-link footer-header-icon">
416                        <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
417                        <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
418                    </svg>
419                    Quick Links
420                </h3>
421                <a href="/home">
422                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
423                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
424                        class="lucide lucide-home footer-icon">
425                        <path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
426                        <polyline points="9 22 9 12 15 12 15 22" />
427                    </svg>
428                    Home
429                </a>
430                <a href="/about">
431                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
432                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
433                        class="lucide lucide-info footer-icon">
434                        <circle cx="12" cy="12" r="10" />
435                        <path d="M12 16v-4" />
436                        <path d="M12 8h.01" />
437                    </svg>
438                    About the Department
439                </a>
440                <a href="/pngetv75">
441                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
442                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
443                        class="lucide lucide-eye footer-icon">
444                        <path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
445                        <circle cx="12" cy="12" r="3" />
446                    </svg>
447                    Vision 2075 (PNGETV75)
448                </a>
449                <a href="/activities">
450                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
451                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
452                        class="lucide lucide-award footer-icon">
453                        <circle cx="12" cy="8" r="7" />
454                        <polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.88" />
455                    </svg>
456                    Programs & Activities
457                </a>
458                <a href="/publications">
459                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
460                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
461                        class="lucide lucide-file-text footer-icon">
462                        <path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
463                        <path d="M14 2v4a2 2 0 0 0 2 2h4" />
464                        <path d="M10 9H8" />
465                        <path d="M16 13H8" />
466                        <path d="M16 17H8" />
467                    </svg>
468                    Publications & Reports
469                </a>
470                <a href="/news">
471                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
472                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
473                        class="lucide lucide-newspaper footer-icon">
474                        <path
475                            d="M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2" />
476                        <path d="M18 14h-8" />
477                        <path d="M15 18h-5" />
478                        <path d="M10 6h8v4h-8V6Z" />
479                    </svg>
480                    Latest News & Events
481                </a>
482            </div>
483
484            <div class="footer-col col-divisions">
485                <h3 class="footer-col-header">
486                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
487                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
488                        class="lucide lucide-users footer-header-icon">
489                        <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
490                        <circle cx="9" cy="7" r="4"></circle>
491                        <path d="M22 21v-2a4 4 0 0 0-3-3.87"></path>
492                        <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
493                    </svg>
494                    Divisions & Portals
495                </h3>
496                <a href="https://tsc.gov.pg" target="_blank" rel="noopener">
497                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
498                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
499                        class="lucide lucide-users footer-icon">
500                        <path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
501                        <circle cx="9" cy="7" r="4" />
502                        <path d="M22 21v-2a4 4 0 0 0-3-3.87" />
503                        <path d="M16 3.13a4 4 0 0 1 0 7.75" />
504                    </svg>
505                    Teaching Service Commission
506                </a>
507                <a href="https://www.ola.gov.pg/" target="_blank" rel="noopener">
508                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
509                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
510                        class="lucide lucide-book-open footer-icon">
511                        <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z" />
512                        <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z" />
513                    </svg>
514                    National Library & Archives
515                </a>
516                <a href="/publications">
517                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
518                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
519                        class="lucide lucide-clipboard-list footer-icon">
520                        <rect width="8" height="4" x="8" y="2" rx="1" ry="1" />
521                        <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" />
522                        <path d="M12 11h4" />
523                        <path d="M12 16h4" />
524                        <path d="M8 11h.01" />
525                        <path d="M8 16h.01" />
526                    </svg>
527                    Measurement Services
528                </a>
529                <a href="/app-gallery">
530                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
531                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
532                        class="lucide lucide-graduation-cap footer-icon">
533                        <path
534                            d="M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z" />
535                        <path d="M6 12v5c0 2 2 3 6 3s6-1 6-3v-5" />
536                    </svg>
537                    e-Learning Portal
538                </a>
539                <a href="/app-gallery">
540                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
541                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
542                        class="lucide lucide-credit-card footer-icon">
543                        <rect width="20" height="14" x="2" y="5" rx="2" />
544                        <line x1="2" x2="22" y1="10" y2="10" />
545                    </svg>
546                    Teacher MyPay
547                </a>
548                <a href="/about">
549                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
550                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
551                        class="lucide lucide-eye footer-icon">
552                        <path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z" />
553                        <circle cx="12" cy="12" r="3" />
554                    </svg>
555                    School Inspection
556                </a>
557            </div>
558
559            <div class="footer-col col-legal">
560                <h3 class="footer-col-header">
561                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
562                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
563                        class="lucide lucide-shield footer-header-icon">
564                        <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
565                    </svg>
566                    Legal & Connect
567                </h3>
568                <a href="/privacy">
569                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
570                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
571                        class="lucide lucide-lock footer-icon">
572                        <rect width="18" height="11" x="3" y="11" rx="2" ry="2" />
573                        <path d="M7 11V7a5 5 0 0 1 10 0v4" />
574                    </svg>
575                    Privacy Policy
576                </a>
577                <a href="/terms">
578                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
579                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
580                        class="lucide lucide-file-text footer-icon">
581                        <path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" />
582                        <path d="M14 2v4a2 2 0 0 0 2 2h4" />
583                        <path d="M10 9H8" />
584                        <path d="M16 13H8" />
585                        <path d="M16 17H8" />
586                    </svg>
587                    Terms of Use
588                </a>
589                <a href="/accessibility">
590                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
591                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
592                        class="lucide lucide-heart footer-icon">
593                        <path
594                            d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z" />
595                    </svg>
596                    Accessibility Statement
597                </a>
598                <a href="/rti">
599                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
600                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
601                        class="lucide lucide-info footer-icon">
602                        <circle cx="12" cy="12" r="10" />
603                        <path d="M12 16v-4" />
604                        <path d="M12 8h.01" />
605                    </svg>
606                    Right to Information
607                </a>
608                <a href="/faq">
609                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
610                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
611                        class="lucide lucide-help-circle footer-icon">
612                        <circle cx="12" cy="12" r="10" />
613                        <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
614                        <path d="M12 17h.01" />
615                    </svg>
616                    Help & FAQ
617                </a>
618                <a href="/contact">
619                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor"
620                        stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
621                        class="lucide lucide-mail footer-icon">
622                        <rect width="20" height="16" x="2" y="4" rx="2" />
623                        <path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" />
624                    </svg>
625                    Contact Us
626                </a>
627            </div>
628        </div>
629        <div class="footer-bottom">
630            <p id="footer-copyright">&copy; 2026 Department of Education, Papua New Guinea. All rights reserved.</p>
631        </div>
632    </footer>
633
634    <!-- Floating Social Widget -->
635    <div class="floating-social-widget" id="floating-social-widget">
636        <button class="social-main-btn" id="social-main-btn" aria-label="Toggle Social Media">
637            <i data-lucide="share-2" style="width: 20px; height: 20px;"></i>
638        </button>
639        <div class="social-links-container">
640            <a href="https://www.facebook.com/png.doe" target="_blank" rel="noopener noreferrer" class="social-icon-btn facebook" aria-label="Facebook">
641                <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"/></svg>
642            </a>
643            <a href="#" class="social-icon-btn whatsapp" aria-label="WhatsApp">
644                <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-message-circle"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>
645            </a>
646            <a href="https://www.linkedin.com/company/department-of-education-papua-new-guinea" target="_blank" rel="noopener noreferrer" class="social-icon-btn linkedin" aria-label="LinkedIn">
647                <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect width="4" height="12" x="2" y="9"/><circle cx="4" cy="4" r="2"/></svg>
648            </a>
649        </div>
650    </div>
651    
652    
652<script>
653        document.getElementById('social-main-btn').addEventListener('click', function() {
654            document.getElementById('floating-social-widget').classList.toggle('expanded');
655        });
656    </script>
656
657
658    <!-- Back to Top Button -->
659    <button class="back-to-top" id="back-to-top" aria-label="Back to Top">
660        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"
661            stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-up">
662            <path d="m18 15-6-6-6 6" />
663        </svg>
664    </button>
665
666    <!-- Utilities and App Logic -->
667    
667<script src="components/api.js?v=2026.20"></script>
667
668    
668<script src="components/home.js?v=2026.20" defer></script>
668
669    
669<script src="components/about.js?v=2026.20" defer></script>
669
670    
670<script src="components/activities.js?v=2026.20" defer></script>
670
671    
671<script src="components/publications.js?v=2026.20" defer></script>
671
672    
672<script src="components/news.js?v=2026.20" defer></script>
672
673    
673<script src="components/careers.js?v=2026.20" defer></script>
673
674    
674<script src="components/contact.js?v=2026.20" defer></script>
674
675    
675<script src="components/forms.js?v=2026.20" defer></script>
675
676    
676<script src="components/form_detail.js?v=2026.20" defer></script>
676
677    
677<script src="components/app_gallery.js?v=2026.20" defer></script>
677
678    
678<script src="components/news_detail.js?v=2026.20" defer></script>
678
679    
679<script src="components/search.js?v=2026.20" defer></script>
679
680    
680<script src="components/elementary.js?v=2026.20" defer></script>
680
681    
681<script src="components/primary.js?v=2026.20" defer></script>
681
682    
682<script src="components/secondary.js?v=2026.20" defer></script>
682
683    
683<script src="components/textbooks.js?v=2026.20" defer></script>
683
684    
684<script src="components/gfep.js?v=2026.20" defer></script>
684
685    
685<script src="components/teachers.js?v=2026.22" defer></script>
685
686    
686<script src="components/pngetv75.js?v=2026.20" defer></script>
686
687    
687<script alt="legal policy component" src="components/legal.js?v=2026.20" defer></script>
687
688    
688<script src="components/gallery.js?v=2026.20" defer></script>
688
689    
689<script src="components/press-release.js?v=2026.20" defer></script>
689
690    
690<script src="components/scholarships.js?v=2026.20" defer></script>
690
691    
691<script src="components/leaders.js?v=2026.20" defer></script>
691
692    
692<script src="components/faq.js?v=2026.20" defer></script>
692
693    
693<script src="components/calendars.js?v=2026.20" defer></script>
693
694    
694<script src="components/notices.js?v=2026.20" defer></script>
694
695    
695<script src="components/leap.js?v=2026.20" defer></script>
695
696    
696<script src="components/gesi.js?v=2026.20" defer></script>
696
697    
697<script src="components/provincial_sites.js?v=2026.20" defer></script>
697
698    
698<script src="components/open_data.js?v=2026.20" defer></script>
698
699    
699<script src="router.js?v=2026.20" defer></script>
699
700
701    
701<script>
702        // Init Lucide
703        if (window.lucide) lucide.createIcons();
704
705        // Hamburger Menu & Mobile Accordion Logic
706        document.addEventListener('DOMContentLoaded', () => {
707            // Init Lucide safely
708            if (window.lucide) window.lucide.createIcons();
709            const hamburger = document.getElementById('hamburger-toggle');
710            const closeBtn = document.getElementById('mobile-nav-close-btn');
711            const nav = document.querySelector('.main-nav');
712
713            function openMenu() {
714                nav.classList.add('active');
715                hamburger.classList.add('active');
716                document.body.style.overflow = 'hidden';
717                document.body.classList.add('menu-open');
718            }
719
720            function closeMenu() {
721                nav.classList.remove('active');
722                hamburger.classList.remove('active');
723                document.body.style.overflow = '';
724                document.body.classList.remove('menu-open');
725                document.querySelectorAll('.dropdown').forEach(d => d.classList.remove('mobile-expanded'));
726                document.querySelectorAll('.nested-dropdown').forEach(nd => nd.classList.remove('active'));
727            }
728
729            // Hamburger opens the menu
730            if (hamburger) hamburger.addEventListener('click', (e) => { e.stopPropagation(); openMenu(); });
731            // X button closes the menu
732            if (closeBtn) closeBtn.addEventListener('click', (e) => { e.stopPropagation(); closeMenu(); });
733
734            // Handle link clicks natively and smartly
735            nav.querySelectorAll('a').forEach(link => {
736                link.addEventListener('click', (e) => {
737                    const dropdownParent = link.parentElement;
738                    const isMobileAccordion = window.innerWidth <= 1199 && dropdownParent.classList.contains('dropdown') && link.classList.contains('nav-link');
739
740                    if (isMobileAccordion) {
741                        e.preventDefault();
742                        const isAlreadyOpen = dropdownParent.classList.contains('mobile-expanded');
743
744                        // Close all primary dropdowns and nested sub-menus before opening the new one
745                        document.querySelectorAll('.dropdown').forEach(d => d.classList.remove('mobile-expanded'));
746                        document.querySelectorAll('.nested-dropdown').forEach(nd => nd.classList.remove('active'));
747
748                        if (!isAlreadyOpen) {
749                            dropdownParent.classList.add('mobile-expanded');
750                        }
751                    } else {
752                        // Regular link click - close menu
753                        closeMenu();
754                    }
755                });
756            });
757
758            // Global Modal Handlers
759            window.openModal = function (id) {
760                document.getElementById(id).classList.add('active');
761                document.body.style.overflow = 'hidden'; // Stop background scroll
762
763                // Temporarily boost the main wrapper's stacking context strictly over the nav bar
764                const appContainer = document.getElementById('app-content');
765                appContainer.style.position = 'relative';
766                appContainer.style.zIndex = '9999';
767            };
768
769            window.closeModal = function (e, id) {
770                // If the event triggered from the background click OR specifically on the close button
771                if (!e || e.target === e.currentTarget) {
772                    document.getElementById(id).classList.remove('active');
773                    document.body.style.overflow = 'auto'; // Restore scroll
774
775                    // Release the main wrapper constraint so the transparent nav works again
776                    document.getElementById('app-content').style.zIndex = 'auto';
777                }
778            };
779
780            // Toggle nested sub-menus (Accordion style within dropdowns)
781            window.toggleNested = function (e) {
782                e.preventDefault();
783                e.stopPropagation();
784                const parent = e.currentTarget.closest('.nested-dropdown');
785                if (parent) {
786                    // Close other nested sub-menus in the same container
787                    const siblingNested = parent.parentElement.querySelectorAll('.nested-dropdown');
788                    siblingNested.forEach(el => {
789                        if (el !== parent) el.classList.remove('active');
790                    });
791
792                    parent.classList.toggle('active');
793                }
794            };
795
796            // Global Click Away to Close Submenus and Dropdowns
797            document.addEventListener('click', (e) => {
798                const isNav = e.target.closest('.main-nav');
799                const isHamburger = e.target.closest('#hamburger-toggle');
800
801                // Close if clicked outside nav and outside hamburger button
802                if (!isNav && !isHamburger) {
803                    closeMenu();
804                }
805            });
806
807            // Handle Escape key to close everything
808            document.addEventListener('keydown', (e) => {
809                if (e.key === 'Escape') {
810                    closeMenu();
811                    document.querySelectorAll('.modal, .modal-overlay').forEach(m => m.classList.remove('active'));
812                    document.body.style.overflow = '';
813                }
814            });
815            // ─── Table Scroll State Manager ──────────────────────────
816            // Watches for tables injected by the SPA router and applies
817            // at-start / at-end classes for the CSS fade-edge mask.
818            function initTableScrollers(root) {
819                root = root || document;
820                root.querySelectorAll('.table-inner').forEach(function (inner) {
821                    if (inner.dataset.scrollInit) return; // already wired
822                    inner.dataset.scrollInit = '1';
823
824                    function update() {
825                        const atStart = inner.scrollLeft <= 4;
826                        const atEnd = inner.scrollLeft + inner.clientWidth >= inner.scrollWidth - 4;
827                        inner.classList.toggle('at-start', atStart);
828                        inner.classList.toggle('at-end', atEnd);
829
830                        // Show/hide the hint pill
831                        const hint = inner.parentElement.querySelector('.table-scroll-hint');
832                        if (hint) hint.style.display = (inner.scrollWidth > inner.clientWidth) ? 'flex' : 'none';
833                    }
834
835                    // Inject mobile scroll hint if not already there
836                    const wrap = inner.closest('.table-scroll-wrap');
837                    if (wrap && !wrap.querySelector('.table-scroll-hint')) {
838                        const hint = document.createElement('div');
839                        hint.className = 'table-scroll-hint';
840                        hint.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg> Scroll <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>';
841                        wrap.appendChild(hint);
842                    }
843
844                    inner.addEventListener('scroll', update, { passive: true });
845                    window.addEventListener('resize', update, { passive: true });
846                    update(); // run immediately
847                });
848            }
849
850            // Run on first load
851            initTableScrollers();
852
853            // Re-run whenever the SPA injects new content
854            const _appContent = document.getElementById('app-content');
855            if (_appContent) {
856                new MutationObserver(function () {
857                    initTableScrollers(_appContent);
858                }).observe(_appContent, { childList: true, subtree: true });
859            }
860
861            // ─── Back to Top Logic ──────────────────────────
862            const backToTopBtn = document.getElementById('back-to-top');
863            window.addEventListener('scroll', () => {
864                if (window.scrollY > 600) {
865                    backToTopBtn.classList.add('active');
866                } else {
867                    backToTopBtn.classList.remove('active');
868                }
869            }, { passive: true });
870
871            backToTopBtn.addEventListener('click', () => {
872                window.scrollTo({ top: 0, behavior: 'smooth' });
873            });
874
875            // ─── Global Branding Injection ──────────────────
876            async function applyGlobalBranding() {
877                const settings = await window.DoEAPI.loadSettings();
878                if (!settings) return;
879
880                const headerLogoUrl = window.DoEAPI.imgUrl(settings.site_logo);
881                const footerLogoUrl = window.DoEAPI.imgUrl(settings.footer_logo || settings.site_logo);
882
883                // Top Banner Logos
884                const leftLogoUrl = settings.brand_logo_left ? window.DoEAPI.imgUrl(settings.brand_logo_left) : 'assets/images/logo/logo-2.png';
885                const rightLogoUrl = settings.brand_logo_right ? window.DoEAPI.imgUrl(settings.brand_logo_right) : 'assets/images/logo/DoE-Logo.png';
886
887                // Update Logos
888                const hLogo = document.getElementById('header-logo');
889                const fLogo = document.getElementById('footer-logo-img');
890                const lLogo = document.getElementById('top-brand-logo-left');
891                const rLogo = document.getElementById('top-brand-logo-right');
892
893                if (hLogo && headerLogoUrl) hLogo.src = headerLogoUrl;
894                
895                // Footer Logo / Video handling
896                const footerLogoKey = settings.footer_logo || settings.site_logo;
897                const container = document.getElementById('footer-brand-container');
898                if (container && footerLogoKey) {
899                    const isVideo = footerLogoKey.match(/\.(mp4|webm)$/i);
900                    if (isVideo) {
901                        container.innerHTML = `<video src="${footerLogoUrl}" class="footer-logo" autoplay loop muted playsinline preload="auto" style="max-width:100%; border-radius:12px; opacity:1;"></video>`;
902                        setTimeout(() => {
903                            const v = container.querySelector('video');
904                            if (v) v.play().catch(e => console.warn('Autoplay failed:', e));
905                        }, 50);
906                    } else {
907                        container.innerHTML = `<img src="${footerLogoUrl}" alt="Department Logo" class="footer-logo" style="opacity:1;">`;
908                    }
909                } else if (fLogo && footerLogoUrl) {
910                    fLogo.src = footerLogoUrl; fLogo.style.opacity = '1';
911                }
912                if (lLogo && leftLogoUrl) lLogo.src = leftLogoUrl;
913                if (rLogo && rightLogoUrl) rLogo.src = rightLogoUrl;
914
915                // Update Footer Branding (Titles & Text)
916                if (settings.site_description) document.getElementById('footer-brand-desc').innerText = settings.site_description;
917                if (settings.site_copyright) document.getElementById('footer-copyright').innerHTML = settings.site_copyright;
918
919                // Update Footer Brand Name (handles the <br> line break if present)
920                if (settings.site_title) {
921                    const brandTitle = document.getElementById('footer-brand-title');
922                    if (brandTitle) brandTitle.innerText = settings.site_title;
923                }
924
925                // Chatbot Toggle Logic
926                const chatbotEnabled = settings.chatbot_enabled;
927                if (chatbotEnabled === '0' || chatbotEnabled === false || chatbotEnabled === 0) {
928                    const chatBubble = document.getElementById('doe-chat-bubble');
929                    const chatWindow = document.getElementById('doe-chat-window');
930                    if (chatBubble) chatBubble.remove();
931                    if (chatWindow) chatWindow.remove();
932                }
933            }
934
935            // ─── Loading Overlay Logic ──────────────────────
936            let isOverlayHidden = false;
937            let spaLoaded = false;
938            let globalBrandingLoaded = false;
939
940            function hideLoadingOverlay() {
941                if (isOverlayHidden) return;
942                isOverlayHidden = true;
943                const overlay = document.getElementById('loading-overlay');
944                if (overlay) {
945                    overlay.classList.add('fade-out');
946                    setTimeout(() => {
947                        overlay.style.display = 'none';
948                    }, 500); // 500ms matches the CSS fade transition
949                }
950            }
951
952            function checkAndHideIfReady() {
953                if (!spaLoaded || !globalBrandingLoaded) return;
954
955                // Query all images to make sure they are completely loaded
956                const images = Array.from(document.querySelectorAll('img'));
957                const pendingImages = images.filter(img => {
958                    // Ignore placeholder images or images that are already complete
959                    if (!img.src || img.src.startsWith('data:') || img.complete) {
960                        return false;
961                    }
962                    return true;
963                });
964
965                if (pendingImages.length === 0) {
966                    hideLoadingOverlay();
967                } else {
968                    let loadedCount = 0;
969                    const onImageDone = () => {
970                        loadedCount++;
971                        if (loadedCount >= pendingImages.length) {
972                            hideLoadingOverlay();
973                        }
974                    };
975                    pendingImages.forEach(img => {
976                        img.addEventListener('load', onImageDone, { once: true });
977                        img.addEventListener('error', onImageDone, { once: true });
978                    });
979                }
980            }
981
982            // 1. Trigger when branding API responds
983            applyGlobalBranding().finally(() => {
984                globalBrandingLoaded = true;
985                checkAndHideIfReady();
986            });
987
988            // 2. Trigger when SPA Router finishes loading the initial route/component
989            window.addEventListener('spa-route-complete', () => {
990                spaLoaded = true;
991                checkAndHideIfReady();
992            }, { once: true });
993
994            // 3. Fallback timeout in case of slow connections or stuck assets
995            setTimeout(hideLoadingOverlay, 5000);
996        });
997    </script>
997
998    <!-- DoE AI Chatbot (EduBot) -->
999    
999<script src="components/chatbot.js?v=2026.20" defer></script>
999
1000</body>
1001
1002</html>

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