<?php
/**
 * WB Store - Catálogo com layout estilo portal, cores WBUARQUE
 */
include ("../../../inc/includes.php");
require_once __DIR__ . "/../inc/guard.php";

use GlpiPlugin\Wbstore\Config;
use GlpiPlugin\Wbstore\Guard;
use GlpiPlugin\Wbstore\License;
use GlpiPlugin\Wbstore\Notifications;
use GlpiPlugin\Wbstore\StoreClient;
use GlpiPlugin\Wbstore\Utils;

Session::checkRight('config', UPDATE);

function wbstore_e($value): string {
   return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
}

function wbstore_mask(string $value, int $start = 6, int $end = 4): string {
   $value = trim($value);
   $len = function_exists('mb_strlen') ? mb_strlen($value) : strlen($value);
   if ($len <= ($start + $end)) {
      return str_repeat('•', max(8, $len));
   }
   $prefix = function_exists('mb_substr') ? mb_substr($value, 0, $start) : substr($value, 0, $start);
   $suffix = function_exists('mb_substr') ? mb_substr($value, -$end) : substr($value, -$end);
   return $prefix . str_repeat('•', max(6, $len - ($start + $end))) . $suffix;
}

function wbstore_timeago($timestamp): string {
   $ts = (int)$timestamp;
   if ($ts <= 0) {
      return 'Nunca';
   }
   $diff = time() - $ts;
   if ($diff < 60) {
      return 'Agora há pouco';
   }
   if ($diff < 3600) {
      return floor($diff / 60) . ' min atrás';
   }
   if ($diff < 86400) {
      return floor($diff / 3600) . ' h atrás';
   }
   if ($diff < 2592000) {
      return floor($diff / 86400) . ' dias atrás';
   }
   return date('d/m/Y H:i', $ts);
}

function wbstore_package_image(array $package): string {
   foreach (['cover_url', 'banner_url', 'image_url', 'icon_url', 'logo_url', 'image', 'icon', 'logo'] as $key) {
      $value = trim((string)($package[$key] ?? ''));
      if ($value !== '' && preg_match('#^https?://#i', $value)) {
         return $value;
      }
   }
   return '';
}

function wbstore_plugin_logo_src(): string {
   static $src = null;
   if ($src !== null) {
      return $src;
   }

   $candidates = [
      dirname(__DIR__) . '/pics/logo.png',
      dirname(__DIR__) . '/plugin-icon2.png',
      dirname(__DIR__) . '/logo.png',
   ];

   foreach ($candidates as $file) {
      if (is_file($file) && is_readable($file)) {
         $ext = strtolower((string)pathinfo($file, PATHINFO_EXTENSION));
         $mime = $ext === 'svg' ? 'image/svg+xml' : ($ext === 'jpg' || $ext === 'jpeg' ? 'image/jpeg' : 'image/png');
         $data = @file_get_contents($file);
         if ($data !== false && $data !== '') {
            $src = 'data:' . $mime . ';base64,' . base64_encode($data);
            return $src;
         }
      }
   }

   $src = '';
   return $src;
}

function wbstore_package_tier(array $package, bool $canDownload): array {
   $buyUrl = trim((string)($package['purchase_url'] ?? ''));
   $isFree = false;

   foreach (['is_free', 'free', 'gratis', 'gratuito'] as $key) {
      if (array_key_exists($key, $package) && (bool)$package[$key]) {
         $isFree = true;
         break;
      }
   }

   if ($isFree) {
      return ['label' => 'Módulo Gratuito', 'class' => 'tier-free'];
   }

   if (!$canDownload && $buyUrl !== '') {
      return ['label' => 'Módulo Licenciado', 'class' => 'tier-paid'];
   }

   if ($canDownload) {
      return ['label' => 'Módulo Liberado', 'class' => 'tier-open'];
   }

   return ['label' => 'Módulo Bloqueado', 'class' => 'tier-locked'];
}

function wbstore_license_badge(bool $configured, bool $valid): array {
   if (!$configured) {
      return ['text' => 'Sem licença', 'class' => 'state-warn'];
   }
   if ($valid) {
      return ['text' => 'Licença válida', 'class' => 'state-ok'];
   }
   return ['text' => 'Validar licença', 'class' => 'state-warn'];
}

$flashOk = '';
$flashErr = '';
$flashInfo = '';

if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {
   $action = trim((string)($_POST['action'] ?? ''));

   if ($action === 'sync_catalog') {
      // Reseta throttle para o clique manual ter efeito real.
      Config::set([
         'license_last_try_at'        => 0,
         'packages_cache_last_try_at' => 0,
      ]);

      $licenseOk = License::isValid(true);
      $cacheOk   = Guard::refreshPackagesCache(true);

      $query = [];
      if ($licenseOk && $cacheOk) {
         $query['sync'] = 'ok';
      } elseif ($cacheOk) {
         $query['sync'] = 'cache_only';
      } else {
         $query['sync'] = 'fail';
      }

      Html::redirect(Plugin::getWebDir('wbstore') . '/front/catalog.php?' . http_build_query($query));
      exit;
   }
}

if (class_exists('PluginWbstoreCron') && method_exists('PluginWbstoreCron', 'ensureRegistered')) {
   PluginWbstoreCron::ensureRegistered();
}

Guard::onCatalogOpen();

$syncFlag = trim((string)($_GET['sync'] ?? ''));
if ($syncFlag === 'ok') {
   $flashOk = 'Catálogo sincronizado e licença validada.';
} elseif ($syncFlag === 'cache_only') {
   $flashOk = 'Catálogo sincronizado. A licença ainda precisa ser conferida.';
} elseif ($syncFlag === 'fail') {
   $flashErr = 'A sincronização falhou. Confira a licença e a comunicação com a WB Store.';
}
$flashInfo = 'A validação online roda no cron do GLPI, uma vez por dia, na madrugada. Use Sincronizar só quando precisar forçar a atualização.';

$conf = Config::all();
$licenseKey = trim((string)($conf['license_key'] ?? ''));
$storeUrl = rtrim((string)($conf['store_url'] ?? 'https://wbuarque.com.br'), '/');
$plan = trim((string)($conf['client_plan'] ?? ''));
if ($plan === '') {
   $plan = $licenseKey !== '' ? 'Cliente ativo' : 'Sem plano';
}

$licenseConfigured = License::isConfigured();
$licenseValid = $licenseConfigured ? License::isValid(false) : false;
$licenseBadge = wbstore_license_badge($licenseConfigured, $licenseValid);

$fullCache = Guard::getFullPackagesCache(true);

