{
    "page_content": "{{-- ============================================================================\r\n     PAGE CONTENT — Galeri (Foto & Video)\r\n     Site  : nres  ·  Page slug: gallery  ·  Page ID: 30\r\n     Sumber: modul media\r\n             · content_photo_gallery (+ _translations) → album foto\r\n             · content_photo_list                      → foto dalam album\r\n             · content_video (+ _translation)          → video\r\n     Konsep: https:\/\/redd.nres.gov.my\/redd-plus\/gallery\r\n             (tab Foto \/ Video + album + lightbox + pemain video)\r\n\r\n     Parameter URL:\r\n       tab        foto (lalai) | video\r\n       kategori   kod GALLERY_CAT (EVENT\/ACTIVITY\/FACILITY\/STAFF\/OTHER) — tab foto\r\n       album      id album → papar foto dalam album itu\r\n       video      id video → auto-buka pemain\r\n\r\n     Nota:\r\n     · SEMUA logik + markup + CSS + JS ada dalam fail ini — tiada komponen, tiada partial.\r\n     · Album: gallery_status = ACTIVE. Foto: photo_main = 1 (baris induk, bukan terjemahan).\r\n     · Video: video_status = ACTIVE. Jenis ikut video_category:\r\n         YOUTUBE  → video_url (embed URL) dipaparkan dalam <iframe>\r\n         UPLOAD   → video_upload (fail pada disk 'public') dipaparkan dalam <video>\r\n         EXTERNAL → video_external: .mp4\/.webm → <video>, pautan YouTube → embed, lain → pautan luar\r\n     · Media disimpan pada disk 'public' → URL = asset('storage\/'.$path).\r\n     · Warna guna CSS variable tema (--teal\/--green\/--fade\/--line\/--ink) → sokong dark mode.\r\n     ============================================================================ --}}\r\n\r\n@php\r\n    \/* --------------------------------------------------------------------\r\n     | 1. Parameter & konteks\r\n     -------------------------------------------------------------------- *\/\r\n    $galBase    = url()->current();\r\n    $galQuery   = request()->query();\r\n    $galLang    = ($lang ?? session('locale', 'ms')) === 'en' ? 'en' : 'ms';\r\n\r\n    $galTab     = (string) ($galQuery['tab'] ?? 'foto');\r\n    $galTab     = in_array($galTab, ['foto', 'video'], true) ? $galTab : 'foto';\r\n\r\n    $galKat     = (string) ($galQuery['kategori'] ?? '');\r\n    $galAlbumId = (int) ($galQuery['album'] ?? 0);\r\n    $galVideoId = (int) ($galQuery['video'] ?? 0);\r\n\r\n    \/\/ URL media: http → kekal; 'dynaweb4\/...' → aset awam; lain → disk 'public'\r\n    $galMedia = function ($path) {\r\n        $path = trim((string) $path);\r\n\r\n        if ($path === '') {\r\n            return '';\r\n        }\r\n\r\n        if (str_starts_with($path, 'http:\/\/') || str_starts_with($path, 'https:\/\/')) {\r\n            return $path;\r\n        }\r\n\r\n        if (str_starts_with($path, 'dynaweb4\/')) {\r\n            return asset($path);\r\n        }\r\n\r\n        return asset('storage\/'.ltrim($path, '\/'));\r\n    };\r\n\r\n    $galTabUrl = fn (string $key) => url()->current().'?tab='.$key;\r\n\r\n    $galUrl = function (array $params = []) use ($galBase, $galTab, $galKat, $galAlbumId, $galVideoId) {\r\n        $query = array_filter([\r\n            'tab'      => array_key_exists('tab', $params) ? $params['tab'] : $galTab,\r\n            'kategori' => array_key_exists('kategori', $params) ? $params['kategori'] : $galKat,\r\n            'album'    => array_key_exists('album', $params) ? $params['album'] : ($galAlbumId ?: null),\r\n            'video'    => array_key_exists('video', $params) ? $params['video'] : null,\r\n        ], fn ($v) => $v !== null && $v !== '');\r\n\r\n        return $query ? $galBase.'?'.http_build_query($query) : $galBase;\r\n    };\r\n\r\n    \/* --------------------------------------------------------------------\r\n     | 2. Rujukan kategori album (GALLERY_CAT) + warna\r\n     -------------------------------------------------------------------- *\/\r\n    $galCatLabel = [];\r\n\r\n    foreach (DB::table('ref')->where('cat', 'GALLERY_CAT')->orderBy('sort')->get() as $galRef) {\r\n        $galCatLabel[(string) $galRef->code] = $galLang === 'en'\r\n            ? ((string) ($galRef->descr_en ?: $galRef->descr))\r\n            : ((string) ($galRef->descr ?: $galRef->descr_en));\r\n    }\r\n\r\n    $galCatColor = [\r\n        'EVENT'    => '#11808f',\r\n        'ACTIVITY' => '#165c4a',\r\n        'FACILITY' => '#b45309',\r\n        'STAFF'    => '#6d28d9',\r\n        'OTHER'    => '#64748b',\r\n    ];\r\n\r\n    if ($galKat !== '' && ! isset($galCatLabel[$galKat])) {\r\n        $galKat = '';\r\n    }\r\n\r\n    $galCatName = fn ($code) => $galCatLabel[(string) $code] ?? (string) $code;\r\n    $galCatTint = fn ($code) => $galCatColor[(string) $code] ?? '#64748b';\r\n\r\n    \/\/ Tarikh paparan: gallery_date disimpan sebagai teks — cuba format, jika gagal kekal asal\r\n    $galDate = function ($value) use ($galLang) {\r\n        $value = trim((string) $value);\r\n\r\n        if ($value === '') {\r\n            return '';\r\n        }\r\n\r\n        try {\r\n            $months = $galLang === 'en'\r\n                ? [1 => 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']\r\n                : [1 => 'Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun', 'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'];\r\n\r\n            $date = \\Carbon\\Carbon::parse($value);\r\n\r\n            return $date->day.' '.$months[(int) $date->month].' '.$date->year;\r\n        } catch (\\Throwable $e) {\r\n            return $value;\r\n        }\r\n    };\r\n    \/* --------------------------------------------------------------------\r\n     | 3. Album foto (aktif) + kiraan foto + terjemahan\r\n     -------------------------------------------------------------------- *\/\r\n    $galAlbums = DB::table('content_photo_gallery')\r\n        ->where('gallery_status', 'ACTIVE')\r\n        ->when($galKat !== '', fn ($q) => $q->where('gallery_cat', $galKat))\r\n        ->orderBy('gallery_sort')\r\n        ->orderByDesc('gallery_date')\r\n        ->orderByDesc('gallery_id')\r\n        ->get();\r\n\r\n    $galAlbumIds = $galAlbums->pluck('gallery_id')->all();\r\n\r\n    $galAlbumTr = $galAlbumIds\r\n        ? DB::table('content_photo_gallery_translations')\r\n            ->whereIn('gallery_translation_parent_id', $galAlbumIds)\r\n            ->get()\r\n            ->groupBy('gallery_translation_parent_id')\r\n        : collect();\r\n\r\n    $galPhotoCount = $galAlbumIds\r\n        ? DB::table('content_photo_list')\r\n            ->whereIn('photo_gallery_id', $galAlbumIds)\r\n            ->where(function ($q) {\r\n                $q->whereNull('photo_main')->orWhere('photo_main', 1);\r\n            })\r\n            ->selectRaw('photo_gallery_id, COUNT(*) as total')\r\n            ->groupBy('photo_gallery_id')\r\n            ->pluck('total', 'photo_gallery_id')\r\n        : collect();\r\n\r\n    $galAlbumVm = [];\r\n\r\n    foreach ($galAlbums as $galRow) {\r\n        $galTr = $galAlbumTr[$galRow->gallery_id] ?? collect();\r\n        $galTr = $galTr->firstWhere('gallery_translation_language', $galLang)\r\n            ?? $galTr->firstWhere('gallery_translation_main', 1)\r\n            ?? $galTr->first();\r\n\r\n        $galAlbumVm[] = [\r\n            'id'       => (int) $galRow->gallery_id,\r\n            'title'    => (string) ($galTr->gallery_translation_title ?? ''),\r\n            'descr'    => (string) ($galTr->gallery_translation_descr ?? ''),\r\n            'cat'      => (string) ($galRow->gallery_cat ?? ''),\r\n            'date'     => $galDate($galRow->gallery_date),\r\n            'location' => (string) ($galRow->gallery_location ?? ''),\r\n            'thumb'    => $galMedia($galRow->gallery_thumbnail),\r\n            'count'    => (int) ($galPhotoCount[$galRow->gallery_id] ?? 0),\r\n        ];\r\n    }\r\n\r\n    \/* --------------------------------------------------------------------\r\n     | 4. Album terpilih + senarai foto\r\n     -------------------------------------------------------------------- *\/\r\n    $galCurrent = null;\r\n    $galPhotos  = [];\r\n\r\n    if ($galAlbumId) {\r\n        $galRow = DB::table('content_photo_gallery')\r\n            ->where('gallery_id', $galAlbumId)\r\n            ->where('gallery_status', 'ACTIVE')\r\n            ->first();\r\n\r\n        if ($galRow) {\r\n            $galTrRows = DB::table('content_photo_gallery_translations')\r\n                ->where('gallery_translation_parent_id', $galAlbumId)\r\n                ->get();\r\n\r\n            $galTrRows = $galTrRows->firstWhere('gallery_translation_language', $galLang)\r\n                ?? $galTrRows->firstWhere('gallery_translation_main', 1)\r\n                ?? $galTrRows->first();\r\n\r\n            $galCurrent = [\r\n                'id'       => (int) $galRow->gallery_id,\r\n                'title'    => (string) ($galTrRows->gallery_translation_title ?? ''),\r\n                'descr'    => (string) ($galTrRows->gallery_translation_descr ?? ''),\r\n                'cat'      => (string) ($galRow->gallery_cat ?? ''),\r\n                'date'     => $galDate($galRow->gallery_date),\r\n                'location' => (string) ($galRow->gallery_location ?? ''),\r\n            ];\r\n\r\n            $galPhotoRows = DB::table('content_photo_list')\r\n                ->where('photo_gallery_id', $galAlbumId)\r\n                ->where(function ($q) {\r\n                    $q->whereNull('photo_main')->orWhere('photo_main', 1);\r\n                })\r\n                ->orderBy('photo_sort')\r\n                ->orderBy('photo_id')\r\n                ->get();\r\n\r\n            \/\/ Keterangan terjemahan (baris anak: photo_parent_id = photo_id)\r\n            $galPhotoTr = $galPhotoRows->isNotEmpty()\r\n                ? DB::table('content_photo_list')\r\n                    ->whereIn('photo_parent_id', $galPhotoRows->pluck('photo_id')->all())\r\n                    ->get()\r\n                    ->groupBy('photo_parent_id')\r\n                : collect();\r\n\r\n            foreach ($galPhotoRows as $galPhotoRow) {\r\n                $galPhotoTrRows = $galPhotoTr[$galPhotoRow->photo_id] ?? collect();\r\n                $galPhotoTrRow  = $galPhotoTrRows->firstWhere('photo_language', $galLang);\r\n\r\n                $galPhotos[] = [\r\n                    'id'    => (int) $galPhotoRow->photo_id,\r\n                    'url'   => $galMedia($galPhotoRow->photo_url),\r\n                    'descr' => (string) ($galPhotoTrRow->photo_descr ?? $galPhotoRow->photo_descr ?? ''),\r\n                ];\r\n            }\r\n\r\n            $galCurrent['count'] = count($galPhotos);\r\n        } else {\r\n            $galAlbumId = 0;   \/\/ album tidak sah \/ tidak aktif → kembali ke senarai album\r\n        }\r\n    }\r\n\r\n    \/* --------------------------------------------------------------------\r\n     | 5. Video (aktif) + terjemahan\r\n     -------------------------------------------------------------------- *\/\r\n    $galVideoRows = DB::table('content_video')\r\n        ->where('video_status', 'ACTIVE')\r\n        ->orderBy('video_sorting')\r\n        ->orderByDesc('video_date')\r\n        ->orderByDesc('video_id')\r\n        ->get();\r\n\r\n    $galVideoIds = $galVideoRows->pluck('video_id')->all();\r\n\r\n    $galVideoTr = $galVideoIds\r\n        ? DB::table('content_video_translation')\r\n            ->whereIn('video_translation_parent_id', $galVideoIds)\r\n            ->get()\r\n            ->groupBy('video_translation_parent_id')\r\n        : collect();\r\n\r\n    $galVideos = [];\r\n\r\n    foreach ($galVideoRows as $galVideoRow) {\r\n        $galTr = $galVideoTr[$galVideoRow->video_id] ?? collect();\r\n        $galTr = $galTr->firstWhere('video_translation_language', $galLang)\r\n            ?? $galTr->firstWhere('video_translation_main', 1)\r\n            ?? $galTr->first();\r\n\r\n        $galVideos[] = [\r\n            'id'       => (int) $galVideoRow->video_id,\r\n            'title'    => (string) ($galTr->video_translation_title ?? ''),\r\n            'descr'    => (string) ($galTr->video_translation_content ?? ''),\r\n            'location' => (string) ($galTr->video_translation_location ?? ''),\r\n            'date'     => $galDate($galVideoRow->video_date),\r\n            'type'     => strtoupper((string) ($galVideoRow->video_category ?? '')),\r\n            'embed'    => (string) ($galVideoRow->video_url ?? ''),\r\n            'upload'   => $galMedia($galVideoRow->video_upload),\r\n            'external' => (string) ($galVideoRow->video_external ?? ''),\r\n            'img'      => $galMedia($galVideoRow->video_img),\r\n        ];\r\n    }\r\n\r\n    $galTotalAlbums = count($galAlbumVm);\r\n    $galTotalVideos = count($galVideos);\r\n@endphp\r\n\r\n<style>\r\n\/* ==========================================================================\r\n   GALERI (FOTO & VIDEO) — gaya skop .gallery (warna ikut tema, sokong dark mode)\r\n   ========================================================================== *\/\r\n.gallery{padding:34px 0 64px;color:var(--ink);font-family:\"Inter\",\"Segoe UI\",system-ui,-apple-system,Roboto,Arial,sans-serif}\r\n.gallery *,.gallery *::before,.gallery *::after{box-sizing:border-box}\r\n.gallery__container{width:min(100% - 32px,1120px);margin:0 auto}\r\n\r\n\/* --- breadcrumb & tajuk -------------------------------------------------- *\/\r\n.gallery__breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:14px;color:var(--bs-secondary-color);font-size:.85rem}\r\n.gallery__breadcrumb a{color:var(--teal);font-weight:600;text-decoration:none}\r\n.gallery__breadcrumb a:hover{text-decoration:underline}\r\n.gallery__header{margin-bottom:20px}\r\n.gallery__eyebrow{display:inline-block;margin-bottom:8px;padding:4px 12px;border-radius:999px;background:var(--fade);color:var(--teal);font-size:.72rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase}\r\n.gallery__header h1{margin:0 0 8px;color:var(--green);font-size:clamp(1.45rem,3vw,2.05rem);font-weight:800;line-height:1.2}\r\n.gallery__header p{margin:0;max-width:74ch;color:var(--bs-secondary-color);font-size:.95rem;line-height:1.65}\r\n\r\n\/* --- tab ----------------------------------------------------------------- *\/\r\n.gallery__tabs{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 18px;padding-bottom:14px;border-bottom:2px solid var(--line)}\r\n.gallery__tab{display:inline-flex;align-items:center;gap:8px;padding:9px 18px;border:1px solid var(--line);border-radius:999px;background:var(--bs-body-bg);color:var(--ink);font-size:.84rem;font-weight:700;text-decoration:none;transition:.18s}\r\n.gallery__tab:hover{border-color:var(--teal);color:var(--teal)}\r\n.gallery__tab.is-active{border-color:var(--teal);background:var(--teal);color:#fff}\r\n.gallery__tab svg{width:15px;height:15px}\r\n.gallery__tab-count{padding:1px 8px;border-radius:999px;background:var(--fade);color:var(--teal);font-size:.68rem;font-weight:800}\r\n.gallery__tab.is-active .gallery__tab-count{background:rgba(255,255,255,.25);color:#fff}\r\n\r\n\/* --- tapisan kategori ---------------------------------------------------- *\/\r\n.gallery__cats{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 18px}\r\n.gallery__cat{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid var(--line);border-radius:999px;background:var(--bs-body-bg);color:var(--ink);font-size:.75rem;font-weight:600;text-decoration:none;transition:.15s}\r\n.gallery__cat:hover{border-color:var(--teal);color:var(--teal)}\r\n.gallery__cat.is-active{border-color:var(--teal);background:var(--teal);color:#fff}\r\n.gallery__dot{width:8px;height:8px;border-radius:50%;background:var(--cat-color,#64748b);flex:none}\r\n.gallery__cat.is-active .gallery__dot{background:#fff}\r\n\r\n\/* --- grid album ---------------------------------------------------------- *\/\r\n.gallery__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(268px,1fr));gap:16px}\r\n.gallery__album{display:flex;flex-direction:column;border:1px solid var(--line);border-radius:16px;background:var(--bs-body-bg);overflow:hidden;text-decoration:none;color:inherit;transition:.2s}\r\n.gallery__album:hover{border-color:var(--teal);box-shadow:0 10px 26px rgba(17,128,143,.16);transform:translateY(-2px)}\r\n.gallery__album-thumb{position:relative;aspect-ratio:16\/10;background:linear-gradient(135deg,var(--fade),var(--line));overflow:hidden}\r\n.gallery__album-thumb img{width:100%;height:100%;object-fit:cover;display:block;transition:.3s}\r\n.gallery__album:hover .gallery__album-thumb img{transform:scale(1.04)}\r\n.gallery__album-noimg{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--teal);opacity:.55}\r\n.gallery__album-noimg svg{width:38px;height:38px}\r\n.gallery__album-badge{position:absolute;top:10px;left:10px;padding:3px 10px;border-radius:999px;background:var(--cat-color,#64748b);color:#fff;font-size:.66rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}\r\n.gallery__album-count{position:absolute;bottom:10px;right:10px;display:inline-flex;align-items:center;gap:5px;padding:3px 10px;border-radius:999px;background:rgba(11,26,26,.72);color:#fff;font-size:.7rem;font-weight:700}\r\n.gallery__album-count svg{width:12px;height:12px}\r\n.gallery__album-body{padding:14px 16px 16px}\r\n.gallery__album-title{margin:0 0 6px;color:var(--green);font-size:.95rem;font-weight:800;line-height:1.35}\r\n.gallery__album-meta{display:flex;flex-wrap:wrap;gap:5px 14px;margin:0;padding:0;list-style:none;color:var(--bs-secondary-color);font-size:.76rem}\r\n.gallery__album-meta li{display:inline-flex;align-items:flex-start;gap:5px}\r\n.gallery__album-meta svg{flex:none;width:12px;height:12px;margin-top:2px;color:var(--teal)}\r\n\r\n\/* --- butiran album ------------------------------------------------------- *\/\r\n.gallery__back{display:inline-flex;align-items:center;gap:7px;margin-bottom:14px;color:var(--teal);font-size:.82rem;font-weight:700;text-decoration:none}\r\n.gallery__back:hover{text-decoration:underline}\r\n.gallery__back svg{width:14px;height:14px}\r\n.gallery__detail-head{margin:0 0 16px;padding:16px 18px;border:1px solid var(--line);border-left:4px solid var(--teal);border-radius:14px;background:var(--bs-body-bg)}\r\n.gallery__detail-head h2{margin:0 0 6px;color:var(--green);font-size:1.15rem;font-weight:800;line-height:1.3}\r\n.gallery__detail-head p{margin:0 0 10px;color:var(--bs-secondary-color);font-size:.86rem;line-height:1.6}\r\n.gallery__detail-meta{display:flex;flex-wrap:wrap;gap:6px 16px;margin:0;padding:0;list-style:none;color:var(--bs-secondary-color);font-size:.78rem}\r\n.gallery__detail-meta li{display:inline-flex;align-items:flex-start;gap:6px}\r\n.gallery__detail-meta svg{flex:none;width:13px;height:13px;margin-top:2px;color:var(--teal)}\r\n.gallery__badge{display:inline-block;padding:3px 10px;border-radius:999px;background:var(--cat-color,#64748b);color:#fff;font-size:.66rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;vertical-align:middle}\r\n\r\n\/* --- grid foto ----------------------------------------------------------- *\/\r\n.gallery__photos{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}\r\n.gallery__photo{position:relative;display:block;width:100%;padding:0;border:1px solid var(--line);border-radius:12px;background:var(--fade);overflow:hidden;cursor:zoom-in;transition:.18s}\r\n.gallery__photo:hover{border-color:var(--teal);box-shadow:0 8px 22px rgba(17,128,143,.16)}\r\n.gallery__photo img{display:block;width:100%;aspect-ratio:4\/3;object-fit:cover;transition:.25s}\r\n.gallery__photo:hover img{transform:scale(1.05)}\r\n.gallery__photo-zoom{position:absolute;right:8px;bottom:8px;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:50%;background:rgba(11,26,26,.68);color:#fff;opacity:0;transition:.2s}\r\n.gallery__photo:hover .gallery__photo-zoom{opacity:1}\r\n.gallery__photo-zoom svg{width:14px;height:14px}\r\n\r\n\/* --- lightbox ------------------------------------------------------------ *\/\r\n.gallery__lb{position:fixed;inset:0;z-index:1080;display:none;align-items:center;justify-content:center;background:rgba(6,18,18,.92);padding:24px}\r\n.gallery__lb.is-open{display:flex}\r\n.gallery__lb-stage{position:relative;max-width:min(100%,1120px);max-height:100%;display:flex;flex-direction:column;gap:10px;align-items:center}\r\n.gallery__lb-img{max-width:100%;max-height:calc(100vh - 150px);border-radius:10px;background:#0b1a1a;display:block}\r\n.gallery__lb-cap{margin:0;max-width:80ch;text-align:center;color:#e8f0ef;font-size:.85rem;line-height:1.55}\r\n.gallery__lb-count{position:absolute;top:-34px;left:0;color:#cfe6ea;font-size:.78rem;font-weight:700;letter-spacing:.04em}\r\n.gallery__lb-btn{position:absolute;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:0;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;cursor:pointer;transition:.15s}\r\n.gallery__lb-btn:hover{background:rgba(255,255,255,.28)}\r\n.gallery__lb-btn svg{width:20px;height:20px}\r\n.gallery__lb-prev{left:-58px}\r\n.gallery__lb-next{right:-58px}\r\n.gallery__lb-close{position:absolute;top:-40px;right:0;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:0;border-radius:50%;background:rgba(255,255,255,.16);color:#fff;cursor:pointer}\r\n.gallery__lb-close:hover{background:rgba(255,255,255,.3)}\r\n.gallery__lb-close svg{width:16px;height:16px}\r\n\r\n\/* --- grid video ---------------------------------------------------------- *\/\r\n.gallery__videos{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}\r\n.gallery__video{display:flex;flex-direction:column;width:100%;padding:0;border:1px solid var(--line);border-radius:16px;background:var(--bs-body-bg);overflow:hidden;cursor:pointer;text-align:left;color:inherit;transition:.2s}\r\n.gallery__video:hover{border-color:var(--teal);box-shadow:0 10px 26px rgba(17,128,143,.16);transform:translateY(-2px)}\r\n.gallery__video-thumb{position:relative;aspect-ratio:16\/9;background:linear-gradient(135deg,var(--fade),var(--line));overflow:hidden}\r\n.gallery__video-thumb img{width:100%;height:100%;object-fit:cover;display:block}\r\n.gallery__video-play{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(11,26,26,.28);transition:.2s}\r\n.gallery__video:hover .gallery__video-play{background:rgba(11,26,26,.42)}\r\n.gallery__video-play span{display:inline-flex;align-items:center;justify-content:center;width:54px;height:54px;border-radius:50%;background:rgba(255,255,255,.92);color:var(--teal);box-shadow:0 6px 18px rgba(0,0,0,.28)}\r\n.gallery__video-play svg{width:22px;height:22px;margin-left:3px}\r\n.gallery__video-tag{position:absolute;top:10px;left:10px;padding:3px 10px;border-radius:999px;background:rgba(11,26,26,.72);color:#fff;font-size:.65rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}\r\n.gallery__video-body{padding:14px 16px 16px}\r\n.gallery__video-title{margin:0 0 6px;color:var(--green);font-size:.93rem;font-weight:800;line-height:1.4}\r\n.gallery__video-meta{display:flex;flex-wrap:wrap;gap:5px 14px;margin:0;padding:0;list-style:none;color:var(--bs-secondary-color);font-size:.76rem}\r\n.gallery__video-meta li{display:inline-flex;align-items:flex-start;gap:5px}\r\n.gallery__video-meta svg{flex:none;width:12px;height:12px;margin-top:2px;color:var(--teal)}\r\n\r\n\/* --- modal pemain video -------------------------------------------------- *\/\r\n.gallery__vm{position:fixed;inset:0;z-index:1090;display:none;align-items:center;justify-content:center;background:rgba(6,18,18,.93);padding:24px}\r\n.gallery__vm.is-open{display:flex}\r\n.gallery__vm-stage{position:relative;width:min(100%,960px);max-height:100%;display:flex;flex-direction:column;gap:10px}\r\n.gallery__vm-player{position:relative;width:100%;aspect-ratio:16\/9;background:#000;border-radius:12px;overflow:hidden}\r\n.gallery__vm-player iframe,.gallery__vm-player video{position:absolute;inset:0;width:100%;height:100%;border:0;display:block;background:#000}\r\n.gallery__vm-fallback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:24px;text-align:center;background:#0b1a1a;color:#e8f0ef}\r\n.gallery__vm-fallback svg{width:34px;height:34px;color:#8fd9bf}\r\n.gallery__vm-fallback p{margin:0;font-size:.85rem;line-height:1.55;color:#cfe6ea}\r\n.gallery__vm-info{color:#e8f0ef}\r\n.gallery__vm-title{margin:0 0 6px;font-size:1rem;font-weight:800;line-height:1.4}\r\n.gallery__vm-meta{display:flex;flex-wrap:wrap;gap:6px 16px;margin:0;padding:0;list-style:none;color:#a9c4c6;font-size:.78rem}\r\n.gallery__vm-meta li{display:inline-flex;align-items:flex-start;gap:6px}\r\n.gallery__vm-meta svg{flex:none;width:13px;height:13px;margin-top:2px;color:#8fd9bf}\r\n.gallery__vm-descr{margin:8px 0 0;color:#a9c4c6;font-size:.82rem;line-height:1.6}\r\n.gallery__vm-descr:empty{display:none}\r\n.gallery__vm-count{position:absolute;top:-34px;left:0;color:#cfe6ea;font-size:.78rem;font-weight:700;letter-spacing:.04em}\r\n.gallery__btn{display:inline-flex;align-items:center;gap:8px;padding:9px 16px;border:1px solid var(--line);border-radius:10px;background:var(--bs-body-bg);color:var(--ink);font-size:.82rem;font-weight:700;text-decoration:none;transition:.15s}\r\n.gallery__btn:hover{border-color:var(--teal);color:var(--teal)}\r\n.gallery__btn--light{border-color:rgba(255,255,255,.4);background:rgba(255,255,255,.12);color:#fff}\r\n.gallery__btn--light:hover{border-color:#fff;background:rgba(255,255,255,.24);color:#fff}\r\n\r\n\/* --- keadaan kosong & nota ---------------------------------------------- *\/\r\n.gallery__empty{padding:34px 22px;border:1px dashed var(--line);border-radius:16px;background:var(--bs-body-bg);text-align:center}\r\n.gallery__empty svg{width:34px;height:34px;margin-bottom:10px;color:var(--teal);opacity:.7}\r\n.gallery__empty h3{margin:0 0 6px;color:var(--green);font-size:.98rem;font-weight:800}\r\n.gallery__empty p{max-width:56ch;margin:0 auto;color:var(--bs-secondary-color);font-size:.85rem;line-height:1.6}\r\n.gallery__empty a{color:var(--teal);font-weight:700;text-decoration:none}\r\n.gallery__empty a:hover{text-decoration:underline}\r\n.gallery__note{margin-top:24px;padding:16px 20px;border:1px solid var(--line);border-left:4px solid var(--teal);border-radius:12px;background:var(--bs-body-bg)}\r\n.gallery__note h2{margin:0 0 8px;color:var(--green);font-size:.8rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}\r\n.gallery__note ul{margin:0;padding-left:20px;color:var(--bs-secondary-color);font-size:.79rem;line-height:1.7}\r\n.gallery__note li{margin-bottom:4px}\r\n.gallery__note li:last-child{margin-bottom:0}\r\n.gallery__note a{color:var(--teal);font-weight:700;text-decoration:none}\r\n.gallery__note a:hover{text-decoration:underline}\r\n\r\n\/* --- responsif ----------------------------------------------------------- *\/\r\n@media (max-width:1020px){\r\n    .gallery__lb-prev{left:6px}\r\n    .gallery__lb-next{right:6px}\r\n    .gallery__lb-btn{background:rgba(11,26,26,.6)}\r\n}\r\n@media (max-width:640px){\r\n    .gallery{padding:24px 0 46px}\r\n    .gallery__grid,.gallery__videos{grid-template-columns:1fr}\r\n    .gallery__photos{grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:10px}\r\n    .gallery__lb,.gallery__vm{padding:14px}\r\n    .gallery__lb-img{max-height:calc(100vh - 190px)}\r\n}\r\n<\/style>\r\n\r\n<section class=\"gallery\" aria-labelledby=\"gallery-title\">\r\n    <div class=\"gallery__container\">\r\n\r\n        {{-- ---------- BREADCRUMB ---------- --}}\r\n        <nav class=\"gallery__breadcrumb\" aria-label=\"Breadcrumb\">\r\n            <a href=\"{{ url($siteSlug.'\/home') }}\">Utama<\/a>\r\n            <span aria-hidden=\"true\">\/<\/span>\r\n            <span>Galeri<\/span>\r\n        <\/nav>\r\n\r\n        {{-- ---------- TAJUK ---------- --}}\r\n        <header class=\"gallery__header\">\r\n            <span class=\"gallery__eyebrow\">Media<\/span>\r\n            <h1 id=\"gallery-title\">Galeri<\/h1>\r\n            <p>Koleksi foto dan video aktiviti, program serta majlis Kementerian Sumber Asli dan Kelestarian Alam.<\/p>\r\n        <\/header>\r\n\r\n        {{-- ---------- TAB: FOTO \/ VIDEO ---------- --}}\r\n        <nav class=\"gallery__tabs\" aria-label=\"Jenis galeri\">\r\n            <a class=\"gallery__tab {{ $galTab === 'foto' ? 'is-active' : '' }}\" href=\"{{ $galTabUrl('foto') }}\"\r\n                @if ($galTab === 'foto') aria-current=\"page\" @endif>\r\n                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n                    stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                    <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"><\/rect>\r\n                    <circle cx=\"8.5\" cy=\"9.5\" r=\"1.5\"><\/circle>\r\n                    <path d=\"M21 16l-5-5-6 6-3-3-4 4\"><\/path>\r\n                <\/svg>\r\n                Foto\r\n                <span class=\"gallery__tab-count\">{{ $galTotalAlbums }}<\/span>\r\n            <\/a>\r\n\r\n            <a class=\"gallery__tab {{ $galTab === 'video' ? 'is-active' : '' }}\" href=\"{{ $galTabUrl('video') }}\"\r\n                @if ($galTab === 'video') aria-current=\"page\" @endif>\r\n                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n                    stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                    <rect x=\"2.5\" y=\"5\" width=\"14\" height=\"14\" rx=\"2.5\"><\/rect>\r\n                    <path d=\"M16.5 10.5l5-3v9l-5-3z\"><\/path>\r\n                <\/svg>\r\n                Video\r\n                <span class=\"gallery__tab-count\">{{ $galTotalVideos }}<\/span>\r\n            <\/a>\r\n        <\/nav>\r\n\r\n        @if ($galTab === 'foto' && count($galCatLabel))\r\n            {{-- ---------- TAPISAN KATEGORI ALBUM ---------- --}}\r\n            <div class=\"gallery__cats\" role=\"group\" aria-label=\"Tapisan kategori album\">\r\n                <a class=\"gallery__cat {{ $galKat === '' ? 'is-active' : '' }}\"\r\n                    href=\"{{ $galUrl(['kategori' => null, 'album' => null]) }}\">Semua<\/a>\r\n\r\n                @foreach ($galCatLabel as $galCode => $galLabel)\r\n                    <a class=\"gallery__cat {{ $galKat === $galCode ? 'is-active' : '' }}\"\r\n                        style=\"--cat-color:{{ $galCatTint($galCode) }}\"\r\n                        href=\"{{ $galUrl(['kategori' => $galCode, 'album' => null]) }}\">\r\n                        <span class=\"gallery__dot\"><\/span>{{ $galLabel }}\r\n                    <\/a>\r\n                @endforeach\r\n            <\/div>\r\n        @endif\r\n\r\n        @if ($galTab === 'foto')\r\n            @if ($galCurrent)\r\n                {{-- ---------- BUTIRAN ALBUM (foto) ---------- --}}\r\n                <a class=\"gallery__back\" href=\"{{ $galUrl(['album' => null]) }}\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"\r\n                        stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                        <path d=\"M19 12H5M12 19l-7-7 7-7\"><\/path>\r\n                    <\/svg>\r\n                    Semua album\r\n                <\/a>\r\n\r\n                <div class=\"gallery__detail-head\">\r\n                    <h2>{{ $galCurrent['title'] }}<\/h2>\r\n\r\n                    @if ($galCurrent['descr'] !== '')\r\n                        <p>{{ $galCurrent['descr'] }}<\/p>\r\n                    @endif\r\n\r\n                    <ul class=\"gallery__detail-meta\">\r\n                        @if ($galCurrent['cat'] !== '')\r\n                            <li>\r\n                                <span class=\"gallery__badge\"\r\n                                    style=\"--cat-color:{{ $galCatTint($galCurrent['cat']) }}\">{{ $galCatName($galCurrent['cat']) }}<\/span>\r\n                            <\/li>\r\n                        @endif\r\n\r\n                        @if ($galCurrent['date'] !== '')\r\n                            <li>\r\n                                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n                                    stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                                    <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\"><\/rect>\r\n                                    <path d=\"M8 3v4M16 3v4M3 11h18\"><\/path>\r\n                                <\/svg>\r\n                                <span>{{ $galCurrent['date'] }}<\/span>\r\n                            <\/li>\r\n                        @endif\r\n\r\n                        @if ($galCurrent['location'] !== '')\r\n                            <li>\r\n                                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n                                    stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                                    <path d=\"M12 21s7-6 7-11a7 7 0 1 0-14 0c0 5 7 11 7 11z\"><\/path>\r\n                                    <circle cx=\"12\" cy=\"10\" r=\"2.5\"><\/circle>\r\n                                <\/svg>\r\n                                <span>{{ $galCurrent['location'] }}<\/span>\r\n                            <\/li>\r\n                        @endif\r\n\r\n                        <li>\r\n                            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n                                stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                                <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"><\/rect>\r\n                                <circle cx=\"8.5\" cy=\"9.5\" r=\"1.5\"><\/circle>\r\n                                <path d=\"M21 16l-5-5-6 6-3-3-4 4\"><\/path>\r\n                            <\/svg>\r\n                            <span>{{ $galCurrent['count'] }} foto<\/span>\r\n                        <\/li>\r\n                    <\/ul>\r\n                <\/div>\r\n\r\n                @if (count($galPhotos))\r\n                    <div class=\"gallery__photos\">\r\n                        @foreach ($galPhotos as $galPhotoIndex => $galPhoto)\r\n                            <button type=\"button\" class=\"gallery__photo\" data-gal-photo=\"{{ $galPhotoIndex }}\"\r\n                                data-gal-src=\"{{ $galPhoto['url'] }}\" data-gal-cap=\"{{ $galPhoto['descr'] }}\"\r\n                                aria-label=\"Lihat foto {{ $galPhotoIndex + 1 }} daripada {{ count($galPhotos) }}\">\r\n                                <img src=\"{{ $galPhoto['url'] }}\"\r\n                                    alt=\"{{ $galPhoto['descr'] !== '' ? $galPhoto['descr'] : $galCurrent['title'] }}\"\r\n                                    loading=\"lazy\">\r\n                                <span class=\"gallery__photo-zoom\" aria-hidden=\"true\">\r\n                                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\"\r\n                                        stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n                                        <circle cx=\"11\" cy=\"11\" r=\"7\"><\/circle>\r\n                                        <path d=\"M20 20l-3.5-3.5M11 8v6M8 11h6\"><\/path>\r\n                                    <\/svg>\r\n                                <\/span>\r\n                            <\/button>\r\n                        @endforeach\r\n                    <\/div>\r\n                @else\r\n                    <div class=\"gallery__empty\">\r\n                        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"\r\n                            stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                            <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"><\/rect>\r\n                            <circle cx=\"8.5\" cy=\"9.5\" r=\"1.5\"><\/circle>\r\n                            <path d=\"M21 16l-5-5-6 6-3-3-4 4\"><\/path>\r\n                        <\/svg>\r\n                        <h3>Tiada foto dalam album ini<\/h3>\r\n                        <p>Album ini belum mempunyai foto.\r\n                            <a href=\"{{ $galUrl(['album' => null]) }}\">Kembali ke senarai album<\/a>.<\/p>\r\n                    <\/div>\r\n                @endif\r\n            @else\r\n                {{-- ---------- SENARAI ALBUM ---------- --}}\r\n                @if ($galTotalAlbums)\r\n                    <div class=\"gallery__grid\">\r\n                        @foreach ($galAlbumVm as $galAlbum)\r\n                            <a class=\"gallery__album\" href=\"{{ $galUrl(['album' => $galAlbum['id']]) }}\">\r\n                                <div class=\"gallery__album-thumb\">\r\n                                    @if ($galAlbum['thumb'] !== '')\r\n                                        <img src=\"{{ $galAlbum['thumb'] }}\" alt=\"{{ $galAlbum['title'] }}\"\r\n                                            loading=\"lazy\">\r\n                                    @else\r\n                                        <span class=\"gallery__album-noimg\" aria-hidden=\"true\">\r\n                                            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n                                                stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n                                                <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"><\/rect>\r\n                                                <circle cx=\"8.5\" cy=\"9.5\" r=\"1.5\"><\/circle>\r\n                                                <path d=\"M21 16l-5-5-6 6-3-3-4 4\"><\/path>\r\n                                            <\/svg>\r\n                                        <\/span>\r\n                                    @endif\r\n\r\n                                    @if ($galAlbum['cat'] !== '')\r\n                                        <span class=\"gallery__album-badge\"\r\n                                            style=\"--cat-color:{{ $galCatTint($galAlbum['cat']) }}\">{{ $galCatName($galAlbum['cat']) }}<\/span>\r\n                                    @endif\r\n\r\n                                    <span class=\"gallery__album-count\">\r\n                                        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n                                            stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                                            <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"><\/rect>\r\n                                            <circle cx=\"8.5\" cy=\"9.5\" r=\"1.5\"><\/circle>\r\n                                            <path d=\"M21 16l-5-5-6 6-3-3-4 4\"><\/path>\r\n                                        <\/svg>\r\n                                        {{ $galAlbum['count'] }}\r\n                                    <\/span>\r\n                                <\/div>\r\n\r\n                                <div class=\"gallery__album-body\">\r\n                                    <h2 class=\"gallery__album-title\">{{ $galAlbum['title'] }}<\/h2>\r\n\r\n                                    <ul class=\"gallery__album-meta\">\r\n                                        @if ($galAlbum['date'] !== '')\r\n                                            <li>\r\n                                                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n                                                    stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n                                                    aria-hidden=\"true\">\r\n                                                    <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\"><\/rect>\r\n                                                    <path d=\"M8 3v4M16 3v4M3 11h18\"><\/path>\r\n                                                <\/svg>\r\n                                                <span>{{ $galAlbum['date'] }}<\/span>\r\n                                            <\/li>\r\n                                        @endif\r\n\r\n                                        @if ($galAlbum['location'] !== '')\r\n                                            <li>\r\n                                                <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n                                                    stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\r\n                                                    aria-hidden=\"true\">\r\n                                                    <path d=\"M12 21s7-6 7-11a7 7 0 1 0-14 0c0 5 7 11 7 11z\"><\/path>\r\n                                                    <circle cx=\"12\" cy=\"10\" r=\"2.5\"><\/circle>\r\n                                                <\/svg>\r\n                                                <span>{{ $galAlbum['location'] }}<\/span>\r\n                                            <\/li>\r\n                                        @endif\r\n                                    <\/ul>\r\n                                <\/div>\r\n                            <\/a>\r\n                        @endforeach\r\n                    <\/div>\r\n                @else\r\n                    <div class=\"gallery__empty\">\r\n                        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"\r\n                            stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                            <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"15\" rx=\"2\"><\/rect>\r\n                            <circle cx=\"8.5\" cy=\"9.5\" r=\"1.5\"><\/circle>\r\n                            <path d=\"M21 16l-5-5-6 6-3-3-4 4\"><\/path>\r\n                        <\/svg>\r\n\r\n                        @if ($galKat !== '')\r\n                            <h3>Tiada album bagi kategori ini<\/h3>\r\n                            <p>Tiada album berkategori <strong>{{ $galCatName($galKat) }}<\/strong>.\r\n                                <a href=\"{{ $galUrl(['kategori' => null, 'album' => null]) }}\">Tampilkan semua\r\n                                    kategori<\/a>.<\/p>\r\n                        @else\r\n                            <h3>Galeri foto sedang dikemaskini<\/h3>\r\n                            <p>Belum ada album foto diterbitkan. Sila semak semula kemudian.<\/p>\r\n                        @endif\r\n                    <\/div>\r\n                @endif\r\n            @endif\r\n        @else\r\n            {{-- ---------- TAB VIDEO ---------- --}}\r\n            @if ($galTotalVideos)\r\n                <div class=\"gallery__videos\">\r\n                    @foreach ($galVideos as $galVideoIndex => $galVideo)\r\n                        <button type=\"button\" class=\"gallery__video\" data-gal-video=\"{{ $galVideoIndex }}\"\r\n                            @if ($galVideoId === $galVideo['id']) data-gal-autoopen=\"1\" @endif\r\n                            data-v-type=\"{{ $galVideo['type'] }}\" data-v-embed=\"{{ $galVideo['embed'] }}\"\r\n                            data-v-upload=\"{{ $galVideo['upload'] }}\" data-v-external=\"{{ $galVideo['external'] }}\"\r\n                            data-v-title=\"{{ $galVideo['title'] }}\" data-v-date=\"{{ $galVideo['date'] }}\"\r\n                            data-v-location=\"{{ $galVideo['location'] }}\" data-v-descr=\"{{ $galVideo['descr'] }}\"\r\n                            aria-label=\"Mainkan video {{ $galVideo['title'] }}\">\r\n                            <div class=\"gallery__video-thumb\">\r\n                                @if ($galVideo['img'] !== '')\r\n                                    <img src=\"{{ $galVideo['img'] }}\" alt=\"{{ $galVideo['title'] }}\" loading=\"lazy\">\r\n                                @endif\r\n\r\n                                <span class=\"gallery__video-tag\">\r\n                                    @if ($galVideo['type'] === 'YOUTUBE')\r\n                                        YouTube\r\n                                    @elseif ($galVideo['type'] === 'UPLOAD')\r\n                                        Video\r\n                                    @else\r\n                                        Pautan\r\n                                    @endif\r\n                                <\/span>\r\n\r\n                                <span class=\"gallery__video-play\" aria-hidden=\"true\">\r\n                                    <span>\r\n                                        <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\">\r\n                                            <path d=\"M8 5.5v13l11-6.5z\"><\/path>\r\n                                        <\/svg>\r\n                                    <\/span>\r\n                                <\/span>\r\n                            <\/div>\r\n\r\n                            <div class=\"gallery__video-body\">\r\n                                <h2 class=\"gallery__video-title\">{{ $galVideo['title'] }}<\/h2>\r\n\r\n                                <ul class=\"gallery__video-meta\">\r\n                                    @if ($galVideo['date'] !== '')\r\n                                        <li>\r\n                                            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n                                                stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                                                <rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\"><\/rect>\r\n                                                <path d=\"M8 3v4M16 3v4M3 11h18\"><\/path>\r\n                                            <\/svg>\r\n                                            <span>{{ $galVideo['date'] }}<\/span>\r\n                                        <\/li>\r\n                                    @endif\r\n\r\n                                    @if ($galVideo['location'] !== '')\r\n                                        <li>\r\n                                            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"\r\n                                                stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                                                <path d=\"M12 21s7-6 7-11a7 7 0 1 0-14 0c0 5 7 11 7 11z\"><\/path>\r\n                                                <circle cx=\"12\" cy=\"10\" r=\"2.5\"><\/circle>\r\n                                            <\/svg>\r\n                                            <span>{{ $galVideo['location'] }}<\/span>\r\n                                        <\/li>\r\n                                    @endif\r\n                                <\/ul>\r\n                            <\/div>\r\n                        <\/button>\r\n                    @endforeach\r\n                <\/div>\r\n            @else\r\n                <div class=\"gallery__empty\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\"\r\n                        stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                        <rect x=\"2.5\" y=\"5\" width=\"14\" height=\"14\" rx=\"2.5\"><\/rect>\r\n                        <path d=\"M16.5 10.5l5-3v9l-5-3z\"><\/path>\r\n                    <\/svg>\r\n                    <h3>Galeri video sedang dikemaskini<\/h3>\r\n                    <p>Belum ada video diterbitkan. Sila semak semula kemudian.<\/p>\r\n                <\/div>\r\n            @endif\r\n        @endif\r\n\r\n        {{-- ---------- LIGHTBOX FOTO ---------- --}}\r\n        <div class=\"gallery__lb\" id=\"galLightbox\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Paparan foto penuh\"\r\n            hidden>\r\n            <div class=\"gallery__lb-stage\">\r\n                <span class=\"gallery__lb-count\" id=\"galLbCount\"><\/span>\r\n\r\n                <button type=\"button\" class=\"gallery__lb-close\" id=\"galLbClose\" aria-label=\"Tutup paparan\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\r\n                        aria-hidden=\"true\">\r\n                        <path d=\"M6 6l12 12M18 6L6 18\"><\/path>\r\n                    <\/svg>\r\n                <\/button>\r\n\r\n                <button type=\"button\" class=\"gallery__lb-btn gallery__lb-prev\" id=\"galLbPrev\"\r\n                    aria-label=\"Foto sebelumnya\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\r\n                        stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                        <path d=\"M15 6l-6 6 6 6\"><\/path>\r\n                    <\/svg>\r\n                <\/button>\r\n\r\n                <img class=\"gallery__lb-img\" id=\"galLbImg\" src=\"\" alt=\"\">\r\n\r\n                <button type=\"button\" class=\"gallery__lb-btn gallery__lb-next\" id=\"galLbNext\"\r\n                    aria-label=\"Foto seterusnya\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\r\n                        stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                        <path d=\"M9 6l6 6-6 6\"><\/path>\r\n                    <\/svg>\r\n                <\/button>\r\n\r\n                <p class=\"gallery__lb-cap\" id=\"galLbCap\"><\/p>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        {{-- ---------- MODAL PEMAIN VIDEO ---------- --}}\r\n        <div class=\"gallery__vm\" id=\"galVideoModal\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Pemain video\" hidden>\r\n            <div class=\"gallery__vm-stage\">\r\n                <span class=\"gallery__vm-count\" id=\"galVmCount\"><\/span>\r\n\r\n                <button type=\"button\" class=\"gallery__lb-close\" id=\"galVmClose\" aria-label=\"Tutup pemain\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\r\n                        aria-hidden=\"true\">\r\n                        <path d=\"M6 6l12 12M18 6L6 18\"><\/path>\r\n                    <\/svg>\r\n                <\/button>\r\n\r\n                <button type=\"button\" class=\"gallery__lb-btn gallery__lb-prev\" id=\"galVmPrev\"\r\n                    aria-label=\"Video sebelumnya\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\r\n                        stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                        <path d=\"M15 6l-6 6 6 6\"><\/path>\r\n                    <\/svg>\r\n                <\/button>\r\n\r\n                <div class=\"gallery__vm-player\" id=\"galVmPlayer\"><\/div>\r\n\r\n                <button type=\"button\" class=\"gallery__lb-btn gallery__lb-next\" id=\"galVmNext\"\r\n                    aria-label=\"Video seterusnya\">\r\n                    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\"\r\n                        stroke-linejoin=\"round\" aria-hidden=\"true\">\r\n                        <path d=\"M9 6l6 6-6 6\"><\/path>\r\n                    <\/svg>\r\n                <\/button>\r\n\r\n                <div class=\"gallery__vm-info\">\r\n                    <h3 class=\"gallery__vm-title\" id=\"galVmTitle\"><\/h3>\r\n                    <ul class=\"gallery__vm-meta\" id=\"galVmMeta\"><\/ul>\r\n                    <p class=\"gallery__vm-descr\" id=\"galVmDescr\"><\/p>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        {{-- ---------- NOTA ---------- --}}\r\n        <aside class=\"gallery__note\">\r\n            <h2>Nota<\/h2>\r\n            <ul>\r\n                <li>Klik pada album untuk melihat semua foto. Klik pada foto untuk paparan penuh — guna anak panah\r\n                    atau kekunci <strong>←<\/strong>\/<strong>→<\/strong> dan <strong>Esc<\/strong> untuk tutup.<\/li>\r\n                <li>Klik pada video untuk memainkannya. Video YouTube dimainkan dalam pemain terbina; video yang\r\n                    dimuat naik dimainkan terus pada halaman ini.<\/li>\r\n                <li>Sebarang pertanyaan atau pembetulan boleh dikemukakan melalui\r\n                    <a href=\"{{ url($siteSlug.'\/complaints-feedback') }}\">Aduan &amp; Maklum Balas<\/a>.<\/li>\r\n            <\/ul>\r\n        <\/aside>\r\n    <\/div>\r\n<\/section>\r\n\r\n<script>\r\n    \/* ======================================================================\r\n       GALERI — lightbox foto + modal pemain video\r\n       JS tulen (tiada library). Data dibaca dari atribut data-* pada elemen.\r\n       ====================================================================== *\/\r\n    (function () {\r\n        'use strict';\r\n\r\n        \/* ------------------------- LIGHTBOX FOTO ------------------------- *\/\r\n        var lb      = document.getElementById('galLightbox');\r\n        var lbImg   = document.getElementById('galLbImg');\r\n        var lbCap   = document.getElementById('galLbCap');\r\n        var lbCount = document.getElementById('galLbCount');\r\n        var thumbs  = Array.prototype.slice.call(document.querySelectorAll('[data-gal-photo]'));\r\n        var lbIndex = 0;\r\n\r\n        function lbRender() {\r\n            if (!thumbs.length) { return; }\r\n\r\n            lbIndex = (lbIndex + thumbs.length) % thumbs.length;\r\n\r\n            var el  = thumbs[lbIndex];\r\n            var cap = el.getAttribute('data-gal-cap') || '';\r\n\r\n            lbImg.setAttribute('src', el.getAttribute('data-gal-src') || '');\r\n            lbImg.setAttribute('alt', cap);\r\n            lbCap.textContent = cap;\r\n            lbCount.textContent = (lbIndex + 1) + ' \/ ' + thumbs.length;\r\n        }\r\n\r\n        function lbOpen(index) {\r\n            if (!lb || !thumbs.length) { return; }\r\n\r\n            lbIndex = index;\r\n            lbRender();\r\n            lb.hidden = false;\r\n            lb.classList.add('is-open');\r\n            document.body.style.overflow = 'hidden';\r\n        }\r\n\r\n        function lbClose() {\r\n            if (!lb) { return; }\r\n\r\n            lb.classList.remove('is-open');\r\n            lb.hidden = true;\r\n            lbImg.setAttribute('src', '');\r\n            document.body.style.overflow = '';\r\n        }\r\n\r\n        thumbs.forEach(function (el, i) {\r\n            el.addEventListener('click', function () { lbOpen(i); });\r\n        });\r\n\r\n        if (lb) {\r\n            document.getElementById('galLbClose').addEventListener('click', lbClose);\r\n            document.getElementById('galLbPrev').addEventListener('click', function () { lbIndex--; lbRender(); });\r\n            document.getElementById('galLbNext').addEventListener('click', function () { lbIndex++; lbRender(); });\r\n            lb.addEventListener('click', function (e) { if (e.target === lb) { lbClose(); } });\r\n        }\r\n\r\n        \/* ---------------------- MODAL PEMAIN VIDEO ---------------------- *\/\r\n        var vm       = document.getElementById('galVideoModal');\r\n        var vmPlayer = document.getElementById('galVmPlayer');\r\n        var vmTitle  = document.getElementById('galVmTitle');\r\n        var vmMeta   = document.getElementById('galVmMeta');\r\n        var vmDescr  = document.getElementById('galVmDescr');\r\n        var vmCount  = document.getElementById('galVmCount');\r\n        var vids     = Array.prototype.slice.call(document.querySelectorAll('[data-gal-video]'));\r\n        var vmIndex  = 0;\r\n\r\n        function vmClear() {\r\n            while (vmPlayer.firstChild) {\r\n                vmPlayer.removeChild(vmPlayer.firstChild);\r\n            }\r\n        }\r\n\r\n        function vmMetaItem(text) {\r\n            var li = document.createElement('li');\r\n            li.textContent = text;\r\n\r\n            return li;\r\n        }\r\n\r\n        \/\/ Bina elemen pemain: <video> untuk fail, <iframe> untuk embed, null jika pautan luar biasa\r\n        function vmNode(type, embed, upload, external, title) {\r\n            var url = '';\r\n\r\n            if (type === 'YOUTUBE' && embed) {\r\n                url = embed;\r\n            } else if (type === 'UPLOAD' && upload) {\r\n                url = upload;\r\n            } else if (external) {\r\n                url = external;\r\n\r\n                var yt = url.match(\/(?:youtube\\.com\\\/watch\\?v=|youtu\\.be\\\/)([A-Za-z0-9_-]{6,})\/);\r\n\r\n                if (yt) {\r\n                    url = 'https:\/\/www.youtube.com\/embed\/' + yt[1];\r\n                }\r\n            }\r\n\r\n            if (!url || url.indexOf('http') !== 0) {\r\n                return null;\r\n            }\r\n\r\n            var node = null;\r\n\r\n            if (\/\\.(mp4|webm|ogg|m4v)(\\?.*)?$\/i.test(url)) {\r\n                node = document.createElement('video');\r\n                node.setAttribute('src', url);\r\n                node.setAttribute('controls', 'controls');\r\n                node.setAttribute('playsinline', 'playsinline');\r\n                node.setAttribute('preload', 'metadata');\r\n\r\n                return node;\r\n            }\r\n\r\n            if (\/youtube\\.com\\\/embed\\\/|player\\.vimeo\\.com\/.test(url)) {\r\n                node = document.createElement('iframe');\r\n                node.setAttribute('src', url);\r\n                node.setAttribute('title', title);\r\n                node.setAttribute('allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; fullscreen');\r\n                node.setAttribute('allowfullscreen', 'allowfullscreen');\r\n\r\n                return node;\r\n            }\r\n\r\n            return null;\r\n        }\r\n\r\n        function vmFallback(external) {\r\n            var box = document.createElement('div');\r\n            box.className = 'gallery__vm-fallback';\r\n\r\n            var text = document.createElement('p');\r\n            text.textContent = external\r\n                ? 'Video ini dibuka di laman luar dan tidak boleh dipaparkan dalam halaman ini.'\r\n                : 'Sumber video tidak tersedia untuk video ini.';\r\n            box.appendChild(text);\r\n\r\n            if (external) {\r\n                var link = document.createElement('a');\r\n                link.className = 'gallery__btn gallery__btn--light';\r\n                link.setAttribute('href', external);\r\n                link.setAttribute('target', '_blank');\r\n                link.setAttribute('rel', 'noopener');\r\n                link.textContent = 'Buka pautan video';\r\n                box.appendChild(link);\r\n            }\r\n\r\n            return box;\r\n        }\r\n\r\n        function vmShow(index) {\r\n            if (!vids.length) { return; }\r\n\r\n            vmIndex = (index + vids.length) % vids.length;\r\n\r\n            var el = vids[vmIndex];\r\n\r\n            var type     = (el.getAttribute('data-v-type') || '').toUpperCase();\r\n            var embed    = el.getAttribute('data-v-embed') || '';\r\n            var upload   = el.getAttribute('data-v-upload') || '';\r\n            var external = el.getAttribute('data-v-external') || '';\r\n            var title    = el.getAttribute('data-v-title') || '';\r\n            var date     = el.getAttribute('data-v-date') || '';\r\n            var location = el.getAttribute('data-v-location') || '';\r\n            var descr    = el.getAttribute('data-v-descr') || '';\r\n\r\n            vmClear();\r\n            vmPlayer.appendChild(vmNode(type, embed, upload, external, title) || vmFallback(external));\r\n\r\n            vmTitle.textContent = title;\r\n            vmDescr.textContent = descr;\r\n            vmCount.textContent = (vmIndex + 1) + ' \/ ' + vids.length;\r\n\r\n            vmMeta.textContent = '';\r\n\r\n            if (date) { vmMeta.appendChild(vmMetaItem(date)); }\r\n            if (location) { vmMeta.appendChild(vmMetaItem(location)); }\r\n        }\r\n\r\n        function vmOpen(index) {\r\n            if (!vm || !vids.length) { return; }\r\n\r\n            vm.hidden = false;\r\n            vm.classList.add('is-open');\r\n            document.body.style.overflow = 'hidden';\r\n            vmShow(index);\r\n        }\r\n\r\n        function vmClose() {\r\n            if (!vm) { return; }\r\n\r\n            vmClear();\r\n            vm.classList.remove('is-open');\r\n            vm.hidden = true;\r\n            document.body.style.overflow = '';\r\n        }\r\n\r\n        vids.forEach(function (el, i) {\r\n            el.addEventListener('click', function () { vmOpen(i); });\r\n        });\r\n\r\n        if (vm) {\r\n            document.getElementById('galVmClose').addEventListener('click', vmClose);\r\n            document.getElementById('galVmPrev').addEventListener('click', function () { vmShow(vmIndex - 1); });\r\n            document.getElementById('galVmNext').addEventListener('click', function () { vmShow(vmIndex + 1); });\r\n            vm.addEventListener('click', function (e) { if (e.target === vm) { vmClose(); } });\r\n        }\r\n\r\n        \/* ------------------ PAPAN KEKUNCI & AUTO-BUKA ------------------ *\/\r\n        document.addEventListener('keydown', function (e) {\r\n            var lbNow = lb && lb.classList.contains('is-open');\r\n            var vmNow = vm && vm.classList.contains('is-open');\r\n\r\n            if (!lbNow && !vmNow) { return; }\r\n\r\n            if (e.key === 'Escape') {\r\n                if (lbNow) { lbClose(); }\r\n                if (vmNow) { vmClose(); }\r\n            } else if (e.key === 'ArrowLeft') {\r\n                if (lbNow) { lbIndex--; lbRender(); }\r\n                if (vmNow) { vmShow(vmIndex - 1); }\r\n            } else if (e.key === 'ArrowRight') {\r\n                if (lbNow) { lbIndex++; lbRender(); }\r\n                if (vmNow) { vmShow(vmIndex + 1); }\r\n            }\r\n        });\r\n\r\n        \/\/ ?video=<id> → buka pemain secara automatik\r\n        var autoOpen = document.querySelector('[data-gal-autoopen]');\r\n\r\n        if (autoOpen) {\r\n            vmOpen(vids.indexOf(autoOpen));\r\n        }\r\n    })();\r\n<\/script>\r\n"
}