<?php
/**
 * 閼哄銇擟MS
 * ============================================================================
 * 芋头CMS 后台管理入口
 * ----------------------------------------------------------------------------
 * 负责后台模块路由、装修接口与公共布局输出。
 * ============================================================================
 * Author: 閼哄銇?<mxgsf@qq.com>
 * Date: 2026-5-20
 */


require_once dirname(__DIR__) . '/core/lib/session.php';
cmsStartSession();
cmsValidateAdminSession();
ob_start();

define('ROOT_PATH', dirname(__DIR__) . '/');

// ========== JSON 接口预处理 ==========
// 在输出页面结构前处理 AJAX 请求，避免响应混入 HTML。
if (isset($_GET['act']) && $_GET['act'] === 'auth' && isset($_GET['action']) && $_GET['action'] === 'activate') {
    if (empty($_SESSION['admin_id'])) {
        http_response_code(401);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['code' => 401, 'msg' => '请先登录后台'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }
    require_once dirname(__DIR__) . '/core/lib/common.php';
    $raw = file_get_contents('php://input');
    $payload = json_decode($raw, true);
    if (!is_array($payload)) {
        $payload = $_POST;
    }
    requireAdminCsrfToken(true, isset($payload['csrf_token']) ? (string) $payload['csrf_token'] : null);
    require_once dirname(__DIR__) . '/core/db/db.php';
    require_once dirname(__DIR__) . '/core/lib/rbac.php';
    $db = \Core\Db\DB::getInstance();
    cmsRequireAdminPermission(cmsLoadCurrentAdminAccess($db), 'auth', true);
    header('Content-Type: application/json');
    $key = trim($payload['license_key'] ?? '');
    $domain = trim($payload['domain'] ?? '');
    if (empty($key)) {
        echo json_encode(['code' => 400, 'msg' => '请输入授权KEY']);
        exit;
    }
    $licenseCenterApi = 'http://yutou.wtbidc.cn/license-center/api.php';
    $ch = curl_init($licenseCenterApi . '?action=check');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode(['license_key' => $key, 'domain' => $domain]),
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_TIMEOUT => 10,
        CURLOPT_CONNECTTIMEOUT => 5,
        CURLOPT_SSL_VERIFYPEER => false,
    ]);
    $resp = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curlErr = curl_error($ch);
    $curlErrno = curl_errno($ch);
    curl_close($ch);
    if (!$resp || $httpCode !== 200) {
        echo json_encode([
            'code' => 500,
            'msg' => '授权平台连接失败',
            'debug' => [
                'http' => $httpCode,
                'curl_err' => $curlErr,
                'curl_errno' => $curlErrno,
                'resp' => substr((string) $resp, 0, 300),
            ]
        ]);
        exit;
    }
    $result = json_decode($resp, true);
    if (!is_array($result)) {
        echo json_encode([
            'code' => 502,
            'msg' => '授权平台返回了非 JSON 内容',
            'debug' => [
                'http' => $httpCode,
                'resp' => substr((string) $resp, 0, 300),
            ]
        ]);
        exit;
    }
    if (!isset($result['code']) || intval($result['code']) !== 200) {
        $errMsg = isset($result['msg']) ? $result['msg'] : '授权校验失败';
        echo json_encode([
            'code' => 403,
            'msg' => $errMsg,
            'debug' => [
                'resp' => substr((string) $resp, 0, 300),
            ]
        ]);
        exit;
    }
    $level = isset($result['level']) ? intval($result['level']) : 1;
    $expireRaw = isset($result['expire']) ? $result['expire'] : null;
    $expireTime = (is_string($expireRaw) && !empty($expireRaw)) ? $expireRaw : null;
    $storeDomain = isset($result['domain']) && trim((string) $result['domain']) !== '' ? trim((string) $result['domain']) : $domain;
    $existing = $db->fetch("SELECT id, site_id, bind_count, max_domains FROM {$db->table('license')} WHERE license_level > 1 AND site_id IS NOT NULL AND site_id <> '' ORDER BY id DESC LIMIT 1");
    if (!$existing) {
        $existing = $db->fetch("SELECT id, site_id, bind_count, max_domains FROM {$db->table('license')} ORDER BY id DESC LIMIT 1");
    }
    $siteId = isset($existing['site_id']) && trim((string) $existing['site_id']) !== ''
        ? trim((string) $existing['site_id'])
        : 'EC' . date('Ymd') . strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 8));
    $maxDomains = isset($result['max_domains']) ? intval($result['max_domains']) : ($level >= 3 ? 999 : 1);
    if ($maxDomains < 1) {
        $maxDomains = 1;
    }
    $bindCount = isset($result['bind_count']) ? intval($result['bind_count']) : intval($existing['bind_count'] ?? 1);
    if ($bindCount < 1) {
        $bindCount = 1;
    }
    $updateData = [
        'license_code' => $key,
        'license_domain' => $storeDomain,
        'license_level' => $level,
        'license_expire' => $expireTime,
        'license_status' => 1,
        'site_id' => $siteId,
        'bind_count' => $bindCount,
        'max_domains' => $maxDomains,
        'update_time' => time(),
    ];
    if ($existing) {
        $db->update('license', $updateData, 'id = ?', [$existing['id']]);
        $db->query("DELETE FROM {$db->table('license')} WHERE id <> ?", [$existing['id']]);
    } else {
        $updateData['create_time'] = time();
        $db->insert('license', $updateData);
    }
    echo json_encode(['code' => 200, 'msg' => '授权激活成功', 'level' => $level]);
    exit;
}
if (isset($_GET['act']) && $_GET['act'] === 'auth' && isset($_GET['action']) && $_GET['action'] === 'reset') {
    if (empty($_SESSION['admin_id'])) {
        http_response_code(401);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['code' => 401, 'msg' => '请先登录后台'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }
    require_once dirname(__DIR__) . '/core/lib/common.php';
    $raw = file_get_contents('php://input');
    $payload = json_decode($raw, true);
    if (!is_array($payload)) {
        $payload = $_POST;
    }
    requireAdminCsrfToken(true, isset($payload['csrf_token']) ? (string) $payload['csrf_token'] : null);
    require_once dirname(__DIR__) . '/core/db/db.php';
    require_once dirname(__DIR__) . '/core/lib/rbac.php';
    $db = \Core\Db\DB::getInstance();
    cmsRequireAdminPermission(cmsLoadCurrentAdminAccess($db), 'auth', true);
    header('Content-Type: application/json');

    $tbl = $db->table('license');
    $currentLicense = $db->fetch("SELECT site_id FROM {$tbl} ORDER BY id DESC LIMIT 1");
    $db->query("DELETE FROM {$tbl} WHERE 1=1");

    $freeCode = 'FREE-' . strtoupper(substr(md5($_SERVER['HTTP_HOST']), 0, 8));
    $siteId = isset($currentLicense['site_id']) && trim((string) $currentLicense['site_id']) !== ''
        ? trim((string) $currentLicense['site_id'])
        : 'EC' . date('Ymd') . strtoupper(substr(md5(uniqid(mt_rand(), true)), 0, 8));
    $domain = $_SERVER['HTTP_HOST'] ?? '';
    $now = time();

    $db->insert('license', [
        'license_code' => $freeCode,
        'license_domain' => $domain,
        'license_level' => 1,
        'license_expire' => null,
        'site_id' => $siteId,
        'bind_count' => 1,
        'max_domains' => 1,
        'license_status' => 1,
        'create_time' => $now,
        'update_time' => $now,
    ]);

    echo json_encode(['code' => 200, 'msg' => '已恢复为当前域名的免费版授权']);
    exit;
}
$act = isset($_GET['act']) ? $_GET['act'] : 'dashboard';
$publicBuilderApiActions = ['business_data', 'submit_form'];
$isPublicBuilderApi = $act === 'builder_api'
    && in_array(trim((string) ($_REQUEST['action'] ?? '')), $publicBuilderApiActions, true);

if (!$isPublicBuilderApi && (!isset($_SESSION['admin_id']) || empty($_SESSION['admin_id']))) {
    header('Location: /admin/login.php');
    exit;
}

require_once dirname(__DIR__) . '/core/db/db.php';
require_once dirname(__DIR__) . '/core/lib/license.php';
require_once dirname(__DIR__) . '/core/lib/template_loader.php';
require_once dirname(__DIR__) . '/core/lib/template_package.php';
require_once dirname(__DIR__) . '/core/lib/safe_zip.php';
require_once dirname(__DIR__) . '/core/lib/common.php';
require_once dirname(__DIR__) . '/core/lib/builder.php';
require_once dirname(__DIR__) . '/core/lib/builder_components.php';
require_once dirname(__DIR__) . '/core/lib/builder_renderer.php';
require_once dirname(__DIR__) . '/core/lib/rbac.php';

// 后台所有已登录写请求统一执行 CSRF 校验。公开建站表单由独立限流逻辑处理。
if (!empty($_SESSION['admin_id']) && $_SERVER['REQUEST_METHOD'] === 'POST') {
    requireAdminCsrfToken(
        isset($_SERVER['HTTP_X_REQUESTED_WITH'])
        || stripos((string) ($_SERVER['HTTP_ACCEPT'] ?? ''), 'application/json') !== false
        || stripos((string) ($_SERVER['CONTENT_TYPE'] ?? ''), 'application/json') !== false
    );
}

$db = \Core\Db\DB::getInstance();
$license = new \Core\Lib\License();
$templatePackageManager = new \Core\Lib\TemplatePackageManager($db, $license);
$adminAccess = !empty($_SESSION['admin_id']) ? cmsLoadCurrentAdminAccess($db) : null;
$adminCanManageCurrentModule = true;
if (!$isPublicBuilderApi && $adminAccess) {
    $permissionAct = in_array($act, ['builder_editor', 'builder_preview', 'builder_preview_live', 'builder_api'], true) ? 'builder' : ($act === 'global_search' ? 'dashboard' : $act);
    $expectsJson = $act === 'builder_api'
        || isset($_SERVER['HTTP_X_REQUESTED_WITH'])
        || stripos((string) ($_SERVER['HTTP_ACCEPT'] ?? ''), 'application/json') !== false;
    $requestCapability = $act === 'notification' ? 'view' : cmsAdminRequestCapability();
    cmsRequireAdminPermission($adminAccess, $permissionAct, $expectsJson, $requestCapability);
    $adminCanManageCurrentModule = cmsAdminCan($adminAccess, $permissionAct, 'manage');
}

function cmsBuilderRequestHasAccess($builderType, $builderRefId)
{
    if (!empty($_SESSION['admin_id'])) {
        return true;
    }
    $token = trim((string) ($_REQUEST['builder_token'] ?? $_GET['builder_token'] ?? $_POST['builder_token'] ?? ''));
    return cmsVerifyBuilderAccessToken($token, $builderType, $builderRefId);
}

if (in_array($act, ['builder_editor', 'builder_preview', 'builder_preview_live', 'builder_api'], true)) {
    $builder = new \Core\Lib\Builder($db);
    $builderCanOperate = $license->canUseBuilder();
    $builderWindowMode = $act === 'builder_editor';
    $builderType = $builder->normalizePageType($_REQUEST['type'] ?? $_REQUEST['builder_type'] ?? 'home');
    $builderRefId = intval($_REQUEST['id'] ?? $_REQUEST['builder_ref_id'] ?? 0);
    $builderRequestAuthorized = cmsBuilderRequestHasAccess($builderType, $builderRefId);

    $builderTargetRows = [
        'page' => $db->fetchAll("SELECT id, page_title FROM {$db->table('page')} WHERE deleted_at = 0 ORDER BY id DESC"),
        'article_category' => $db->fetchAll("SELECT id, channel_name FROM {$db->table('channel')} WHERE channel_type = 1 ORDER BY list_order ASC, id ASC"),
        'product_category' => $db->fetchAll("SELECT id, channel_name FROM {$db->table('channel')} WHERE channel_type = 2 ORDER BY list_order ASC, id ASC"),
        'page_category' => $db->fetchAll("SELECT id, channel_name FROM {$db->table('channel')} WHERE channel_type = 3 ORDER BY list_order ASC, id ASC"),
    ];
    $builderMapById = [];
    foreach ($builderTargetRows as $mapKey => $rows) {
        $builderMapById[$mapKey] = [];
        foreach ($rows as $row) {
            $builderMapById[$mapKey][intval($row['id'])] = $row;
        }
    }
    if ($builder->requiresReferenceId($builderType) && $builderRefId > 0 && !isset($builderMapById['page'][$builderRefId])) {
        $builderRefId = 0;
    }
    if (!$builder->requiresReferenceId($builderType)) {
        $builderRefId = 0;
    }

    $builderTargetLabelMap = [
        'home' => '首页装修',
        'page' => '单页装修',
        'article_list' => '文章列表页装修',
        'article_detail' => '文章详情页装修',
        'product_list' => '产品列表页装修',
        'product_detail' => '产品详情页装修',
        'image_list' => '图片列表页装修',
        'image_detail' => '图片详情页装修',
        'download_list' => '下载列表页装修',
        'download_detail' => '下载详情页装修',
        'video_list' => '视频列表页装修',
        'video_detail' => '视频详情页装修',
        'recruit_list' => '招聘列表页装修',
        'recruit_detail' => '招聘详情页装修',
    ];

    $builderPage = $builder->getDraftByType($builderType, $builderRefId);
    $builderFallbackTitle = $builderTargetLabelMap[$builderType] ?? '妞ょ敻娼扮憗鍛叏';
    if ($builderType === 'page' && $builderRefId > 0 && isset($builderMapById['page'][$builderRefId]['page_title'])) {
        $builderFallbackTitle = trim((string) $builderMapById['page'][$builderRefId]['page_title']);
    }
    $builderLayout = $builderPage && isset($builderPage['layout']) && is_array($builderPage['layout'])
        ? $builderPage['layout']
        : $builder->getDefaultLayout($builderFallbackTitle);
    $builderDefinitions = \Core\Lib\BuilderComponents::getDefinitions();
    $builderStyleFields = \Core\Lib\BuilderComponents::getStyleFields();
    $builderPresetLayouts = \Core\Lib\BuilderComponents::getPresetLayouts();

    if ($act === 'builder_preview' || $act === 'builder_preview_live') {
        if ($act === 'builder_preview_live') {
            requireAdminCsrfToken(true);
            $incomingLayout = json_decode((string) ($_POST['layout_json'] ?? ''), true);
            $builderTitle = trim((string) ($_POST['builder_title'] ?? ''));
            $builderLayout = is_array($incomingLayout)
                ? $builder->normalizeLayout($incomingLayout, $builderTitle !== '' ? $builderTitle : $builderFallbackTitle)
                : $builderLayout;
            if ($builderTitle !== '') {
                $builderLayout['page']['title'] = $builderTitle;
            }
        } else {
            if (!$builderCanOperate) {
                http_response_code(403);
            echo '当前授权版本不支持页面装修。';
                exit;
            }
            $publishedLayout = $builder->getLayoutByType($builderType, $builderRefId);
            if (is_array($publishedLayout)) {
                $builderLayout = $publishedLayout;
            }
        }

        $siteConfigRows = $db->fetchAll("SELECT config_key, config_value FROM {$db->table('config')}");
        $siteConfig = [];
        foreach ($siteConfigRows as $cfg) {
            $siteConfig[$cfg['config_key']] = $cfg['config_value'];
        }
        $renderer = new \Core\Lib\BuilderRenderer($db, $siteConfig);
        $renderer->render($builderLayout, ['module' => 'builder_preview', 'builder_type' => $builderType, 'id' => $builderRefId]);
        exit;
    }

    if ($act === 'builder_api') {
        header('Content-Type: application/json; charset=utf-8');
        $apiAction = trim((string) ($_REQUEST['action'] ?? ''));
        $publicBuilderApiActions = ['business_data', 'submit_form'];
        if (!in_array($apiAction, $publicBuilderApiActions, true) && !$builderRequestAuthorized) {
            echo json_encode(['code' => 403, 'msg' => '未获得前台装修访问授权'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'permission') {
            echo json_encode([
                'code' => 200,
                'data' => [
                    'can_use_builder' => $builderCanOperate,
                    'level_name' => $license->getLevelName(),
                ],
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if (!in_array($apiAction, $publicBuilderApiActions, true) && !$builderCanOperate) {
            echo json_encode(['code' => 403, 'msg' => '当前授权版本不支持页面装修'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'heartbeat' || $apiAction === 'leave_edit') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $editorToken = trim((string) ($payload['editor_token'] ?? ''));
            if ($apiAction === 'leave_edit') {
                echo json_encode($builder->leaveEditSession($editorToken), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            $adminId = intval($_SESSION['admin_id'] ?? 0);
            $adminName = trim((string) ($_SESSION['admin_realname'] ?? $_SESSION['admin_name'] ?? ''));
            if ($adminName === '') {
                $adminName = $adminId > 0 ? ('管理员 #' . $adminId) : '临时装修访问';
            }
            $result = $builder->heartbeatEditSession($builderType, $builderRefId, $editorToken, $adminId, $adminName, intval($payload['version_no'] ?? 0));
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'load') {
            $history = $builderPage ? $builder->getHistory(intval($builderPage['id'])) : [];
            echo json_encode([
                'code' => 200,
                'data' => [
                    'builder_type' => $builderType,
                    'builder_ref_id' => $builderRefId,
                    'title' => trim((string) ($builderPage['title'] ?? ($builderLayout['page']['title'] ?? $builderFallbackTitle))),
                    'layout' => $builderLayout,
                    'page' => $builderPage,
                    'history' => $history,
                    'definitions' => $builderDefinitions,
                    'style_fields' => $builderStyleFields,
                    'preset_layouts' => $builderPresetLayouts,
                ],
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'preflight') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $layoutInput = isset($payload['layout']) && is_array($payload['layout']) ? $payload['layout'] : [];
            $title = trim((string) ($payload['title'] ?? ''));
            $normalizedLayout = $builder->normalizeLayout($layoutInput, $title !== '' ? $title : $builderFallbackTitle);
            if ($title !== '') {
                $normalizedLayout['page']['title'] = $title;
            }
            echo json_encode($builder->preflightLayout($normalizedLayout), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'save_draft' || $apiAction === 'publish') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $layoutInput = isset($payload['layout']) && is_array($payload['layout']) ? $payload['layout'] : [];
            $title = trim((string) ($payload['title'] ?? ''));
            $enabled = isset($payload['is_enabled']) ? intval($payload['is_enabled']) : 1;
            $expectedVersion = max(0, intval($payload['expected_version'] ?? 0));
            $normalizedLayout = $builder->normalizeLayout($layoutInput, $title !== '' ? $title : $builderFallbackTitle);
            if ($title !== '') {
                $normalizedLayout['page']['title'] = $title;
            }

            $result = $apiAction === 'publish'
                ? $builder->publishPage($builderType, $builderRefId, $title, $normalizedLayout, $enabled, $expectedVersion)
                : $builder->saveDraft($builderType, $builderRefId, $title, $normalizedLayout, $enabled, $expectedVersion);

            if (intval($result['code'] ?? 500) === 200) {
                addLog(
                    $apiAction === 'publish' ? '发布页面装修' : '保存页面装修草稿',
                    '页面装修',
                    ($apiAction === 'publish' ? '发布页面 ' : '保存页面草稿 ') . $builder->makePageKey($builderType, $builderRefId),
                    json_encode($normalizedLayout, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
                );
            }
            if (intval($result['code'] ?? 0) === 409) {
                http_response_code(409);
            }
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'sync_widget_all_pages') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $widgetKey = trim((string) ($payload['widget_key'] ?? ''));
            $widgetEnabled = array_key_exists('widget_enabled', $payload) ? intval($payload['widget_enabled']) : null;
            $widgetConfig = isset($payload['widget_config']) && is_array($payload['widget_config']) ? $payload['widget_config'] : null;
            $result = $builder->syncWidgetToAllPages($widgetKey, $widgetConfig, $widgetEnabled);
            if (intval($result['code'] ?? 500) === 200) {
                addLog('修改', '模板装修', '同步挂件到所有页面 ' . $widgetKey, json_encode([
                    'widget_key' => $widgetKey,
                    'widget_enabled' => $widgetEnabled,
                    'widget_config' => $widgetConfig,
                ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
            }
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'sync_site_contact') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $allowedKeys = ['site_phone', 'site_tel', 'site_email', 'site_address', 'contact_wechat', 'site_wechat', 'contact_person', 'contact_qq', 'site_qq'];
            $fieldKey = trim((string) ($payload['field_key'] ?? ''));
            $fieldValue = trim((string) ($payload['field_value'] ?? ''));
            if ($fieldKey === '' || !in_array($fieldKey, $allowedKeys, true)) {
                echo json_encode(['code' => 422, 'msg' => '不支持同步当前公共信息字段'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            $exists = $db->fetch("SELECT id FROM {$db->table('config')} WHERE config_key = ? LIMIT 1", [$fieldKey]);
            if ($exists) {
                $db->update('config', ['config_value' => $fieldValue], 'config_key = ?', [$fieldKey]);
            } else {
                $db->insert('config', [
                    'config_key' => $fieldKey,
                    'config_value' => $fieldValue,
                    'config_type' => 'text',
                    'config_group' => 'basic',
                ]);
            }
            if ($fieldKey === 'contact_wechat') {
                $siteWechatExists = $db->fetch("SELECT id FROM {$db->table('config')} WHERE config_key = 'site_wechat' LIMIT 1");
                if ($siteWechatExists) {
                    $db->update('config', ['config_value' => $fieldValue], 'config_key = ?', ['site_wechat']);
                }
            }
            if ($fieldKey === 'contact_qq') {
                $siteQqExists = $db->fetch("SELECT id FROM {$db->table('config')} WHERE config_key = 'site_qq' LIMIT 1");
                if ($siteQqExists) {
                    $db->update('config', ['config_value' => $fieldValue], 'config_key = ?', ['site_qq']);
                }
            }
            addLog('修改', '模板装修', '同步公共联系信息: ' . $fieldKey, json_encode([
                'field_key' => $fieldKey,
                'field_value' => $fieldValue,
            ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
            echo json_encode(['code' => 200, 'msg' => '公共联系信息已同步到全站'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'update_business_item') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $itemType = trim((string) ($payload['item_type'] ?? ''));
            $itemId = intval($payload['item_id'] ?? 0);
            $fields = isset($payload['fields']) && is_array($payload['fields']) ? $payload['fields'] : [];
            if ($itemId <= 0 || !in_array($itemType, ['article', 'product'], true)) {
                echo json_encode(['code' => 400, 'msg' => '数据类型或编号无效'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }

            $now = time();
            if ($itemType === 'article') {
                $current = $db->fetch("SELECT id, title, summary FROM {$db->table('article')} WHERE id = ? AND deleted_at = 0", [$itemId]);
                if (!$current) {
                    echo json_encode(['code' => 404, 'msg' => '文章不存在'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $data = [
                    'title' => trim((string) ($fields['title'] ?? $current['title'] ?? '')),
                    'summary' => trim((string) ($fields['summary'] ?? $current['summary'] ?? '')),
                    'update_time' => $now,
                ];
                if ($data['title'] === '') {
                    echo json_encode(['code' => 422, 'msg' => '鏂囩珷鏍囬涓嶈兘涓虹┖'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $db->update('article', $data, 'id = ? AND deleted_at = 0', [$itemId]);
                $row = $db->fetch("SELECT id, title, summary FROM {$db->table('article')} WHERE id = ? AND deleted_at = 0", [$itemId]);
                addLog('修改', '模板装修', '前台装修修改文章 ' . $data['title']);
                echo json_encode(['code' => 200, 'msg' => '文章已同步更新', 'data' => $row], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }

            $current = $db->fetch("SELECT id, title, summary, price, litpic FROM {$db->table('product')} WHERE id = ? AND deleted_at = 0", [$itemId]);
            if (!$current) {
                echo json_encode(['code' => 404, 'msg' => '产品不存在'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            $priceValue = trim((string) ($fields['price'] ?? $current['price'] ?? ''));
            $data = [
                'title' => trim((string) ($fields['title'] ?? $current['title'] ?? '')),
                'summary' => trim((string) ($fields['summary'] ?? $current['summary'] ?? '')),
                'price' => $priceValue === '' ? 0 : floatval($priceValue),
                'litpic' => trim((string) ($fields['litpic'] ?? $current['litpic'] ?? '')),
                'update_time' => $now,
            ];
            if ($data['title'] === '') {
                echo json_encode(['code' => 422, 'msg' => '产品标题不能为空'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            $db->update('product', $data, 'id = ? AND deleted_at = 0', [$itemId]);
            $row = $db->fetch("SELECT id, title, summary, price, litpic FROM {$db->table('product')} WHERE id = ? AND deleted_at = 0", [$itemId]);
            addLog('修改', '模板装修', '前台装修修改产品 ' . $data['title']);
            echo json_encode(['code' => 200, 'msg' => '产品已同步更新', 'data' => $row], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'business_data') {
            $dataType = trim((string) ($_GET['data_type'] ?? ''));
            $normalizeSlides = function (array $rows) {
                $result = [];
                foreach ($rows as $row) {
                    $result[] = [
                        'title' => (string) ($row['title'] ?? $row['slide_name'] ?? ''),
                        'pic_path' => (string) ($row['pic_path'] ?? $row['litpic'] ?? ''),
                        'link_url' => (string) ($row['link_url'] ?? $row['link'] ?? ''),
                        'target' => (string) ($row['target'] ?? '_self'),
                    ];
                }
                return $result;
            };
            $normalizeLinks = function (array $rows) {
                $result = [];
                foreach ($rows as $row) {
                    $result[] = [
                        'webname' => (string) ($row['webname'] ?? $row['link_name'] ?? ''),
                        'url' => (string) ($row['url'] ?? $row['link_url'] ?? ''),
                        'logo' => (string) ($row['logo'] ?? $row['link_logo'] ?? ''),
                        'target' => (string) ($row['target'] ?? '_blank'),
                    ];
                }
                return $result;
            };
            if ($dataType === 'articles') {
                $channelId = intval($_GET['channel_id'] ?? 0);
                $limit = max(1, min(20, intval($_GET['limit'] ?? 6)));
                $orderBy = trim((string) ($_GET['order_by'] ?? 'id_desc'));
                $timeFrom = trim((string) ($_GET['time_from'] ?? ''));
                $timeTo = trim((string) ($_GET['time_to'] ?? ''));
                $keyword = trim((string) ($_GET['keyword'] ?? ''));
                $tag = trim((string) ($_GET['tag'] ?? ''));
                $sql = "SELECT id, title, summary, create_time FROM {$db->table('article')} WHERE status = 1";
                $params = [];
                if ($channelId > 0) {
                    $sql .= " AND channel_id = ?";
                    $params[] = $channelId;
                }
                if ($keyword !== '') {
                    $sql .= " AND (title LIKE ? OR tags LIKE ? OR seo_keywords LIKE ?)";
                    $params[] = '%' . $keyword . '%';
                    $params[] = '%' . $keyword . '%';
                    $params[] = '%' . $keyword . '%';
                }
                if ($tag !== '') {
                    $sql .= " AND tags LIKE ?";
                    $params[] = '%' . $tag . '%';
                }
                if ($timeFrom !== '') {
                    $sql .= " AND create_time >= ?";
                    $params[] = strtotime($timeFrom);
                }
                if ($timeTo !== '') {
                    $sql .= " AND create_time <= ?";
                    $params[] = strtotime($timeTo . ' 23:59:59');
                }
                $orderSql = ' ORDER BY id DESC';
                if ($orderBy === 'id_asc') {
                    $orderSql = ' ORDER BY id ASC';
                } elseif ($orderBy === 'time_asc') {
                    $orderSql = ' ORDER BY create_time ASC, id ASC';
                } elseif ($orderBy === 'time_desc') {
                    $orderSql = ' ORDER BY create_time DESC, id DESC';
                } elseif ($orderBy === 'sort_asc') {
                    $orderSql = ' ORDER BY sort_order ASC, id ASC';
                } elseif ($orderBy === 'sort_desc') {
                    $orderSql = ' ORDER BY sort_order DESC, id DESC';
                }
                $sql .= $orderSql . " LIMIT {$limit}";
                echo json_encode(['code' => 200, 'data' => $db->fetchAll($sql, $params)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'products') {
                $channelId = intval($_GET['channel_id'] ?? 0);
                $limit = max(1, min(20, intval($_GET['limit'] ?? 6)));
                $orderBy = trim((string) ($_GET['order_by'] ?? 'id_desc'));
                $timeFrom = trim((string) ($_GET['time_from'] ?? ''));
                $timeTo = trim((string) ($_GET['time_to'] ?? ''));
                $keyword = trim((string) ($_GET['keyword'] ?? ''));
                $tag = trim((string) ($_GET['tag'] ?? ''));
                $sql = "SELECT id, title, litpic, price, summary FROM {$db->table('product')} WHERE status = 1";
                $params = [];
                if ($channelId > 0) {
                    $sql .= " AND channel_id = ?";
                    $params[] = $channelId;
                }
                if ($keyword !== '') {
                    $sql .= " AND (title LIKE ? OR tags LIKE ? OR seo_keywords LIKE ?)";
                    $params[] = '%' . $keyword . '%';
                    $params[] = '%' . $keyword . '%';
                    $params[] = '%' . $keyword . '%';
                }
                if ($tag !== '') {
                    $sql .= " AND tags LIKE ?";
                    $params[] = '%' . $tag . '%';
                }
                if ($timeFrom !== '') {
                    $sql .= " AND create_time >= ?";
                    $params[] = strtotime($timeFrom);
                }
                if ($timeTo !== '') {
                    $sql .= " AND create_time <= ?";
                    $params[] = strtotime($timeTo . ' 23:59:59');
                }
                $orderSql = ' ORDER BY id DESC';
                if ($orderBy === 'id_asc') {
                    $orderSql = ' ORDER BY id ASC';
                } elseif ($orderBy === 'time_asc') {
                    $orderSql = ' ORDER BY create_time ASC, id ASC';
                } elseif ($orderBy === 'time_desc') {
                    $orderSql = ' ORDER BY create_time DESC, id DESC';
                } elseif ($orderBy === 'sort_asc') {
                    $orderSql = ' ORDER BY sort_order ASC, id ASC';
                } elseif ($orderBy === 'sort_desc') {
                    $orderSql = ' ORDER BY sort_order DESC, id DESC';
                }
                $sql .= $orderSql . " LIMIT {$limit}";
                echo json_encode(['code' => 200, 'data' => $db->fetchAll($sql, $params)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'article_item') {
                $itemId = intval($_GET['item_id'] ?? 0);
                if ($itemId <= 0) {
                    echo json_encode(['code' => 400, 'msg' => '文章编号无效'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $articleRow = $db->fetch("SELECT id, title, summary, litpic, content FROM {$db->table('article')} WHERE id = ? AND status = 1 LIMIT 1", [$itemId]);
                if (!$articleRow) {
                    echo json_encode(['code' => 404, 'msg' => '文章不存在'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                echo json_encode(['code' => 200, 'data' => $articleRow], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'product_item') {
                $itemId = intval($_GET['item_id'] ?? 0);
                if ($itemId <= 0) {
                    echo json_encode(['code' => 400, 'msg' => '产品编号无效'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $productRow = $db->fetch("SELECT id, title, summary, price, litpic, content FROM {$db->table('product')} WHERE id = ? AND status = 1 LIMIT 1", [$itemId]);
                if (!$productRow) {
                    echo json_encode(['code' => 404, 'msg' => '产品不存在'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                echo json_encode(['code' => 200, 'data' => $productRow], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'slides') {
                $slides = $normalizeSlides(
                    $db->fetchAll("SELECT * FROM {$db->table('slide')} WHERE status = 1 ORDER BY sort_order ASC, id DESC LIMIT 10")
                );
                echo json_encode(['code' => 200, 'data' => $slides], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'links') {
                $linkRows = $normalizeLinks(
                    $db->fetchAll("SELECT * FROM {$db->table('link')} WHERE status = 1 ORDER BY sort_order ASC, id DESC LIMIT 20")
                );
                echo json_encode(['code' => 200, 'data' => $linkRows], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'votes') {
                $now = time();
                $status = trim((string) ($_GET['status'] ?? 'active'));
                $keyword = trim((string) ($_GET['keyword'] ?? ''));
                $orderBy = trim((string) ($_GET['order_by'] ?? 'id_desc'));
                $limit = max(1, min(20, intval($_GET['limit'] ?? 20)));
                $sql = "SELECT id, vote_title, vote_type, vote_options, start_time, end_time FROM {$db->table('vote')} WHERE 1=1";
                $params = [];
                if ($status === 'active') {
                    $sql .= " AND is_enabled = 1 AND (start_time IS NULL OR start_time = 0 OR start_time <= ?) AND (end_time IS NULL OR end_time = 0 OR end_time >= ?)";
                    $params[] = $now;
                    $params[] = $now;
                } elseif ($status === 'ended') {
                    $sql .= " AND end_time > 0 AND end_time < ?";
                    $params[] = $now;
                } elseif ($status === 'upcoming') {
                    $sql .= " AND start_time > ?";
                    $params[] = $now;
                }
                if ($keyword !== '') {
                    $sql .= " AND vote_title LIKE ?";
                    $params[] = '%' . $keyword . '%';
                }
                if ($orderBy === 'time_asc') {
                    $sql .= " ORDER BY start_time ASC, id ASC";
                } elseif ($orderBy === 'time_desc') {
                    $sql .= " ORDER BY start_time DESC, id DESC";
                } else {
                    $sql .= " ORDER BY id DESC";
                }
                $sql .= " LIMIT {$limit}";
                $voteRows = $db->fetchAll(
                    $sql,
                    $params
                );
                foreach ($voteRows as &$voteRow) {
                    $voteRow['vote_options'] = json_decode((string) ($voteRow['vote_options'] ?? '[]'), true);
                    if (!is_array($voteRow['vote_options'])) {
                        $voteRow['vote_options'] = [];
                    }
                }
                unset($voteRow);
                echo json_encode(['code' => 200, 'data' => $voteRows], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'member_state') {
                $requestUri = trim((string) ($_GET['redirect'] ?? ($_SERVER['HTTP_REFERER'] ?? '/')));
                if ($requestUri === '' || strpos($requestUri, 'http://') === 0 || strpos($requestUri, 'https://') === 0 || strpos($requestUri, '//') === 0) {
                    $requestUri = '/';
                }
                echo json_encode([
                    'code' => 200,
                    'data' => [
                        'logged_in' => !empty($_SESSION['member_id']),
                        'member_name' => trim((string) ($_SESSION['member_nickname'] ?? $_SESSION['member_name'] ?? '')),
                        'login_url' => '/member/login.php?redirect=' . urlencode($requestUri),
                        'register_url' => '/member/register.php',
                        'center_url' => '/member/index.php',
                        'logout_url' => '/member/logout.php',
                    ],
                ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'site_contact') {
                $configRows = $db->fetchAll(
                    "SELECT config_key, config_value FROM {$db->table('config')}
                     WHERE config_key IN ('site_name', 'site_phone', 'site_tel', 'site_email', 'site_address', 'site_qq', 'site_wechat', 'contact_person', 'contact_qq', 'contact_wechat', 'site_icp', 'site_police_icp')"
                );
                $contact = [];
                foreach ($configRows as $cfg) {
                    $contact[$cfg['config_key']] = $cfg['config_value'];
                }
                if (empty($contact['site_qq']) && !empty($contact['contact_qq'])) {
                    $contact['site_qq'] = $contact['contact_qq'];
                }
                if (empty($contact['site_wechat']) && !empty($contact['contact_wechat'])) {
                    $contact['site_wechat'] = $contact['contact_wechat'];
                }
                echo json_encode(['code' => 200, 'data' => $contact], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'article_categories') {
                echo json_encode(['code' => 200, 'data' => array_values($builderTargetRows['article_category'])], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'product_categories') {
                echo json_encode(['code' => 200, 'data' => array_values($builderTargetRows['product_category'])], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'pages') {
                echo json_encode(['code' => 200, 'data' => array_values($builderTargetRows['page'])], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($dataType === 'all') {
                $voteRows = $db->fetchAll(
                    "SELECT id, vote_title, vote_type, vote_options, start_time, end_time
                     FROM {$db->table('vote')}
                     WHERE is_enabled = 1
                     ORDER BY id DESC LIMIT 20"
                );
                foreach ($voteRows as &$voteRow) {
                    $voteRow['vote_options'] = json_decode((string) ($voteRow['vote_options'] ?? '[]'), true);
                    if (!is_array($voteRow['vote_options'])) {
                        $voteRow['vote_options'] = [];
                    }
                }
                unset($voteRow);
                $contactRows = $db->fetchAll(
                    "SELECT config_key, config_value FROM {$db->table('config')}
                     WHERE config_key IN ('site_name', 'site_phone', 'site_tel', 'site_email', 'site_address', 'site_qq', 'site_wechat', 'contact_person', 'contact_qq', 'contact_wechat', 'site_icp', 'site_police_icp')"
                );
                $siteContact = [];
                foreach ($contactRows as $cfg) {
                    $siteContact[$cfg['config_key']] = $cfg['config_value'];
                }
                if (empty($siteContact['site_qq']) && !empty($siteContact['contact_qq'])) {
                    $siteContact['site_qq'] = $siteContact['contact_qq'];
                }
                if (empty($siteContact['site_wechat']) && !empty($siteContact['contact_wechat'])) {
                    $siteContact['site_wechat'] = $siteContact['contact_wechat'];
                }
                $requestUri = trim((string) ($_GET['redirect'] ?? ($_SERVER['HTTP_REFERER'] ?? '/')));
                if ($requestUri === '' || strpos($requestUri, 'http://') === 0 || strpos($requestUri, 'https://') === 0 || strpos($requestUri, '//') === 0) {
                    $requestUri = '/';
                }
                echo json_encode([
                    'code' => 200,
                    'data' => [
                        'article_categories' => array_values($builderTargetRows['article_category']),
                        'product_categories' => array_values($builderTargetRows['product_category']),
                        'pages' => array_values($builderTargetRows['page']),
                        'slides' => $normalizeSlides(
                            $db->fetchAll("SELECT * FROM {$db->table('slide')} WHERE status = 1 ORDER BY sort_order ASC, id DESC LIMIT 10")
                        ),
                        'links' => $normalizeLinks(
                            $db->fetchAll("SELECT * FROM {$db->table('link')} WHERE status = 1 ORDER BY sort_order ASC, id DESC LIMIT 20")
                        ),
                        'votes' => $voteRows,
                        'site_contact' => $siteContact,
                        'member_state' => [
                            'logged_in' => !empty($_SESSION['member_id']),
                            'member_name' => trim((string) ($_SESSION['member_nickname'] ?? $_SESSION['member_name'] ?? '')),
                            'login_url' => '/member/login.php?redirect=' . urlencode($requestUri),
                            'register_url' => '/member/register.php',
                            'center_url' => '/member/index.php',
                            'logout_url' => '/member/logout.php',
                        ],
                    ],
                ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            echo json_encode(['code' => 200, 'data' => []], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'submit_form') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $formType = trim((string) ($payload['form_type'] ?? 'guestbook'));
            if ($formType === 'guestbook') {
                $name = trim((string) ($payload['name'] ?? ''));
                $phone = trim((string) ($payload['phone'] ?? ''));
                $title = trim((string) ($payload['title'] ?? '网站留言'));
                $content = trim((string) ($payload['content'] ?? ''));
                if ($name === '' || $content === '') {
                    echo json_encode(['code' => 400, 'msg' => '姓名和留言内容不能为空'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $ip = $_SERVER['REMOTE_ADDR'] ?? '';
                $recentGuestbook = $db->fetch(
                    "SELECT id FROM {$db->table('guestbook')} WHERE ip = ? AND create_time >= ? ORDER BY id DESC LIMIT 1",
                    [$ip, time() - 15]
                );
                if ($recentGuestbook) {
                    echo json_encode(['code' => 429, 'msg' => '提交过于频繁，请稍后再试'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $channel = $db->fetch("SELECT id FROM {$db->table('channel')} WHERE channel_type = 8 AND is_show = 1 LIMIT 1");
                $guestbookData = [
                    'channel_id' => intval($channel['id'] ?? 0),
                    'title' => $title,
                    'content' => $content,
                    'name' => $name,
                    'phone' => $phone,
                    'ip' => $ip,
                    'create_time' => time(),
                    'status' => 0,
                    'is_show' => 0,
                ];
                if (!empty($_SESSION['member_id'])) {
                    $guestbookData['member_id'] = intval($_SESSION['member_id']);
                }
                $db->insert('guestbook', $guestbookData);
                echo json_encode(['code' => 200, 'msg' => '提交成功'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            if ($formType === 'vote') {
                $voteId = intval($payload['vote_id'] ?? 0);
                $selectedOptions = $payload['options'] ?? ($payload['option'] ?? []);
                if (!is_array($selectedOptions)) {
                    $selectedOptions = [$selectedOptions];
                }
                $selectedOptions = array_values(array_unique(array_filter(array_map('intval', $selectedOptions), static function ($value) {
                    return $value >= 0;
                })));
                if ($voteId <= 0 || empty($selectedOptions)) {
                    echo json_encode(['code' => 400, 'msg' => 'Please choose a vote option'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $vote = $db->fetch("SELECT * FROM {$db->table('vote')} WHERE id = ? AND is_enabled = 1 LIMIT 1", [$voteId]);
                if (!$vote) {
                    echo json_encode(['code' => 404, 'msg' => 'Vote not found'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $now = time();
                if (intval($vote['start_time'] ?? 0) > 0 && intval($vote['start_time']) > $now) {
                    echo json_encode(['code' => 400, 'msg' => 'Voting has not started'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                if (intval($vote['end_time'] ?? 0) > 0 && intval($vote['end_time']) < $now) {
                    echo json_encode(['code' => 400, 'msg' => 'Voting has ended'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                if (intval($vote['vote_type'] ?? 1) === 1 && count($selectedOptions) !== 1) {
                    echo json_encode(['code' => 400, 'msg' => 'Single choice vote requires one option'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $voteCookieKey = 'cms_frontend_vote_' . $voteId;
                if (!empty($_SESSION[$voteCookieKey]) || isset($_COOKIE[$voteCookieKey])) {
                    echo json_encode(['code' => 409, 'msg' => 'You have already voted'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                $voteOptions = json_decode((string) ($vote['vote_options'] ?? '[]'), true);
                if (!is_array($voteOptions) || empty($voteOptions)) {
                    echo json_encode(['code' => 500, 'msg' => 'Vote data is invalid'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    exit;
                }
                foreach ($selectedOptions as $optionIndex) {
                    if (!isset($voteOptions[$optionIndex])) {
                        echo json_encode(['code' => 400, 'msg' => 'Vote option does not exist'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                        exit;
                    }
                }
                foreach ($selectedOptions as $optionIndex) {
                    $voteOptions[$optionIndex]['votes'] = intval($voteOptions[$optionIndex]['votes'] ?? 0) + 1;
                }
                $db->update('vote', [
                    'vote_options' => json_encode($voteOptions, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
                ], 'id = ?', [$voteId]);
                $_SESSION[$voteCookieKey] = 1;
                setcookie($voteCookieKey, '1', time() + 86400 * 365, '/');
                echo json_encode([
                    'code' => 200,
                    'msg' => 'Vote submitted successfully',
                    'data' => [
                        'vote_id' => $voteId,
                        'vote_options' => $voteOptions,
                    ],
                ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                exit;
            }
            echo json_encode(['code' => 400, 'msg' => '提交的数据无效'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'restore_history') {
            $payload=json_decode(file_get_contents('php://input'),true);if(!is_array($payload))$payload=$_POST;
            $historyId = intval($payload['history_id'] ?? 0);
            $builderPageId = intval($payload['builder_page_id'] ?? 0);
            $expectedVersion = max(0, intval($payload['expected_version'] ?? 0));
            $result = $builder->restoreHistory($builderPageId, $historyId, $expectedVersion);
            if (intval($result['code'] ?? 0) === 409) {
                http_response_code(409);
            }
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }

        if ($apiAction === 'clear_history') {
            $payload = json_decode(file_get_contents('php://input'), true);
            if (!is_array($payload)) {
                $payload = $_POST;
            }
            $builderPageId = intval($payload['builder_page_id'] ?? 0);
            if ($builderPageId <= 0 && $builderPage) {
                $builderPageId = intval($builderPage['id'] ?? 0);
            }
            $result = $builder->clearHistory($builderPageId);
            echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
            exit;
        }
        echo json_encode(['code' => 400, 'msg' => '不支持的操作'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }

    if ($act === 'builder_editor') {
        if (!$builderCanOperate) {
            header('Location: /admin/main.php?act=auth');
            exit;
        }
        $builderEditorUrl = cmsResolveBuilderFrontendUrl($builderType, $builderRefId, cmsBuildFrontendUrl('home'));
        $builderAccessToken = cmsBuildBuilderAccessToken($builderType, $builderRefId, time() + 7200);
        $builderEditorUrl .= (strpos($builderEditorUrl, '?') !== false ? '&' : '?') . http_build_query([
            'builder_edit' => 1,
            'builder_type' => $builderType,
            'builder_ref_id' => $builderRefId,
            'builder_token' => $builderAccessToken,
        ]);
        header('Location: ' . $builderEditorUrl);
        exit;
    }
}

// Handle toggle action early (no HTML output)
if ($act === 'channel' && isset($_GET['action']) && $_GET['action'] === 'toggle') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $id = intval($_POST['id'] ?? 0);
    $isShow = intval($_POST['is_show'] ?? 0);
    $db->update('channel', ['is_show' => $isShow, 'update_time' => time()], 'id = ?', [$id]);
    echo json_encode(['code' => 200, 'msg' => '状态更新成功'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($act === 'article' && isset($_GET['action']) && $_GET['action'] === 'toggle') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $id = intval($_POST['id'] ?? 0);
    $status = intval($_POST['status'] ?? 0);
    $db->update('article', ['status' => $status, 'update_time' => time()], 'id = ?', [$id]);
    echo json_encode(['code' => 200, 'msg' => '状态更新成功'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($act === 'product' && isset($_GET['action']) && $_GET['action'] === 'toggle') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $id = intval($_POST['id'] ?? 0);
    $status = intval($_POST['status'] ?? 0);
    $db->update('product', ['status' => $status, 'update_time' => time()], 'id = ?', [$id]);
    echo json_encode(['code' => 200, 'msg' => '状态更新成功'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($act === 'image' && isset($_GET['action']) && $_GET['action'] === 'toggle') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $id = intval($_POST['id'] ?? 0);
    $status = intval($_POST['status'] ?? 0);
    $db->update('image', ['status' => $status, 'update_time' => time()], 'id = ?', [$id]);
    echo json_encode(['code' => 200, 'msg' => '状态更新成功'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($act === 'download' && isset($_GET['action']) && $_GET['action'] === 'toggle') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $id = intval($_POST['id'] ?? 0);
    $status = intval($_POST['status'] ?? 0);
    $db->update('download', ['status' => $status, 'update_time' => time()], 'id = ?', [$id]);
    echo json_encode(['code' => 200, 'msg' => '状态更新成功'], JSON_UNESCAPED_UNICODE);
    exit;
}
if ($act === 'upload') {
    require_once dirname(__DIR__) . '/core/lib/common.php';
    requireAdminCsrfToken(true);
    $uploadBuilderType = trim((string) ($_REQUEST['builder_type'] ?? 'home'));
    $uploadBuilderRefId = intval($_REQUEST['builder_ref_id'] ?? $_REQUEST['id'] ?? 0);
    if (!cmsBuilderRequestHasAccess($uploadBuilderType, $uploadBuilderRefId)) {
        header('Content-Type: application/json');
        echo json_encode(['code' => 403, 'msg' => '未获得前台装修上传授权'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        exit;
    }
    $uploadType = isset($_POST['upload_type']) ? $_POST['upload_type'] : 'image';
    if ($uploadType === 'video') {
        header('Content-Type: application/json');
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_FILES['file'])) {
            echo json_encode(['code' => 400, 'msg' => '请选择要上传的视频文件']);
            exit;
        }
        $file = $_FILES['file'];
        if ($file['error'] !== UPLOAD_ERR_OK) {
            echo json_encode(['code' => 400, 'msg' => '视频上传失败']);
            exit;
        }
        $allowedExt = ['mp4', 'webm', 'ogg', 'avi', 'mov', 'mkv', 'wmv', 'flv'];
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if (!in_array($ext, $allowedExt)) {
            echo json_encode(['code' => 400, 'msg' => '不支持的视频格式'], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $uploadDir = dirname(__DIR__) . '/uploads/video/' . date('Ym') . '/';
        if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); }
        $newName = uniqid() . '_' . time() . '.' . $ext;
        $destPath = $uploadDir . $newName;
        if (move_uploaded_file($file['tmp_name'], $destPath)) {
            $siteUrl = rtrim(getSiteConfig('site_url', 'http://' . $_SERVER['HTTP_HOST']), '/');
            echo json_encode(['code' => 200, 'msg' => '上传成功', 'data' => ['url' => $siteUrl . '/uploads/video/' . date('Ym') . '/' . $newName]]);
        } else {
            echo json_encode(['code' => 500, 'msg' => '视频保存失败']);
        }
        exit;
    }
    if ($uploadType === 'attachment') {
        header('Content-Type: application/json');
        if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_FILES['file'])) {
            echo json_encode(['code' => 400, 'msg' => '请选择要上传的附件']);
            exit;
        }
        $file = $_FILES['file'];
        if ($file['error'] !== UPLOAD_ERR_OK) {
            echo json_encode(['code' => 400, 'msg' => '附件上传失败']);
            exit;
        }
        $maxSize = 20 * 1024 * 1024;
        if ($file['size'] > $maxSize) {
            echo json_encode(['code' => 400, 'msg' => '闂勫嫪娆㈡径褍鐨稉宥堝厴鐡掑懓绻?0MB']);
            exit;
        }
        $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $allowedExt = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', '7z', 'txt', 'csv', 'mp3', 'mp4'];
        if ($ext === '' || !in_array($ext, $allowedExt, true)) {
            echo json_encode(['code' => 400, 'msg' => '不支持的附件格式'], JSON_UNESCAPED_UNICODE);
            exit;
        }
        $uploadDir = dirname(__DIR__) . '/uploads/attachment/' . date('Ym') . '/';
        if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); }
        $baseName = pathinfo($file['name'], PATHINFO_FILENAME);
        $safeBaseName = preg_replace('/[^A-Za-z0-9_\-\x{4e00}-\x{9fa5}]/u', '_', $baseName);
        $safeBaseName = trim($safeBaseName, '_');
        if ($safeBaseName === '') {
            $safeBaseName = 'attachment';
        }
        $newName = $safeBaseName . '_' . time() . '_' . substr(md5(uniqid('', true)), 0, 8) . '.' . $ext;
        $destPath = $uploadDir . $newName;
        if (move_uploaded_file($file['tmp_name'], $destPath)) {
            $siteUrl = rtrim(getSiteConfig('site_url', 'http://' . $_SERVER['HTTP_HOST']), '/');
            echo json_encode([
                'code' => 200,
                'msg' => '上传成功',
                'data' => [
                    'url' => $siteUrl . '/uploads/attachment/' . date('Ym') . '/' . $newName,
                    'name' => $file['name']
                ]
            ]);
        } else {
            echo json_encode(['code' => 500, 'msg' => '附件保存失败']);
        }
        exit;
    }
    $allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
    $maxSize = 5 * 1024 * 1024;
    header('Content-Type: application/json');
    if ($_SERVER['REQUEST_METHOD'] !== 'POST' || empty($_FILES['file'])) {
        echo json_encode(['code' => 400, 'msg' => '请选择要上传的图片']);
        exit;
    }
    $file = $_FILES['file'];
    if ($file['error'] !== UPLOAD_ERR_OK) {
        echo json_encode(['code' => 400, 'msg' => '图片上传失败']);
        exit;
    }
    if ($file['size'] > $maxSize) {
        echo json_encode(['code' => 400, 'msg' => '閺傚洣娆㈡径褍鐨稉宥堝厴鐡掑懓绻?MB']);
        exit;
    }
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mimeType = finfo_file($finfo, $file['tmp_name']);
    finfo_close($finfo);
    if (!in_array($mimeType, $allowedTypes)) {
        echo json_encode(['code' => 400, 'msg' => '仅支持 JPG/PNG/GIF/WebP 图片']);
        exit;
    }
    $uploadDir = dirname(__DIR__) . '/uploads/' . date('Ymd') . '/';
    if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); }
    $saveResult = cmsStoreUploadedImage($file['tmp_name'], $file['name'], $uploadDir, 'upload', [
        'apply_watermark' => !isset($_POST['apply_watermark']) || (string) $_POST['apply_watermark'] !== '0',
    ]);
    if ($saveResult['success']) {
        $siteUrl = rtrim(getSiteConfig('site_url', 'http://' . $_SERVER['HTTP_HOST']), '/');
        echo json_encode([
            'code' => 200,
            'msg' => '上传成功',
            'data' => [
                'url' => $siteUrl . '/uploads/' . date('Ymd') . '/' . $saveResult['filename'],
                'filename' => $saveResult['filename'],
                'converted' => !empty($saveResult['converted'])
            ]
        ]);
    } else {
        echo json_encode(['code' => 500, 'msg' => $saveResult['message'] ?? '图片保存失败']);
    }
    exit;
}
$templateAction = $act === 'template'
    ? trim((string) ($_POST['action'] ?? $_GET['action'] ?? ''))
    : '';
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'switch_template') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $template_key = trim($_POST['template_key'] ?? '');
    if ($template_key === '') {
        echo json_encode(['code' => 400, 'msg' => '模板标识不能为空'], JSON_UNESCAPED_UNICODE);
        exit;
    }

    $levelNames = [1 => '免费版', 2 => '基础版', 3 => '专业版'];
    $templateLoader = new \Core\Lib\TemplateLoader($license);
    $licenseInfo = $license->getStatus();
    $currentLevel = (int) ($licenseInfo['level'] ?? 1);
    $templateInfo = $templateLoader->getRemoteTemplate($template_key);
    if (!is_array($templateInfo)) {
        echo json_encode(['code' => 400, 'msg' => '模板信息获取失败']);
        exit;
    }

    $requiredLevel = (int) ($templateInfo['required_level'] ?? 1);
    $isFree = (int) ($templateInfo['is_free'] ?? 0) === 1 || $requiredLevel <= 1;
    if (!$isFree && $requiredLevel > $currentLevel) {
        echo json_encode(['code' => 403, 'msg' => '当前授权等级不足，需要 ' . ($levelNames[$requiredLevel] ?? '更高版本') . '，当前为 ' . ($levelNames[$currentLevel] ?? '未知版本')]);
        exit;
    }

    $ensureResult = $templateLoader->ensureTemplateAvailable($template_key, $templateInfo);
    if ((int) ($ensureResult['code'] ?? 500) !== 200) {
        echo json_encode([
            'code' => (int) ($ensureResult['code'] ?? 500),
            'msg' => (string) ($ensureResult['msg'] ?? '模板准备失败'),
        ]);
        exit;
    }

    $activateResult = $templateLoader->activateTemplate($template_key, $db);
    if ((int) ($activateResult['code'] ?? 500) !== 200) {
        echo json_encode([
            'code' => (int) ($activateResult['code'] ?? 500),
            'msg' => (string) ($activateResult['msg'] ?? '模板启用失败'),
        ]);
        exit;
    }

    addLog('閸氼垳鏁ゅΟ鈩冩緲: ' . $template_key);
    echo json_encode([
        'code' => 200,
        'msg' => '濡剝婢橀妴? ' . ($templateInfo['name'] ?? $template_key) . ' 閵嗗秴鎯庨悽銊﹀灇閸?',
        'template' => $template_key
    ]);
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'activate_local_template') {
    requireAdminCsrfToken(true);
    while (ob_get_level() > 0) {
        ob_end_clean();
    }
    header('Content-Type: application/json');
    $templateLoader = new \Core\Lib\TemplateLoader($license);
    $template_key = trim($_POST['template_key'] ?? '');
    $validateResult = $templatePackageManager->validateLocalActivation($template_key);
    if ((int) ($validateResult['code'] ?? 500) !== 200) {
        echo json_encode([
            'code' => (int) ($validateResult['code'] ?? 500),
            'msg' => (string) ($validateResult['msg'] ?? '模板校验失败'),
        ]);
        exit;
    }

    $activateResult = $templateLoader->activateTemplate($template_key, $db);
    if ((int) ($activateResult['code'] ?? 500) !== 200) {
        echo json_encode([
            'code' => (int) ($activateResult['code'] ?? 500),
            'msg' => (string) ($activateResult['msg'] ?? '模板启用失败'),
        ]);
        exit;
    }

    addLog('启用本地模板: ' . $template_key);
    echo json_encode([
        'code' => 200,
        'msg' => '模板已启用',
        'template' => $template_key,
    ]);
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'export_local_template') {
    requireAdminCsrfToken();
    $template_key = trim($_POST['template_key'] ?? '');
    $exportResult = $templatePackageManager->exportPackage($template_key);
    if ((int) ($exportResult['code'] ?? 500) !== 200) {
        echo '<script>alert(' . json_encode((string) ($exportResult['msg'] ?? '模板包导出失败'), JSON_UNESCAPED_UNICODE) . ');history.back();</script>';
        exit;
    }

    $downloadPath = (string) ($exportResult['path'] ?? '');
    $downloadName = (string) ($exportResult['download_name'] ?? 'template-package.zip');
    $cleanupRoot = (string) ($exportResult['cleanup_root'] ?? '');
    if ($downloadPath === '' || !is_file($downloadPath)) {
        echo '<script>alert("模板包文件生成失败");history.back();</script>';
        exit;
    }

    addLog('导出模板包: ' . (string) ($exportResult['template_key'] ?? $template_key));
    while (ob_get_level() > 0) {
        ob_end_clean();
    }
    header('Content-Type: application/zip');
    header('Content-Length: ' . filesize($downloadPath));
    header('Content-Disposition: attachment; filename="' . basename($downloadName) . '"; filename*=UTF-8\'\'' . rawurlencode($downloadName));
    readfile($downloadPath);
    $templatePackageManager->cleanupWorkPath($cleanupRoot);
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'preview_local_template') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $template_key = trim($_POST['template_key'] ?? '');
    $previewResult = $templatePackageManager->getPackagePreview($template_key, [
        'include_template_config' => !empty($_POST['include_template_config']),
        'include_builder_pages' => !empty($_POST['include_builder_pages']),
        'include_custom_vars' => !empty($_POST['include_custom_vars']),
        'export_basic' => !empty($_POST['export_basic']),
        'export_seo' => !empty($_POST['export_seo']),
        'export_appearance' => !empty($_POST['export_appearance']),
        'export_contact' => !empty($_POST['export_contact']),
    ]);
    echo json_encode($previewResult, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'import_local_template') {
    requireAdminCsrfToken();
    if (!isset($_FILES['template_package']) || intval($_FILES['template_package']['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
        echo '<script>alert("请选择要导入的模板包 ZIP 文件");history.back();</script>';
        exit;
    }

    $importResult = $templatePackageManager->importPackage($_FILES['template_package']['tmp_name'], [
        'activate_after_import' => !empty($_POST['activate_after_import']),
        'apply_site_config' => !empty($_POST['apply_site_config']),
        'import_builder_pages' => !empty($_POST['import_builder_pages']),
        'import_custom_vars' => !empty($_POST['import_custom_vars']),
        'import_basic' => !empty($_POST['import_basic']),
        'import_seo' => !empty($_POST['import_seo']),
        'import_appearance' => !empty($_POST['import_appearance']),
        'import_contact' => !empty($_POST['import_contact']),
    ]);
    if ((int) ($importResult['code'] ?? 500) !== 200) {
        echo '<script>alert(' . json_encode((string) ($importResult['msg'] ?? '模板包导入失败'), JSON_UNESCAPED_UNICODE) . ');history.back();</script>';
        exit;
    }

    addLog('导入模板包: ' . (string) ($importResult['template_key'] ?? ''));
    echo '<script>alert("模板包导入成功");location.href="?act=template";</script>';
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'delete_local_template') {
    requireAdminCsrfToken();
    $template_key = trim($_POST['template_key'] ?? '');
    $deleteResult = $templatePackageManager->deleteLocalTemplate($template_key);
    if ((int) ($deleteResult['code'] ?? 500) !== 200) {
        echo '<script>alert(' . json_encode((string) ($deleteResult['msg'] ?? '模板删除失败'), JSON_UNESCAPED_UNICODE) . ');history.back();</script>';
        exit;
    }

    addLog('删除本地模板: ' . (string) ($deleteResult['template_key'] ?? $template_key));
    echo '<script>alert("模板已删除");location.href="?act=template";</script>';
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'delete_invalid_local_templates') {
    requireAdminCsrfToken();
    $deleteResult = $templatePackageManager->deleteInvalidLocalTemplates();
    if ((int) ($deleteResult['code'] ?? 500) !== 200) {
        echo '<script>alert(' . json_encode((string) ($deleteResult['msg'] ?? '批量删除失败'), JSON_UNESCAPED_UNICODE) . ');history.back();</script>';
        exit;
    }

    addLog('批量删除待修复模板: ' . implode(',', (array) ($deleteResult['deleted'] ?? [])));
    $message = '批量清理完成，已删除 ' . intval($deleteResult['deleted_count'] ?? 0) . ' 个模板';
    if (intval($deleteResult['skipped_count'] ?? 0) > 0) {
        $message .= '，跳过 ' . intval($deleteResult['skipped_count']) . ' 个模板';
    }
    echo '<script>alert(' . json_encode($message, JSON_UNESCAPED_UNICODE) . ');location.href="?act=template";</script>';
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && $templateAction === 'switch_template') {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $template_key = trim($_POST['template_key'] ?? '');
    if (empty($template_key)) {
        echo json_encode(['code' => 400, 'msg' => '模板标识不能为空'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    // 濡偓閺屻儱缍嬮崜宥囩彲閻愯宸块弶鍐獓閸?    $license = new \Core\Lib\License();
    $licenseInfo = $license->getStatus();
    $currentLevel = $licenseInfo['level'] ?? 1;
    // 娴犲孩宸块弶鍐ㄩ挬閸欐媽骞忛崣鏍侀弶璺ㄩ獓閸掝偉顩﹀Ч?    $apiBase = 'http://yutou.wtbidc.cn/license-center';
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $apiBase . '/api.php?action=template_list');
    curl_setopt($ch, CURLOPT_TIMEOUT, 8);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['level' => $currentLevel]));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $resp = curl_exec($ch);
    curl_close($ch);
    $levelNames = [1 => '免费版', 2 => '基础版', 3 => '专业版'];
    $templateInfo = null;
    if ($resp) {
        $result = json_decode($resp, true);
        if ($result && $result['code'] == 200) {
            foreach ($result['templates'] as $t) {
                if ($t['template_key'] === $template_key) {
                    $templateInfo = $t;
                    break;
                }
            }
        }
    }
    if (!$templateInfo) {
        // 濡剝婢橀崷銊﹀房閺夊啫閽╅崣棰佺瑝鐎涙ê婀?
        echo json_encode(['code' => 400, 'msg' => '模板信息获取失败']);
        exit;
    }
    // 濡偓閺屻儲宸块弶鍐獓閸?
    if (!$templateInfo['is_free'] && $templateInfo['required_level'] > $currentLevel) {
        echo json_encode(['code' => 403, 'msg' => '当前授权等级不足，需要 ' . ($levelNames[$templateInfo['required_level']] ?? '更高版本') . '，当前为 ' . ($levelNames[$currentLevel] ?? '未知版本')]);
        exit;
    }
    $templateDir = dirname(__DIR__) . '/template/' . $template_key;
    // 统一接收页面装修表单提交的数据。
    if (!is_dir($templateDir)) {
        $downloadUrl = $apiBase . '/api.php?action=template_package';
        $downloadPayload = json_encode([
            'template_key' => $template_key,
            'license_key' => $licenseInfo['license_key'] ?? ($licenseInfo['code'] ?? ''),
            'domain' => $licenseInfo['domain'] ?? ($_SERVER['HTTP_HOST'] ?? ''),
        ]);
        $downloadCh = curl_init($downloadUrl);
        curl_setopt_array($downloadCh, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $downloadPayload,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 20,
            CURLOPT_CONNECTTIMEOUT => 8,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        ]);
        $zipData = curl_exec($downloadCh);
        curl_close($downloadCh);
        if ($zipData && strlen($zipData) > 0 && substr($zipData, 0, 4) === 'PK') {
            if (!is_dir($templateDir)) mkdir($templateDir, 0755, true);
            $zipFile = $templateDir . '/__download.zip';
            file_put_contents($zipFile, $zipData);
            $zip = new ZipArchive();
            if ($zip->open($zipFile) === true) {
                try {
                    \Core\Lib\SafeZip::extract($zip, $templateDir);
                    $zip->close();
                    unlink($zipFile);
                } catch (Throwable $e) {
                    $zip->close();
                    @unlink($zipFile);
                    echo json_encode(['code' => 400, 'msg' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
                    exit;
                }
            } else {
                @unlink($zipFile);
                echo json_encode(['code' => 400, 'msg' => '濡剝婢橀崠鍛靶掗崢瀣亼鐠?']);
                exit;
            }
        } else {
        echo json_encode(['code' => 400, 'msg' => '模板目录不存在或不可读取'], JSON_UNESCAPED_UNICODE);
            exit;
        }
    }
    $exists = $db->fetch("SELECT id FROM {$db->table('config')} WHERE config_key = 'site_template'");
    if ($exists) {
        $db->update('config', ['config_value' => $template_key], 'config_key = ?', ['site_template']);
    } else {
        $db->insert('config', ['config_key' => 'site_template', 'config_value' => $template_key, 'config_type' => 'text', 'config_group' => 'basic']);
    }
    echo json_encode(['code' => 200, 'msg' => '濡剝婢橀妴? ' . $templateInfo['name'] . ' 閵嗗秴鎯庨悽銊﹀灇閸?', 'template' => $template_key]);
    exit;
}
if ($act === 'template' && $_SERVER['REQUEST_METHOD'] === 'POST' && in_array($templateAction, ['install_template', 'upload_template'], true)) {
    requireAdminCsrfToken(true);
    header('Content-Type: application/json');
    $template_key = trim($_POST['template_key'] ?? $_POST['template_name'] ?? '');
    if (!preg_match('/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/', $template_key)) {
        echo json_encode(['code' => 400, 'msg' => '模板标识不能为空'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $templateZipField = isset($_FILES['template_zip']) ? 'template_zip' : (isset($_FILES['template_package']) ? 'template_package' : '');
    if ($templateZipField === '' || $_FILES[$templateZipField]['error'] !== UPLOAD_ERR_OK) {
        echo json_encode(['code' => 400, 'msg' => '请选择要上传的模板 ZIP 文件'], JSON_UNESCAPED_UNICODE);
        exit;
    }
    $uploadDir = dirname(__DIR__) . '/template/' . $template_key . '/';
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0755, true);
    }
    // 处理上传文件信息。
    if (is_dir($uploadDir)) {
        foreach (glob("$uploadDir*") as $f) {
            if (is_dir($f)) {
                foreach (glob("$f/*") as $sf) { @unlink($sf); }
                @rmdir($f);
            } else {
                @unlink($f);
            }
        }
    }
    // 保存配置。
    $zipFile = $uploadDir . '__upload.zip';
    if (!move_uploaded_file($_FILES[$templateZipField]['tmp_name'], $zipFile)) {
        echo json_encode(['code' => 500, 'msg' => '上传文件保存失败']);
        exit;
    }
    $zip = new ZipArchive();
    if ($zip->open($zipFile) === true) {
        try {
            \Core\Lib\SafeZip::extract($zip, $uploadDir);
            $zip->close();
            unlink($zipFile);
        } catch (Throwable $e) {
            $zip->close();
            @unlink($zipFile);
            echo json_encode(['code' => 400, 'msg' => $e->getMessage()], JSON_UNESCAPED_UNICODE);
            exit;
        }
    } else {
        unlink($zipFile);
        echo json_encode(['code' => 400, 'msg' => 'ZIP 文件解压失败']);
        exit;
    }
    // 返回操作结果。
    $exists = $db->fetch("SELECT id FROM {$db->table('config')} WHERE config_key = 'site_template'");
    if ($exists) {
        $db->update('config', ['config_value' => $template_key], 'config_key = ?', ['site_template']);
    } else {
        $db->insert('config', ['config_key' => 'site_template', 'config_value' => $template_key, 'config_type' => 'text', 'config_group' => 'basic']);
    }
    echo json_encode(['code' => 200, 'msg' => '模板上传并启用成功', 'template' => $template_key], JSON_UNESCAPED_UNICODE);
    exit;
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="/template/default/skin/images/logo.png">
    <title>芋头CMS 管理后台</title>
    <style>
    *{margin:0;padding:0;box-sizing:border-box;}
    body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;font-size:14px;color:#334155;background:#f1f5f9;line-height:1.6;}
    .page-container{max-width:1400px;margin:0 auto;padding:20px;}
    .page-header{background:#fff;border-radius:8px;padding:20px 24px;margin-bottom:20px;display:flex;justify-content:space-between;align-items:center;box-shadow:0 1px 3px rgba(0,0,0,0.08);border:1px solid #e2e8f0;}
    .page-title{display:flex;align-items:center;gap:12px;}
    .page-title h1{font-size:18px;font-weight:600;color:#1e293b;margin:0;}
    .page-title p{font-size:12px;color:#64748b;margin:0;}
    .page-icon{font-size:24px;}
    .page-actions{display:flex;gap:10px;}
    .btn{display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border-radius:6px;font-size:14px;font-weight:500;text-decoration:none;cursor:pointer;border:none;transition:all 0.2s;}
    .btn-primary{background:#2563eb;color:#fff;}.btn-primary:hover{background:#1d4ed8;}
    .btn-secondary{background:#f1f5f9;color:#475569;border:1px solid #e2e8f0;}.btn-secondary:hover{background:#e2e8f0;}
    .btn-success{background:#10b981;color:#fff;}.btn-success:hover{background:#059669;}
    .btn-danger{background:#ef4444;color:#fff;}.btn-danger:hover{background:#dc2626;}
    .btn-gray{background:#64748b;color:#fff;}.btn-gray:hover{background:#475569;}
    .btn-sm{padding:5px 10px;font-size:12px;}.btn-lg{padding:12px 24px;font-size:15px;}
    .content-card{background:#fff;border-radius:8px;box-shadow:0 1px 3px rgba(0,0,0,0.08);border:1px solid #e2e8f0;overflow:hidden;}
    .data-table{width:100%;border-collapse:collapse;}.data-table th,.data-table td{padding:12px 16px;text-align:left;border-bottom:1px solid #e2e8f0;}
    .data-table th{background:#f8fafc;font-weight:600;color:#475569;font-size:13px;}
    .data-table tr:hover{background:#f8fafc;}.data-table tr:last-child td{border-bottom:none;}
    .id-cell{color:#94a3b8;font-size:12px;font-family:monospace;}
    .badge{display:inline-flex;align-items:center;padding:3px 10px;border-radius:20px;font-size:12px;font-weight:500;}
    .badge-success{background:#ecfdf5;color:#10b981;}.badge-warning{background:#fffbeb;color:#f59e0b;}
    .badge-danger{background:#fef2f2;color:#ef4444;}.badge-gray{background:#f1f5f9;color:#64748b;}
    .badge-primary{background:#eff6ff;color:#2563eb;}
    .btn-group{display:flex;gap:6px;}
    .filter-bar{background:#fff;border-radius:8px;padding:16px;margin-bottom:16px;box-shadow:0 1px 3px rgba(0,0,0,0.08);border:1px solid #e2e8f0;}
    .filter-bar form{display:flex;gap:12px;flex-wrap:wrap;align-items:center;}
    .filter-bar input,.filter-bar select{padding:8px 12px;border:1px solid #e2e8f0;border-radius:6px;font-size:14px;outline:none;}
    .filter-bar input:focus,.filter-bar select:focus{border-color:#2563eb;}
    .filter-item{display:flex;align-items:center;gap:8px;}.filter-item label{font-size:13px;color:#64748b;}
    .pagination{display:flex;justify-content:center;gap:6px;padding:16px;}
    .pagination a{padding:6px 12px;border:1px solid #e2e8f0;border-radius:6px;color:#475569;text-decoration:none;font-size:13px;}
    .pagination a:hover{background:#f1f5f9;}.pagination a.active{background:#2563eb;color:#fff;border-color:#2563eb;}
    .empty-state{text-align:center;padding:60px 20px;color:#64748b;}
    .empty-icon{font-size:48px;margin-bottom:16px;}.empty-state h3{font-size:16px;color:#475569;margin-bottom:8px;}
    .empty-state p{font-size:14px;color:#94a3b8;}
    .form-section{background:#fff;border:1px solid #e2e8f0;border-radius:8px;margin-bottom:20px;}
    .form-section-header{padding:14px 20px;border-bottom:1px solid #e2e8f0;font-size:14px;font-weight:600;color:#1e293b;}
    .form-section-body{padding:20px;}
    .form-section-body .editor-wrapper{margin:-20px 0 0 0;}
    .form-section-body .editor-toolbar{margin-bottom:0;padding:12px;}
    .form-section-body .editor-toolbar{margin-bottom:0;}
    .form-group{margin-bottom:16px;}.form-group label{display:block;font-size:14px;font-weight:500;color:#475569;margin-bottom:6px;}
    .form-control{width:100%;padding:10px 12px;border:1px solid #e2e8f0;border-radius:6px;font-size:14px;outline:none;transition:border-color 0.2s;}
    .form-control:focus{border-color:#2563eb;}
    .form-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px;}
    .form-actions{background:#fff;padding:20px;border-radius:8px;display:flex;gap:12px;}
    .required{color:#ef4444;}
    textarea.form-control{resize:vertical;min-height:100px;}select.form-control{background:#fff;}
    .upload-preview{width:200px;height:150px;border:2px dashed #e2e8f0;border-radius:8px;display:flex;align-items:center;justify-content:center;overflow:hidden;margin-top:10px;}
    .upload-preview img{width:100%;height:100%;object-fit:cover;}
    .upload-preview .placeholder{text-align:center;color:#94a3b8;}.upload-preview .placeholder .icon{font-size:32px;margin-bottom:4px;}
    .upload-preview.has-image{border-color:#2563eb;}
    .rich-editor-container{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;}
    .rich-editor-toolbar{display:flex;flex-wrap:wrap;gap:4px;padding:10px;background:#f8fafc;border-bottom:1px solid #e2e8f0;}
    .toolbar-btn{width:32px;height:32px;border:1px solid #e2e8f0;border-radius:4px;background:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;}
    .toolbar-btn:hover{background:#f1f5f9;border-color:#2563eb;}.toolbar-btn.active{background:#2563eb;color:#fff;border-color:#2563eb;}
    .rich-editor-content{min-height:300px;padding:16px;outline:none;overflow:auto;background:#fff;}.rich-editor-content:focus{outline:none;}
    .editor-wrapper{border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;background:#fff;}
    .editor-toolbar{display:flex;flex-wrap:wrap;gap:4px;padding:10px;background:#f8fafc;border-bottom:1px solid #e2e8f0;}
    .editor-toolbar button{width:32px;height:32px;border:1px solid #e2e8f0;border-radius:4px;background:#fff;cursor:pointer;font-size:13px;font-weight:600;}
    .editor-toolbar button:hover{background:#e2e8f0;}
    .editor-toolbar .upload-btn{width:auto;padding:0 12px;height:32px;background:#2563eb;color:#fff;border:none;border-radius:4px;font-size:12px;cursor:pointer;display:flex;align-items:center;}
    .toolbar-divider{width:1px;height:24px;background:#e2e8f0;margin:0 4px;}
    .editor-content{min-height:300px;padding:16px;outline:none;overflow:auto;background:#fff;}
    .fade-in{animation:fadeIn 0.3s ease;}
    @keyframes fadeIn{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:translateY(0);}}
    @media(max-width:768px){.page-header{flex-direction:column;gap:12px;align-items:flex-start;}.form-row{grid-template-columns:1fr;}}

    /* UI polish layer: only overrides visual layout, no backend behavior. */
    :root{--primary:#2563eb;--primary-dark:#1d4ed8;--primary-soft:#eff6ff;--success:#10b981;--warning:#f59e0b;--danger:#ef4444;--dark:#0f172a;--text:#334155;--text-light:#64748b;--gray-50:#f8fafc;--gray-100:#f1f5f9;--gray-200:#e2e8f0;--gray-300:#cbd5e1;--gray-400:#94a3b8;--gray-500:#64748b;--gray-600:#475569;--gray-800:#1e293b;--border:#e2e8f0;--border-light:#e7eaf3;--radius:10px;--radius-lg:16px;--shadow-xs:0 8px 24px rgba(15,23,42,.04);--shadow-sm:0 12px 30px rgba(15,23,42,.06);--shadow-md:0 18px 45px rgba(15,23,42,.09);}
    body{font-family:"Microsoft YaHei","PingFang SC",-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:linear-gradient(180deg,#f8fafc 0%,#f1f5f9 100%);-webkit-font-smoothing:antialiased;}
    .page-container{max-width:1440px;padding:22px;}
    .page-header{background:linear-gradient(135deg,#fff 0%,#f8fbff 100%);border-radius:18px;gap:16px;flex-wrap:wrap;box-shadow:var(--shadow-xs);}
    .page-actions{flex-wrap:wrap;}
    .btn{justify-content:center;border-radius:10px;font-weight:700;transition:transform .18s ease,box-shadow .18s ease,background .18s ease,border-color .18s ease,color .18s ease;white-space:nowrap;}
    .btn:hover{transform:translateY(-1px);}
    .btn-primary{background:linear-gradient(135deg,#2563eb 0%,#3b82f6 100%);box-shadow:0 10px 22px rgba(37,99,235,.2);}
    .btn-primary:hover{background:linear-gradient(135deg,#1d4ed8 0%,#2563eb 100%);}
    .btn-secondary{background:#fff;border-color:#e2e8f0;}
    .btn-secondary:hover{background:#f8fafc;border-color:#cbd5e1;}
    .btn-ghost{background:transparent;color:#64748b;border:1px solid transparent;box-shadow:none;}
    .btn-ghost:hover{background:#f8fafc;border-color:#e2e8f0;color:#1e293b;}
    .btn-group{align-items:center;flex-wrap:wrap;}
    .header-actions{display:flex;align-items:center;justify-content:flex-end;gap:10px;flex-wrap:wrap;}
    .content-card{border-radius:16px;box-shadow:var(--shadow-xs);overflow:auto;}
    .data-table{border-collapse:separate;border-spacing:0;}
    .data-table th,.data-table td{vertical-align:middle;}
    .data-table th{font-size:12px;font-weight:800;letter-spacing:.02em;}
    .data-table tr:hover{background:#fbfdff;}
    .badge-info{background:#ecfeff;color:#0891b2;}
    .badge-secondary{background:#f1f5f9;color:#64748b;}
    .alert{padding:14px 16px;border-radius:14px;border:1px solid #dbeafe;background:#eff6ff;color:#1d4ed8;margin-bottom:16px;line-height:1.7;}
    .alert-success{border-color:#bbf7d0;background:#f0fdf4;color:#15803d;}
    .alert-warning{border-color:#fed7aa;background:#fff7ed;color:#9a3412;}
    .alert-danger{border-color:#fecaca;background:#fef2f2;color:#b91c1c;}
    .filter-bar{border-radius:16px;box-shadow:var(--shadow-xs);}
    .filter-bar input,.filter-bar select,.form-control{border-radius:10px;transition:border-color .2s,box-shadow .2s;}
    .filter-bar input:focus,.filter-bar select:focus,.form-control:focus{box-shadow:0 0 0 4px rgba(37,99,235,.08);}
    .stats-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px;margin-bottom:20px;}
    .stat-card{background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:18px;display:flex;align-items:center;gap:14px;box-shadow:var(--shadow-xs);min-width:0;transition:box-shadow .2s,transform .2s,border-color .2s;}
    .stat-card:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm);border-color:#cbd5e1;}
    .stat-icon{width:46px;height:46px;min-width:46px;border-radius:12px;display:flex;align-items:center;justify-content:center;}
    .stat-icon svg{display:block;max-width:24px;max-height:24px;}
    .stat-info{min-width:0;flex:1;}
    .stat-value{font-size:22px;font-weight:800;color:#1e293b;line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .stat-label{font-size:13px;color:#64748b;margin-top:4px;line-height:1.3;}
    .page-context-bar,.article-context-bar,.product-context-bar,.download-context-bar,.image-context-bar,.video-context-bar,.channel-context-bar{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:16px;}
    .page-context-item,.article-context-item,.product-context-item,.download-context-item,.image-context-item,.video-context-item,.channel-context-item{background:#fff;border:1px solid #e2e8f0;border-radius:16px;padding:14px 16px;box-shadow:var(--shadow-xs);}
    .page-context-label,.article-context-label,.product-context-label,.download-context-label,.image-context-label,.video-context-label,.channel-context-label{display:block;font-size:12px;color:#94a3b8;margin-bottom:6px;}
    .page-context-value,.article-context-value,.product-context-value,.download-context-value,.image-context-value,.video-context-value,.channel-context-value{display:block;font-size:15px;font-weight:800;color:#1e293b;line-height:1.5;}
    .card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:14px;}
    .table-footer{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:14px 16px;border-top:1px solid #e2e8f0;background:#fbfdff;}
    .table-info{font-size:13px;color:#64748b;}
    .batch-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
    .tab-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 14px;border-radius:999px;font-size:13px;font-weight:700;color:#64748b;border:1px solid #e2e8f0;background:#fff;text-decoration:none;transition:all .18s ease;}
    .tab-btn:hover{border-color:#93c5fd;color:#2563eb;background:#eff6ff;}
    .tab-btn.active{background:#2563eb;color:#fff;border-color:#2563eb;box-shadow:0 10px 22px rgba(37,99,235,.16);}
    .tab-count{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;padding:0 7px;border-radius:999px;background:rgba(15,23,42,.08);font-size:12px;}
    .tab-btn.active .tab-count{background:rgba(255,255,255,.22);color:#fff;}
    .form-section{border-radius:16px;box-shadow:var(--shadow-xs);overflow:hidden;}
    .form-section-header{font-weight:800;background:#fbfdff;display:flex;align-items:center;gap:8px;}
    .upload-preview{border-radius:14px;background:#f8fafc;transition:border-color .18s ease,box-shadow .18s ease,background .18s ease;}
    .upload-preview:hover{border-color:#93c5fd;box-shadow:0 0 0 4px rgba(37,99,235,.06);background:#fff;}
    .detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px;}
    .detail-grid>div{background:#fff;border:1px solid #e2e8f0;border-radius:14px;padding:14px 16px;}
    .cms-ueditor-wrap,.product-ueditor-wrap{overflow:visible !important;max-width:100% !important;min-width:0 !important;}
    .cms-ueditor-wrap script[type="text/plain"],.product-ueditor-wrap script[type="text/plain"],#article_content_editor,#product_content_editor,#download_content_editor,#page_content_editor,#recruit_content_editor,#video_content_editor{width:100% !important;max-width:100% !important;}
    .cms-ueditor-wrap .edui-editor,.product-ueditor-wrap .edui-editor,.cms-ueditor-wrap .edui-editor-toolbarbox,.product-ueditor-wrap .edui-editor-toolbarbox,.cms-ueditor-wrap .edui-editor-iframeholder,.product-ueditor-wrap .edui-editor-iframeholder{width:100% !important;max-width:100% !important;box-sizing:border-box !important;}
    .content-card>table,.content-card .data-table{width:100%;}
    .content-card>table.data-table,.content-card .data-table{min-width:760px;}
    .content-card [style*="overflow-x:auto"]{border-radius:inherit;}
    .content-card code,.tag-example{white-space:pre-wrap;word-break:break-word;}
    .btn-group[style*="width:"],td[style*="width:330px"],td[style*="width:250px"],td[style*="width:200px"]{width:auto !important;}
    .btn-group .btn{min-height:34px;}
    .data-table th[style*="width:320px"],.data-table th[style*="width:300px"],.data-table th[style*="width:250px"]{width:220px !important;}
    .data-table td[style*="width:250px"],.data-table td[style*="width:300px"],.data-table td[style*="width:330px"]{width:auto !important;max-width:260px;}
    .data-table td:last-child .btn-group,.data-table td:last-child [class*="actions"]{justify-content:flex-start;}
    .data-table td:last-child .btn,.action-cell .btn{min-width:0;}
    .data-table img,.content-table img{max-width:100%;object-fit:cover;}
    .page-container [id$="Preview"],.page-container [class*="preview"],.page-container [class*="Preview"]{max-width:100%;}
    .page-container [id$="Preview"] img,.page-container [class*="preview"] img,.page-container [class*="Preview"] img{max-width:100%;height:auto;border-radius:12px;}
    .page-container [style*="width:220px"][style*="height"],.page-container [style*="width:240px"][style*="height"],.page-container [style*="width:200px"][style*="height"]{max-width:100% !important;border-radius:14px !important;}
    .channel-admin-page .content-card{border:1px solid #e2e8f0;border-radius:18px;box-shadow:0 14px 34px rgba(15,23,42,.06);overflow:hidden;}
    .channel-page-actions{display:flex;gap:10px;flex-wrap:wrap;}
    .channel-context-bar{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin-bottom:16px;}
    .channel-context-item{background:linear-gradient(180deg,#ffffff 0%,#f8fbff 100%);border:1px solid #e2e8f0;border-radius:16px;padding:14px 16px;box-shadow:var(--shadow-xs);}
    .channel-context-label{display:block;font-size:12px;color:#94a3b8;margin-bottom:6px;}
    .channel-context-value{display:block;font-size:14px;font-weight:800;color:#1e293b;line-height:1.6;}
    .channel-context-muted{color:#475569;font-weight:600;}
    .channel-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:16px;padding:14px 16px;background:#fff;border:1px solid #e2e8f0;border-radius:16px;box-shadow:var(--shadow-xs);}
    .channel-sort-mode{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
    .channel-sort-label{font-size:13px;color:#64748b;font-weight:800;}
    .channel-sort-option{display:flex;align-items:center;gap:6px;cursor:pointer;font-size:13px;color:#475569;}
    .channel-table-shell{overflow-x:auto;border-radius:18px;}
    .channel-data-table{min-width:900px !important;}
    .channel-data-table thead th{background:#f8fafc;color:#64748b;font-size:12px;font-weight:800;}
    .channel-data-table tbody tr{transition:background .18s ease,box-shadow .18s ease;}
    .channel-data-table tbody tr:hover{background:#fbfdff;}
    .channel-name-cell{display:flex;align-items:center;gap:8px;min-width:0;}
    .channel-depth-tree{display:inline-flex;align-items:center;gap:2px;flex-shrink:0;}
    .channel-type-icon{width:32px;height:32px;background:#eff6ff;border-radius:10px;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;font-size:16px;}
    .channel-name-meta{display:flex;align-items:center;gap:8px;min-width:0;}
    .channel-name-text{font-weight:700;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:280px;}
    .channel-level-tag{font-size:11px;color:#2563eb;background:#eff6ff;border-radius:999px;padding:2px 8px;flex-shrink:0;font-weight:800;}
    .channel-code{font-size:12px;color:#64748b;background:#f1f5f9;padding:4px 8px;border-radius:8px;}
    .channel-status-text{font-size:12px;font-weight:800;}
    .channel-status-text.is-show{color:#10b981;}
    .channel-status-text.is-hide{color:#94a3b8;}
    .channel-row-actions{display:flex;gap:6px;flex-wrap:wrap;max-width:240px;}
    .channel-row-actions .btn{flex:0 0 auto;min-width:58px;text-align:center;}
    .channel-btn-lite{min-width:58px;text-align:center;background:#eff6ff;color:#2563eb;border:1px solid #bfdbfe;}
    .channel-btn-danger{min-width:58px;text-align:center;color:#ef4444;background:#fef2f2;border:1px solid #fecaca;}
    .channel-move-modal{position:fixed;inset:0;background:rgba(15,23,42,.42);z-index:9999;align-items:center;justify-content:center;padding:18px;backdrop-filter:blur(6px);}
    .channel-move-card{width:420px;max-width:100%;padding:24px;background:linear-gradient(180deg,#fff 0%,#f8fbff 100%);border:1px solid #e2e8f0;border-radius:20px;box-shadow:0 24px 70px rgba(15,23,42,.22);}
    .channel-move-card h3{font-size:16px;font-weight:800;margin:0 0 18px;color:#1e293b;}
    .channel-move-field{margin-bottom:18px;}
    .channel-move-field label{display:block;font-size:13px;color:#64748b;margin-bottom:8px;font-weight:700;}
    .channel-move-actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;}
    .filter-bar form[style]{display:flex !important;align-items:center;gap:10px !important;flex-wrap:wrap !important;}
    .filter-bar input[style*="width:"],.filter-bar select[style*="width:"]{max-width:100% !important;}
    .page-container [style*="grid-template-columns:1fr 1fr"],.page-container [style*="grid-template-columns:1fr 1fr 1fr"],.page-container [style*="grid-template-columns:repeat(3,1fr)"],.panel-form-row,.yt-shop-grid,.yt-shop-metrics{grid-template-columns:repeat(auto-fit,minmax(260px,1fr)) !important;}
    .page-container [style*="grid-template-columns:240px 1fr"]{grid-template-columns:minmax(180px,240px) minmax(0,1fr) !important;}
    .page-container [style*="width:240px"][style*="height:160px"],.page-container [style*="width:220px"][style*="height:110px"],.upload-preview img{max-width:100% !important;}
    .page-container [style*="background:#f8fafc"][style*="border:1px solid #e2e8f0"],.page-container [style*="background:#fff"][style*="border:1px solid #e2e8f0"]{box-shadow:var(--shadow-xs);}
    .pagination a,.pagination span,.content-pagination a,.content-pagination span{transition:background .18s ease,border-color .18s ease,color .18s ease,transform .18s ease;}
    .pagination a:hover,.content-pagination a:hover{transform:translateY(-1px);}
    .tag-table,.content-card table{font-size:13px;}
    .tag-table{min-width:820px;}
    .tagLabel,.tag-example,td code{border-radius:8px !important;}
    .tag-section{overflow-x:auto;border-radius:16px;box-shadow:var(--shadow-xs);}
    .tag-section-title{position:sticky;left:0;z-index:1;border-radius:16px 16px 0 0 !important;}
    .intro-box{border-radius:16px !important;box-shadow:var(--shadow-xs);}
    .yt-refund-stats,.yt-review-stats,.yt-ship-stats{display:grid !important;grid-template-columns:repeat(auto-fit,minmax(180px,1fr)) !important;gap:14px !important;margin-bottom:18px !important;}
    .yt-refund-stat,.yt-review-stat,.yt-ship-stat{border-radius:16px !important;box-shadow:var(--shadow-xs);transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease;background:linear-gradient(135deg,#fff 0%,#fbfdff 100%) !important;}
    .yt-refund-stat:hover,.yt-review-stat:hover,.yt-ship-stat:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm);border-color:#bfdbfe !important;}
    .yt-refund-stat strong,.yt-review-stat strong,.yt-ship-stat strong{font-size:24px !important;font-weight:800 !important;color:#1e293b !important;}
    .yt-shop-config-row{border-radius:14px;padding:18px !important;margin:0 -6px;border-bottom:1px solid #eef2f7;transition:background .18s ease;}
    .yt-shop-config-row:hover{background:#f8fafc;}
    .yt-switch span{box-shadow:inset 0 0 0 1px rgba(15,23,42,.06);}
    .content-card[style*="max-width:760px"]{max-width:920px !important;width:100%;}
    .page-container [style*="border:1px solid #fdba74"][style*="background:linear-gradient"]{box-shadow:var(--shadow-xs);}
    .page-container [style*="grid-template-columns:1fr 1fr 1fr auto"]{grid-template-columns:repeat(auto-fit,minmax(180px,1fr)) !important;}
    .page-container [style*="display:grid"][style*="repeat(auto-fill,minmax(280px,1fr))"]{grid-template-columns:repeat(auto-fill,minmax(260px,1fr)) !important;}
    .hover-lift{transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease !important;}
    .hover-lift:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm);border-color:#bfdbfe !important;}
    .form-control:disabled,input:disabled,textarea:disabled,select:disabled{background:#f8fafc;color:#94a3b8;cursor:not-allowed;}
    .badge-gray{background:#f1f5f9;color:#64748b;}
    .badge-primary{background:#eff6ff;color:#1d4ed8;}
    .badge-warning{background:#fffbeb;color:#b45309;}
    .badge-success{background:#f0fdf4;color:#15803d;}
    .badge-danger{background:#fef2f2;color:#b91c1c;}
    .template-summary-grid,.template-local-grid,.template-remote-grid{gap:16px !important;}
    .template-summary-card,.template-local-card,.template-card,.template-package-panel,.auth-hero-card,.auth-compare-card,.auth-activate-card,.auth-plan-card{border-radius:18px !important;box-shadow:var(--shadow-xs);transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease;}
    .template-summary-card:hover,.template-local-card:hover,.template-card:hover,.auth-plan-item:hover{transform:translateY(-2px);box-shadow:var(--shadow-sm);border-color:#bfdbfe !important;}
    .template-tab-bar,.template-filter-bar{gap:10px !important;}
    .template-tab-btn,.template-filter-chip{border-radius:999px !important;font-weight:800 !important;transition:background .18s ease,border-color .18s ease,color .18s ease,transform .18s ease,box-shadow .18s ease;}
    .template-tab-btn:hover,.template-filter-chip:hover{transform:translateY(-1px);box-shadow:0 10px 22px rgba(15,23,42,.06);}
    .template-tab-btn.active,.template-filter-chip.active{background:linear-gradient(135deg,#2563eb 0%,#3b82f6 100%) !important;color:#fff !important;border-color:#2563eb !important;box-shadow:0 10px 22px rgba(37,99,235,.16);}
    .template-tab-btn.active .template-filter-count,.template-filter-chip.active .template-filter-count{color:rgba(255,255,255,.78) !important;}
    .template-thumb{border-radius:14px;background:linear-gradient(135deg,#f8fafc 0%,#eef4ff 100%) !important;}
    .template-card .template-thumb{border-radius:14px 14px 0 0;}
    .template-local-card .template-thumb{border-radius:14px;}
    .template-thumb img{transition:transform .35s ease,filter .35s ease;}
    .template-card:hover .template-thumb img,.template-local-card:hover .template-thumb img{transform:scale(1.035);filter:saturate(1.05);}
    .template-state-badge{backdrop-filter:blur(8px);box-shadow:0 10px 20px rgba(15,23,42,.18);}
    .template-actions,.template-local-actions{align-items:center;}
    .template-inline-form{margin:0;}
    .template-package-group,.template-package-preview{border-radius:16px !important;}
    .template-package-check{padding:6px 8px;border-radius:10px;transition:background .18s ease;}
    .template-package-check:hover{background:#f8fafc;}
    .template-package-file{width:100%;padding:12px;border:1px dashed #cbd5e1;border-radius:14px;background:#f8fafc;}
    .auth-main-grid,.auth-side-stack{gap:20px !important;}
    .auth-input:focus{border-color:#2563eb;box-shadow:0 0 0 4px rgba(37,99,235,.08);outline:none;}
    .auth-btn-primary,.auth-btn-reset,.auth-plan-btn{transition:transform .18s ease,box-shadow .18s ease,background .18s ease;}
    .auth-btn-primary:hover,.auth-btn-reset:hover,.auth-plan-btn:hover{transform:translateY(-1px);box-shadow:0 12px 26px rgba(15,23,42,.08);}
    .license-compare-table{min-width:760px;}
    .compare-table-wrap{border-radius:16px;border:1px solid #e2e8f0;}
    .compare-table-wrap .license-compare-table th,.compare-table-wrap .license-compare-table td{border-color:#eef2f7;}
    .version-card,[style*="升级历史"],[style*="更新说明"]{border-radius:16px !important;}
    .content-manage-layout{gap:18px !important;min-height:calc(100vh - 132px) !important;}
    .channel-sidebar,.content-overview-head,.content-topbar,.content-context-bar,.content-list-wrapper{border-radius:16px !important;box-shadow:var(--shadow-xs);border-color:#e2e8f0 !important;}
    .channel-sidebar{width:176px !important;background:linear-gradient(180deg,#fff 0%,#fbfdff 100%) !important;}
    .channel-sidebar-header{background:linear-gradient(135deg,#f8fbff 0%,#fff 100%) !important;}
    .channel-tree-item{border-radius:10px !important;transition:background .18s ease,color .18s ease,transform .18s ease !important;}
    .channel-tree-item:hover{transform:translateX(2px);}
    .channel-tree-item.active{background:#eff6ff !important;box-shadow:inset 3px 0 0 #2563eb;}
    .channel-count-badge,.list-meta-pill,.type-badge,.status-badge{border-radius:999px !important;font-weight:800 !important;}
    .content-main{min-width:0 !important;}
    .content-overview-head,.content-topbar,.content-context-bar,.list-meta-bar{flex-wrap:wrap;}
    .content-table{min-width:980px;}
    .content-list-wrapper{overflow:auto !important;}
    .content-table th{font-weight:800 !important;color:#475569 !important;}
    .content-table td{border-color:#eef2f7 !important;}
    .title-link{font-weight:700 !important;}
    .row-thumb{width:42px !important;height:42px !important;border-radius:10px !important;}
    .action-cell{flex-wrap:wrap;}
    .action-cell button{border-radius:9px !important;font-weight:700 !important;}
    .search-input{border-radius:10px !important;}
    .search-input:focus{box-shadow:0 0 0 4px rgba(37,99,235,.08) !important;}
    .table-meta{padding:14px 16px;margin:0 !important;border-bottom:1px solid #eef2f7;background:#fbfdff;}
    .table-meta + .data-table{margin-top:0;}
    .data-table img[style*="width:48px"]{width:54px !important;height:54px !important;border-radius:12px !important;}
    .data-table div[style*="width:48px"][style*="height:48px"]{width:54px !important;height:54px !important;border-radius:12px !important;}
    .data-table span[style*="border:1px dashed #cbd5e1"]{border-radius:999px !important;background:#f8fafc !important;}
    .content-card .filter-bar{margin:0 !important;border:none !important;box-shadow:none !important;background:#fbfdff !important;border-radius:16px !important;}
    .filter-bar > .btn,.filter-bar form > .btn,.filter-bar form > a.btn{min-height:38px;}
    .data-table td[style*="max-width"],.data-table div[style*="max-width"]{overflow-wrap:anywhere;}
    .data-table td[style*="font-family:monospace"],.data-table code{font-variant-ligatures:none;}
    .btn-danger{background:#fef2f2;color:#dc2626;border:1px solid #fecaca;}
    .btn-danger:hover{background:#fee2e2;color:#b91c1c;}
    div[id$="Modal"][style*="position:fixed"]{backdrop-filter:blur(4px);}
    div[id$="Modal"][style*="position:fixed"]>div,div[class*="modal-card"],.yt-ship-modal-card{animation:modalPop .18s ease both;}
    @keyframes modalPop{from{opacity:0;transform:translateY(8px) scale(.98);}to{opacity:1;transform:translateY(0) scale(1);}}
    @media(max-width:1200px){.stats-grid[style*="repeat(6"]{grid-template-columns:repeat(3,minmax(0,1fr)) !important;}.channel-context-bar{grid-template-columns:repeat(2,minmax(0,1fr));}}
    @media(max-width:900px){.content-card>.data-table,.content-card .data-table{min-width:720px;}.filter-bar form{align-items:stretch;}.filter-bar input,.filter-bar select,.filter-bar .btn{width:100%;}.page-actions{width:100%;}.page-actions .btn{flex:1;}.page-container [style*="grid-template-columns:240px 1fr"]{grid-template-columns:1fr !important;}.content-manage-layout{flex-direction:column !important;min-height:auto !important;}.channel-sidebar{width:100% !important;max-height:360px !important;}.content-table{min-width:900px;}.content-overview-head,.content-topbar,.content-context-bar{align-items:stretch !important;}.topbar-left,.topbar-right,.search-form{width:100% !important;}.channel-data-table{min-width:820px !important;}.channel-row-actions{max-width:200px;}}
    @media(max-width:768px){.page-container{padding:14px;}.page-header{padding:16px;}.stats-grid,.stats-grid[style]{grid-template-columns:1fr !important;}.stat-card{padding:16px;}.form-section-body{padding:16px;}.page-container [style*="display:flex"][style*="gap:12px"]{flex-wrap:wrap;}.btn-group{width:100% !important;}.btn-group .btn{flex:1 1 auto;}.content-card{border-radius:14px;}.table-footer{align-items:stretch;}.batch-actions,.table-info{width:100%;}.pagination{overflow-x:auto;justify-content:flex-start;}.yt-shop-config-row{align-items:flex-start !important;}.yt-shop-config-row .yt-switch{margin-top:4px;}.tag-section{margin-left:-2px;margin-right:-2px;}.channel-context-bar{grid-template-columns:1fr;}.channel-toolbar{flex-direction:column;align-items:stretch;}.channel-sort-mode{width:100%;}.channel-row-actions{max-width:none;}.channel-move-card{padding:20px;border-radius:18px;}.channel-move-actions .btn{flex:1;}}
    </style>
    <link rel="stylesheet" href="/public/css/rich-editor.css">
    <link rel="stylesheet" href="/public/css/admin-design-system.css?v=20260711">
    <script src="/public/ueditor/cms-editor.js?v=<?php echo @filemtime(ROOT_PATH . 'public/ueditor/cms-editor.js'); ?>"></script>
</head>
<body class="<?php echo $adminCanManageCurrentModule ? '' : 'cms-rbac-readonly'; ?>">
<div class="page-container fade-in">
<?php if (!$adminCanManageCurrentModule): ?><div class="cms-readonly-notice"><strong>只读模式</strong><span>当前角色可以查看此模块，但不能新增、编辑、删除或批量处理。</span></div><?php endif; ?>
<?php

switch ($act) {
    case 'content':
        include 'modules/content.php';
        break;
    case 'content_list':
        header('Content-Type: text/html; charset=utf-8');
        include 'modules/content_list.php';
        exit;
    case 'dashboard':
        include 'modules/dashboard.php';
        break;
    case 'global_search':
        include 'modules/global_search.php';
        break;
    case 'notification':
        include 'modules/notification.php';
        break;
    case 'channel':
        include 'modules/channel.php';
        break;
    case 'article':
        include 'modules/article.php';
        break;
    case 'product':
        include 'modules/product.php';
        break;
    case 'page':
        include 'modules/page.php';
        break;
    case 'image':
        include 'modules/image.php';
        break;
    case 'download':
        include 'modules/download.php';
        break;
    case 'video':
        include 'modules/video.php';
        break;
    case 'recruit':
        include 'modules/recruit.php';
        break;
    case 'member':
        include 'modules/member.php';
        break;
    case 'member_group':
        include 'modules/member_group.php';
        break;
    case 'message':
        include 'modules/message.php';
        break;
    case 'guestbook':
        include 'modules/guestbook.php';
        break;
    case 'comment':
        include 'modules/comment.php';
        break;
    case 'vote':
        include 'modules/vote.php';
        break;
    case 'contribute':
        include 'modules/contribute.php';
        break;
    case 'slide':
        include 'modules/slide.php';
        break;
    case 'link':
        include 'modules/link.php';
        break;
    case 'ads':
        include 'modules/ads.php';
        break;
    case 'template':
        include 'modules/template.php';
        break;
    case 'media':
        include 'modules/media.php';
        break;
    case 'builder':
        if (!$license->canUseBuilder()) {
            header('Location: /admin/main.php?act=auth');
            exit;
        }
        $builder = new \Core\Lib\Builder($db);
        $builderType = $builder->normalizePageType($_REQUEST['type'] ?? $_REQUEST['builder_type'] ?? 'home');
        $builderRefId = intval($_REQUEST['id'] ?? $_REQUEST['builder_ref_id'] ?? 0);
        if (!$builder->requiresReferenceId($builderType)) {
            $builderRefId = 0;
        }
        $builderEntryUrl = cmsResolveBuilderFrontendUrl($builderType, $builderRefId, cmsBuildFrontendUrl('home'));
        $builderEntryUrl .= (strpos($builderEntryUrl, '?') !== false ? '&' : '?') . http_build_query([
            'builder_edit' => 1,
            'builder_type' => $builderType,
            'builder_ref_id' => $builderRefId,
            'builder_token' => cmsBuildBuilderAccessToken($builderType, $builderRefId, time() + 7200),
        ]);
        header('Location: ' . $builderEntryUrl);
        exit;
    case 'content_quality':
        include 'modules/content_quality.php';
        break;
    case 'data_import':
        include 'modules/data_import.php';
        break;
    case 'tag_help':
        include 'modules/tag_help.php';
        break;
    case 'version':
        include 'modules/version.php';
        break;
    case 'custom_var':
        include 'modules/custom_var.php';
        break;
    case 'recharge':
        include 'modules/recharge.php';
        break;
    case 'pay_order':
        if (!$license->canUseOrder()) {
            echo '<div style="padding:40px;text-align:center;"><h2 style="color:#dc2626;">免费版仅支持查看订单</h2><p style="color:#64748b;margin-top:10px;">发货、取消、完成、删除等操作需要升级专业版授权。<a href="?act=auth" style="color:#2563eb;">去升级</a></p></div>';
        } else {
            require_once dirname(__DIR__) . '/core/lib/module_loader.php';
            $payOrderFile = dirname(__DIR__) . '/modules-premium/pro/order/pay_order.php';
            if (!is_file($payOrderFile)) {
                (new \Core\Lib\ModuleLoader($license))->syncAuthorizedModules();
            }
            if (is_file($payOrderFile)) {
                require $payOrderFile;
            } else {
                echo '<div class="empty-state"><h3>支付订单模块未安装</h3><p>请到授权信息页面同步商业模块。</p></div>';
            }
        }
        break;
    case 'order':
        include 'modules/order.php';
        break;
    case 'shop':
        include 'modules/shop.php';
        break;
    case 'shipping':
        include 'modules/shipping.php';
        break;
    case 'refund':
        include 'modules/refund.php';
        break;
    case 'review':
        include 'modules/review.php';
        break;
    case 'shop_config':
        include 'modules/shop_config.php';
        break;
    case 'site':
        include 'modules/site.php';
        break;
    case 'online_service':
        include 'modules/online_service.php';
        break;
    case 'redirect':
        include 'modules/redirect.php';
        break;
    case 'system_status':
        include 'modules/system_status.php';
        break;
    case 'task_center':
        include 'modules/task_center.php';
        break;
    case 'seo_tools':
        include 'modules/seo_tools.php';
        break;
    case 'payment':
        if (!$license->canUsePayment()) {
            echo '<div style="padding:40px;text-align:center;"><h2 style="color:#dc2626;">免费版仅支持查看支付设置</h2><p style="color:#64748b;margin-top:10px;">支付接口配置和管理需要升级专业版授权。<a href="?act=auth" style="color:#2563eb;">去升级</a></p></div>';
        } else {
            include 'modules/payment.php';
        }
        break;
    case 'auth':
        include 'modules/auth.php';
        break;
    case 'log':
        include 'modules/log.php';
        break;
    case 'database':
        include 'modules/database.php';
        break;
    case 'profile':
        include 'modules/profile.php';
        break;
    case 'admin_user':
        include 'modules/admin_user.php';
        break;
    case 'role':
        include 'modules/role.php';
        break;
    default:
        include 'modules/dashboard.php';
        break;
}
?>
<style id="yt-final-admin-theme">
/* Final backend theme layer: rendered after module styles so visual changes are actually visible. */
body {
    background:
        radial-gradient(circle at 8% 0%, rgba(37, 99, 235, .10), transparent 30%),
        linear-gradient(180deg, #f5f7fb 0%, #eef2f7 100%) !important;
}
.page-container {
    max-width: 1480px !important;
    padding: 24px !important;
}
.page-header {
    position: relative !important;
    overflow: hidden !important;
    padding: 22px 24px !important;
    border: 1px solid rgba(255, 255, 255, .34) !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 86% 10%, rgba(96, 165, 250, .36), transparent 28%),
        linear-gradient(135deg, #0f172a 0%, #1d4ed8 100%) !important;
    color: #fff !important;
    box-shadow: 0 22px 52px rgba(30, 64, 175, .20) !important;
}
.page-header::after {
    content: "";
    position: absolute;
    inset: auto -40px -80px auto;
    width: 220px;
    height: 220px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .12);
    pointer-events: none;
}
.page-header h1,
.page-header h2,
.page-header h3,
.page-header p,
.page-header .page-title,
.page-header .page-title h1,
.page-header .page-title p {
    color: #fff !important;
}
.page-header p {
    opacity: .78 !important;
}
.page-icon {
    background: rgba(255, 255, 255, .16) !important;
    color: #fff !important;
    border: 1px solid rgba(255, 255, 255, .18) !important;
    box-shadow: none !important;
}
.content-card,
.form-section,
.filter-bar,
.page-context-item,
.stat-card,
.template-summary-card,
.template-local-card,
.template-card,
.auth-hero-card,
.auth-compare-card,
.auth-activate-card,
.auth-plan-card,
.channel-sidebar,
.content-overview-head,
.content-topbar,
.content-context-bar,
.content-list-wrapper {
    border: 1px solid rgba(226, 232, 240, .96) !important;
    border-radius: 18px !important;
    background: rgba(255, 255, 255, .96) !important;
    box-shadow: 0 14px 34px rgba(15, 23, 42, .07) !important;
}
.auth-page .auth-hero-card {
    background:
        radial-gradient(circle at 92% -8%, rgba(56, 189, 248, .34), transparent 32%),
        radial-gradient(circle at 8% 12%, rgba(37, 99, 235, .26), transparent 34%),
        linear-gradient(135deg, #0f172a 0%, #1e293b 52%, #1d4ed8 100%) !important;
    color: #fff !important;
    border-color: rgba(148, 163, 184, .24) !important;
}
.auth-page .auth-hero-card .auth-hero-badge,
.auth-page .auth-hero-card .auth-hero-desc,
.auth-page .auth-hero-card .auth-stat-item span,
.auth-page .auth-hero-card .auth-hero-field label {
    color: rgba(255, 255, 255, .78) !important;
}
.auth-page .auth-hero-card .auth-hero-title,
.auth-page .auth-hero-card .auth-hero-chip,
.auth-page .auth-hero-card .auth-stat-item strong,
.auth-page .auth-hero-card .auth-hero-value {
    color: #fff !important;
}
.auth-page .auth-hero-card .auth-stat-item,
.auth-page .auth-hero-card .auth-hero-field {
    background: rgba(15, 23, 42, .24) !important;
    border-color: rgba(255, 255, 255, .12) !important;
}
.auth-page .auth-hero-card .auth-copy-btn,
.auth-page .auth-hero-card .auth-hero-chip,
.auth-page .auth-hero-card .auth-hero-badge {
    background: rgba(255, 255, 255, .14) !important;
    border-color: rgba(255, 255, 255, .18) !important;
}
.filter-bar,
.content-card .filter-bar {
    padding: 16px !important;
    background: rgba(255, 255, 255, .94) !important;
}
.data-table th,
.content-table th {
    background: linear-gradient(180deg, #f8fbff 0%, #eef4ff 100%) !important;
    color: #334155 !important;
    font-weight: 900 !important;
}
.data-table td,
.content-table td {
    border-bottom-color: #edf2f7 !important;
}
.data-table tr:hover td,
.content-table tr:hover td {
    background: #f8fbff !important;
}
.btn-primary,
button.btn-primary,
a.btn-primary {
    background: linear-gradient(135deg, #1d4ed8 0%, #38bdf8 100%) !important;
    color: #fff !important;
    border: none !important;
    box-shadow: 0 12px 24px rgba(37, 99, 235, .22) !important;
}
.btn-secondary,
a.btn-secondary,
button.btn-secondary {
    background: #fff !important;
    color: #334155 !important;
    border: 1px solid #dbe3ef !important;
}
.btn,
.template-tab-btn,
.template-filter-chip {
    border-radius: 12px !important;
    font-weight: 800 !important;
}
.badge,
.type-badge,
.status-badge,
.list-meta-pill {
    border-radius: 999px !important;
    font-weight: 800 !important;
}
.form-control,
input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
select,
textarea {
    border-radius: 12px !important;
}
.dashboard-fk-page {
    max-width: 1560px !important;
}
.dashboard-fk-page .fk-workbench {
    display: grid !important;
    grid-template-columns: minmax(0, 1.65fr) minmax(340px, .8fr) !important;
    gap: 22px !important;
    align-items: start !important;
}
.dashboard-fk-page .fk-panel,
.dashboard-fk-page .fk-side-card,
.dashboard-fk-page .fk-promo-card,
.dashboard-fk-page .fk-calendar-card,
.dashboard-fk-page .fk-announce-card {
    border: 1px solid rgba(226, 232, 240, .9) !important;
    border-radius: 24px !important;
    background: rgba(255,255,255,.96) !important;
    box-shadow: 0 18px 42px rgba(15,23,42,.08) !important;
    overflow: hidden !important;
}
.dashboard-fk-page .fk-hero-panel {
    background:
        radial-gradient(circle at 16% 0%, rgba(56,189,248,.16), transparent 30%),
        linear-gradient(135deg, #ffffff 0%, #f4f8ff 100%) !important;
}
.dashboard-fk-page .fk-hero-grid {
    gap: 18px !important;
}
.dashboard-fk-page .fk-scene-card {
    min-height: 190px !important;
    border-radius: 22px !important;
    padding: 24px !important;
    box-shadow: 0 20px 45px rgba(37,99,235,.16) !important;
    transition: transform .2s ease, box-shadow .2s ease !important;
}
.dashboard-fk-page .fk-scene-card:hover,
.dashboard-fk-page .fk-template-card:hover,
.dashboard-fk-page .fk-entry-item:hover,
.dashboard-fk-page .fk-help-card:hover {
    transform: translateY(-4px) !important;
}
.dashboard-fk-page .fk-scene-card-desktop {
    background: linear-gradient(135deg, #1d4ed8 0%, #06b6d4 100%) !important;
}
.dashboard-fk-page .fk-scene-card-mobile {
    background: linear-gradient(135deg, #0f766e 0%, #22c55e 100%) !important;
}
.dashboard-fk-page .fk-site-card {
    border-radius: 22px !important;
    padding: 22px !important;
    background: #fff !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.08) !important;
}
.dashboard-fk-page .fk-entry-grid {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)) !important;
    gap: 12px !important;
    padding-top: 18px !important;
}
.dashboard-fk-page .fk-entry-item {
    min-height: 108px !important;
    border-radius: 20px !important;
    background: linear-gradient(180deg, #fff 0%, #f8fbff 100%) !important;
    border: 1px solid #e2e8f0 !important;
    box-shadow: 0 12px 28px rgba(15,23,42,.05) !important;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease !important;
}
.dashboard-fk-page .fk-entry-icon {
    width: 42px !important;
    height: 42px !important;
    border-radius: 15px !important;
    background: #eff6ff !important;
    color: #2563eb !important;
}
.dashboard-fk-page .fk-panel-head {
    padding: 18px 20px !important;
    border-bottom: 1px solid #eef2f7 !important;
    background: linear-gradient(180deg, #fff 0%, #fbfdff 100%) !important;
}
.dashboard-fk-page .fk-template-body {
    padding: 18px !important;
}
.dashboard-fk-page .fk-template-grid {
    gap: 16px !important;
}
.dashboard-fk-page .fk-template-card {
    border-radius: 20px !important;
    background: #fff !important;
    border: 1px solid #e2e8f0 !important;
    box-shadow: 0 14px 32px rgba(15,23,42,.06) !important;
    transition: transform .2s ease, box-shadow .2s ease !important;
}
.dashboard-fk-page .fk-template-shot {
    border-radius: 16px !important;
    overflow: hidden !important;
}
.dashboard-fk-page .fk-seo-row,
.dashboard-fk-page .fk-notice-row {
    border-radius: 16px !important;
    margin: 8px 14px !important;
    padding: 14px 16px !important;
    background: #fbfdff !important;
    border: 1px solid #eef2f7 !important;
}
.dashboard-fk-page .fk-help-card {
    border-radius: 18px !important;
    box-shadow: 0 14px 30px rgba(15,23,42,.07) !important;
    transition: transform .2s ease, box-shadow .2s ease !important;
}
.form-section {
    margin-bottom: 22px !important;
}
.form-section-header {
    padding: 16px 20px !important;
    background: linear-gradient(180deg, #fff 0%, #f8fbff 100%) !important;
    border-bottom: 1px solid #edf2f7 !important;
}
.form-section-body {
    padding: 22px !important;
}
.form-row {
    gap: 18px !important;
}
.form-actions {
    position: sticky !important;
    bottom: 0 !important;
    z-index: 8 !important;
    margin: 22px -24px -24px !important;
    padding: 16px 24px !important;
    background: rgba(255,255,255,.86) !important;
    border-top: 1px solid #e2e8f0 !important;
    backdrop-filter: blur(12px) !important;
}
.data-table {
    border-collapse: separate !important;
    border-spacing: 0 !important;
}
.data-table th:first-child,
.data-table td:first-child {
    padding-left: 18px !important;
}
.data-table th:last-child,
.data-table td:last-child {
    padding-right: 18px !important;
}
.article-manage-page,
.product-manage-page {
    max-width: 1520px !important;
}
.article-context-bar,
.product-context-bar {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
    gap: 14px !important;
}
.article-context-item,
.product-context-item {
    position: relative !important;
    overflow: hidden !important;
    min-height: 96px !important;
    border-radius: 20px !important;
    background: linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 14px 32px rgba(15,23,42,.06) !important;
}
.article-context-item::after,
.product-context-item::after {
    content: "";
    position: absolute;
    right: -28px;
    bottom: -36px;
    width: 96px;
    height: 96px;
    border-radius: 999px;
    background: rgba(37,99,235,.08);
}
.article-context-label,
.product-context-label {
    letter-spacing: .04em !important;
    text-transform: uppercase !important;
}
.article-context-value,
.product-context-value {
    font-size: 18px !important;
}
.article-filter-bar,
.product-filter-bar {
    display: flex !important;
    align-items: center !important;
    gap: 14px !important;
    border-radius: 20px !important;
    box-shadow: 0 14px 32px rgba(15,23,42,.06) !important;
}
.article-filter-form,
.product-filter-form {
    width: 100% !important;
}
.article-filter-form::before,
.product-filter-form::before {
    content: "筛选";
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 38px;
    padding: 0 14px;
    border-radius: 999px;
    background: #eff6ff;
    color: #1d4ed8;
    font-size: 13px;
    font-weight: 900;
}
.article-list-card,
.product-list-card {
    border-radius: 22px !important;
    overflow: hidden !important;
}
.article-data-table,
.product-data-table {
    min-width: 980px !important;
}
.article-data-table th,
.product-data-table th {
    height: 48px !important;
}
.article-data-table td,
.product-data-table td {
    padding-top: 14px !important;
    padding-bottom: 14px !important;
}
.article-data-table img,
.product-data-table img {
    border-radius: 12px !important;
    box-shadow: 0 8px 18px rgba(15,23,42,.08) !important;
}
.article-data-table a,
.product-data-table a {
    font-weight: 800 !important;
}
.article-data-table .btn,
.product-data-table .btn {
    min-height: 34px !important;
    padding: 7px 12px !important;
}
.page-container > form > div[style*="grid-template-columns:minmax(0,1fr)"] {
    gap: 24px !important;
}
.page-container > form > div[style*="grid-template-columns:minmax(0,1fr)"] > div:last-child {
    position: sticky !important;
    top: 18px !important;
    align-self: start !important;
}
.page-container > form > div[style*="grid-template-columns:minmax(0,1fr)"] > div:last-child .form-section {
    border-radius: 20px !important;
}
.upload-preview,
#litpicPreview {
    border-radius: 18px !important;
    border: 2px dashed #cbd5e1 !important;
    background: linear-gradient(135deg, #f8fafc 0%, #eef4ff 100%) !important;
}
.cms-ueditor-wrap,
.product-ueditor-wrap {
    border-radius: 0 0 20px 20px !important;
}
.cms-ueditor-wrap .edui-editor,
.product-ueditor-wrap .edui-editor {
    border-radius: 14px !important;
    overflow: hidden !important;
    box-shadow: 0 12px 28px rgba(15,23,42,.06) !important;
}
.page-context-bar {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
    gap: 14px !important;
    margin-bottom: 18px !important;
}
.page-context-item {
    position: relative !important;
    overflow: hidden !important;
    min-height: 92px !important;
    padding: 18px 20px !important;
    background:
        radial-gradient(circle at 100% 0%, rgba(56, 189, 248, .14), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
}
.page-context-label {
    display: block !important;
    margin-bottom: 8px !important;
    color: #64748b !important;
    font-size: 12px !important;
    font-weight: 800 !important;
    letter-spacing: .06em !important;
}
.page-context-value {
    display: block !important;
    color: #0f172a !important;
    font-size: 19px !important;
    font-weight: 900 !important;
    line-height: 1.35 !important;
}
.page-context-muted {
    color: #2563eb !important;
}
/* Content-first summary strips: keep operational metrics without pushing lists below the fold. */
.page-context-bar,
.article-context-bar,
.product-context-bar,
.download-context-bar,
.image-context-bar,
.video-context-bar,
.channel-context-bar,
.content-context-bar {
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
    flex-wrap: wrap !important;
    margin-bottom: 12px !important;
}
.page-context-item,
.article-context-item,
.product-context-item,
.download-context-item,
.image-context-item,
.video-context-item,
.channel-context-item,
.content-context-item,
.content-context-bar .context-block {
    display: inline-flex !important;
    flex: 0 1 auto !important;
    min-width: 0 !important;
    min-height: 0 !important;
    max-width: 100% !important;
    align-items: center !important;
    flex-direction: row !important;
    gap: 6px !important;
    overflow: visible !important;
    padding: 9px 12px !important;
    border: 1px solid #dbe3f0 !important;
    border-radius: 12px !important;
    background: rgba(255,255,255,.9) !important;
    box-shadow: none !important;
}
.page-context-label,
.article-context-label,
.product-context-label,
.download-context-label,
.image-context-label,
.video-context-label,
.channel-context-label,
.content-context-label,
.content-context-bar .context-label {
    display: inline !important;
    flex: 0 0 auto !important;
    margin: 0 !important;
    color: #94a3b8 !important;
    font-size: 11px !important;
    font-weight: 700 !important;
    letter-spacing: 0 !important;
}
.page-context-label::after,
.article-context-label::after,
.product-context-label::after,
.download-context-label::after,
.image-context-label::after,
.video-context-label::after,
.channel-context-label::after,
.content-context-label::after,
.content-context-bar .context-label::after {
    content: "：";
}
.page-context-value,
.article-context-value,
.product-context-value,
.download-context-value,
.image-context-value,
.video-context-value,
.channel-context-value,
.content-context-value,
.content-context-bar .context-value {
    display: inline !important;
    min-width: 0 !important;
    color: #334155 !important;
    font-size: 13px !important;
    font-weight: 750 !important;
    line-height: 1.45 !important;
}
.article-context-item-action {
    justify-content: flex-start !important;
}
.article-context-item-action .article-context-btn {
    min-height: 30px !important;
    margin: 0 0 0 4px !important;
    padding: 7px 10px !important;
}
.yt-ship-stats,
.yt-refund-stats,
.yt-review-stats,
.card-grid {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) !important;
    gap: 14px !important;
    margin-bottom: 18px !important;
}
.yt-ship-stat,
.yt-refund-stat,
.yt-review-stat,
.stat-card {
    position: relative !important;
    overflow: hidden !important;
    min-height: 104px !important;
    padding: 20px 22px !important;
    border: 1px solid rgba(226, 232, 240, .96) !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 88% 8%, rgba(37, 99, 235, .14), transparent 30%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.07) !important;
    color: #334155 !important;
    text-decoration: none !important;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease !important;
}
.yt-ship-stat:hover,
.yt-refund-stat:hover,
.yt-review-stat:hover,
.stat-card:hover {
    transform: translateY(-3px) !important;
    border-color: rgba(37, 99, 235, .32) !important;
    box-shadow: 0 22px 44px rgba(30,64,175,.12) !important;
}
.yt-ship-stat span,
.yt-refund-stat span,
.yt-review-stat span,
.stat-card-label {
    color: #64748b !important;
    font-size: 13px !important;
    font-weight: 800 !important;
}
.yt-ship-stat strong,
.yt-refund-stat strong,
.yt-review-stat strong,
.stat-card-value {
    color: #0f172a !important;
    font-size: 28px !important;
    font-weight: 950 !important;
    letter-spacing: -.03em !important;
}
.content-card > form.filter-bar,
.content-card[style*="padding:16px"] > form,
.filter-bar form {
    display: flex !important;
    align-items: center !important;
    gap: 12px !important;
    flex-wrap: wrap !important;
}
.content-card[style*="padding:16px"] {
    padding: 18px !important;
}
.filter-bar input,
.filter-bar select,
.content-card > form input,
.content-card > form select {
    min-height: 40px !important;
    border-color: #dbe3ef !important;
    background: #fff !important;
    box-shadow: inset 0 1px 0 rgba(15,23,42,.02) !important;
}
.filter-bar input:focus,
.filter-bar select:focus,
.content-card > form input:focus,
.content-card > form select:focus {
    border-color: #2563eb !important;
    box-shadow: 0 0 0 4px rgba(37,99,235,.08) !important;
    outline: none !important;
}
.table-meta {
    margin: 0 !important;
    padding: 16px 18px !important;
    border-bottom: 1px solid #edf2f7 !important;
    background:
        linear-gradient(180deg, #fff 0%, #fbfdff 100%) !important;
}
.content-card > .data-table {
    min-width: 920px !important;
}
.data-table td {
    vertical-align: middle !important;
    word-break: break-word !important;
}
.data-table td > div[style*="min-width:220px"] {
    min-width: 260px !important;
}
.data-table img[style*="width:48px"],
.data-table div[style*="width:48px"][style*="height:48px"] {
    width: 58px !important;
    height: 58px !important;
    border-radius: 15px !important;
    box-shadow: 0 10px 24px rgba(15,23,42,.09) !important;
}
.data-table td[style*="font-family:monospace"] {
    color: #1d4ed8 !important;
    font-weight: 800 !important;
}
.data-table td[style*="color:#2563eb"],
.data-table td[style*="color: #2563eb"] {
    font-size: 15px !important;
}
.btn-group {
    align-items: center !important;
}
.btn-group .btn,
.data-table .btn,
.batch-actions .btn {
    min-height: 34px !important;
    padding: 7px 12px !important;
    font-size: 12px !important;
}
.btn-ghost,
button.btn-ghost,
a.btn-ghost {
    background: #fff !important;
    border: 1px solid #e2e8f0 !important;
    color: #475569 !important;
}
.btn-ghost:hover {
    background: #f8fbff !important;
    border-color: #bfdbfe !important;
}
.table-footer {
    margin-top: 0 !important;
    padding: 16px 18px !important;
    border-top: 1px solid #edf2f7 !important;
    background: linear-gradient(180deg, #fbfdff 0%, #fff 100%) !important;
}
.pagination,
.content-card .pagination {
    padding: 18px !important;
    gap: 8px !important;
}
.pagination a,
.pagination .page-link {
    min-width: 36px !important;
    min-height: 36px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    border-radius: 12px !important;
    font-weight: 800 !important;
}
.modal,
.yt-ship-modal {
    backdrop-filter: blur(8px) !important;
    background: rgba(15,23,42,.50) !important;
}
.modal-content,
.yt-ship-modal-card {
    border: 1px solid rgba(255,255,255,.72) !important;
    border-radius: 24px !important;
    background: rgba(255,255,255,.98) !important;
    box-shadow: 0 30px 80px rgba(15,23,42,.26) !important;
    overflow: hidden !important;
}
.modal-header,
.yt-ship-modal-card h3 {
    background: linear-gradient(180deg, #fff 0%, #f8fbff 100%) !important;
}
.modal-close {
    border-radius: 999px !important;
}
.modal-body,
.modal-footer {
    background: #fff !important;
}
.modal-footer {
    border-top-color: #edf2f7 !important;
}
.alert,
div[style*="border:1px solid #fdba74"] {
    border-radius: 20px !important;
    box-shadow: 0 16px 34px rgba(234,88,12,.10) !important;
}
[class$="-context-bar"] {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
    gap: 14px !important;
    margin-bottom: 18px !important;
}
[class$="-context-item"] {
    position: relative !important;
    overflow: hidden !important;
    min-height: 92px !important;
    padding: 18px 20px !important;
    border: 1px solid rgba(226, 232, 240, .96) !important;
    border-radius: 20px !important;
    background:
        radial-gradient(circle at 92% 0%, rgba(14, 165, 233, .14), transparent 32%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 14px 32px rgba(15,23,42,.06) !important;
}
[class$="-context-label"] {
    display: block !important;
    margin-bottom: 8px !important;
    color: #64748b !important;
    font-size: 12px !important;
    font-weight: 850 !important;
    letter-spacing: .05em !important;
}
[class$="-context-value"] {
    display: block !important;
    color: #0f172a !important;
    font-size: 18px !important;
    font-weight: 900 !important;
    line-height: 1.45 !important;
}
[class$="-context-muted"] {
    color: #2563eb !important;
}
.download-list-card,
.video-list-card,
.link-list-card,
.ads-list-card {
    border-radius: 22px !important;
    overflow: auto !important;
    border: 1px solid rgba(226,232,240,.96) !important;
    background: #fff !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.07) !important;
}
.download-data-table,
.video-data-table,
.link-data-table,
.ads-data-table {
    min-width: 920px !important;
}
.download-page-actions,
.video-page-actions,
.page-actions,
.header-actions {
    gap: 10px !important;
    flex-wrap: wrap !important;
}
.form-section .cms-ueditor-wrap {
    min-height: 420px !important;
    padding: 18px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 18px !important;
    background: linear-gradient(180deg, #fff 0%, #fbfdff 100%) !important;
}
.form-section .cms-ueditor-wrap script + script + script[style],
.form-section script[type="text/plain"][style*="width:100%"] {
    max-width: 100% !important;
}
.page-header {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 16px !important;
}
.page-header > div:first-child,
.page-title {
    min-width: 0 !important;
}
.page-header .page-actions,
.page-header .header-actions {
    flex: 0 0 auto !important;
    justify-content: flex-end !important;
}
.content-card {
    max-width: 100% !important;
    overflow: auto !important;
}
.content-card > .data-table,
.content-card table.data-table {
    width: 100% !important;
}
@media (min-width: 1101px) {
    .content-card > .data-table:has(tbody td:last-child .btn),
    .content-card table.data-table:has(tbody td:last-child .btn),
    .content-list-wrapper .content-table {
        border-collapse: separate !important;
        border-spacing: 0 !important;
    }
    .content-card > .data-table:has(tbody td:last-child .btn) th:last-child,
    .content-card table.data-table:has(tbody td:last-child .btn) th:last-child,
    .content-list-wrapper .content-table th:last-child {
        position: sticky !important;
        right: 0 !important;
        z-index: 5 !important;
        box-shadow: -12px 0 24px rgba(15, 23, 42, .05) !important;
    }
    .content-card > .data-table:has(tbody td:last-child .btn) td:last-child,
    .content-card table.data-table:has(tbody td:last-child .btn) td:last-child,
    .content-list-wrapper .content-table td:last-child {
        position: sticky !important;
        right: 0 !important;
        z-index: 4 !important;
        min-width: 150px !important;
        background: rgba(255, 255, 255, .98) !important;
        box-shadow: -12px 0 24px rgba(15, 23, 42, .04) !important;
    }
    .content-card > .data-table:has(tbody td:last-child .btn) tr:hover td:last-child,
    .content-card table.data-table:has(tbody td:last-child .btn) tr:hover td:last-child,
    .content-list-wrapper .content-table tr:hover td:last-child {
        background: #f8fbff !important;
    }
    .content-card > .data-table:has(tbody td:last-child .btn) td:last-child .btn-group,
    .content-card table.data-table:has(tbody td:last-child .btn) td:last-child .btn-group,
    .content-list-wrapper .content-table td:last-child .action-cell {
        justify-content: flex-start !important;
        max-width: 280px !important;
    }
}
.filter-bar,
.content-card > form.filter-bar,
.content-card[style*="padding:16px"] > form {
    max-width: 100% !important;
}
.filter-bar input[type="text"],
.filter-bar select,
.content-card > form input[type="text"],
.content-card > form select {
    flex: 1 1 180px !important;
    max-width: 100% !important;
}
.filter-bar .btn,
.content-card > form.filter-bar .btn,
.content-card[style*="padding:16px"] > form .btn {
    flex: 0 0 auto !important;
}
.batch-actions,
.page-actions,
.header-actions,
.table-meta {
    row-gap: 10px !important;
}
.table-meta > div:first-child {
    font-weight: 800 !important;
    color: #334155 !important;
}
.table-meta > div:last-child {
    line-height: 1.6 !important;
}
.page-container > form > div[style*="grid-template-columns:minmax(0,1fr)"] > div:first-child {
    min-width: 0 !important;
}
.page-container > form > div[style*="grid-template-columns:minmax(0,1fr)"] > div:last-child {
    min-width: 280px !important;
}
.help-layout {
    grid-template-columns: 260px minmax(0, 1fr) !important;
    gap: 22px !important;
}
.help-nav,
.help-panel,
.help-card {
    border: 1px solid rgba(226,232,240,.96) !important;
    border-radius: 22px !important;
    background: rgba(255,255,255,.96) !important;
    box-shadow: 0 18px 42px rgba(15,23,42,.08) !important;
}
.help-nav {
    top: 24px !important;
    padding: 18px 14px !important;
}
.help-nav-title {
    padding: 0 10px 10px !important;
    color: #0f172a !important;
    font-weight: 900 !important;
}
.help-nav a {
    border-radius: 14px !important;
    font-weight: 750 !important;
    transition: background .18s ease, color .18s ease, transform .18s ease !important;
}
.help-nav a:hover {
    transform: translateX(3px) !important;
    background: #eff6ff !important;
}
.help-panel {
    padding: 22px !important;
}
.help-intro {
    border-radius: 20px !important;
    padding: 18px 20px !important;
    background:
        radial-gradient(circle at 90% 0%, rgba(56,189,248,.18), transparent 32%),
        linear-gradient(135deg, #eff6ff 0%, #fff 100%) !important;
    box-shadow: 0 14px 30px rgba(37,99,235,.08) !important;
}
.help-panel > div[style*="grid-template-columns"] > a {
    border-radius: 20px !important;
    padding: 18px !important;
    box-shadow: 0 12px 28px rgba(15,23,42,.06) !important;
    transition: transform .2s ease, box-shadow .2s ease !important;
}
.help-panel > div[style*="grid-template-columns"] > a:hover {
    transform: translateY(-3px) !important;
    box-shadow: 0 18px 38px rgba(15,23,42,.10) !important;
}
.help-section-head {
    border-radius: 20px 20px 0 0 !important;
    background:
        radial-gradient(circle at 94% 0%, rgba(251,146,60,.20), transparent 28%),
        linear-gradient(135deg, #fff7ed 0%, #fff 100%) !important;
}
.help-card {
    border-radius: 0 0 20px 20px !important;
}
.help-step {
    grid-template-columns: 108px minmax(0, 1fr) !important;
    padding: 18px 20px !important;
}
.help-step-no {
    height: 40px !important;
    border-radius: 999px !important;
    background: linear-gradient(135deg, #1d4ed8 0%, #38bdf8 100%) !important;
    box-shadow: 0 10px 22px rgba(37,99,235,.20) !important;
}
.help-note {
    border-radius: 14px !important;
}
.hover-lift,
.content-card [class*="hover-lift"],
.content-card div[style*="border:1px solid var(--border-light)"] {
    border-radius: 18px !important;
    background: linear-gradient(180deg, #fff 0%, #fbfdff 100%) !important;
    box-shadow: 0 12px 28px rgba(15,23,42,.05) !important;
    transition: transform .2s ease, box-shadow .2s ease !important;
}
.hover-lift:hover,
.content-card [class*="hover-lift"]:hover,
.content-card div[style*="border:1px solid var(--border-light)"]:hover {
    transform: translateY(-3px) !important;
    box-shadow: 0 18px 38px rgba(15,23,42,.10) !important;
}
.payment-readonly-panel,
.auth-notice,
.version-card {
    border-radius: 20px !important;
    box-shadow: 0 16px 34px rgba(15,23,42,.07) !important;
}
.site-page-overview {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
    gap: 14px !important;
    margin-bottom: 20px !important;
}
.site-overview-item {
    position: relative !important;
    overflow: hidden !important;
    min-height: 96px !important;
    padding: 18px 20px !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 94% 0%, rgba(56,189,248,.16), transparent 32%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 16px 34px rgba(15,23,42,.07) !important;
}
.overview-label {
    letter-spacing: .05em !important;
    font-weight: 850 !important;
}
.overview-value {
    font-size: 18px !important;
    font-weight: 950 !important;
    line-height: 1.35 !important;
}
.site-tabs {
    position: sticky !important;
    top: 0 !important;
    z-index: 7 !important;
    gap: 8px !important;
    padding: 10px !important;
    border-radius: 20px !important;
    background: rgba(255,255,255,.88) !important;
    backdrop-filter: blur(12px) !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.08) !important;
}
.site-tab {
    flex: 1 1 160px !important;
    justify-content: center !important;
    min-height: 44px !important;
    border-radius: 14px !important;
}
.site-tab.active {
    background: linear-gradient(135deg, #1d4ed8 0%, #38bdf8 100%) !important;
}
.site-tab-panel.active {
    animation: ytPanelIn .22s ease both;
}
@keyframes ytPanelIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}
.site-tab-panel .form-section {
    border-radius: 24px !important;
}
.site-tab-panel .form-section-header {
    min-height: 56px !important;
    font-size: 15px !important;
}
.site-tab-panel .form-help,
.license-tip-box {
    border-radius: 16px !important;
}
.toggle-group {
    gap: 10px !important;
}
.toggle-item {
    min-height: 42px !important;
    border-radius: 14px !important;
    font-weight: 800 !important;
}
.toggle-item.active {
    box-shadow: 0 10px 22px rgba(37,99,235,.12) !important;
}
.upload-box {
    min-height: 150px !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 90% 0%, rgba(37,99,235,.10), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.72) !important;
}
.upload-placeholder {
    gap: 10px !important;
}
.upload-placeholder svg {
    width: 34px !important;
    height: 34px !important;
}
.upload-preview {
    min-height: 150px !important;
    background: transparent !important;
}
.upload-preview img {
    max-height: 138px !important;
    border-radius: 14px !important;
}
.upload-remove {
    width: 28px !important;
    height: 28px !important;
    box-shadow: 0 8px 18px rgba(220,38,38,.22) !important;
}
.channel-admin-page {
    max-width: 1540px !important;
}
.channel-toolbar {
    border-radius: 22px !important;
    padding: 16px 18px !important;
    background:
        radial-gradient(circle at 100% 0%, rgba(14,165,233,.12), transparent 30%),
        rgba(255,255,255,.96) !important;
    box-shadow: 0 14px 32px rgba(15,23,42,.07) !important;
}
.channel-sort-mode {
    gap: 12px !important;
}
.channel-sort-label {
    padding: 6px 12px !important;
    border-radius: 999px !important;
    background: #eff6ff !important;
    color: #1d4ed8 !important;
    font-weight: 900 !important;
}
.channel-sort-option {
    min-height: 38px !important;
    padding: 6px 12px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 999px !important;
    background: #fff !important;
    font-weight: 800 !important;
}
.channel-table-shell {
    border-radius: 22px !important;
    overflow: auto !important;
}
.channel-data-table {
    min-width: 1060px !important;
}
.channel-data-table th {
    height: 50px !important;
}
.channel-row td {
    padding-top: 14px !important;
    padding-bottom: 14px !important;
}
.channel-name-cell {
    min-width: 280px !important;
}
.channel-type-icon {
    width: 38px !important;
    height: 38px !important;
    border-radius: 14px !important;
    background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%) !important;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.72) !important;
}
.channel-name-text {
    max-width: 260px !important;
    font-size: 14px !important;
    font-weight: 900 !important;
}
.channel-level-tag,
.channel-code,
.channel-status-text {
    border-radius: 999px !important;
}
.channel-code {
    display: inline-flex !important;
    max-width: 120px !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
}
.channel-status-text {
    display: inline-flex !important;
    align-items: center !important;
    min-height: 28px !important;
    padding: 0 10px !important;
    background: #f1f5f9 !important;
}
.channel-status-text.is-show {
    background: #ecfdf5 !important;
}
.channel-status-text.is-hide {
    background: #f8fafc !important;
}
.channel-row-actions {
    max-width: 300px !important;
}
.channel-row-actions .btn {
    min-width: 58px !important;
}
.sort-input {
    height: 34px !important;
    border-radius: 10px !important;
    font-weight: 800 !important;
}
#moveModal {
    backdrop-filter: blur(8px) !important;
    background: rgba(15,23,42,.52) !important;
}
#moveModal > div {
    border-radius: 24px !important;
    border: 1px solid rgba(255,255,255,.72) !important;
    box-shadow: 0 30px 80px rgba(15,23,42,.26) !important;
}
#thumbPreview {
    width: 110px !important;
    height: 110px !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 90% 0%, rgba(37,99,235,.12), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
}
.download-manage-page,
.video-manage-page {
    max-width: 1540px !important;
}
#imagePreviewBox,
#slidePreview,
#litpicPreview,
.album-item,
.page-container [id$="Preview"][class*="upload-preview"] {
    position: relative !important;
    overflow: hidden !important;
    border: 2px dashed #cbd5e1 !important;
    border-radius: 24px !important;
    background:
        radial-gradient(circle at 90% 0%, rgba(37,99,235,.13), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.82), 0 14px 30px rgba(15,23,42,.06) !important;
    transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease !important;
}
#imagePreviewBox:hover,
#slidePreview:hover,
#litpicPreview:hover,
.album-item:hover,
.page-container [id$="Preview"][class*="upload-preview"]:hover {
    border-color: #60a5fa !important;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.82), 0 20px 42px rgba(37,99,235,.12) !important;
    transform: translateY(-2px) !important;
}
#imagePreviewBox,
#slidePreview {
    width: 100% !important;
    min-height: 190px !important;
}
#imagePreviewBox img,
#slidePreview img,
#litpicPreview img,
.album-item img,
.data-table img[style*="width:60px"],
.data-table img[style*="width:44px"] {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    border-radius: 18px !important;
}
#imagePreviewBox > div,
#slidePreview .placeholder,
#litpicPreview .placeholder {
    color: #64748b !important;
    font-weight: 800 !important;
}
#typeImage div[style*="grid-template-columns:240px 1fr"],
.page-container div[style*="grid-template-columns:240px 1fr"] {
    grid-template-columns: minmax(260px, 360px) minmax(0, 1fr) !important;
    gap: 22px !important;
}
#typeImage input[type="text"],
#imgUrlInput,
#slideLitpic,
#litpicInput,
#videoPath,
input[name="file_path"] {
    min-height: 42px !important;
    border-radius: 14px !important;
}
.ad-type-btn {
    border-radius: 999px !important;
    font-weight: 850 !important;
    background: #fff !important;
}
.ad-type-btn.active {
    background: linear-gradient(135deg, #eff6ff 0%, #fff 100%) !important;
    box-shadow: 0 10px 22px rgba(37,99,235,.10) !important;
}
#typeText,
#typeCode,
#typeImage {
    padding: 18px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 22px !important;
    background: linear-gradient(180deg, #fff 0%, #fbfdff 100%) !important;
}
#ad_code_area {
    min-height: 180px !important;
    border-radius: 18px !important;
    background: #0f172a !important;
    color: #86efac !important;
    box-shadow: inset 0 1px 0 rgba(255,255,255,.08), 0 14px 30px rgba(15,23,42,.10) !important;
}
#albumsList {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)) !important;
    gap: 14px !important;
}
.album-item {
    height: 126px !important;
}
.album-item button {
    top: 8px !important;
    right: 8px !important;
    width: 28px !important;
    height: 28px !important;
    border-radius: 999px !important;
    background: rgba(15,23,42,.72) !important;
    box-shadow: 0 8px 18px rgba(15,23,42,.18) !important;
}
.video-data-table img,
.download-data-table img,
.data-table img[style*="width:60px"],
.data-table img[style*="width:44px"] {
    width: 68px !important;
    height: 46px !important;
    border-radius: 14px !important;
    box-shadow: 0 10px 22px rgba(15,23,42,.10) !important;
}
.download-data-table td[style*="word-break:break-all"],
.video-data-table td div[style*="font-size:12px"] {
    max-width: 320px !important;
    padding: 6px 10px !important;
    border-radius: 12px !important;
    background: #f8fafc !important;
}
#videoUploadStatus {
    display: inline-flex !important;
    align-items: center !important;
    min-height: 34px !important;
    padding: 0 10px !important;
    border-radius: 999px !important;
    background: #f8fafc !important;
    color: #64748b !important;
}
.download-manage-page .form-section,
.video-manage-page .form-section {
    border-radius: 24px !important;
}
.template-summary-grid {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
    gap: 14px !important;
}
.template-summary-card {
    position: relative !important;
    overflow: hidden !important;
    min-height: 96px !important;
    border-radius: 22px !important;
    padding: 20px !important;
    background:
        radial-gradient(circle at 92% 0%, rgba(59,130,246,.14), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 16px 34px rgba(15,23,42,.07) !important;
}
.template-summary-label {
    font-weight: 850 !important;
    letter-spacing: .05em !important;
}
.template-summary-value {
    font-size: 26px !important;
    font-weight: 950 !important;
}
.template-tab-bar {
    position: sticky !important;
    top: 0 !important;
    z-index: 7 !important;
    padding: 10px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 20px !important;
    background: rgba(255,255,255,.88) !important;
    backdrop-filter: blur(12px) !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.08) !important;
}
.template-tab-btn {
    min-height: 42px !important;
    border-radius: 14px !important;
    font-weight: 900 !important;
}
.template-tab-btn.active {
    background: linear-gradient(135deg, #1d4ed8 0%, #38bdf8 100%) !important;
    box-shadow: 0 12px 24px rgba(37,99,235,.18) !important;
}
.template-filter-block {
    padding: 16px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 22px !important;
    background: linear-gradient(180deg, #fff 0%, #fbfdff 100%) !important;
}
.template-filter-chip {
    min-height: 36px !important;
    font-weight: 850 !important;
}
.template-filter-count {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    min-width: 24px !important;
    height: 22px !important;
    padding: 0 8px !important;
    border-radius: 999px !important;
    background: #eef2ff !important;
    color: #1d4ed8 !important;
    font-size: 12px !important;
    font-weight: 950 !important;
    line-height: 1 !important;
}
.template-filter-chip.active .template-filter-count {
    background: rgba(255,255,255,.18) !important;
    color: #fff !important;
}
.template-local-grid {
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)) !important;
    gap: 18px !important;
}
.template-remote-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    gap: 16px !important;
    align-items: start !important;
}
.template-local-card,
.template-card {
    border-radius: 24px !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.07) !important;
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease !important;
}
.template-local-card:hover,
.template-card:hover {
    transform: translateY(-4px) !important;
    box-shadow: 0 24px 48px rgba(15,23,42,.11) !important;
}
.template-card.active,
.template-local-card.active {
    border-color: #2563eb !important;
    box-shadow: 0 0 0 1px rgba(37,99,235,.16), 0 20px 42px rgba(37,99,235,.12) !important;
}
.template-thumb {
    height: 160px !important;
    border-radius: 20px !important;
    margin: 12px 12px 0 !important;
    background:
        radial-gradient(circle at 88% 0%, rgba(59,130,246,.16), transparent 34%),
        linear-gradient(135deg, #f8fbff 0%, #eef4ff 100%) !important;
}
.template-card .template-thumb {
    background: #fff !important;
    width: 100% !important;
    height: auto !important;
    aspect-ratio: 16 / 9 !important;
    margin: 0 !important;
    border-radius: 24px 24px 0 0 !important;
}
.template-card .template-thumb img {
    object-fit: contain !important;
    object-position: center !important;
}
.template-card:hover .template-thumb img {
    transform: none !important;
}
.template-info {
    padding: 16px 18px 18px !important;
}
.template-name,
.template-local-name {
    font-size: 15px !important;
    font-weight: 950 !important;
    line-height: 1.45 !important;
}
.template-meta span {
    font-weight: 800 !important;
}
.template-desc {
    min-height: 42px !important;
    line-height: 1.65 !important;
    display: -webkit-box !important;
    -webkit-box-orient: vertical !important;
    -webkit-line-clamp: 2 !important;
    overflow: hidden !important;
}
.template-actions,
.template-local-actions {
    margin-top: auto !important;
}
.template-package-panel {
    padding: 18px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 24px !important;
    background:
        radial-gradient(circle at 96% 0%, rgba(14,165,233,.12), transparent 32%),
        linear-gradient(135deg, #fff 0%, #fbfdff 100%) !important;
}
.template-package-head {
    padding-bottom: 14px !important;
    border-bottom: 1px solid #eef2f7 !important;
}
.template-package-head strong {
    font-size: 18px !important;
    font-weight: 950 !important;
}
.template-package-group {
    padding: 16px !important;
    border-radius: 18px !important;
}
.template-package-check {
    min-height: 34px !important;
    padding: 6px 10px !important;
    background: #fff !important;
}
.template-package-file {
    min-height: 48px !important;
    border-radius: 16px !important;
}
.template-package-preview {
    border-radius: 20px !important;
    background: #fff !important;
    box-shadow: 0 14px 30px rgba(15,23,42,.07) !important;
}
.tag-section {
    border-radius: 22px !important;
    overflow: auto !important;
    background: #fff !important;
    box-shadow: 0 16px 36px rgba(15,23,42,.07) !important;
}
.tag-section-title {
    position: sticky !important;
    top: 0 !important;
    z-index: 3 !important;
    min-height: 54px !important;
    border-radius: 22px 22px 0 0 !important;
    background:
        radial-gradient(circle at 96% 0%, rgba(34,197,94,.16), transparent 32%),
        linear-gradient(135deg, #f0fdf4 0%, #fff 100%) !important;
    font-size: 15px !important;
}
.tag-table {
    min-width: 980px !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
}
.tag-table th {
    position: sticky !important;
    top: 54px !important;
    z-index: 2 !important;
    background: linear-gradient(180deg, #f8fbff 0%, #eef4ff 100%) !important;
    font-weight: 900 !important;
}
.tag-table td {
    line-height: 1.7 !important;
}
.tagLabel,
.tag-table .tag-label {
    display: inline-flex !important;
    max-width: 260px !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    border-radius: 999px !important;
    font-weight: 850 !important;
}
.tag-example,
.tag-table code,
.template-package-preview code {
    display: block !important;
    max-width: 100% !important;
    overflow: auto !important;
    padding: 10px 12px !important;
    border-radius: 14px !important;
    background: #0f172a !important;
    color: #86efac !important;
    line-height: 1.7 !important;
    white-space: pre-wrap !important;
    word-break: break-word !important;
}
.tag-note {
    border-radius: 999px !important;
    font-weight: 750 !important;
}
.intro-box {
    border-radius: 22px !important;
    padding: 18px 20px !important;
    background:
        radial-gradient(circle at 90% 0%, rgba(59,130,246,.14), transparent 34%),
        linear-gradient(135deg, #eff6ff 0%, #fff 100%) !important;
    box-shadow: 0 16px 34px rgba(37,99,235,.08) !important;
}
.intro-box code {
    display: inline-flex !important;
    padding: 2px 7px !important;
    border-radius: 8px !important;
    background: #dbeafe !important;
    color: #1d4ed8 !important;
}
.help-section {
    scroll-margin-top: 24px !important;
}
.help-step h3 {
    font-size: 16px !important;
    font-weight: 950 !important;
}
.help-step ul {
    line-height: 1.8 !important;
}
.site-page-overview {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)) !important;
    gap: 14px !important;
    margin: 18px 0 !important;
}
.site-overview-item,
.page-container > div[style*="grid-template-columns:repeat(auto-fit,minmax(180px,1fr))"] > .content-card {
    position: relative !important;
    overflow: hidden !important;
    padding: 18px 20px !important;
    border: 1px solid rgba(226, 232, 240, .96) !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 92% 0%, rgba(59,130,246,.14), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 16px 34px rgba(15,23,42,.07) !important;
    transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease !important;
}
.site-overview-item:hover,
.page-container > div[style*="grid-template-columns:repeat(auto-fit,minmax(180px,1fr))"] > .content-card:hover {
    transform: translateY(-2px) !important;
    border-color: #bfdbfe !important;
    box-shadow: 0 22px 44px rgba(37,99,235,.11) !important;
}
.overview-label,
.site-overview-item > div:first-child,
.page-container > div[style*="grid-template-columns:repeat(auto-fit,minmax(180px,1fr))"] > .content-card > div:first-child {
    display: block !important;
    margin-bottom: 8px !important;
    color: #64748b !important;
    font-size: 12px !important;
    font-weight: 850 !important;
    letter-spacing: .08em !important;
    text-transform: uppercase !important;
}
.overview-value,
.site-overview-item > div:last-child,
.page-container > div[style*="grid-template-columns:repeat(auto-fit,minmax(180px,1fr))"] > .content-card > div:last-child {
    color: #0f172a !important;
    font-size: 25px !important;
    font-weight: 950 !important;
    letter-spacing: -.03em !important;
}
.form-section .form-section-body > div[style*="display:flex;gap:12px;flex-wrap:wrap"] {
    align-items: center !important;
    padding: 6px !important;
    border-radius: 18px !important;
    background: #f8fafc !important;
}
.form-section .form-section-body > div[style*="display:flex;gap:12px;flex-wrap:wrap"] form {
    margin: 0 !important;
}
.form-help a,
.alert a {
    color: #1d4ed8 !important;
    font-weight: 800 !important;
    text-decoration: none !important;
}
.form-help a:hover,
.alert a:hover {
    text-decoration: underline !important;
}
.page-container .table {
    width: 100% !important;
    border-collapse: separate !important;
    border-spacing: 0 !important;
    overflow: hidden !important;
    border-radius: 18px !important;
    background: #fff !important;
}
.page-container .table th,
.page-container .table td {
    padding: 13px 16px !important;
    border-bottom: 1px solid #eef2f7 !important;
    color: #334155 !important;
    font-size: 13px !important;
    line-height: 1.65 !important;
    vertical-align: middle !important;
}
.page-container .table th {
    position: sticky !important;
    top: 0 !important;
    z-index: 1 !important;
    background: linear-gradient(180deg, #f8fbff 0%, #eef4ff 100%) !important;
    color: #475569 !important;
    font-size: 12px !important;
    font-weight: 950 !important;
}
.page-container .table tr:hover td {
    background: #fbfdff !important;
}
#autoBackupPanel {
    border-radius: 20px !important;
    padding: 18px !important;
    background:
        radial-gradient(circle at 92% 0%, rgba(34,197,94,.12), transparent 34%),
        linear-gradient(135deg, #f8fafc 0%, #fff 100%) !important;
}
#autoBackupPanel form > div[style*="grid-template-columns:1fr 1fr 1fr auto"] {
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)) !important;
}
.content-card code {
    border: 1px solid #e2e8f0 !important;
    border-radius: 10px !important;
    background: #f8fafc !important;
    color: #1e293b !important;
}
#avatarPreview,
#panelAvatarPreview {
    background:
        radial-gradient(circle at 35% 18%, rgba(59,130,246,.24), transparent 34%),
        linear-gradient(135deg, #eff6ff 0%, #fff 100%) !important;
    border: 4px solid #fff !important;
    box-shadow: 0 18px 38px rgba(37,99,235,.18) !important;
}
.panel-form-control,
#panelAvatarInput {
    min-height: 42px !important;
    border-radius: 14px !important;
    border-color: #e2e8f0 !important;
    background: #fff !important;
    transition: border-color .18s ease, box-shadow .18s ease !important;
}
.panel-form-control:focus,
#panelAvatarInput:focus {
    border-color: #2563eb !important;
    box-shadow: 0 0 0 4px rgba(37,99,235,.08) !important;
}
.panel-save-btn {
    min-height: 46px !important;
    border-radius: 16px !important;
    background: linear-gradient(135deg, #1d4ed8 0%, #38bdf8 100%) !important;
    box-shadow: 0 16px 30px rgba(37,99,235,.22) !important;
    font-weight: 900 !important;
}
.panel-password-section {
    padding: 16px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 18px !important;
    background: #f8fafc !important;
}
.page-container > form > div[style*="grid-template-columns:1fr 320px"] {
    grid-template-columns: minmax(0, 1fr) minmax(280px, 340px) !important;
    gap: 22px !important;
}
.page-container > form > div[style*="grid-template-columns:1fr 320px"] > div:last-child {
    position: sticky !important;
    top: 20px !important;
    align-self: start !important;
}
.page-container > div[style*="background:#fff"][style*="border:1px solid var(--border-light)"] {
    border: 1px solid #e2e8f0 !important;
    border-radius: 24px !important;
    background:
        radial-gradient(circle at 92% 0%, rgba(14,165,233,.13), transparent 34%),
        linear-gradient(135deg, #fff 0%, #fbfdff 100%) !important;
    box-shadow: 0 18px 42px rgba(15,23,42,.08) !important;
}
.page-container > div[style*="background:#fff"][style*="border:1px solid var(--border-light)"] h3 {
    font-weight: 950 !important;
}
.channel-admin-page .content-card {
    border-radius: 24px !important;
    overflow: auto !important;
}
.channel-admin-page .channel-table-shell {
    border-radius: 24px !important;
    overflow-x: auto !important;
}
.channel-data-table {
    min-width: 960px !important;
}
.channel-data-table th,
.channel-data-table td {
    padding-top: 14px !important;
    padding-bottom: 14px !important;
}
.channel-data-table th:last-child,
.channel-data-table td:last-child {
    width: 220px !important;
}
.channel-row-actions {
    width: auto !important;
    min-width: 0 !important;
    justify-content: flex-start !important;
    gap: 6px !important;
}
.channel-row-actions .btn {
    min-width: 58px !important;
    padding-left: 10px !important;
    padding-right: 10px !important;
}
#moveModal {
    background: rgba(15,23,42,.52) !important;
    backdrop-filter: blur(8px) !important;
    padding: 18px !important;
}
#moveModal > div {
    width: min(460px, calc(100vw - 32px)) !important;
    max-width: calc(100vw - 32px) !important;
    border: 1px solid rgba(226,232,240,.92) !important;
    border-radius: 24px !important;
    background:
        radial-gradient(circle at 90% 0%, rgba(59,130,246,.13), transparent 34%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
    box-shadow: 0 30px 80px rgba(15,23,42,.24) !important;
}
#moveModal h3 {
    font-size: 18px !important;
    font-weight: 950 !important;
}
.dashboard-fk-page .fk-workbench {
    grid-template-columns: minmax(0, 1fr) minmax(340px, 380px) !important;
    gap: 22px !important;
}
.dashboard-fk-page .fk-panel,
.dashboard-fk-page .fk-side-card,
.dashboard-fk-page .fk-site-card {
    border-radius: 26px !important;
    border: 1px solid rgba(226,232,240,.92) !important;
    box-shadow: 0 18px 42px rgba(15,23,42,.08) !important;
}
.dashboard-fk-page .fk-entry-grid {
    grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)) !important;
    gap: 10px !important;
    padding-top: 16px !important;
}
.dashboard-fk-page .fk-entry-item {
    min-height: 104px !important;
    border: 1px solid #eef2f7 !important;
    border-radius: 18px !important;
    background: #fff !important;
}
.dashboard-fk-page .fk-template-body {
    grid-template-columns: 76px minmax(0, 1fr) !important;
}
.dashboard-fk-page .fk-template-grid,
.dashboard-fk-page .fk-help-cards {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
}
.dashboard-fk-page .fk-template-shot {
    height: clamp(170px, 18vw, 230px) !important;
}
.dashboard-fk-page .fk-template-side button {
    border-radius: 16px !important;
}
.upload-preview,
#slidePreview,
#litpicPreview,
#imagePreviewBox {
    width: 100% !important;
    max-width: 420px !important;
    min-height: 180px !important;
    border-radius: 22px !important;
    background:
        radial-gradient(circle at 85% 0%, rgba(59,130,246,.14), transparent 34%),
        linear-gradient(135deg, #f8fbff 0%, #fff 100%) !important;
}
#slidePreview img,
#litpicPreview img,
#imagePreviewBox img,
.upload-preview img,
.album-item img,
.data-table img {
    max-width: 100% !important;
    object-fit: cover !important;
}
#slidePreview img,
#litpicPreview img,
.upload-preview img {
    width: 100% !important;
    height: 100% !important;
    min-height: 160px !important;
    border-radius: 18px !important;
}
.album-item {
    min-height: 126px !important;
    border-radius: 18px !important;
}
.data-table th[style*="width:250px"],
.data-table th[style*="width:280px"],
.data-table th[style*="width:300px"],
.data-table th[style*="width:330px"],
.data-table td[style*="width:250px"],
.data-table td[style*="width:280px"],
.data-table td[style*="width:300px"],
.data-table td[style*="width:330px"] {
    width: auto !important;
    min-width: 180px !important;
}
.data-table td[style*="max-width"],
.content-table td[style*="max-width"] {
    white-space: normal !important;
    line-height: 1.7 !important;
}
.btn-group {
    flex-wrap: wrap !important;
    width: auto !important;
}
.cms-ueditor-wrap,
.product-ueditor-wrap {
    border-radius: 22px !important;
    background: #fff !important;
}
.cms-ueditor-wrap .edui-editor,
.product-ueditor-wrap .edui-editor {
    border-radius: 18px !important;
    overflow: hidden !important;
    border-color: #dbe3f0 !important;
    box-shadow: 0 14px 30px rgba(15,23,42,.06) !important;
}
.cms-ueditor-wrap .edui-editor-toolbarbox,
.product-ueditor-wrap .edui-editor-toolbarbox {
    border-radius: 18px 18px 0 0 !important;
}
.channel-admin-page .channel-context-bar {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
}
.channel-admin-page .channel-toolbar {
    position: sticky !important;
    top: 0 !important;
    z-index: 8 !important;
    backdrop-filter: blur(12px) !important;
    background: rgba(255,255,255,.9) !important;
    border-radius: 22px !important;
    box-shadow: 0 14px 34px rgba(15,23,42,.07) !important;
}
.channel-data-table .channel-name-cell {
    min-width: 260px !important;
}
.channel-data-table .channel-code {
    display: inline-flex !important;
    max-width: 160px !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
}
.channel-data-table .sort-input {
    width: 72px !important;
    border-radius: 12px !important;
    font-weight: 850 !important;
}
.channel-row-actions {
    padding: 6px !important;
    border-radius: 16px !important;
    background: #f8fafc !important;
}
.channel-row-actions .btn {
    border-radius: 12px !important;
    box-shadow: none !important;
}
#moveModal .form-control {
    min-height: 46px !important;
    border-radius: 14px !important;
}
#moveModal > div > div:last-child {
    padding-top: 14px !important;
    border-top: 1px solid #eef2f7 !important;
}
.dashboard-fk-page .fk-side-col {
    position: sticky !important;
    top: 18px !important;
}
.dashboard-fk-page .fk-hero-panel {
    background:
        radial-gradient(circle at 92% 0%, rgba(56,189,248,.16), transparent 32%),
        linear-gradient(135deg, #fff 0%, #f8fbff 100%) !important;
}
.dashboard-fk-page .fk-panel-head,
.dashboard-fk-page .fk-side-head {
    min-height: 58px !important;
    padding: 18px 20px !important;
}
.dashboard-fk-page .fk-panel-tabs {
    flex-wrap: wrap !important;
}
.dashboard-fk-page .fk-panel-tabs button,
.dashboard-fk-page .fk-panel-link,
.dashboard-fk-page .fk-site-open {
    border-radius: 999px !important;
}
.dashboard-fk-page .fk-help-search {
    padding: 8px !important;
    border-radius: 18px !important;
    background: #f8fafc !important;
}
.dashboard-fk-page .fk-help-search input {
    min-height: 38px !important;
}
.dashboard-fk-page .fk-service-box {
    grid-template-columns: minmax(110px, 138px) minmax(0, 1fr) !important;
    align-items: center !important;
}
.dashboard-fk-page .fk-qr-box {
    border-radius: 24px !important;
    box-shadow: 0 18px 38px rgba(15,23,42,.10) !important;
}
.dashboard-fk-page .fk-template-card strong {
    min-height: 58px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
}
#slidePreview,
#litpicPreview,
#imagePreviewBox,
#thumbPreview,
#logoPreview {
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    overflow: hidden !important;
}
#thumbPreview {
    width: 112px !important;
    height: 112px !important;
    border-radius: 24px !important;
    background:
        radial-gradient(circle at 80% 0%, rgba(59,130,246,.14), transparent 34%),
        linear-gradient(135deg, #f8fbff 0%, #fff 100%) !important;
}
#logoPreview img,
#thumbPreview img,
#slidePreview img,
#litpicPreview img,
#imagePreviewBox img,
#albumsList img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    max-height: none !important;
    object-fit: cover !important;
}
#albumsList .album-item {
    aspect-ratio: 4 / 3 !important;
    height: auto !important;
    min-height: 118px !important;
}
#albumsList .album-item button {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    top: 8px !important;
    right: 8px !important;
}
.filter-bar input[style*="width:"],
.filter-bar select[style*="width:"],
.article-filter-form input[style*="width:"],
.product-filter-form input[style*="width:"],
.content-card form input[style*="width:220px"],
.content-card form input[style*="width:240px"],
.content-card form input[style*="width:260px"] {
    width: clamp(180px, 24vw, 280px) !important;
}
.data-table th[style*="width:200px"],
.data-table th[style*="width:220px"],
.data-table th[style*="width:230px"],
.data-table th[style*="width:240px"],
.data-table th[style*="width:250px"],
.data-table th[style*="width:260px"],
.data-table th[style*="width:280px"],
.data-table th[style*="width:320px"],
.data-table th[style*="width:330px"],
.data-table td[style*="width:200px"],
.data-table td[style*="width:220px"],
.data-table td[style*="width:230px"],
.data-table td[style*="width:240px"],
.data-table td[style*="width:250px"],
.data-table td[style*="width:260px"],
.data-table td[style*="width:280px"],
.data-table td[style*="width:320px"],
.data-table td[style*="width:330px"] {
    width: auto !important;
}
.data-table th:last-child,
.data-table td:last-child {
    min-width: 170px !important;
}
.data-table td:last-child .btn-group,
.data-table td:last-child [class*="actions"] {
    justify-content: flex-end !important;
}
.data-table td[style*="word-break:break-all"],
.data-table td[style*="word-break:break-word"] {
    max-width: 340px !important;
}
.cms-ueditor-wrap::before,
.product-ueditor-wrap::before {
    content: "内容编辑区";
    display: inline-flex;
    margin: 0 0 10px;
    padding: 5px 10px;
    border-radius: 999px;
    background: #eff6ff;
    color: #1d4ed8;
    font-size: 12px;
    font-weight: 900;
}
.cms-ueditor-wrap .edui-editor-toolbarboxouter,
.product-ueditor-wrap .edui-editor-toolbarboxouter {
    background: linear-gradient(180deg, #f8fbff 0%, #eef4ff 100%) !important;
}
.cms-ueditor-wrap .edui-editor-iframeholder,
.product-ueditor-wrap .edui-editor-iframeholder {
    min-height: 360px !important;
}
.cms-ueditor-wrap textarea,
.product-ueditor-wrap textarea {
    border-radius: 16px !important;
}
/* Flat professional dashboard v0 */
body .dashboard-fk-page {
    max-width: 1680px !important;
    margin: 0 auto !important;
    padding: 18px !important;
    background: #f5f7fa !important;
    color: #172033 !important;
}
.dashboard-fk-page .fk-dashboard-head {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 20px !important;
    margin-bottom: 12px !important;
    padding: 20px 22px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 10px !important;
    background: #fff !important;
    box-shadow: none !important;
}
.dashboard-fk-page .fk-dashboard-eyebrow {
    display: block !important;
    margin-bottom: 5px !important;
    color: #2563eb !important;
    font-size: 11px !important;
    font-weight: 800 !important;
    letter-spacing: .08em !important;
}
.dashboard-fk-page .fk-dashboard-head h1 {
    margin: 0 !important;
    color: #172033 !important;
    font-size: 24px !important;
    font-weight: 800 !important;
    line-height: 1.3 !important;
}
.dashboard-fk-page .fk-dashboard-head p {
    margin: 5px 0 0 !important;
    color: #64748b !important;
    font-size: 12px !important;
}
.dashboard-fk-page .fk-dashboard-actions {
    display: flex !important;
    align-items: center !important;
    gap: 8px !important;
    flex-wrap: wrap !important;
}
.dashboard-fk-page .fk-flat-btn {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    min-height: 34px !important;
    padding: 0 12px !important;
    border: 1px solid #dbe3ee !important;
    border-radius: 6px !important;
    background: #fff !important;
    color: #475569 !important;
    font-size: 12px !important;
    font-weight: 700 !important;
    box-shadow: none !important;
}
.dashboard-fk-page .fk-flat-btn:hover {
    border-color: #93c5fd !important;
    color: #1d4ed8 !important;
    background: #f8fbff !important;
}
.dashboard-fk-page .fk-flat-btn-primary,
.dashboard-fk-page .fk-flat-btn-primary:hover {
    border-color: #2563eb !important;
    background: #2563eb !important;
    color: #fff !important;
}
.dashboard-fk-page .fk-metric-grid {
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    gap: 10px !important;
    margin-bottom: 12px !important;
}
.dashboard-fk-page .fk-metric-card {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) auto !important;
    grid-template-rows: auto auto !important;
    align-items: end !important;
    gap: 3px 12px !important;
    min-height: 86px !important;
    padding: 15px 16px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 8px !important;
    background: #fff !important;
    box-shadow: none !important;
    transition: border-color .14s ease, background-color .14s ease !important;
}
.dashboard-fk-page .fk-metric-card:hover {
    border-color: #bfdbfe !important;
    background: #fbfdff !important;
    transform: none !important;
}
.dashboard-fk-page .fk-metric-card span {
    grid-column: 1 !important;
    color: #64748b !important;
    font-size: 12px !important;
    font-weight: 700 !important;
}
.dashboard-fk-page .fk-metric-card strong {
    grid-column: 2 !important;
    grid-row: 1 / span 2 !important;
    align-self: center !important;
    color: #172033 !important;
    font-size: 28px !important;
    font-weight: 800 !important;
    line-height: 1 !important;
}
.dashboard-fk-page .fk-metric-card small {
    grid-column: 1 !important;
    color: #94a3b8 !important;
    font-size: 11px !important;
}
.dashboard-fk-page .fk-workbench {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) 320px !important;
    gap: 12px !important;
    align-items: start !important;
}
.dashboard-fk-page .fk-main-col,
.dashboard-fk-page .fk-side-col {
    gap: 12px !important;
}
.dashboard-fk-page .fk-side-col {
    position: sticky !important;
    top: 12px !important;
}
.dashboard-fk-page .fk-panel,
.dashboard-fk-page .fk-side-card,
.dashboard-fk-page .fk-site-card,
.dashboard-fk-page .fk-scene-card,
.dashboard-fk-page .fk-template-card,
.dashboard-fk-page .fk-help-card {
    border: 1px solid #e2e8f0 !important;
    border-radius: 8px !important;
    background: #fff !important;
    box-shadow: none !important;
}
.dashboard-fk-page .fk-panel {
    overflow: hidden !important;
    transform: none !important;
}
.dashboard-fk-page .fk-panel::before,
.dashboard-fk-page .fk-scene-card::before,
.dashboard-fk-page .fk-scene-card::after,
.dashboard-fk-page .fk-promo-card::after {
    display: none !important;
}
.dashboard-fk-page .fk-panel:hover,
.dashboard-fk-page .fk-scene-card:hover,
.dashboard-fk-page .fk-template-card:hover,
.dashboard-fk-page .fk-entry-item:hover,
.dashboard-fk-page .fk-help-card:hover {
    transform: none !important;
    box-shadow: none !important;
}
.dashboard-fk-page .fk-hero-panel {
    padding: 14px !important;
}
.dashboard-fk-page .fk-hero-grid {
    display: grid !important;
    grid-template-columns: repeat(2, minmax(0, 1fr)) minmax(260px, .9fr) !important;
    gap: 10px !important;
}
.dashboard-fk-page .fk-scene-card,
.dashboard-fk-page .fk-site-card {
    min-height: 150px !important;
}
.dashboard-fk-page .fk-scene-card {
    padding: 20px !important;
    color: #172033 !important;
}
.dashboard-fk-page .fk-scene-card-desktop,
.dashboard-fk-page .fk-scene-card-mobile {
    background: #fff !important;
}
.dashboard-fk-page .fk-scene-icon {
    width: 34px !important;
    height: 34px !important;
    border-radius: 7px !important;
    background: #eff6ff !important;
    color: #2563eb !important;
}
.dashboard-fk-page .fk-scene-copy strong {
    margin-bottom: 5px !important;
    color: #172033 !important;
    font-size: 16px !important;
}
.dashboard-fk-page .fk-scene-copy span {
    color: #64748b !important;
    font-size: 12px !important;
    line-height: 1.65 !important;
}
.dashboard-fk-page .fk-scene-copy em {
    margin-top: 10px !important;
    padding: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    color: #2563eb !important;
    font-size: 12px !important;
}
.dashboard-fk-page .fk-site-card {
    padding: 18px !important;
    background: #f8fafc !important;
}
.dashboard-fk-page .fk-site-head h3 { font-size: 15px !important; }
.dashboard-fk-page .fk-site-head p { margin-top: 5px !important; font-size: 11px !important; }
.dashboard-fk-page .fk-site-open {
    min-width: 54px !important;
    height: 30px !important;
    border: 1px solid #dbeafe !important;
    border-radius: 6px !important;
    background: #eff6ff !important;
    color: #2563eb !important;
    font-size: 11px !important;
}
.dashboard-fk-page .fk-domain-form { margin-top: 12px !important; }
.dashboard-fk-page .fk-domain-input,
.dashboard-fk-page .fk-domain-form button {
    height: 34px !important;
    border-radius: 6px !important;
    background: #fff !important;
}
.dashboard-fk-page .fk-upgrade-pill {
    margin-top: 10px !important;
    padding: 8px 10px !important;
    border: 1px solid #fde68a !important;
    border-radius: 6px !important;
    background: #fffbeb !important;
    color: #92400e !important;
}
.dashboard-fk-page .fk-entry-grid {
    grid-template-columns: repeat(5, minmax(0, 1fr)) !important;
    gap: 0 !important;
    margin-top: 14px !important;
    border: 1px solid #e2e8f0 !important;
    border-radius: 8px !important;
    overflow: hidden !important;
}
.dashboard-fk-page .fk-entry-item {
    min-height: 72px !important;
    flex-direction: row !important;
    gap: 8px !important;
    padding: 10px !important;
    border-right: 1px solid #edf2f7 !important;
    border-bottom: 1px solid #edf2f7 !important;
    color: #334155 !important;
}
.dashboard-fk-page .fk-entry-icon {
    width: 30px !important;
    height: 30px !important;
    flex: 0 0 30px !important;
    border-radius: 6px !important;
    background: #f1f5f9 !important;
    color: #2563eb !important;
}
.dashboard-fk-page .fk-entry-icon svg { width: 17px !important; height: 17px !important; }
.dashboard-fk-page .fk-entry-item span:last-child { font-size: 12px !important; }
.dashboard-fk-page .fk-pro-tag { padding: 1px 4px !important; border-radius: 4px !important; font-size: 9px !important; }
.dashboard-fk-page .fk-panel-head,
.dashboard-fk-page .fk-feature-head,
.dashboard-fk-page .fk-side-head {
    min-height: 48px !important;
    padding: 12px 14px !important;
    border-bottom: 1px solid #e2e8f0 !important;
}
.dashboard-fk-page .fk-template-body { grid-template-columns: 58px minmax(0, 1fr) !important; min-height: 310px !important; }
.dashboard-fk-page .fk-template-side { background: #f8fafc !important; border-right-color: #e2e8f0 !important; }
.dashboard-fk-page .fk-template-side button { font-size: 13px !important; }
.dashboard-fk-page .fk-template-grid { padding: 14px !important; gap: 10px !important; }
.dashboard-fk-page .fk-template-shot { height: 190px !important; min-height: 0 !important; background: #f8fafc !important; }
.dashboard-fk-page .fk-template-card strong { padding: 11px !important; font-size: 12px !important; }
.dashboard-fk-page .fk-template-badge { border-radius: 4px !important; background: #2563eb !important; font-size: 10px !important; }
.dashboard-fk-page .fk-seo-list { gap: 0 !important; padding: 0 !important; }
.dashboard-fk-page .fk-seo-row {
    min-height: 54px !important;
    padding: 0 14px !important;
    border: 0 !important;
    border-bottom: 1px solid #edf2f7 !important;
    border-radius: 0 !important;
    background: #fff !important;
}
.dashboard-fk-page .fk-promo-card {
    min-height: 112px !important;
    margin: 14px 14px 0 !important;
    padding: 18px !important;
    border-radius: 8px !important;
    background: #172033 !important;
    color: #fff !important;
}
.dashboard-fk-page .fk-promo-copy strong { font-size: 20px !important; letter-spacing: 0 !important; }
.dashboard-fk-page .fk-promo-copy span { margin-top: 6px !important; font-size: 12px !important; line-height: 1.6 !important; }
.dashboard-fk-page .fk-feature-list { margin-top: 14px !important; }
.dashboard-fk-page .fk-feature-row { min-height: 40px !important; padding: 0 14px !important; }
.dashboard-fk-page .fk-feature-row span { font-size: 12px !important; }
.dashboard-fk-page .fk-help-search { margin: 12px 14px 0 !important; height: 36px !important; border-radius: 6px !important; }
.dashboard-fk-page .fk-help-cards { grid-template-columns: 1fr !important; padding: 10px 14px 14px !important; gap: 6px !important; }
.dashboard-fk-page .fk-help-card {
    min-height: 44px !important;
    padding: 10px 12px !important;
    flex-direction: row !important;
    align-items: center !important;
    background: #f8fafc !important;
}
.dashboard-fk-page .fk-help-card span { font-size: 12px !important; }
.dashboard-fk-page .fk-service-box { grid-template-columns: 88px minmax(0, 1fr) !important; gap: 12px !important; padding: 14px !important; }
.dashboard-fk-page .fk-qr-box { width: 88px !important; height: 88px !important; padding: 7px !important; border-radius: 6px !important; }
.dashboard-fk-page .fk-service-copy { gap: 5px !important; }
.dashboard-fk-page .fk-service-copy strong { font-size: 13px !important; }
.dashboard-fk-page .fk-service-copy span { font-size: 11px !important; }
.dashboard-fk-page .fk-runtime-list { padding: 8px 14px 14px !important; gap: 0 !important; }
.dashboard-fk-page .fk-runtime-row {
    margin: 0 !important;
    padding: 8px 0 !important;
    border: 0 !important;
    border-bottom: 1px solid #edf2f7 !important;
    border-radius: 0 !important;
    background: transparent !important;
    font-size: 11px !important;
}
.dashboard-fk-page .fk-section-heading {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    margin: 0 0 12px !important;
}
.dashboard-fk-page .fk-section-heading-apps {
    margin: 14px 0 9px !important;
    padding-top: 14px !important;
    border-top: 1px solid #e2e8f0 !important;
}
.dashboard-fk-page .fk-section-heading strong,
.dashboard-fk-page .fk-panel-title strong {
    display: block !important;
    color: #172033 !important;
    font-size: 14px !important;
    font-weight: 800 !important;
}
.dashboard-fk-page .fk-section-heading span,
.dashboard-fk-page .fk-panel-title span {
    display: block !important;
    margin-top: 3px !important;
    color: #94a3b8 !important;
    font-size: 11px !important;
}
.dashboard-fk-page .fk-template-body {
    display: block !important;
    min-height: 0 !important;
}
.dashboard-fk-page .fk-template-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
}
.dashboard-fk-page .fk-template-empty {
    display: flex !important;
    min-height: 180px !important;
    padding: 28px !important;
    align-items: center !important;
    justify-content: center !important;
    flex-direction: column !important;
    text-align: center !important;
    background: #f8fafc !important;
}
.dashboard-fk-page .fk-template-empty strong {
    color: #334155 !important;
    font-size: 14px !important;
}
.dashboard-fk-page .fk-template-empty span {
    max-width: 520px !important;
    margin-top: 6px !important;
    color: #94a3b8 !important;
    font-size: 12px !important;
    line-height: 1.6 !important;
}
.dashboard-fk-page .fk-template-empty a {
    margin-top: 12px !important;
    padding: 7px 11px !important;
    border: 1px solid #bfdbfe !important;
    border-radius: 6px !important;
    background: #eff6ff !important;
    color: #1d4ed8 !important;
    font-size: 12px !important;
    font-weight: 700 !important;
}
.dashboard-fk-page .fk-side-head > span {
    color: #94a3b8 !important;
    font-size: 10px !important;
}
.dashboard-fk-page .fk-todo-list {
    display: grid !important;
}
.dashboard-fk-page .fk-todo-row {
    display: flex !important;
    min-height: 48px !important;
    padding: 0 14px !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 12px !important;
    border-bottom: 1px solid #edf2f7 !important;
    background: #fff !important;
}
.dashboard-fk-page .fk-todo-row:last-child {
    border-bottom: 0 !important;
}
.dashboard-fk-page .fk-todo-row:hover {
    background: #f8fbff !important;
}
.dashboard-fk-page .fk-todo-row > span {
    color: #475569 !important;
    font-size: 12px !important;
}
.dashboard-fk-page .fk-todo-row > strong {
    color: #172033 !important;
    font-size: 16px !important;
    font-weight: 800 !important;
}
.dashboard-fk-page .fk-todo-row small {
    margin-left: 3px !important;
    color: #94a3b8 !important;
    font-size: 10px !important;
    font-weight: 600 !important;
}
.dashboard-fk-page .fk-runtime-row {
    display: flex !important;
    align-items: center !important;
    justify-content: space-between !important;
    gap: 12px !important;
}
.dashboard-fk-page .fk-runtime-row span {
    color: #94a3b8 !important;
}
.dashboard-fk-page .fk-runtime-row strong {
    min-width: 0 !important;
    overflow: hidden !important;
    color: #334155 !important;
    font-size: 11px !important;
    font-weight: 700 !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
}
@media (max-width: 1180px) {
    .dashboard-fk-page .fk-workbench { grid-template-columns: 1fr !important; }
    .dashboard-fk-page .fk-side-col { position: static !important; display: grid !important; grid-template-columns: repeat(3, minmax(0,1fr)) !important; }
}
@media (max-width: 900px) {
    .dashboard-fk-page .fk-metric-grid { grid-template-columns: repeat(2, minmax(0,1fr)) !important; }
    .dashboard-fk-page .fk-hero-grid { grid-template-columns: 1fr !important; }
    .dashboard-fk-page .fk-side-col { grid-template-columns: 1fr !important; }
    .dashboard-fk-page .fk-entry-grid { grid-template-columns: repeat(2, minmax(0,1fr)) !important; }
}
/* Flat enterprise components: final visual layer, behavior remains untouched. */
:root {
    --cms-flat-bg: #f5f7fa;
    --cms-flat-surface: #ffffff;
    --cms-flat-soft: #f8fafc;
    --cms-flat-line: #e2e8f0;
    --cms-flat-line-strong: #cbd5e1;
    --cms-flat-text: #172033;
    --cms-flat-muted: #64748b;
    --cms-flat-brand: #2563eb;
}
html,
body {
    background: var(--cms-flat-bg) !important;
    color: var(--cms-flat-text) !important;
}
.page-container {
    max-width: 1680px !important;
    margin: 0 auto !important;
    padding: 18px !important;
}
.page-header {
    min-height: 64px !important;
    margin-bottom: 12px !important;
    padding: 14px 16px !important;
    overflow: visible !important;
    border: 1px solid var(--cms-flat-line) !important;
    border-radius: 8px !important;
    background: var(--cms-flat-surface) !important;
    box-shadow: none !important;
}
.page-header::before,
.page-header::after {
    display: none !important;
}
.page-header h1,
.page-header h2,
.page-header h3,
.page-header p,
.page-header .page-title,
.page-header .page-title h1,
.page-header .page-title p {
    color: var(--cms-flat-text) !important;
    text-shadow: none !important;
}
.page-header .page-title h1 {
    font-size: 20px !important;
    font-weight: 800 !important;
    letter-spacing: 0 !important;
}
.page-header .page-title p,
.page-header p {
    color: var(--cms-flat-muted) !important;
    opacity: 1 !important;
}
.page-icon {
    width: 34px !important;
    height: 34px !important;
    border: 1px solid #dbeafe !important;
    border-radius: 7px !important;
    background: #eff6ff !important;
    color: var(--cms-flat-brand) !important;
    box-shadow: none !important;
}
.content-card,
.form-section,
.filter-bar,
.template-card,
.template-local-card,
.template-summary-card,
.channel-sidebar,
.content-overview-head,
.content-topbar,
.content-list-wrapper,
.health-card,
.notification-list,
.task-card {
    border: 1px solid var(--cms-flat-line) !important;
    border-radius: 8px !important;
    background: var(--cms-flat-surface) !important;
    box-shadow: none !important;
}
.filter-bar {
    margin-bottom: 10px !important;
    padding: 10px 12px !important;
}
.form-section-header,
.content-card-header,
.card-header {
    min-height: 44px !important;
    padding: 11px 14px !important;
    border-bottom: 1px solid var(--cms-flat-line) !important;
    background: var(--cms-flat-soft) !important;
    color: #334155 !important;
}
.form-section-body {
    padding: 16px !important;
}
.btn,
button.btn,
a.btn {
    min-height: 32px !important;
    padding: 6px 11px !important;
    border-radius: 6px !important;
    box-shadow: none !important;
    font-size: 12px !important;
    font-weight: 700 !important;
    transform: none !important;
    transition: background-color .14s ease, border-color .14s ease, color .14s ease !important;
}
.btn-primary,
.btn-success,
button.btn-primary,
a.btn-primary {
    border-color: var(--cms-flat-brand) !important;
    background: var(--cms-flat-brand) !important;
    color: #fff !important;
}
.btn-primary:hover,
.btn-success:hover {
    border-color: #1d4ed8 !important;
    background: #1d4ed8 !important;
}
.btn-secondary,
.btn-ghost {
    border-color: var(--cms-flat-line-strong) !important;
    background: #fff !important;
    color: #475569 !important;
}
.btn-secondary:hover,
.btn-ghost:hover {
    border-color: #93c5fd !important;
    background: #f8fbff !important;
    color: #1d4ed8 !important;
}
.btn-danger {
    border-color: #fecaca !important;
    background: #fff !important;
    color: #dc2626 !important;
}
.form-control,
input[type="text"],
input[type="search"],
input[type="number"],
input[type="password"],
input[type="url"],
select,
textarea {
    border-color: var(--cms-flat-line-strong) !important;
    border-radius: 6px !important;
    background: #fff !important;
    box-shadow: none !important;
}
.form-control:focus,
input:focus,
select:focus,
textarea:focus {
    border-color: #60a5fa !important;
    box-shadow: 0 0 0 3px rgba(37,99,235,.10) !important;
}
.data-table {
    border-collapse: separate !important;
    border-spacing: 0 !important;
    background: #fff !important;
}
.data-table thead th {
    height: 42px !important;
    padding-top: 9px !important;
    padding-bottom: 9px !important;
    border-bottom: 1px solid var(--cms-flat-line) !important;
    background: var(--cms-flat-soft) !important;
    color: #64748b !important;
    font-size: 11px !important;
    font-weight: 800 !important;
    letter-spacing: .02em !important;
}
.data-table tbody td {
    padding-top: 10px !important;
    padding-bottom: 10px !important;
    border-bottom-color: #edf2f7 !important;
}
.data-table tbody tr:hover {
    background: #f8fbff !important;
}
.data-table img {
    border-radius: 5px !important;
    box-shadow: none !important;
}
.article-subnav,
.cms-workflow-nav {
    gap: 6px !important;
    margin-bottom: 10px !important;
}
.article-subnav-link,
.cms-workflow-link {
    min-height: 34px !important;
    padding: 7px 11px !important;
    border-radius: 6px !important;
    background: #fff !important;
    color: #64748b !important;
    font-size: 12px !important;
    box-shadow: none !important;
}
.article-subnav-link.is-active,
.cms-workflow-link.is-active {
    border-color: #bfdbfe !important;
    background: #eff6ff !important;
    color: #1d4ed8 !important;
}
.badge,
[class*="badge-"] {
    border-radius: 4px !important;
    box-shadow: none !important;
}
.pagination {
    gap: 4px !important;
    margin-top: 10px !important;
}
.pagination a,
.pagination span {
    min-width: 32px !important;
    height: 32px !important;
    border-radius: 5px !important;
    box-shadow: none !important;
}
.modal-content,
.dialog-card,
.yt-ship-modal-card {
    border: 1px solid var(--cms-flat-line) !important;
    border-radius: 10px !important;
    background: #fff !important;
    box-shadow: 0 18px 44px rgba(15,23,42,.14) !important;
}
.empty-state {
    padding: 48px 20px !important;
}
.empty-icon {
    border-radius: 8px !important;
    background: #f1f5f9 !important;
    box-shadow: none !important;
}
/* Readable typography and refined controls */
body {
    font-size: 14px !important;
    line-height: 1.6 !important;
}
.page-header .page-title h1 {
    font-size: 22px !important;
    line-height: 1.35 !important;
}
.page-header .page-title p,
.page-header p {
    font-size: 13px !important;
    line-height: 1.55 !important;
}
.content-card h2,
.content-card h3,
.form-section-header {
    font-size: 15px !important;
}
.form-group label,
.form-label,
label.form-label {
    color: #475569 !important;
    font-size: 13px !important;
    font-weight: 700 !important;
}
.form-control,
input[type="text"],
input[type="search"],
input[type="number"],
input[type="password"],
input[type="url"],
select {
    min-height: 38px !important;
    font-size: 14px !important;
}
textarea {
    font-size: 14px !important;
    line-height: 1.65 !important;
}
.btn,
button.btn,
a.btn {
    min-height: 36px !important;
    padding: 7px 13px !important;
    font-size: 13px !important;
    line-height: 20px !important;
}
.btn-primary,
.btn-success,
button.btn-primary,
a.btn-primary {
    box-shadow: 0 2px 6px rgba(37,99,235,.18) !important;
}
.btn-primary:hover,
.btn-success:hover {
    box-shadow: 0 4px 10px rgba(37,99,235,.22) !important;
    transform: translateY(-1px) !important;
}
.btn-secondary,
.btn-ghost {
    background: #f8fafc !important;
}
.btn-danger {
    background: #fff7f7 !important;
}
.btn-sm,
.data-table .btn,
.btn-group .btn {
    min-height: 31px !important;
    padding: 5px 9px !important;
    font-size: 12px !important;
    line-height: 19px !important;
}
.data-table thead th {
    font-size: 12px !important;
    line-height: 1.45 !important;
}
.data-table tbody td {
    color: #334155 !important;
    font-size: 13px !important;
    line-height: 1.55 !important;
}
.article-subnav-link,
.cms-workflow-link {
    min-height: 36px !important;
    padding: 8px 12px !important;
    font-size: 13px !important;
}
.badge,
[class*="badge-"] {
    padding: 4px 7px !important;
    font-size: 11px !important;
    line-height: 1.35 !important;
}
.dashboard-fk-page .fk-dashboard-head h1 {
    font-size: 26px !important;
}
.dashboard-fk-page .fk-dashboard-head p,
.dashboard-fk-page .fk-dashboard-eyebrow {
    font-size: 12px !important;
}
.dashboard-fk-page .fk-metric-card span {
    font-size: 13px !important;
}
.dashboard-fk-page .fk-metric-card strong {
    font-size: 30px !important;
}
.dashboard-fk-page .fk-metric-card small,
.dashboard-fk-page .fk-section-heading span,
.dashboard-fk-page .fk-panel-title span {
    font-size: 12px !important;
}
.dashboard-fk-page .fk-section-heading strong,
.dashboard-fk-page .fk-panel-title strong,
.dashboard-fk-page .fk-side-head strong {
    font-size: 15px !important;
}
.dashboard-fk-page .fk-scene-copy strong {
    font-size: 17px !important;
}
.dashboard-fk-page .fk-scene-copy span,
.dashboard-fk-page .fk-entry-item span:last-child,
.dashboard-fk-page .fk-todo-row > span,
.dashboard-fk-page .fk-help-card span {
    font-size: 13px !important;
}
.dashboard-fk-page .fk-runtime-row,
.dashboard-fk-page .fk-runtime-row strong {
    font-size: 12px !important;
}
@media (max-width: 768px) {
    .page-container { padding: 14px !important; }
    .page-header { padding: 14px !important; border-radius: 8px !important; }
    .dashboard-fk-page .fk-workbench { grid-template-columns: 1fr !important; }
    .dashboard-fk-page .fk-entry-grid { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .form-actions { margin: 18px -14px -14px !important; padding: 14px !important; }
    .page-container > form > div[style*="grid-template-columns:minmax(0,1fr)"] > div:last-child {
        position: static !important;
    }
    .article-filter-form::before,
    .product-filter-form::before {
        width: 100%;
    }
    .page-context-bar,
    .yt-ship-stats,
    .yt-refund-stats,
    .yt-review-stats,
    .card-grid {
        grid-template-columns: 1fr !important;
    }
    .content-card > .data-table {
        min-width: 820px !important;
    }
    .content-card > form.filter-bar,
    .content-card[style*="padding:16px"] > form,
    .filter-bar form {
        align-items: stretch !important;
    }
    .content-card > form.filter-bar input,
    .content-card > form.filter-bar select,
    .content-card > form.filter-bar .btn,
    .content-card[style*="padding:16px"] > form input,
    .content-card[style*="padding:16px"] > form select,
    .content-card[style*="padding:16px"] > form .btn {
        width: 100% !important;
    }
    .page-header {
        align-items: stretch !important;
        flex-direction: column !important;
    }
    .page-header .page-actions,
    .page-header .header-actions {
        width: 100% !important;
    }
    .page-header .page-actions .btn,
    .page-header .header-actions .btn {
        flex: 1 1 auto !important;
    }
    .content-card > .data-table,
    .content-card table.data-table {
        min-width: 720px !important;
    }
    .site-tabs {
        position: static !important;
    }
    .site-tab {
        width: 100% !important;
    }
    .channel-toolbar {
        align-items: stretch !important;
    }
    .channel-sort-mode,
    .channel-sort-option {
        width: 100% !important;
    }
    .channel-sort-option {
        justify-content: center !important;
    }
    .channel-data-table {
        min-width: 860px !important;
    }
    .channel-row-actions {
        justify-content: flex-start !important;
    }
    .dashboard-fk-page .fk-workbench,
    .dashboard-fk-page .fk-template-body {
        grid-template-columns: 1fr !important;
    }
    .dashboard-fk-page .fk-side-col {
        position: static !important;
    }
    .dashboard-fk-page .fk-service-box {
        grid-template-columns: 1fr !important;
    }
    .dashboard-fk-page .fk-template-side {
        flex-direction: row !important;
    }
    .dashboard-fk-page .fk-template-side button {
        writing-mode: initial !important;
        text-orientation: initial !important;
        letter-spacing: 0 !important;
    }
    .upload-preview,
    #slidePreview,
    #litpicPreview,
    #imagePreviewBox,
    #logoPreview {
        max-width: 100% !important;
    }
    .filter-bar input[style*="width:"],
    .filter-bar select[style*="width:"],
    .article-filter-form input[style*="width:"],
    .product-filter-form input[style*="width:"],
    .content-card form input[style*="width:220px"],
    .content-card form input[style*="width:240px"],
    .content-card form input[style*="width:260px"] {
        width: 100% !important;
    }
    .data-table td:last-child .btn-group,
    .data-table td:last-child [class*="actions"] {
        justify-content: flex-start !important;
    }
    #typeImage div[style*="grid-template-columns:240px 1fr"],
    .page-container div[style*="grid-template-columns:240px 1fr"] {
        grid-template-columns: 1fr !important;
    }
    #imagePreviewBox,
    #slidePreview,
    #litpicPreview {
        min-height: 180px !important;
    }
    #albumsList {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }
    .template-tab-bar {
        position: static !important;
    }
    .template-tab-btn,
    .template-filter-chip {
        flex: 1 1 auto !important;
    }
    .template-local-grid,
    .template-remote-grid {
        grid-template-columns: 1fr !important;
    }
    .tag-section-title {
        position: static !important;
    }
    .tag-table th {
        position: static !important;
    }
    .modal-content,
    .yt-ship-modal-card {
        width: calc(100vw - 28px) !important;
        max-width: calc(100vw - 28px) !important;
    }
    [class$="-context-bar"],
    .help-layout,
    .help-panel > div[style*="grid-template-columns"] {
        grid-template-columns: 1fr !important;
    }
    .help-nav {
        position: static !important;
    }
    .help-step {
        grid-template-columns: 1fr !important;
    }
    .page-container > form > div[style*="grid-template-columns:1fr 320px"] {
        grid-template-columns: 1fr !important;
    }
    .page-container > form > div[style*="grid-template-columns:1fr 320px"] > div:last-child {
        position: static !important;
    }
    .site-page-overview {
        grid-template-columns: 1fr !important;
    }
}
</style>
<link rel="stylesheet" href="/public/css/admin-content-polish.css?v=<?php echo @filemtime(ROOT_PATH . 'public/css/admin-content-polish.css'); ?>">
<link rel="stylesheet" href="/public/css/admin-enterprise-content.css?v=<?php echo @filemtime(ROOT_PATH . 'public/css/admin-enterprise-content.css'); ?>">
<link rel="stylesheet" href="/public/css/cms-ueditor.css?v=<?php echo @filemtime(ROOT_PATH . 'public/css/cms-ueditor.css'); ?>">
<?php
ob_end_flush();
if (!isset($license) || !is_object($license)) {
    $license = new \Core\Lib\License();
}
if (is_object($license)) {
    $licStatus = $license->getStatus();
    if (!$licStatus['can_remove_copyright']): ?>
<div style="background:#f8fafc;border-top:1px solid #e2e8f0;padding:12px 20px;text-align:center;font-size:12px;color:#94a3b8;">
    芋头CMS <?php echo htmlspecialchars($licStatus['level_name']); ?> | <a href="http://www.yutoucms.cn" target="_blank" style="color:#94a3b8;text-decoration:none;">Powered by yutoucms</a>
</div>
    <?php endif;
} else {
    echo '<div style="background:#f8fafc;border-top:1px solid #e2e8f0;padding:12px 20px;text-align:center;font-size:12px;color:#94a3b8;">芋头CMS | <a href="http://www.yutoucms.cn" target="_blank" style="color:#94a3b8;text-decoration:none;">Powered by yutoucms</a></div>';
}
?>
<script>
(function () {
    var token = <?php echo json_encode(getAdminCsrfToken(), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
    if (!token) return;

    function isSameOrigin(url) {
        try {
            return new URL(url || window.location.href, window.location.href).origin === window.location.origin;
        } catch (error) {
            return false;
        }
    }

    document.addEventListener('submit', function (event) {
        var form = event.target;
        if (!form || String(form.method || 'get').toLowerCase() !== 'post') return;
        if (!isSameOrigin(form.action)) return;
        if (!form.querySelector('input[name="csrf_token"]')) {
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'csrf_token';
            input.value = token;
            form.appendChild(input);
        }
    }, true);

    if (window.fetch) {
        var originalFetch = window.fetch;
        window.fetch = function (input, init) {
            init = init || {};
            var method = String(init.method || (input && input.method) || 'GET').toUpperCase();
            var requestUrl = typeof input === 'string' ? input : (input && input.url);
            if (method === 'POST' && isSameOrigin(requestUrl)) {
                var headers = new Headers(init.headers || {});
                headers.set('X-CSRF-Token', token);
                init.headers = headers;
                if (init.body instanceof FormData && !init.body.has('csrf_token')) {
                    init.body.append('csrf_token', token);
                }
            }
            return originalFetch.call(this, input, init);
        };
    }

    var originalOpen = XMLHttpRequest.prototype.open;
    var originalSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.open = function (method, url) {
        this.__cmsMethod = String(method || 'GET').toUpperCase();
        this.__cmsSameOrigin = isSameOrigin(url);
        return originalOpen.apply(this, arguments);
    };
    XMLHttpRequest.prototype.send = function (body) {
        if (this.__cmsMethod === 'POST' && this.__cmsSameOrigin) {
            this.setRequestHeader('X-CSRF-Token', token);
            if (body instanceof FormData && !body.has('csrf_token')) {
                body.append('csrf_token', token);
            }
        }
        return originalSend.call(this, body);
    };
})();
</script>
<?php if (!$adminCanManageCurrentModule): ?>
<style>
.cms-readonly-notice{display:flex;align-items:center;gap:12px;margin:0 0 16px;padding:13px 16px;border:1px solid #bfdbfe;border-radius:14px;background:#eff6ff;color:#1e40af}.cms-readonly-notice span{font-size:13px;color:#475569}.cms-rbac-readonly [data-rbac-write]{display:none!important}
</style>
<script>
(function(){
    var safeActions={"":1,list:1,view:1,detail:1,preview:1,search:1,config:1,permission:1,load:1,get_url:1};
    document.querySelectorAll('a[href],form[action]').forEach(function(node){
        var raw=node.getAttribute('href')||node.getAttribute('action')||'';
        try{
            var url=new URL(raw,location.href), action=url.searchParams.get('action')||'';
            if(action&&!safeActions[action])node.style.display='none';
            if(node.tagName==='FORM'&&String(node.method||'get').toLowerCase()==='post'&&!/(search|filter)/i.test(node.className||''))node.style.display='none';
        }catch(error){}
    });
    document.querySelectorAll('[onclick]').forEach(function(node){
        if(/delete|remove|batch|toggle|approve|reject|save|edit|ship|refund/i.test(node.getAttribute('onclick')||''))node.style.display='none';
    });
})();
</script>
<?php endif; ?>
</div>
<script src="/public/js/admin-ui.js?v=<?php echo @filemtime(ROOT_PATH . 'public/js/admin-ui.js'); ?>"></script>
<script src="/public/js/admin-icons.js?v=<?php echo @filemtime(ROOT_PATH . 'public/js/admin-icons.js'); ?>"></script>
</body>
</html>