$packages = [];
if (isset($fullCache['packages']) && is_array($fullCache['packages'])) {
   $packages = $fullCache['packages'];
} elseif (is_array($fullCache)) {
   $packages = $fullCache;
}

if (empty($packages) && $flashErr === '') {
   $flashInfo = 'O catálogo local ainda não foi sincronizado. Aguarde a rotina automática da madrugada ou use o botão Sincronizar.';
}

$moduleCards = [];
$totalModules = 0;
$activeModules = 0;
$installedModules = 0;
$availableModules = 0;
$lockedModules = 0;
$currentGlpiVersion = Utils::glpiVersion();
$currentGlpiMajor = Utils::glpiMajor();
$allowedFilterMajors = ['all', 'current', '10', '11'];
$glpiFilter = trim((string)($_GET['glpi_filter'] ?? 'current'));
if (!in_array($glpiFilter, $allowedFilterMajors, true)) {
   $glpiFilter = 'current';
}
$filterGlpiMajor = 0;
if ($glpiFilter === 'current') {
   $filterGlpiMajor = $currentGlpiMajor;
} elseif (ctype_digit($glpiFilter)) {
   $filterGlpiMajor = (int)$glpiFilter;
}
$glpiFilterLabel = $glpiFilter === 'all' ? 'Todos os ramos' : (($glpiFilter === 'current' && $currentGlpiMajor > 0) ? ('GLPI atual (' . $currentGlpiVersion . ')') : ('GLPI ' . $filterGlpiMajor));
$hiddenByGlpiFilter = 0;

foreach ($packages as $package) {
   if (!is_array($package)) {
      continue;
   }

   $slug = trim((string)($package['slug'] ?? ''));
   if ($slug === '') {
      continue;
   }

   if ($filterGlpiMajor > 0 && !Utils::packageMatchesGlpiMajor($package, $filterGlpiMajor)) {
      $hiddenByGlpiFilter++;
      continue;
   }

   $name = trim((string)($package['name'] ?? $slug));
   $description = trim((string)($package['description'] ?? ''));
   if ($description === '') {
      $description = 'Plugin pronto para uso no GLPI, focado em operação real e instalação direta pela WB Store.';
   }

   $pluginDir = trim((string)($package['plugin_dir'] ?? ($package['dir'] ?? $slug)));
   $status = Utils::pluginStatus($pluginDir);
   $installed = (bool)($status['installed'] ?? false);
   $activated = (bool)($status['activated'] ?? false);
   $canDownload = array_key_exists('can_download', $package) ? (bool)$package['can_download'] : true;

   $tier = wbstore_package_tier($package, $canDownload);
   $image = wbstore_package_image($package);
   $demoUrl = trim((string)($package['demo_url'] ?? ''));
   $buyUrl = trim((string)($package['purchase_url'] ?? ''));
   $version = trim((string)($package['latest_version'] ?? ($package['version'] ?? '')));
   $minGlpi = trim((string)($package['min_glpi'] ?? ''));
   $glpiLabel = Utils::packageGlpiLabel($package);
   $author = trim((string)($package['author'] ?? $package['vendor'] ?? 'WBUARQUE'));

   $cardStatus = 'available';
   if ($activated) {
      $cardStatus = 'active';
      $activeModules++;
   } elseif ($installed) {
      $cardStatus = 'installed';
      $installedModules++;
   } elseif (!$canDownload) {
      $cardStatus = 'locked';
      $lockedModules++;
   } else {
      $availableModules++;
   }

   if ($activated && $installed) {
      $installedModules++;
   }

   $totalModules++;

   $moduleCards[] = [
      'slug'        => $slug,
      'name'        => $name,
      'description' => $description,
      'plugin_dir'  => $pluginDir,
      'installed'   => $installed,
      'activated'   => $activated,
      'can'         => $canDownload,
      'status'      => $cardStatus,
      'tier'        => $tier,
      'image'       => $image,
      'demo'        => $demoUrl,
      'buy'         => $buyUrl,
      'version'     => $version,
      'min_glpi'    => $minGlpi,
      'glpi_label'  => $glpiLabel,
      'author'      => $author,
   ];
}

usort($moduleCards, static function (array $a, array $b): int {
   $order = ['active' => 0, 'installed' => 1, 'available' => 2, 'locked' => 3];
   $pa = $order[$a['status']] ?? 9;
   $pb = $order[$b['status']] ?? 9;
   if ($pa !== $pb) {
      return $pa <=> $pb;
   }
   return strcasecmp($a['name'], $b['name']);
});

$allCount = count($moduleCards);
$unreadNotices = class_exists(Notifications::class) ? Notifications::countUnread() : 0;
$recentNotices = class_exists(Notifications::class) ? Notifications::listRecent(4, false) : [];
$lastLicenseOkAt = (int)($conf['license_last_ok_at'] ?? 0);
$licenseValidUntil = (int)($conf['license_valid_until'] ?? 0);
$fullCacheUntil = (int)($conf['packages_full_cache_until'] ?? 0);
$instanceId = trim((string)($conf['instance_id'] ?? ''));
$domain = trim((string)($conf['domain'] ?? Utils::currentDomain()));
$clientName = trim((string)($conf['client_name'] ?? ''));
$clientEmail = trim((string)($conf['client_email'] ?? ''));
$clientPhone = trim((string)($conf['client_phone'] ?? ''));
$clientCompany = trim((string)($conf['client_company'] ?? ''));

Html::header('WB Store', $_SERVER['PHP_SELF'], 'config', 'plugins');

$logoWeb = wbstore_plugin_logo_src();
$siteLink = $storeUrl !== '' ? $storeUrl : 'https://wbuarque.com.br';
$releasesLink = $siteLink . '/releases';
$termsLink = $siteLink . '/termos-de-uso';
$configLink = Plugin::getWebDir('wbstore') . '/front/config.php';
$notificationsLink = Plugin::getWebDir('wbstore') . '/front/notifications.php';

$maskedLicense = $licenseKey !== '' ? wbstore_mask($licenseKey, 7, 5) : 'Não configurada';
$maskedInstance = $instanceId !== '' ? wbstore_mask($instanceId, 8, 6) : 'Indefinida';
?>
<style>
:root{
   --wb-bg:#f4f7fb;
   --wb-card:#ffffff;
   --wb-border:#dbe5f0;
   --wb-text:#16324f;
   --wb-muted:#66788a;
   --wb-primary:#0f4c81;
   --wb-primary-2:#1b8fd9;
   --wb-primary-3:#1aa5a3;
   --wb-accent:#72d692;
   --wb-gold:#f2bf41;
   --wb-ok:#1d9d55;
   --wb-warn:#d68a1d;
   --wb-bad:#c95d3b;
   --wb-shadow:0 16px 35px rgba(15, 76, 129, .10);
}
.wb-page,.wb-page *{box-sizing:border-box}.wb-page{max-width:1260px;margin:0 auto;padding:0 10px 16px;color:var(--wb-text)}
.wb-shell{display:grid;grid-template-columns:240px minmax(0,1fr);gap:14px;align-items:start}
.wb-sidebar{position:sticky;top:14px;background:var(--wb-card);border:1px solid var(--wb-border);border-radius:18px;box-shadow:var(--wb-shadow);overflow:hidden;min-width:0}
.wb-brand{padding:16px 15px;border-bottom:1px solid var(--wb-border);background:linear-gradient(135deg, rgba(15,76,129,.10), rgba(114,214,146,.18))}
.wb-brand-top{display:flex;align-items:center;gap:10px;margin-bottom:8px}
.wb-brand-logo{width:46px;height:46px;border-radius:14px;background:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 10px 20px rgba(15,76,129,.16);overflow:hidden;position:relative}
.wb-brand-logo img{width:34px;height:34px;object-fit:contain;display:block}
.wb-brand-fallback{display:none;width:40px;height:40px;border-radius:12px;background:linear-gradient(135deg, var(--wb-primary), var(--wb-primary-3));color:#fff;font-size:14px;font-weight:900;align-items:center;justify-content:center;letter-spacing:.04em}
.wb-brand-logo.is-fallback .wb-brand-fallback{display:flex}
.wb-brand-logo.is-fallback img{display:none}
.wb-brand h2{margin:0;font-size:18px;font-weight:900;letter-spacing:.2px}
.wb-brand p{margin:4px 0 0;font-size:12px;color:var(--wb-muted)}
.wb-license-state{display:inline-flex;align-items:center;gap:8px;padding:8px 12px;border-radius:999px;font-size:12px;font-weight:900;border:1px solid transparent}
.wb-license-state.state-ok{background:rgba(29,157,85,.12);color:#166a3a;border-color:rgba(29,157,85,.22)}
.wb-license-state.state-warn{background:rgba(242,191,65,.16);color:#9a6a00;border-color:rgba(242,191,65,.30)}
.wb-nav{padding:10px}
.wb-nav-title{margin:6px 10px 10px;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:var(--wb-muted)}
.wb-nav a{display:flex;align-items:center;gap:10px;padding:10px 12px;margin-bottom:6px;border-radius:12px;text-decoration:none;color:var(--wb-text);font-weight:800;border:1px solid transparent;background:#fff}
.wb-filter a{display:inline-flex;align-items:center;justify-content:center;padding:10px 14px;border:1px solid var(--wb-border);border-radius:999px;background:#fff;color:var(--wb-text);text-decoration:none;font-weight:800;transition:.18s ease}
.wb-filter a:hover,.wb-filter a.active{border-color:rgba(15,76,129,.25);background:linear-gradient(135deg, rgba(15,76,129,.10), rgba(114,214,146,.14));color:var(--wb-primary)}
.wb-nav a:hover,.wb-nav a.active{background:linear-gradient(135deg, rgba(15,76,129,.08), rgba(114,214,146,.12));border-color:rgba(15,76,129,.14);color:var(--wb-primary)}
.wb-sidebar-foot{padding:12px 14px;border-top:1px solid var(--wb-border);background:#fbfdff}
.wb-foot-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.wb-foot-card{border:1px solid var(--wb-border);border-radius:12px;padding:9px 10px;background:#fff}
.wb-foot-card b{display:block;font-size:16px;line-height:1.1}
.wb-foot-card span{display:block;margin-top:4px;font-size:11px;color:var(--wb-muted)}
.wb-main{min-width:0}
.wb-flash{margin-bottom:14px}
.wb-hero{display:flex;justify-content:space-between;gap:16px;align-items:stretch;padding:18px;border-radius:18px;background:linear-gradient(135deg, var(--wb-primary) 0%, #5c48d8 38%, var(--wb-primary-2) 68%, var(--wb-primary-3) 100%);color:#fff;box-shadow:0 18px 32px rgba(17, 56, 122, .18)}
.wb-hero-left{flex:1;min-width:280px}
.wb-hero-right{width:240px;display:flex;flex-direction:column;justify-content:space-between;align-items:flex-end;gap:14px}
.wb-badge{display:inline-flex;align-items:center;gap:8px;padding:7px 12px;border-radius:999px;background:rgba(255,255,255,.16);font-size:12px;font-weight:900;backdrop-filter:blur(6px)}
.wb-hero h1{margin:8px 0 6px;font-size:24px;font-weight:900;line-height:1.08}
.wb-hero p{margin:0;color:rgba(255,255,255,.95);max-width:680px;font-size:14px}
.wb-hero ul{margin:14px 0 0;padding:0;list-style:none}
.wb-hero li{margin:7px 0;padding-left:18px;position:relative;color:rgba(255,255,255,.94);font-weight:700}
.wb-hero li:before{content:'•';position:absolute;left:0;top:0;color:var(--wb-gold)}
.wb-sync-form{margin:0}
.wb-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:10px 14px;border-radius:12px;font-weight:900;text-decoration:none;border:1px solid transparent;cursor:pointer;transition:.18s ease;font-size:13px}
.wb-btn:hover{transform:translateY(-1px)}
.wb-btn-sync{background:var(--wb-gold);color:#473100;box-shadow:0 10px 24px rgba(242,191,65,.28)}
.wb-btn-light{background:rgba(255,255,255,.16);color:#fff;border-color:rgba(255,255,255,.22)}
.wb-hero-links{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:10px}
.wb-hero-links a{color:#fff;text-decoration:none;font-size:13px;font-weight:800;opacity:.95}
.wb-hero-links a:hover{text-decoration:underline}
.wb-top-grid{display:grid;grid-template-columns:1fr;gap:16px;margin-top:18px}
.wb-section{margin-top:14px;background:var(--wb-card);border:1px solid var(--wb-border);border-radius:18px;box-shadow:var(--wb-shadow);overflow:hidden}
.wb-section-head{display:flex;justify-content:space-between;gap:12px;align-items:center;padding:16px 16px;border-bottom:1px solid var(--wb-border);background:linear-gradient(180deg, #ffffff 0%, #f8fbff 100%)}
.wb-section-title{display:flex;align-items:center;gap:12px;min-width:0}
.wb-title-mark{width:16px;height:32px;border-radius:0 0 6px 6px;background:linear-gradient(180deg, #b63cc8, #824df0);position:relative}
.wb-title-mark:before{content:'';position:absolute;left:0;right:0;bottom:-8px;margin:auto;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid #824df0;width:0}
.wb-section-title h3{margin:0;font-size:22px;font-weight:900;line-height:1.05}
.wb-section-title p{margin:4px 0 0;color:var(--wb-muted);font-weight:700}
.wb-pills{display:flex;flex-wrap:wrap;gap:8px}
.wb-pill{display:inline-flex;align-items:center;gap:8px;padding:7px 12px;border-radius:999px;font-size:12px;font-weight:900;border:1px solid transparent}
.wb-pill-neutral{background:#eef4fb;color:#49627b;border-color:#d4e2ef}
.wb-pill-ok{background:rgba(29,157,85,.12);color:#166a3a;border-color:rgba(29,157,85,.18)}
.wb-pill-lock{background:rgba(201,93,59,.12);color:#8c3c24;border-color:rgba(201,93,59,.18)}
.wb-tools{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:14px 16px;border-bottom:1px solid var(--wb-border);background:#fbfdff}
.wb-search{flex:1;min-width:260px;position:relative}
.wb-search input{width:100%;padding:11px 12px 11px 38px;border-radius:12px;border:1px solid var(--wb-border);background:#fff;outline:none;font-weight:700;color:var(--wb-text)}
.wb-search input:focus{border-color:rgba(27,143,217,.48);box-shadow:0 0 0 4px rgba(27,143,217,.12)}
.wb-search i{position:absolute;left:14px;top:50%;transform:translateY(-50%);color:#7d93a9}
.wb-filter{display:flex;flex-wrap:wrap;gap:6px}
.wb-filter button{padding:8px 10px;border-radius:10px;border:1px solid var(--wb-border);background:#fff;color:var(--wb-text);font-weight:900;cursor:pointer;font-size:12px}
.wb-filter button.active,.wb-filter button:hover{background:linear-gradient(135deg, rgba(15,76,129,.08), rgba(114,214,146,.10));border-color:rgba(15,76,129,.16);color:var(--wb-primary)}
.wb-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px;padding:14px}
.wb-card{position:relative;display:flex;gap:12px;padding:14px;border-radius:16px;border:1px solid rgba(54, 128, 110, .35);background:linear-gradient(180deg, #ffffff 0%, #fbfeff 100%);box-shadow:0 10px 20px rgba(15, 76, 129, .05)}
.wb-card[data-status='active']{border-color:rgba(29,157,85,.40)}
.wb-card[data-status='installed']{border-color:rgba(27,143,217,.34)}
.wb-card[data-status='locked']{border-color:rgba(201,93,59,.28)}
.wb-card-cover{width:62px;height:62px;flex:0 0 62px;border-radius:16px;background:linear-gradient(135deg, rgba(15,76,129,.14), rgba(114,214,146,.24));display:flex;align-items:center;justify-content:center;overflow:hidden;border:1px solid rgba(15,76,129,.12)}
.wb-card-cover img{width:100%;height:100%;object-fit:cover}
.wb-card-cover span{font-size:24px;font-weight:900;color:var(--wb-primary)}
.wb-card-body{min-width:0;flex:1}
.wb-card-top{display:flex;justify-content:space-between;gap:12px;align-items:flex-start}
.wb-card-top h4{margin:0;font-size:17px;font-weight:900;line-height:1.1}
.wb-card-meta{margin-top:3px;font-size:11px;color:var(--wb-muted);font-weight:700}
.wb-tier{display:inline-flex;align-items:center;gap:8px;padding:6px 10px;border-radius:999px;font-size:11px;font-weight:900;white-space:nowrap;border:1px solid transparent}
.wb-tier.tier-free{background:rgba(29,157,85,.12);color:#166a3a;border-color:rgba(29,157,85,.18)}
.wb-tier.tier-open{background:rgba(27,143,217,.12);color:#165987;border-color:rgba(27,143,217,.18)}
.wb-tier.tier-paid{background:rgba(242,191,65,.16);color:#8c6205;border-color:rgba(242,191,65,.22)}
.wb-tier.tier-locked{background:rgba(201,93,59,.12);color:#8c3c24;border-color:rgba(201,93,59,.18)}
.wb-card-desc{margin:10px 0 0;color:#42566d;line-height:1.4;font-size:13px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:5;overflow:hidden}.wb-card-desc.is-expanded{display:block;-webkit-line-clamp:unset;overflow:visible}.wb-readmore{display:inline-flex;align-items:center;gap:6px;margin-top:8px;padding:0;border:0;background:none;color:var(--wb-primary);font-size:12px;font-weight:900;cursor:pointer}.wb-readmore:hover{text-decoration:underline}.wb-readmore.is-hidden{display:none}
.wb-card-flags{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
.wb-mini{display:inline-flex;align-items:center;gap:6px;padding:5px 9px;border-radius:999px;background:#f3f8fd;border:1px solid #dde9f4;color:#4f6982;font-size:10px;font-weight:900}
.wb-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
.wb-actions .wb-btn{padding:9px 11px;border-radius:10px;font-size:12px}
.wb-btn-primary{background:var(--wb-primary);color:#fff}
.wb-btn-secondary{background:#fff;color:var(--wb-text);border-color:var(--wb-border)}
.wb-btn-buy{background:var(--wb-gold);color:#473100}
.wb-actions .disabled{pointer-events:none;opacity:.48;filter:grayscale(.15)}
.wb-grid-info{display:grid;grid-template-columns:repeat(3, minmax(0, 1fr));gap:12px;padding:14px}
.wb-info-card{border:1px solid var(--wb-border);border-radius:16px;padding:14px;background:linear-gradient(180deg, #ffffff 0%, #fbfdff 100%)}
.wb-info-card h4{margin:0 0 10px;font-size:16px;font-weight:900}
.wb-info-card p{margin:0;color:#42566d;line-height:1.5}
.wb-list{display:flex;flex-direction:column;gap:10px;margin-top:12px}
.wb-list-row{display:flex;justify-content:space-between;gap:10px;padding:10px 12px;border-radius:14px;background:#f7fbff;border:1px solid #e0ebf5}
.wb-list-row span{display:block}
.wb-list-row small{color:var(--wb-muted);font-weight:700}
.wb-inline-links{display:flex;flex-wrap:wrap;gap:10px;margin-top:14px}
.wb-inline-links a{text-decoration:none;font-weight:900;color:var(--wb-primary)}
.wb-inline-links a:hover{text-decoration:underline}
.wb-empty{padding:26px 20px;color:var(--wb-muted);font-weight:800}
.wb-log-list{display:flex;flex-direction:column;gap:10px;margin-top:12px}
.wb-log{padding:12px 14px;border-radius:14px;border:1px solid var(--wb-border);background:#f9fcff}
.wb-log strong{display:block;font-size:13px;margin-bottom:4px}
.wb-table{padding:0 14px 14px}
.wb-table-wrap{overflow:auto;border:1px solid var(--wb-border);border-radius:18px}
.wb-table table{width:100%;border-collapse:collapse;background:#fff;min-width:740px}
.wb-table th,.wb-table td{padding:13px 14px;border-bottom:1px solid #edf3f8;text-align:left;font-size:13px}
.wb-table th{background:#f7fbff;color:#51697f;font-weight:900;text-transform:uppercase;font-size:11px;letter-spacing:.04em}
.wb-table tr:last-child td{border-bottom:none}
.wb-table td strong{display:block;font-size:14px}
.wb-table td small{color:var(--wb-muted)}
@media (max-width: 1260px){
   .wb-shell{grid-template-columns:220px minmax(0,1fr)}
   .wb-grid-info{grid-template-columns:1fr 1fr}
}
@media (max-width: 1120px){
   .wb-cards{grid-template-columns:1fr}
}
@media (max-width: 980px){
   .wb-shell{grid-template-columns:1fr}
   .wb-sidebar{position:static}
   .wb-hero{flex-direction:column}
   .wb-hero-right{width:auto;align-items:flex-start}
   .wb-section-head{flex-direction:column;align-items:flex-start}
   .wb-grid-info{grid-template-columns:1fr}
}
@media (max-width: 720px){
   .wb-page{padding:0 8px 18px}
   .wb-brand-top{align-items:flex-start}
   .wb-hero h1{font-size:24px}
   .wb-card{flex-direction:column}
   .wb-card-cover{width:64px;height:64px;flex-basis:64px}
   .wb-card-top{flex-direction:column}
   .wb-tools{flex-direction:column;align-items:stretch}
}
</style>
<div class="wb-page">
   <?php if ($flashOk !== ''): ?>
      <div class="alert alert-success wb-flash"><?= wbstore_e($flashOk) ?></div>
   <?php endif; ?>
   <?php if ($flashErr !== ''): ?>
      <div class="alert alert-danger wb-flash"><?= wbstore_e($flashErr) ?></div>
   <?php endif; ?>
   <?php if ($flashInfo !== ''): ?>
      <div class="alert alert-info wb-flash"><?= wbstore_e($flashInfo) ?></div>
   <?php endif; ?>

   <div class="wb-shell">
      <aside class="wb-sidebar">
         <div class="wb-brand">
            <div class="wb-brand-top">
               <div class="wb-brand-logo <?= $logoWeb === '' ? 'is-fallback' : '' ?>">
                  <?php if ($logoWeb !== ''): ?>
                     <img src="<?= wbstore_e($logoWeb) ?>" alt="WB Store" onerror="this.parentNode.classList.add('is-fallback')">
                  <?php endif; ?>
                  <span class="wb-brand-fallback">WB</span>
               </div>
               <div>
                  <h2>WB Store</h2>
                  <p>Catálogo privado da WBUARQUE dentro do GLPI.</p>
               </div>
            </div>
            <span class="wb-license-state <?= wbstore_e($licenseBadge['class']) ?>">
               <i class="fas fa-shield-alt"></i>
               <?= wbstore_e($licenseBadge['text']) ?>
            </span>
         </div>

         <nav class="wb-nav">
            <div class="wb-nav-title">Navegação</div>
            <a href="#modulos" class="active"><i class="fas fa-puzzle-piece"></i> Módulos</a>
            <a href="#contato"><i class="fas fa-address-card"></i> Contato</a>
            <a href="#licenciamento"><i class="fas fa-key"></i> Licenciamento</a>
            <a href="#logs"><i class="fas fa-file-alt"></i> Logs</a>
            <a href="#todos"><i class="fas fa-th-list"></i> Todos</a>
         </nav>

         <div class="wb-sidebar-foot">
            <div class="wb-foot-grid">
               <div class="wb-foot-card">
                  <b><?= (int)$allCount ?></b>
                  <span>Módulos no catálogo</span>
               </div>
               <div class="wb-foot-card">
                  <b><?= (int)$activeModules ?></b>
                  <span>Módulos ativos</span>
               </div>
               <div class="wb-foot-card">
                  <b><?= (int)$unreadNotices ?></b>
                  <span>Avisos pendentes</span>
               </div>
               <div class="wb-foot-card">
                  <b><?= wbstore_e($plan) ?></b>
                  <span>Plano atual</span>
               </div>
            </div>
         </div>
      </aside>

      <main class="wb-main">
         <section class="wb-hero">
            <div class="wb-hero-left">
               <span class="wb-badge"><i class="fas fa-crown"></i> Plano atual: <?= wbstore_e($plan) ?></span>
               <h1>WB Store com visual de portal e identidade WBUARQUE.</h1>
               <p>Catálogo centralizado de plugins, sincronização manual, leitura de licenciamento e diagnóstico local sem depender de chute.</p>
               <ul>
                  <li>Consulta o cache local e organiza o catálogo com foco em operação.</li>
                  <li>Mostra status real de licença, instalação, ativação e módulos bloqueados.</li>
                  <li>Entrega navegação limpa, leitura rápida e layout no padrão de loja interna.</li>
               </ul>
            </div>
            <div class="wb-hero-right">
               <form method="post" class="wb-sync-form">
                  <?= Html::hidden('_glpi_csrf_token', ['value' => Session::getNewCSRFToken()]); ?>
                  <input type="hidden" name="action" value="sync_catalog">
                  <button type="submit" class="wb-btn wb-btn-sync"><i class="fas fa-sync-alt"></i> Sincronizar</button>
               </form>
               <div class="wb-hero-links">
                  <a href="#contato">Contato</a>
                  <a href="<?= wbstore_e($siteLink) ?>" target="_blank" rel="noopener">Site</a>
                  <a href="<?= wbstore_e($releasesLink) ?>" target="_blank" rel="noopener">Releases</a>
                  <a href="<?= wbstore_e($termsLink) ?>" target="_blank" rel="noopener">Termos</a>
               </div>
               <a href="<?= wbstore_e($notificationsLink) ?>" class="wb-btn wb-btn-light"><i class="fas fa-bell"></i> Avisos</a>
            </div>
         </section>

         <section class="wb-section" id="modulos">
            <div class="wb-section-head">
               <div class="wb-section-title">
                  <span class="wb-title-mark"></span>
                  <div>
                     <h3>Módulos disponíveis</h3>
                     <p>Catálogo visual com status real por plugin.</p>
                  </div>
               </div>
               <div class="wb-pills">
                  <span class="wb-pill wb-pill-neutral"><i class="fas fa-code-branch"></i> <?= wbstore_e($glpiFilterLabel) ?></span>
                  <span class="wb-pill wb-pill-neutral"><i class="fas fa-cubes"></i> <?= (int)$allCount ?> total</span>
                  <span class="wb-pill wb-pill-ok"><i class="fas fa-check-circle"></i> <?= (int)$activeModules ?> ativos</span>
                  <span class="wb-pill wb-pill-neutral"><i class="fas fa-box-open"></i> <?= (int)$installedModules ?> instalados</span>
                  <span class="wb-pill wb-pill-lock"><i class="fas fa-lock"></i> <?= (int)$lockedModules ?> bloqueados</span>
                  <?php if ($hiddenByGlpiFilter > 0): ?>
                     <span class="wb-pill wb-pill-neutral"><i class="fas fa-filter"></i> <?= (int)$hiddenByGlpiFilter ?> ocultos por versão</span>
                  <?php endif; ?>
               </div>
            </div>

            <div class="wb-tools">
               <div class="wb-search">
                  <i class="fas fa-search"></i>
                  <input id="wb-search" type="text" placeholder="Pesquisar módulo por nome ou slug...">
               </div>
               <div class="wb-filter">
                  <button type="button" class="active" data-filter="all">Todos</button>
                  <button type="button" data-filter="active">Ativos</button>
                  <button type="button" data-filter="installed">Instalados</button>
                  <button type="button" data-filter="available">Liberados</button>
                  <button type="button" data-filter="locked">Bloqueados</button>
               </div>
               <div class="wb-filter" style="margin-left:auto">
                  <a class="<?= $glpiFilter === 'current' ? 'active' : '' ?>" href="<?= wbstore_e(Plugin::getWebDir('wbstore') . '/front/catalog.php?glpi_filter=current') ?>#modulos">Atual</a>
                  <a class="<?= $glpiFilter === '10' ? 'active' : '' ?>" href="<?= wbstore_e(Plugin::getWebDir('wbstore') . '/front/catalog.php?glpi_filter=10') ?>#modulos">GLPI 10</a>
                  <a class="<?= $glpiFilter === '11' ? 'active' : '' ?>" href="<?= wbstore_e(Plugin::getWebDir('wbstore') . '/front/catalog.php?glpi_filter=11') ?>#modulos">GLPI 11</a>
                  <a class="<?= $glpiFilter === 'all' ? 'active' : '' ?>" href="<?= wbstore_e(Plugin::getWebDir('wbstore') . '/front/catalog.php?glpi_filter=all') ?>#modulos">Todos</a>
               </div>
            </div>

            <?php if (empty($moduleCards)): ?>
               <div class="wb-empty">Sem módulos para exibir no filtro <?= wbstore_e($glpiFilterLabel) ?>. Confira a licença e sincronize o catálogo.</div>
            <?php else: ?>
               <div class="wb-cards" id="wb-cards">
                  <?php foreach ($moduleCards as $card): ?>
                     <?php
                        $installUrl = Plugin::getWebDir('wbstore') . '/front/install.php?slug=' . rawurlencode($card['slug']);
                        $installText = $card['installed'] ? ($card['activated'] ? 'Reinstalar' : 'Reinstalar') : 'Baixar e instalar';
                        $titleInitial = function_exists('mb_substr') ? mb_substr($card['name'], 0, 1) : substr($card['name'], 0, 1);
                     ?>
                     <article class="wb-card" data-status="<?= wbstore_e($card['status']) ?>" data-name="<?= wbstore_e(function_exists('mb_strtolower') ? mb_strtolower($card['name']) : strtolower($card['name'])) ?>" data-slug="<?= wbstore_e(function_exists('mb_strtolower') ? mb_strtolower($card['slug']) : strtolower($card['slug'])) ?>">
                        <div class="wb-card-cover">
                           <?php if ($card['image'] !== ''): ?>
                              <img src="<?= wbstore_e($card['image']) ?>" alt="<?= wbstore_e($card['name']) ?>">
                           <?php else: ?>
                              <span><?= wbstore_e($titleInitial) ?></span>
                           <?php endif; ?>
                        </div>
                        <div class="wb-card-body">
                           <div class="wb-card-top">
                              <div>
                                 <h4><?= wbstore_e($card['name']) ?></h4>
                                 <div class="wb-card-meta">
                                    <?= $card['version'] !== '' ? 'v' . wbstore_e($card['version']) . ' · ' : '' ?>
                                    <?= wbstore_e($card['author']) ?>
                                 </div>
                              </div>
                              <span class="wb-tier <?= wbstore_e($card['tier']['class']) ?>"><?= wbstore_e($card['tier']['label']) ?></span>
                           </div>

                           <p class="wb-card-desc" data-fulltext="1"><?= wbstore_e($card['description']) ?></p>
                           <button type="button" class="wb-readmore is-hidden" data-label-more="Ler mais" data-label-less="Ler menos"><i class="fas fa-angle-down"></i> Ler mais</button>

                           <div class="wb-card-flags">
                              <?php if ($card['activated']): ?>
                                 <span class="wb-mini"><i class="fas fa-check-circle"></i> Ativo no GLPI</span>
                              <?php elseif ($card['installed']): ?>
                                 <span class="wb-mini"><i class="fas fa-box-open"></i> Instalado</span>
                              <?php endif; ?>
                              <?php if ($card['glpi_label'] !== ''): ?>
                                 <span class="wb-mini"><i class="fas fa-code-branch"></i> <?= wbstore_e($card['glpi_label']) ?></span>
                              <?php elseif ($card['min_glpi'] !== ''): ?>
                                 <span class="wb-mini"><i class="fas fa-arrow-up"></i> GLPI <?= wbstore_e($card['min_glpi']) ?>+</span>
                              <?php endif; ?>
                              <span class="wb-mini"><i class="fas fa-fingerprint"></i> <?= wbstore_e($card['slug']) ?></span>
                           </div>

                           <div class="wb-actions">
                              <a class="wb-btn wb-btn-primary<?= !$card['can'] ? ' disabled' : '' ?>" href="<?= wbstore_e($installUrl) ?>"><i class="fas fa-download"></i> <?= wbstore_e($installText) ?></a>
                              <?php if ($card['demo'] !== ''): ?>
                                 <a class="wb-btn wb-btn-secondary" href="<?= wbstore_e($card['demo']) ?>" target="_blank" rel="noopener"><i class="fas fa-play-circle"></i> Demonstração</a>
                              <?php endif; ?>
                              <?php if ($card['buy'] !== ''): ?>
                                 <a class="wb-btn wb-btn-buy" href="<?= wbstore_e($card['buy']) ?>" target="_blank" rel="noopener"><i class="fas fa-handshake"></i> Contratar</a>
                              <?php endif; ?>
                           </div>
                        </div>
                     </article>
                  <?php endforeach; ?>
               </div>
            <?php endif; ?>
         </section>

         <section class="wb-section" id="contato">
            <div class="wb-section-head">
               <div class="wb-section-title">
                  <span class="wb-title-mark"></span>
                  <div>
                     <h3>Contato</h3>
                     <p>Atendimento e atalhos do portal.</p>
                  </div>
               </div>
               <div class="wb-pills">
                  <span class="wb-pill wb-pill-neutral"><i class="fas fa-globe"></i> <?= wbstore_e($domain !== '' ? $domain : 'Domínio não definido') ?></span>
               </div>
            </div>
            <div class="wb-grid-info">
               <div class="wb-info-card">
                  <h4>Canal principal</h4>
                  <p>Use a WB Store para concentrar instalação, atualização e leitura do ambiente sem depender de acesso manual em cada plugin.</p>
                  <div class="wb-inline-links">
                     <a href="<?= wbstore_e($siteLink) ?>" target="_blank" rel="noopener">Abrir site</a>
                     <a href="<?= wbstore_e($notificationsLink) ?>">Abrir avisos</a>
                     <a href="<?= wbstore_e($configLink) ?>">Abrir configurações</a>
                  </div>
               </div>
               <div class="wb-info-card">
                  <h4>Cadastro do cliente</h4>
                  <div class="wb-list">
                     <div class="wb-list-row"><span>Responsável</span><small><?= wbstore_e($clientName !== '' ? $clientName : 'Não informado') ?></small></div>
                     <div class="wb-list-row"><span>Empresa</span><small><?= wbstore_e($clientCompany !== '' ? $clientCompany : 'Não informada') ?></small></div>
                     <div class="wb-list-row"><span>E-mail</span><small><?= wbstore_e($clientEmail !== '' ? $clientEmail : 'Não informado') ?></small></div>
                     <div class="wb-list-row"><span>Telefone</span><small><?= wbstore_e($clientPhone !== '' ? $clientPhone : 'Não informado') ?></small></div>
                  </div>
               </div>
               <div class="wb-info-card">
                  <h4>Avisos recentes</h4>
                  <?php if (empty($recentNotices)): ?>
                     <p>Sem avisos salvos localmente. A área de notificações continua disponível para consulta direta.</p>
                  <?php else: ?>
                     <div class="wb-log-list">
                        <?php foreach ($recentNotices as $notice): ?>
                           <div class="wb-log">
                              <strong><?= wbstore_e($notice['title'] ?? 'Aviso') ?></strong>
                              <div><?= wbstore_e($notice['message'] ?? '') ?></div>
                           </div>
                        <?php endforeach; ?>
                     </div>
                  <?php endif; ?>
               </div>
            </div>
         </section>

         <section class="wb-section" id="licenciamento">
            <div class="wb-section-head">
               <div class="wb-section-title">
                  <span class="wb-title-mark"></span>
                  <div>
                     <h3>Licenciamento</h3>
                     <p>Leitura rápida do estado local da licença.</p>
                  </div>
               </div>
               <div class="wb-pills">
                  <span class="wb-pill <?= $licenseValid ? 'wb-pill-ok' : 'wb-pill-lock' ?>"><i class="fas fa-key"></i> <?= wbstore_e($licenseBadge['text']) ?></span>
               </div>
            </div>
            <div class="wb-grid-info">
               <div class="wb-info-card">
                  <h4>Credenciais</h4>
                  <div class="wb-list">
                     <div class="wb-list-row"><span>Licença</span><small><?= wbstore_e($maskedLicense) ?></small></div>
                     <div class="wb-list-row"><span>Instância</span><small><?= wbstore_e($maskedInstance) ?></small></div>
                     <div class="wb-list-row"><span>Domínio</span><small><?= wbstore_e($domain !== '' ? $domain : 'Não definido') ?></small></div>
                  </div>
               </div>
               <div class="wb-info-card">
                  <h4>Validação</h4>
                  <div class="wb-list">
                     <div class="wb-list-row"><span>Último OK</span><small><?= wbstore_e(wbstore_timeago($lastLicenseOkAt)) ?></small></div>
                     <div class="wb-list-row"><span>Válida até</span><small><?= wbstore_e($licenseValidUntil > 0 ? date('d/m/Y H:i', $licenseValidUntil) : 'Sem cache') ?></small></div>
                     <div class="wb-list-row"><span>Cache catálogo</span><small><?= wbstore_e($fullCacheUntil > 0 ? date('d/m/Y H:i', $fullCacheUntil) : 'Sem cache') ?></small></div>
                     <div class="wb-list-row"><span>Modo seguro</span><small><?= !empty($conf['safe_mode']) ? 'Ativo' : 'Desligado' ?></small></div>
                  </div>
               </div>
               <div class="wb-info-card">
                  <h4>Ações</h4>
                  <p>Quando a licença falhar, o ponto certo para corrigir é a configuração da WB Store. Sem isso, qualquer outro ajuste vira remendo.</p>
                  <div class="wb-inline-links">
                     <a href="<?= wbstore_e($configLink) ?>">Revisar configuração</a>
                     <a href="<?= wbstore_e($siteLink) ?>" target="_blank" rel="noopener">Portal WBUARQUE</a>
                  </div>
               </div>
            </div>
         </section>

         <section class="wb-section" id="logs">
            <div class="wb-section-head">
               <div class="wb-section-title">
                  <span class="wb-title-mark"></span>
                  <div>
                     <h3>Logs e diagnóstico</h3>
                     <p>Resumo local para saber onde está o problema sem perder tempo.</p>
                  </div>
               </div>
               <div class="wb-pills">
                  <span class="wb-pill wb-pill-neutral"><i class="fas fa-bell"></i> <?= (int)$unreadNotices ?> pendentes</span>
               </div>
            </div>
            <div class="wb-grid-info">
               <div class="wb-info-card">
                  <h4>Estado geral</h4>
                  <div class="wb-log-list">
                     <div class="wb-log"><strong>Licença</strong><?= $licenseConfigured ? ($licenseValid ? 'Válida e em cache local.' : 'Configurada, mas precisa de validação.') : 'Ainda não configurada.' ?></div>
                     <div class="wb-log"><strong>Catálogo</strong><?= $allCount > 0 ? 'Pacotes carregados do cache/portal.' : 'Nenhum pacote disponível no momento.' ?></div>
                     <div class="wb-log"><strong>Sincronização</strong><?= wbstore_e($fullCacheUntil > 0 ? 'Cache local atualizado até ' . date('d/m/Y H:i', $fullCacheUntil) : 'Sem cache local válido.') ?></div>
                  </div>
               </div>
               <div class="wb-info-card">
                  <h4>Operação</h4>
                  <div class="wb-log-list">
                     <div class="wb-log"><strong>Módulos ativos</strong><?= (int)$activeModules ?> plugin(s) ativado(s) no GLPI.</div>
                     <div class="wb-log"><strong>Módulos instalados</strong><?= (int)$installedModules ?> plugin(s) encontrado(s) no diretório local.</div>
                     <div class="wb-log"><strong>Módulos bloqueados</strong><?= (int)$lockedModules ?> item(ns) dependem de licença/plano.</div>
                  </div>
               </div>
               <div class="wb-info-card">
                  <h4>Leitura rápida</h4>
                  <p>Se o catálogo não carregar, primeiro confira licença, domínio e sincronização da loja. Só depois mexa em plugin individual.</p>
                  <div class="wb-inline-links">
                     <a href="<?= wbstore_e($notificationsLink) ?>">Ver avisos completos</a>
                     <a href="<?= wbstore_e($configLink) ?>">Abrir tela de configuração</a>
                  </div>
               </div>
            </div>
         </section>

         <section class="wb-section" id="todos">
            <div class="wb-section-head">
               <div class="wb-section-title">
                  <span class="wb-title-mark"></span>
                  <div>
                     <h3>Todos os módulos</h3>
                     <p>Visão consolidada do catálogo.</p>
                  </div>
               </div>
            </div>
            <div class="wb-table">
               <div class="wb-table-wrap">
                  <table>
                     <thead>
                        <tr>
                           <th>Módulo</th>
                           <th>Status</th>
                           <th>Versão</th>
                           <th>Compatibilidade GLPI</th>
                           <th>Slug</th>
                        </tr>
                     </thead>
                     <tbody>
                        <?php if (empty($moduleCards)): ?>
                           <tr>
                              <td colspan="5">Sem dados para exibir.</td>
                           </tr>
                        <?php else: ?>
                           <?php foreach ($moduleCards as $card): ?>
                              <tr>
                                 <td>
                                    <strong><?= wbstore_e($card['name']) ?></strong>
                                    <small><?= wbstore_e($card['author']) ?></small>
                                 </td>
                                 <td><?= wbstore_e($card['tier']['label']) ?></td>
                                 <td><?= wbstore_e($card['version'] !== '' ? $card['version'] : '—') ?></td>
                                 <td><?= wbstore_e($card['glpi_label'] !== '' ? $card['glpi_label'] : ($card['min_glpi'] !== '' ? $card['min_glpi'] : '—')) ?></td>
                                 <td><?= wbstore_e($card['slug']) ?></td>
                              </tr>
                           <?php endforeach; ?>
                        <?php endif; ?>
                     </tbody>
                  </table>
               </div>
            </div>
         </section>
      </main>
   </div>
</div>
<script>
(function(){
   const search = document.getElementById('wb-search');
   const cardsWrap = document.getElementById('wb-cards');
   const filters = document.querySelectorAll('.wb-filter button');
   let activeFilter = 'all';

   function applyFilters(){
      if (!cardsWrap) return;
      const query = (search && search.value ? search.value : '').toLowerCase().trim();
      const cards = cardsWrap.querySelectorAll('.wb-card');
      cards.forEach(function(card){
         const name = (card.getAttribute('data-name') || '').toLowerCase();
         const slug = (card.getAttribute('data-slug') || '').toLowerCase();
         const status = card.getAttribute('data-status') || 'all';
         const textMatch = !query || name.indexOf(query) >= 0 || slug.indexOf(query) >= 0;
         const statusMatch = activeFilter === 'all' || status === activeFilter;
         card.style.display = (textMatch && statusMatch) ? '' : 'none';
      });
      window.setTimeout(refreshReadMore, 20);
   }

   function refreshReadMore(){
      if (!cardsWrap) return;
      cardsWrap.querySelectorAll('.wb-card').forEach(function(card){
         const desc = card.querySelector('.wb-card-desc');
         const btn = card.querySelector('.wb-readmore');
         if (!desc || !btn) return;
         desc.classList.remove('is-expanded');
         btn.classList.remove('is-hidden');
         const needsToggle = desc.scrollHeight > (desc.clientHeight + 6);
         btn.classList.toggle('is-hidden', !needsToggle);
         btn.innerHTML = '<i class="fas fa-angle-down"></i> ' + (btn.getAttribute('data-label-more') || 'Ler mais');
      });
   }

   if (search) {
      search.addEventListener('input', applyFilters);
   }

   filters.forEach(function(btn){
      btn.addEventListener('click', function(){
         filters.forEach(function(other){ other.classList.remove('active'); });
         btn.classList.add('active');
         activeFilter = btn.getAttribute('data-filter') || 'all';
         applyFilters();
      });
   });

   if (cardsWrap) {
      cardsWrap.addEventListener('click', function(event){
         const btn = event.target.closest('.wb-readmore');
         if (!btn) return;
         const card = btn.closest('.wb-card');
         const desc = card ? card.querySelector('.wb-card-desc') : null;
         if (!desc) return;
         const expanded = desc.classList.toggle('is-expanded');
         btn.innerHTML = expanded
            ? '<i class="fas fa-angle-up"></i> ' + (btn.getAttribute('data-label-less') || 'Ler menos')
            : '<i class="fas fa-angle-down"></i> ' + (btn.getAttribute('data-label-more') || 'Ler mais');
      });
   }

   window.addEventListener('resize', refreshReadMore);
   window.setTimeout(refreshReadMore, 60);

   const navLinks = document.querySelectorAll('.wb-nav a');
   const sections = Array.from(document.querySelectorAll('main .wb-section[id]'));
   if (navLinks.length && sections.length) {
      const observer = new IntersectionObserver(function(entries){
         entries.forEach(function(entry){
            if (!entry.isIntersecting) return;
            const id = entry.target.getAttribute('id');
            navLinks.forEach(function(link){
               link.classList.toggle('active', link.getAttribute('href') === '#' + id);
            });
         });
      }, {rootMargin:'-30% 0px -55% 0px', threshold:0.01});
      sections.forEach(function(section){ observer.observe(section); });
   }
})();
</script>
<?php Html::footer();
