{"id":31237,"date":"2024-07-03T15:06:32","date_gmt":"2024-07-03T07:06:32","guid":{"rendered":"https:\/\/www.goglobalsafe.com\/?page_id=31237"},"modified":"2026-05-27T13:40:25","modified_gmt":"2026-05-27T05:40:25","slug":"student-users","status":"publish","type":"page","link":"https:\/\/www.goglobalsafe.com\/zh\/student-users\/","title":{"rendered":"\u6211\u7684\u8d26\u6237"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"31237\" class=\"elementor elementor-31237\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-fdccd65 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"fdccd65\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-19760bb\" data-id=\"19760bb\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-00c50d6 user-center-section elementor-widget elementor-widget-shortcode\" data-id=\"00c50d6\" data-element_type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><link rel=\"stylesheet\" href=\"https:\/\/www.goglobalsafe.com\/wp-content\/themes\/astra\/css\/user-center.css?v=20260528-01\">\n<script src=\"\/wp-content\/static\/js\/vue.global.js\"><\/script>\n\n<div class=\"uc-app\" id=\"uc-app\" v-cloak>\n    <svg class=\"uc-icon-sprite\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\">\n        <symbol id=\"uc-i-activity\" viewbox=\"0 0 24 24\"><path d=\"M22 12h-4l-3 8-6-16-3 8H2\"\/><\/symbol>\n        <symbol id=\"uc-i-alert\" viewbox=\"0 0 24 24\"><path d=\"M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z\"\/><path d=\"M12 9v4\"\/><path d=\"M12 17h.01\"\/><\/symbol>\n        <symbol id=\"uc-i-apple\" viewbox=\"0 0 24 24\"><path d=\"M16.38 12.63c.03 3.14 2.75 4.18 2.78 4.19-.02.07-.43 1.48-1.43 2.93-.86 1.26-1.76 2.51-3.17 2.54-1.39.03-1.84-.82-3.43-.82s-2.09.8-3.4.85c-1.36.05-2.41-1.36-3.28-2.61-1.78-2.58-3.14-7.29-1.31-10.47.91-1.58 2.54-2.58 4.31-2.61 1.34-.03 2.61.9 3.43.9.81 0 2.34-1.11 3.95-.95.67.03 2.57.27 3.78 2.05-.1.06-2.26 1.32-2.23 4Zm-2.6-7.75c.72-.87 1.2-2.08 1.07-3.28-1.03.04-2.27.68-3.01 1.55-.66.77-1.24 2.01-1.08 3.19 1.14.09 2.31-.58 3.02-1.46Z\" fill=\"currentColor\" stroke=\"none\"\/><\/symbol>\n        <symbol id=\"uc-i-arrow-left\" viewbox=\"0 0 24 24\"><path d=\"m12 19-7-7 7-7\"\/><path d=\"M19 12H5\"\/><\/symbol>\n        <symbol id=\"uc-i-book\" viewbox=\"0 0 24 24\"><path d=\"M4 19.5A2.5 2.5 0 0 1 6.5 17H20\"\/><path d=\"M4 4.5A2.5 2.5 0 0 1 6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5z\"\/><\/symbol>\n        <symbol id=\"uc-i-building\" viewbox=\"0 0 24 24\"><rect width=\"16\" height=\"20\" x=\"4\" y=\"2\" rx=\"2\"\/><path d=\"M9 22v-4h6v4\"\/><path d=\"M8 6h.01\"\/><path d=\"M16 6h.01\"\/><path d=\"M12 6h.01\"\/><path d=\"M8 10h.01\"\/><path d=\"M12 10h.01\"\/><path d=\"M16 10h.01\"\/><path d=\"M8 14h.01\"\/><path d=\"M12 14h.01\"\/><path d=\"M16 14h.01\"\/><\/symbol>\n        <symbol id=\"uc-i-check\" viewbox=\"0 0 24 24\"><path d=\"M20 6 9 17l-5-5\"\/><\/symbol>\n        <symbol id=\"uc-i-check-circle\" viewbox=\"0 0 24 24\"><path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"\/><path d=\"m9 11 3 3L22 4\"\/><\/symbol>\n        <symbol id=\"uc-i-chevron-down\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"\/><\/symbol>\n        <symbol id=\"uc-i-chevron-left\" viewbox=\"0 0 24 24\"><path d=\"m15 18-6-6 6-6\"\/><\/symbol>\n        <symbol id=\"uc-i-chevron-right\" viewbox=\"0 0 24 24\"><path d=\"m9 18 6-6-6-6\"\/><\/symbol>\n        <symbol id=\"uc-i-clock\" viewbox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M12 6v6l4 2\"\/><\/symbol>\n        <symbol id=\"uc-i-coffee\" viewbox=\"0 0 24 24\"><path d=\"M10 2v2\"\/><path d=\"M14 2v2\"\/><path d=\"M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h12Z\"\/><path d=\"M17 8h1a4 4 0 0 1 0 8h-1\"\/><\/symbol>\n        <symbol id=\"uc-i-copy\" viewbox=\"0 0 24 24\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\"\/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"\/><\/symbol>\n        <symbol id=\"uc-i-credit-card\" viewbox=\"0 0 24 24\"><rect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"2\"\/><path d=\"M2 10h20\"\/><\/symbol>\n        <symbol id=\"uc-i-dashboard\" viewbox=\"0 0 24 24\"><rect width=\"7\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\"\/><rect width=\"7\" height=\"7\" x=\"14\" y=\"3\" rx=\"1\"\/><rect width=\"7\" height=\"7\" x=\"14\" y=\"14\" rx=\"1\"\/><rect width=\"7\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\"\/><\/symbol>\n        <symbol id=\"uc-i-dollar\" viewbox=\"0 0 24 24\"><line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"22\"\/><path d=\"M17 5H9.5a3.5 3.5 0 0 0 0 7H14a3.5 3.5 0 0 1 0 7H6\"\/><\/symbol>\n        <symbol id=\"uc-i-download\" viewbox=\"0 0 24 24\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"\/><path d=\"M7 10l5 5 5-5\"\/><path d=\"M12 15V3\"\/><\/symbol>\n        <symbol id=\"uc-i-external\" viewbox=\"0 0 24 24\"><path d=\"M15 3h6v6\"\/><path d=\"M10 14 21 3\"\/><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"\/><\/symbol>\n        <symbol id=\"uc-i-eye\" viewbox=\"0 0 24 24\"><path d=\"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/symbol>\n        <symbol id=\"uc-i-file\" viewbox=\"0 0 24 24\"><path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"\/><path d=\"M14 2v6h6\"\/><path d=\"M16 13H8\"\/><path d=\"M16 17H8\"\/><path d=\"M10 9H8\"\/><\/symbol>\n        <symbol id=\"uc-i-file-check\" viewbox=\"0 0 24 24\"><path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"\/><path d=\"M14 2v6h6\"\/><path d=\"m9 15 2 2 4-4\"\/><\/symbol>\n        <symbol id=\"uc-i-gift\" viewbox=\"0 0 24 24\"><polyline points=\"20 12 20 22 4 22 4 12\"\/><rect width=\"20\" height=\"5\" x=\"2\" y=\"7\"\/><line x1=\"12\" x2=\"12\" y1=\"22\" y2=\"7\"\/><path d=\"M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z\"\/><path d=\"M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z\"\/><\/symbol>\n        <symbol id=\"uc-i-help\" viewbox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M9.1 9a3 3 0 1 1 5.8 1c0 2-3 2-3 4\"\/><path d=\"M12 17h.01\"\/><\/symbol>\n        <symbol id=\"uc-i-info\" viewbox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M12 16v-4\"\/><path d=\"M12 8h.01\"\/><\/symbol>\n        <symbol id=\"uc-i-image\" viewbox=\"0 0 24 24\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"\/><circle cx=\"9\" cy=\"9\" r=\"2\"\/><path d=\"m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21\"\/><\/symbol>\n        <symbol id=\"uc-i-lock\" viewbox=\"0 0 24 24\"><rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"\/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"\/><\/symbol>\n        <symbol id=\"uc-i-logout\" viewbox=\"0 0 24 24\"><path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\"\/><polyline points=\"16 17 21 12 16 7\"\/><line x1=\"21\" x2=\"9\" y1=\"12\" y2=\"12\"\/><\/symbol>\n        <symbol id=\"uc-i-map-pin\" viewbox=\"0 0 24 24\"><path d=\"M20 10c0 6-8 12-8 12S4 16 4 10a8 8 0 1 1 16 0Z\"\/><circle cx=\"12\" cy=\"10\" r=\"3\"\/><\/symbol>\n        <symbol id=\"uc-i-message\" viewbox=\"0 0 24 24\"><path d=\"M21 15a4 4 0 0 1-4 4H7l-4 4V7a4 4 0 0 1 4-4h10a4 4 0 0 1 4 4z\"\/><\/symbol>\n        <symbol id=\"uc-i-plus\" viewbox=\"0 0 24 24\"><path d=\"M5 12h14\"\/><path d=\"M12 5v14\"\/><\/symbol>\n        <symbol id=\"uc-i-search\" viewbox=\"0 0 24 24\"><circle cx=\"11\" cy=\"11\" r=\"8\"\/><path d=\"m21 21-4.3-4.3\"\/><\/symbol>\n        <symbol id=\"uc-i-send\" viewbox=\"0 0 24 24\"><path d=\"m22 2-7 20-4-9-9-4Z\"\/><path d=\"M22 2 11 13\"\/><\/symbol>\n        <symbol id=\"uc-i-shield\" viewbox=\"0 0 24 24\"><path d=\"M20 13c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V5l8-3 8 3v8Z\"\/><\/symbol>\n        <symbol id=\"uc-i-upload\" viewbox=\"0 0 24 24\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"\/><path d=\"m17 8-5-5-5 5\"\/><path d=\"M12 3v12\"\/><\/symbol>\n        <symbol id=\"uc-i-users\" viewbox=\"0 0 24 24\"><path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"\/><circle cx=\"9\" cy=\"7\" r=\"4\"\/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"\/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"\/><\/symbol>\n        <symbol id=\"uc-i-qrcode\" viewbox=\"0 0 24 24\"><rect x=\"2\" y=\"2\" width=\"7\" height=\"7\" rx=\"1\"\/><rect x=\"15\" y=\"2\" width=\"7\" height=\"7\" rx=\"1\"\/><rect x=\"2\" y=\"15\" width=\"7\" height=\"7\" rx=\"1\"\/><path d=\"M15 15h3v3h-3zM19 19h3v3h-3zM15 20h2M20 15h2\"\/><\/symbol>\n        <symbol id=\"uc-i-x\" viewbox=\"0 0 24 24\"><path d=\"M18 6 6 18\"\/><path d=\"m6 6 12 12\"\/><\/symbol>\n    <\/svg>\n\n    <div class=\"uc-mobile-topbar\">\n        <button type=\"button\" class=\"uc-mobile-menu-button\" aria-label=\"Toggle menu\" @click=\"toggleMobileMenu\">\n            <svg class=\"uc-icon\" width=\"22\" height=\"22\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-dashboard\"><\/use><\/svg>\n            <span>{{ t('menu', 'Menu') }}<\/span>\n        <\/button>\n    <\/div>\n\n    <div class=\"uc-mobile-overlay\" :class=\"{ 'is-open': mobileMenuOpen }\" @click=\"closeMobileMenu\"><\/div>\n\n    <aside class=\"uc-sidebar\" :class=\"{ 'is-open': mobileMenuOpen }\" aria-label=\"Sidebar\">\n        <nav class=\"uc-nav\" aria-label=\"Main Navigation\">\n            <button\n                v-for=\"item in sidebarNavItems\"\n                :key=\"item.id\"\n                type=\"button\"\n                class=\"uc-nav-button\"\n                :class=\"{ 'is-active': activeTab === item.id }\"\n                :aria-selected=\"activeTab === item.id ? 'true' : 'false'\"\n                @click=\"setActiveTab(item.id); closeMobileMenu()\"\n            >\n                <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use :href=\"'#uc-i-' + item.icon\"><\/use><\/svg>\n                <span>{{ item.labelKey ? t(item.labelKey, item.label) : item.label }}<\/span>\n                <i v-if=\"shouldShowNavUnreadDot(item)\" class=\"uc-nav-unread-dot\" aria-hidden=\"true\"><\/i>\n            <\/button>\n        <\/nav>\n        <div class=\"uc-sidebar-footer\">\n            <button type=\"button\" class=\"uc-logout\" @click=\"requestLogout\">\n                <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-logout\"><\/use><\/svg>\n                <span>{{ t('logout', 'Log out') }}<\/span>\n            <\/button>\n        <\/div>\n    <\/aside>\n\n    <main class=\"uc-main\" @click=\"mobileMenuOpen ? closeMobileMenu() : null\">\n        <div class=\"uc-container\">\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'dashboard' }\">\n                <div class=\"uc-page-stack\">\n                    <section class=\"uc-welcome\" aria-label=\"Welcome Status\">\n                        <div>\n                            <h2 class=\"uc-hero-title\">{{ t('hello', 'Hello') }}, {{ dashboardDisplayName }}! <span class=\"uc-wave-hand\" aria-hidden=\"true\">\ud83d\udc4b<\/span><\/h2>\n                            <div class=\"uc-school-pill\">\n                                <span aria-hidden=\"true\">\ud83c\udfdb\ufe0f<\/span>\n                                <span>{{ dashboardSchoolName }}<\/span>\n                            <\/div>\n                        <\/div>\n                        <div\n                            ref=\"statusFlowRoot\"\n                            class=\"uc-status-block uc-flow-status\"\n                            :class=\"{ 'is-open': statusFlowOpen }\"\n                        >\n                            <button\n                                type=\"button\"\n                                class=\"uc-flow-status-trigger\"\n                                :aria-expanded=\"statusFlowOpen ? 'true' : 'false'\"\n                                :title=\"t('click_view_progress', 'Click to view progress')\"\n                                @click.stop=\"toggleStatusFlow\"\n                            >\n                                <p>{{ t('current_status', 'Current Status') }}<\/p>\n                                <strong :class=\"dashboardCurrentFlowStatusClass\">\n                                    {{ dashboardCurrentTimelineStep.title }}\n                                    <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-info\"><\/use><\/svg>\n                                <\/strong>\n                                <small>{{ dashboardCurrentTimelineStep.desc }}<\/small>\n                            <\/button>\n                            <div ref=\"statusFlowPopover\" class=\"uc-flow-popover\" role=\"dialog\" aria-label=\"Plan Progress\" @click.stop>\n                                <div class=\"uc-flow-popover-head\">\n                                    <span>{{ t('plan_progress', 'Plan Progress') }}<\/span>\n                                    <strong>{{ dashboardCurrentTimelineStep.title }}<\/strong>\n                                <\/div>\n                                <div class=\"uc-flow-popover-list\">\n                                    <button\n                                        v-for=\"step in dashboardStatusTimeline\"\n                                        :key=\"'status-popover-' + step.key\"\n                                        type=\"button\"\n                                        class=\"uc-flow-popover-step\"\n                                        :class=\"['is-' + step.state, { 'is-clickable': isDashboardTimelineStepActionable(step) }]\"\n                                        :disabled=\"!isDashboardTimelineStepActionable(step)\"\n                                        @click=\"handleDashboardTimelineStep(step)\"\n                                    >\n                                        <span class=\"uc-flow-popover-dot\">\n                                            <svg v-if=\"step.state === 'done'\" class=\"uc-icon\" width=\"13\" height=\"13\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg>\n                                        <\/span>\n                                        <span class=\"uc-flow-popover-copy\">\n                                            <strong>{{ step.title }}<\/strong>\n                                            <small>{{ step.desc }}<\/small>\n                                        <\/span>\n                                        <em\n                                            v-if=\"isDashboardTimelineStepActionable(step)\"\n                                            class=\"uc-flow-step-cue\"\n                                            :class=\"{ 'is-upload': step.key === 'waiver' && dashboardRegion !== 'au' }\"\n                                        >\n                                            {{ getDashboardStepActionLabel(step) }}\n                                            <svg class=\"uc-icon\" width=\"13\" height=\"13\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                                        <\/em>\n                                    <\/button>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/section>\n\n                    <div class=\"uc-dashboard-grid\" :class=\"{ 'is-au-layout': dashboardRegion === 'au' }\">\n                        <div class=\"uc-main-column\">\n                            <section aria-label=\"Current Plan\">\n                                <div class=\"uc-section-line\">\n                                    <h3>{{ t('current_plan', 'Current Plan') }}<\/h3>\n                                    <button type=\"button\" class=\"uc-link-button\" @click=\"handleCurrentPlanPrimaryAction\">{{ currentPlanHeaderActionLabel }}<\/button>\n                                <\/div>\n\n                                <div class=\"uc-plan-card\">\n                                    <div class=\"uc-soft-orb\" aria-hidden=\"true\"><\/div>\n                                    <div class=\"uc-plan-head\">\n                                        <h3>\n                                            {{ dashboardPlanName }}\n                                            <span\n                                                v-if=\"showPlusCrown\"\n                                                class=\"uc-crown-wrap\"\n                                                @mouseenter=\"handlePlusBenefitsHoverEnter\"\n                                                @mouseleave=\"handlePlusBenefitsHoverLeave\"\n                                            >\n                                                <button\n                                                    ref=\"plusBenefitsTrigger\"\n                                                    type=\"button\"\n                                                    class=\"uc-crown-trigger\"\n                                                    aria-label=\"Show Plus Benefits\"\n                                                    :aria-expanded=\"plusBenefitsOpen ? 'true' : 'false'\"\n                                                    @click.stop=\"handlePlusBenefitsTriggerClick\"\n                                                ><\/button>\n                                                <div\n                                                    v-if=\"plusBenefitsOpen\"\n                                                    ref=\"plusBenefitsPopover\"\n                                                    class=\"uc-plus-benefits-popover\"\n                                                    role=\"dialog\"\n                                                    aria-label=\"Plus Exclusive Benefits\"\n                                                    @click.stop\n>\n                                                    <h4>{{ t('plus_benefits_title', 'Plus Exclusive Benefits') }}<\/h4>\n                                                    <ul>\n                                                        <li>{{ t('plus_benefit_lounge', 'Airport VIP Lounge access') }}<\/li>\n                                                        <li>{{ t('plus_benefit_travel', 'Up to 2 weeks free travel insurance') }}<\/li>\n                                                        <li>{{ t('plus_benefit_merch', 'Exclusive GGS member merch') }}<\/li>\n                                                    <\/ul>\n                                                    <div class=\"uc-plus-benefits-divider\"><\/div>\n                                                    <div class=\"uc-plus-benefits-qr\">\n                                                        <img v-if=\"!plusBenefitsQrFailed\" :src=\"supportQrUrl\" alt=\"Support WeChat QR\" @error=\"handlePlusBenefitsQrError\">\n                                                        <img v-else :src=\"supportQrFallbackUrl\" alt=\"Support WeChat QR\">\n                                                    <\/div>\n                                                    <p>{{ t('plus_benefits_claim_hint', 'Please add customer service WeChat to claim.') }}<\/p>\n                                                <\/div>\n                                            <\/span>\n                                        <\/h3>\n                                        <span v-if=\"canShowRenewEntry()\" class=\"uc-warning-badge\" :class=\"dashboardStatusBadgeClass\">\n                                            <svg class=\"uc-icon\" width=\"12\" height=\"12\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-info\"><\/use><\/svg>\n                                            {{ t('action_required', 'Action Required') }}\n                                        <\/span>\n                                    <\/div>\n\n                                    <div class=\"uc-plan-meta\">\n                                        <div>\n                                            <p>{{ t('coverage_period', 'Coverage Period') }}<\/p>\n                                            <strong>{{ dashboardCoveragePeriod }}<\/strong>\n                                        <\/div>\n                                        <div>\n                                            <p>{{ dashboardSecondaryLabel }}<\/p>\n                                            <strong>{{ dashboardSecondaryValue }}<\/strong>\n                                        <\/div>\n                                    <\/div>\n\n                                    <div v-if=\"canShowWaiveCenter\" class=\"uc-waive-alert\">\n                                        <div>\n                                            <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-shield\"><\/use><\/svg>\n                                            <div class=\"uc-waive-alert-copy\">\n                                                <h4>{{ t('waive_deadline_approaching', 'Waive Deadline Approaching') }}<\/h4>\n                                                <p>{{ dashboardWaiveDeadlineText }}<\/p>\n                                            <\/div>\n                                        <\/div>\n                                        <button type=\"button\" class=\"uc-button uc-button-orange\" @click=\"setActiveTab('waive')\">{{ t('complete_waiver_now', 'Complete Waiver Now') }}<\/button>\n                                    <\/div>\n\n                                    <div class=\"uc-plan-actions\">\n                                        <button type=\"button\" class=\"uc-button uc-button-outline-light\" @click=\"handleCurrentPlanPrimaryAction\">\n                                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use :href=\"currentPlanPrimaryActionIcon\"><\/use><\/svg>\n                                            {{ currentPlanPrimaryActionLabel }}\n                                        <\/button>\n                                        <button v-if=\"canShowRenewEntry()\" type=\"button\" class=\"uc-button uc-button-yellow\" @click=\"openRenewReminderDialog\">\n                                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file-check\"><\/use><\/svg>\n                                            {{ t('renew', 'Renew') }}\n                                        <\/button>\n                                    <\/div>\n\n                                <\/div>\n                            <\/section>\n\n                            <section aria-label=\"Quick Actions\">\n                                <h3 class=\"uc-section-title\">{{ t('quick_actions', 'Quick Actions') }}<\/h3>\n\n                                <div v-if=\"dashboardTopActions.length\" class=\"uc-action-grid\">\n                                    <button v-for=\"action in dashboardTopActions\" :key=\"action.id\" type=\"button\" class=\"uc-color-action\" :class=\"[action.className, { 'is-locked': isDashboardActionLocked(action) }]\" @click=\"handleTopAction(action)\">\n                                        <span class=\"uc-icon-box\">\n                                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use :href=\"'#uc-i-' + action.icon\"><\/use><\/svg>\n                                        <\/span>\n                                        <strong>{{ getActionTitle(action) }}<\/strong>\n                                        <span>{{ getActionDesc(action) }}<\/span>\n                                    <\/button>\n                                <\/div>\n\n                                <div class=\"uc-mini-action-grid\">\n                                    <button v-for=\"action in dashboardBottomActions\" :key=\"action.id\" type=\"button\" class=\"uc-mini-action\" :class=\"{ 'is-locked': isDashboardActionLocked(action) }\" @click=\"handleBottomAction(action)\">\n                                        <svg class=\"uc-icon\" :class=\"action.color\" width=\"22\" height=\"22\" viewbox=\"0 0 24 24\"><use :href=\"'#uc-i-' + action.icon\"><\/use><\/svg>\n                                        <span>{{ getActionLabel(action) }}<\/span>\n                                    <\/button>\n                                <\/div>\n                            <\/section>\n                        <\/div>\n\n                        <aside class=\"uc-side-column\">\n                            <section class=\"uc-refer-card\" aria-label=\"Refer & Earn\">\n                                <div class=\"uc-soft-orb\" aria-hidden=\"true\"><\/div>\n                                <h3 class=\"text-lg font-bold flex items-center gap-2 mb-2\">\n                                    <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-gift\"><\/use><\/svg>\n                                    {{ t('refer_earn', 'Refer & Earn') }}\n                                <\/h3>\n                                <p v-if=\"dashboardReferralPromoText\" class=\"text-sm text-blue-100 uc-refer-subtext\">{{ dashboardReferralPromoText }}<\/p>\n                                <div class=\"uc-referral-code\">\n                                    <span class=\"text-xs text-blue-200 font-semibold mb-1 uppercase tracking-widest\">{{ t('your_referral_code', 'Your Referral Code') }}<\/span>\n                                    <strong class=\"text-2xl font-bold tracking-widest\">{{ dashboardReferralCode }}<\/strong>\n                                <\/div>\n                                <button v-if=\"dashboardRegion !== 'au'\" type=\"button\" class=\"uc-button uc-button-yellow uc-full\" @click=\"handleDashboardReferralRewardsClick\">{{ t('view_rewards', 'View Rewards') }}<\/button>\n                                <div class=\"uc-refer-foot\">\n                                    <a class=\"hover:text-white underline decoration-blue-200\/50 underline-offset-2\" href=\"#rules\" @click.prevent=\"openRulesModal()\">{{ t('activity_rules', 'Activity Rules') }}<\/a>\n                                    <span v-if=\"dashboardRegion !== 'au'\">{{ dashboardInvitedCount }} {{ t('invited', 'Invited') }}<\/span>\n                                <\/div>\n                            <\/section>\n\n                            <section class=\"uc-card uc-notifications\" aria-label=\"Notifications\">\n                                <div class=\"uc-card-head\">\n                                    <h3>{{ t('notifications', 'Notifications') }}<\/h3>\n                                    <span v-if=\"unreadMessageCount > 0\" aria-hidden=\"true\"><\/span>\n                                <\/div>\n                                <ul>\n                                    <li v-for=\"item in notifications\" :key=\"item.id || item.title\">\n                                        <button type=\"button\" @click=\"openNotificationDetail(item)\">\n                                            <strong>{{ item.title }}<\/strong>\n                                            <span>{{ item.subtitle || item.summary || item.desc }}<\/span>\n                                        <\/button>\n                                    <\/li>\n                                <\/ul>\n                            <\/section>\n                        <\/aside>\n                    <\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'plans' }\">\n                <div class=\"uc-page-stack\">\n                    <div class=\"uc-title-row\">\n                        <span><\/span>\n                        <h2>{{ t('current_plan', 'Current Plan') }}<\/h2>\n                    <\/div>\n\n                    <div class=\"uc-two-column\" :class=\"{ 'is-plan-only': dashboardRegion === 'au' }\">\n                        <section class=\"uc-plan-card uc-plan-card-large\" aria-label=\"Current Plan Details\">\n                            <div class=\"uc-soft-orb\" aria-hidden=\"true\"><\/div>\n                            <div class=\"uc-plan-head\">\n                                <h3>\n                                    {{ currentPlanName }}\n                                    <span\n                                        v-if=\"showPlusCrown\"\n                                        class=\"uc-crown-wrap\"\n                                        @mouseenter=\"handlePlusBenefitsHoverEnter\"\n                                        @mouseleave=\"handlePlusBenefitsHoverLeave\"\n                                    >\n                                        <button\n                                            ref=\"plusBenefitsTrigger\"\n                                            type=\"button\"\n                                            class=\"uc-crown-trigger\"\n                                            aria-label=\"Show Plus Benefits\"\n                                            :aria-expanded=\"plusBenefitsOpen ? 'true' : 'false'\"\n                                            @click.stop=\"handlePlusBenefitsTriggerClick\"\n                                        ><\/button>\n                                        <div\n                                            v-if=\"plusBenefitsOpen\"\n                                            ref=\"plusBenefitsPopover\"\n                                            class=\"uc-plus-benefits-popover\"\n                                            role=\"dialog\"\n                                            aria-label=\"Plus Exclusive Benefits\"\n                                            @click.stop\n>\n                                            <h4>{{ t('plus_benefits_title', 'Plus Exclusive Benefits') }}<\/h4>\n                                            <ul>\n                                                <li>{{ t('plus_benefit_lounge', 'Airport VIP Lounge access') }}<\/li>\n                                                <li>{{ t('plus_benefit_travel', 'Up to 2 weeks free travel insurance') }}<\/li>\n                                                <li>{{ t('plus_benefit_merch', 'Exclusive GGS member merch') }}<\/li>\n                                            <\/ul>\n                                            <div class=\"uc-plus-benefits-divider\"><\/div>\n                                            <div class=\"uc-plus-benefits-qr\">\n                                                <img v-if=\"!plusBenefitsQrFailed\" :src=\"supportQrUrl\" alt=\"Support WeChat QR\" @error=\"handlePlusBenefitsQrError\">\n                                                <img v-else :src=\"supportQrFallbackUrl\" alt=\"Support WeChat QR\">\n                                            <\/div>\n                                            <p>{{ t('plus_benefits_claim_hint', 'Please add customer service WeChat to claim.') }}<\/p>\n                                        <\/div>\n                                    <\/span>\n                                <\/h3>\n                                <span v-if=\"currentPlanBadgeLabel\" class=\"uc-warning-badge\" :class=\"dashboardStatusBadgeClass\">\n                                    <svg class=\"uc-icon\" width=\"12\" height=\"12\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-info\"><\/use><\/svg>\n                                    {{ currentPlanBadgeLabel }}\n                                <\/span>\n                            <\/div>\n                            <div class=\"uc-plan-meta\">\n                                <div>\n                                    <p>{{ t('coverage_period', 'Coverage Period') }}<\/p>\n                                    <strong>{{ currentPlanCoveragePeriod }}<\/strong>\n                                <\/div>\n                                <div>\n                                    <p>{{ currentPlanSecondaryLabel }}<\/p>\n                                    <strong>{{ currentPlanSecondaryValue }}<\/strong>\n                                <\/div>\n                            <\/div>\n                            <div class=\"uc-plan-actions uc-plan-actions-left\">\n                                <button v-if=\"canShowRenewEntry()\" type=\"button\" class=\"uc-button uc-button-yellow\" @click=\"openRenewReminderDialog\">\n                                    <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file-check\"><\/use><\/svg>\n                                    {{ t('renew', 'Renew') }}\n                                <\/button>\n                                <button v-if=\"dashboardRegion !== 'au'\" type=\"button\" class=\"uc-button uc-button-black\" @click=\"handleAppleWalletClick\">\n                                    <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\" style=\"fill:currentColor;stroke:none;\"><use href=\"#uc-i-apple\"><\/use><\/svg>\n                                    {{ t('add_to_apple_wallet', 'Add to Apple Wallet') }}\n                                <\/button>\n                            <\/div>\n                        <\/section>\n\n                        <section v-if=\"dashboardRegion !== 'au'\" class=\"uc-card uc-coverage-card\" aria-label=\"Key Coverage\">\n                            <h3>{{ t('key_coverage', 'Key Coverage') }}<\/h3>\n                            <dl>\n                                <div v-for=\"item in currentPlanCoverageItems\" :key=\"item.label\"><dt>{{ item.label}}<\/dt><dd>{{ item.value }}<\/dd><\/div>\n                            <\/dl>\n                        <\/section>\n                    <\/div>\n\n                    <section v-if=\"dashboardRegion !== 'au'\" aria-label=\"Important Materials\">\n                        <h3 class=\"uc-panel-heading\">{{ t('important_materials', 'Important Materials') }}<\/h3>\n                        <div class=\"uc-material-grid\">\n                            <button v-for=\"material in dashboardMaterials\" :key=\"material.id\" type=\"button\" class=\"uc-material-card\" :class=\"[material.className, { 'is-locked': !canUsePlanBenefits }]\" @click=\"handleMaterialAction(material)\">\n                                <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use :href=\"'#uc-i-' + material.icon\"><\/use><\/svg>\n                                <strong>{{ getMaterialTitle(material) }}<\/strong>\n                                <span>{{ getMaterialDesc(material) }}<\/span>\n                                <em>{{ getMaterialUsage(material) }}<\/em>\n                            <\/button>\n                        <\/div>\n                    <\/section>\n\n                    <div class=\"uc-docs-grid\" :class=\"{ 'is-orders-only': dashboardRegion === 'au' }\">\n                        <section v-if=\"dashboardRegion !== 'au'\" id=\"uc-plan-documents-section\" aria-label=\"Documents List\">\n                            <h3 class=\"uc-panel-heading\">{{ t('documents', 'Documents') }}<\/h3>\n                            <div class=\"uc-card uc-list-card\">\n                                <div class=\"uc-list-scroll\">\n                                    <a v-for=\"doc in documents\" :key=\"doc.name\" href=\"#download\" @click.prevent=\"handleDocumentDownload(doc)\">\n                                        <span class=\"uc-doc-icon\">\n                                            <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file\"><\/use><\/svg>\n                                        <\/span>\n                                        <span><strong>{{ doc.name }}<\/strong><small>{{ formatDocumentMeta(doc) }}<\/small><\/span>\n                                        <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-download\"><\/use><\/svg>\n                                    <\/a>\n                                <\/div>\n                                <button v-if=\"false\" type=\"button\" class=\"uc-list-download-all\" @click=\"downloadAllDocuments\">{{ t('download_all_zip', 'Download All (ZIP)') }}<\/button>\n                            <\/div>\n                        <\/section>\n\n                        <section aria-label=\"Order History\">\n                            <h3 class=\"uc-panel-heading\">{{ t('order_history', 'Order History') }}<\/h3>\n                            <div class=\"uc-card uc-table-card\">\n                                <table>\n                                    <thead>\n                                        <tr>\n                                            <th>{{ t('plan', 'Plan') }}<\/th>\n                                            <th>{{ t('period', 'Period') }}<\/th>\n                                            <th>{{ t('total', 'Total') }}<\/th>\n                                            <th>{{ t('status', 'Status') }}<\/th>\n                                            <th>{{ t('actions', 'Actions') }}<\/th>\n                                        <\/tr>\n                                    <\/thead>\n                                    <tbody>\n                                        <template v-for=\"(order, pageIndex) in pagedOrders\" :key=\"getOrderDetailKey(order, pageIndex)\">\n                                            <tr>\n                                                <td>{{ formatPlanName(order.plan) }}<\/td>\n                                                <td class=\"uc-preline\">{{ order.periodDisplay || order.period }}<\/td>\n                                                <td>{{ order.total }}<\/td>\n                                                <td><span class=\"uc-status\" :class=\"order.className\">{{ order.status }}<\/span><\/td>\n                                                <td>\n                                                    <div class=\"uc-table-action-stack\">\n                                                        <button v-if=\"canShowOrderPayNow(order)\" type=\"button\" class=\"uc-table-action uc-table-action-pay\" @click=\"handleOrderPayNow(order)\">\n                                                            <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-credit-card\"><\/use><\/svg>\n                                                            {{ t('pay_now', 'Pay Now') }}\n                                                        <\/button>\n                                                        <button type=\"button\" class=\"uc-table-action\" @click=\"toggleDetail(getOrderDetailKey(order, pageIndex))\">\n                                                            <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-eye\"><\/use><\/svg>\n                                                            {{ t('details', 'Details') }}\n                                                            <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-down\"><\/use><\/svg>\n                                                        <\/button>\n                                                    <\/div>\n                                                <\/td>\n                                            <\/tr>\n                                            <tr class=\"uc-detail-row\" :class=\"{ 'is-open': isDetailOpen(getOrderDetailKey(order, pageIndex)) }\">\n                                                <td colspan=\"5\">\n                                                    <div v-if=\"order.region === 'au'\" class=\"uc-detail-grid uc-order-detail-grid\">\n                                                        <div><span>{{ t('order_id', 'Order ID') }}<\/span><strong>{{ order.id || '-' }}<\/strong><\/div>\n                                                        <div><span>{{ t('insurance_name', 'Insurance Name') }}<\/span><strong>{{ formatPlanName(order.plan) }}<\/strong><\/div>\n                                                        <div><span>{{ t('insurance_time', 'Insurance Time') }}<\/span><strong>{{ order.period || '-' }}<\/strong><\/div>\n                                                        <div><span>{{ t('member', 'Member') }}<\/span><strong>{{ maskName(order.memberName) }}<\/strong><\/div>\n                                                        <div><span>{{ t('email', 'Email') }}<\/span><strong>{{ maskEmail(order.contactEmail) }}<\/strong><\/div>\n                                                        <div><span>{{ t('phone', 'Phone') }}<\/span><strong>{{ maskPhone(order.contactPhone) }}<\/strong><\/div>\n                                                        <div><span>{{ t('total', 'Total') }}<\/span><strong>{{ order.total || '-' }}<\/strong><\/div>\n                                                        <div><span>{{ t('order_status', 'Order Status') }}<\/span><strong>{{ order.status || '-' }}<\/strong><\/div>\n                                                    <\/div>\n                                                    <div v-else class=\"uc-detail-grid uc-order-detail-grid\">\n                                                        <div><span>{{ t('member', 'Member') }}<\/span><strong>{{ maskName(order.memberName) }}<\/strong><\/div>\n                                                        <div><span>{{ t('coverage_type', 'Coverage Type') }}<\/span><strong>{{ order.coverageType || '-' }}<\/strong><\/div>\n                                                        <div><span>{{ t('email', 'Email') }}<\/span><strong>{{ maskEmail(order.contactEmail) }}<\/strong><\/div>\n                                                        <div><span>{{ t('phone', 'Phone') }}<\/span><strong>{{ maskPhone(order.contactPhone) }}<\/strong><\/div>\n                                                        <div><span>{{ t('school', 'School') }}<\/span><strong>{{ order.schoolName || '-' }}<\/strong><\/div>\n                                                        <div><span>{{ t('visa', 'Visa') }}<\/span><strong>{{ order.visaType || '-' }}<\/strong><\/div>\n                                                    <\/div>\n                                                <\/td>\n                                            <\/tr>\n                                        <\/template>\n                                    <\/tbody>\n                                <\/table>\n                                <div class=\"uc-pagination uc-order-pagination\" v-if=\"orderPageCount > 1\">\n                                    <button type=\"button\" :disabled=\"orderCurrentPage <= 1\" @click=\"changeOrderPage(orderCurrentPage - 1)\">\n                                        <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-left\"><\/use><\/svg>\n                                        {{ t('prev', 'Prev') }}\n                                    <\/button>\n                                    <span>{{ orderCurrentPage }} \/ {{ orderPageCount }}<\/span>\n                                    <button type=\"button\" :disabled=\"orderCurrentPage >= orderPageCount\" @click=\"changeOrderPage(orderCurrentPage + 1)\">\n                                        {{ t('next', 'Next') }}\n                                        <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                                    <\/button>\n                                <\/div>\n                            <\/div>\n                        <\/section>\n                    <\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'waive' }\">\n                <div class=\"uc-page-stack\">\n                    <section class=\"uc-banner uc-banner-blue\" aria-label=\"Waive Center Banner\">\n                        <div>\n                            <h2>{{ t('waive_center', 'GGS Waiver Center') }}<\/h2>\n                            <p>\n                                <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-building\"><\/use><\/svg>\n                                {{ t('detected_school', 'Detected School') }}:\n                                <a\n                                    v-if=\"waivePortalLinkUrl\"\n                                    :href=\"waivePortalLinkUrl\"\n                                    target=\"_blank\"\n                                    rel=\"noopener noreferrer\"\n                                    class=\"uc-banner-school-link\"\n                                >\n                                    <strong>{{ dashboardSchoolName }}<\/strong>\n                                <\/a>\n                                <strong v-else>{{ dashboardSchoolName }}<\/strong>\n                            <\/p>\n                        <\/div>\n                    <\/section>\n\n                    <div class=\"uc-two-column uc-wide-left\">\n                        <div class=\"uc-page-stack\">\n                            <section class=\"uc-card uc-steps-card\" :class=\"{ 'is-waiver-complete': hasWaiverApprovalUploaded }\" aria-label=\"Waiver Steps\">\n                                <h3>{{ t('waiver_steps', 'Waiver Steps') }}<\/h3>\n                                <div class=\"uc-stepper\" :class=\"{ 'is-complete': hasWaiverApprovalUploaded }\" :style=\"{ '--uc-waiver-step-progress-ratio': waiverGuideProgressRatio }\">\n                                    <div v-for=\"(step, index) in waiveGuideStepItems\" :key=\"'waive-step-' + index + '-' + step.title\" :class=\"{ 'is-complete': isWaiverGuideStepComplete(index) }\">\n                                        <span>\n                                            <svg v-if=\"isWaiverGuideStepComplete(index)\" class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check\"><\/use><\/svg>\n                                            <template v-else>{{ index + 1 }}<\/template>\n                                        <\/span>\n                                        <strong>{{ step.title }}<\/strong>\n                                    <\/div>\n                                <\/div>\n                                <h4>{{ t('detailed_instructions', 'Detailed Instructions') }}<\/h4>\n                                <input id=\"waiverApprovalUploadInput\" type=\"file\" accept=\".jpg,.jpeg,.png,.webp,image\/jpeg,image\/png,image\/webp\" style=\"display:none;\" @change=\"handleWaiverApprovalFileSelect\">\n                                <div class=\"uc-timeline\">\n                                    <div v-for=\"(step, index) in waiveGuideStepItems\" :key=\"'waive-detail-' + index + '-' + step.title\" :class=\"{ 'is-complete': isWaiverGuideStepComplete(index), 'is-final': isWaiverApprovalStep(index) }\">\n                                        <span><\/span>\n                                        <div>\n                                            <h5>{{ step.title }}<\/h5>\n                                            <p>{{ step.detail }}<\/p>\n                                            <div v-if=\"index === 2 && schoolWaiveLinkUrl\" class=\"uc-waive-step-guide\">\n                                                <a class=\"uc-waive-step-guide-toggle\" :href=\"schoolWaiveLinkUrl\" target=\"_blank\" rel=\"noopener noreferrer\">\n                                                    <span>\n                                                        <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-image\"><\/use><\/svg>\n                                                        {{ t('view_detailed_guide', 'View detailed guide') }}\n                                                    <\/span>\n                                                    <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                                                <\/a>\n                                            <\/div>\n                                            <div v-if=\"isWaiverApprovalStep(index)\" class=\"uc-waiver-approval-actions\">\n                                                <div v-if=\"currentWaiverApprovalUrl\" class=\"uc-waiver-complete-card\">\n                                                    <div class=\"uc-waiver-complete-copy\">\n                                                        <span class=\"uc-waiver-complete-mini-icon\">\n                                                            \ud83c\udf89\n                                                        <\/span>\n                                                        <p>{{ t('waiver_all_done_desc', 'Your approval screenshot is saved. All waiver steps are complete.') }}<\/p>\n                                                    <\/div>\n                                                    <button type=\"button\" class=\"uc-button uc-button-plain uc-waiver-approval-view\" @click=\"openInNewTab(currentWaiverApprovalUrl)\">\n                                                        {{ t('view_approval_image', 'View Image') }}\n                                                    <\/button>\n                                                <\/div>\n                                                <div v-else class=\"uc-waiver-approval-cta\">\n                                                    <div>\n                                                        <button type=\"button\" class=\"uc-button uc-button-primary uc-waiver-approval-button\" :disabled=\"waiverApprovalUploading\" @click=\"triggerWaiverApprovalFileSelect\">\n                                                            <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-upload\"><\/use><\/svg>\n                                                            {{ waiverApprovalUploading ? t('uploading', 'Uploading') : t('complete_last_step', 'Complete Last Step') }}\n                                                        <\/button>\n                                                    <\/div>\n                                                    <small>{{ t('waiver_approval_upload_hint', 'Upload your waiver approval screenshot to complete the final step.') }}<\/small>\n                                                <\/div>\n                                            <\/div>\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n                            <\/section>\n\n                            <section class=\"uc-card uc-faq-card\" aria-label=\"Waiver FAQ\">\n                                <div class=\"uc-card-head\">\n                                    <h3>{{ t('waiver_faq', 'Waiver FAQ') }}<\/h3>\n                                    <span class=\"uc-muted-badge\">{{ waiveFaqUpdatedBadgeText }}<\/span>\n                                <\/div>\n                                <div\n                                    v-for=\"(article, index) in waiveFaqArticles\"\n                                    :key=\"'waive-faq-' + index + '-' + article.id\"\n                                    class=\"uc-question\"\n                                    :class=\"{ 'is-open': isDetailOpen(getWaiveFaqDetailKey(article, index)) }\"\n                                >\n                                    <button\n                                        type=\"button\"\n                                        class=\"uc-question-toggle\"\n                                        @click=\"toggleDetail(getWaiveFaqDetailKey(article, index))\"\n                                    >\n                                        <strong>{{ t('question_prefix', 'Q') }}: {{ article.title }}<\/strong>\n                                        <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-down\"><\/use><\/svg>\n                                    <\/button>\n                                    <div class=\"uc-question-body\">\n                                        <p v-if=\"article.content\" v-html=\"article.content\"><\/p>\n                                        <p v-else>-<\/p>\n                                    <\/div>\n                                <\/div>\n                            <\/section>\n                        <\/div>\n\n                        <aside class=\"uc-page-stack\">\n                            <a v-if=\"waiveGuideLinkUrl\" :href=\"waiveGuideLinkUrl\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"uc-guide-link\">\n                                <span><strong><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-help\"><\/use><\/svg> {{ t('waive_guide', 'Waive Guide') }}<\/strong><small>{{ t('waive_guide_subtitle', 'Step-by-step visual instructions') }}<\/small><\/span>\n                                <span class=\"uc-guide-link-badge\">\n                                    <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-external\"><\/use><\/svg>\n                                <\/span>\n                            <\/a>\n                            <section v-if=\"dashboardRegion !== 'au'\" class=\"uc-warning-panel\">\n                                <h4><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-alert\"><\/use><\/svg> {{ t('important_deadline', 'Important Deadline') }}<\/h4>\n                                <p v-if=\"waiveDeadlineDisplayDate\">\n                                    {{ waiveDeadlineIntroText }}\n                                    <strong>{{ waiveDeadlineDisplayDate }}<\/strong>.\n                                <\/p>\n                                <p v-else>{{ dashboardWaiveDeadlineText }}<\/p>\n                            <\/section>\n                            <section class=\"uc-card uc-doc-buttons\">\n                                <h3>{{ t('required_documents', 'Required Documents') }}<\/h3>\n                                <button\n                                    v-for=\"material in dashboardMaterials\"\n                                    :key=\"'waive-doc-' + material.id\"\n                                    type=\"button\"\n                                    class=\"uc-doc-entry\"\n                                    @click=\"handleMaterialAction(material)\"\n                                >\n                                    <span class=\"uc-doc-entry-main\">\n                                        <span class=\"uc-doc-entry-icon\">\n                                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use :href=\"'#uc-i-' + material.icon\"><\/use><\/svg>\n                                        <\/span>\n                                        <span class=\"uc-doc-entry-copy\">\n                                            <strong>{{ getMaterialTitle(material) }}<\/strong>\n                                            <small>{{ getMaterialDesc(material) }}<\/small>\n                                            <em>{{ getMaterialUsage(material) }}<\/em>\n                                        <\/span>\n                                    <\/span>\n                                    <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-download\"><\/use><\/svg>\n                                <\/button>\n                                <button type=\"button\" class=\"uc-doc-more-trigger\" @click=\"goToPlanDocuments\">\n                                    {{ t('more_files', 'More Files') }}\n                                    <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                                <\/button>\n                            <\/section>\n                            <section class=\"uc-card uc-fixed-info\">\n                                <h3>{{ t('waiver_details', 'Waiver Details') }}<\/h3>\n                                <div><span>{{ t('address', 'Address') }}<\/span><strong>1825 Ponce De Leon BLVD #207,<br>Coral Gables, FL 33134<\/strong><\/div>\n                                <div><span>{{ t('phone', 'Phone') }}<\/span><strong>+1-855-773-7810<\/strong><\/div>\n                            <\/section>\n                            <button v-if=\"waivePortalLinkUrl\" type=\"button\" class=\"uc-button uc-button-primary uc-full\" @click=\"openInNewTab(waivePortalLinkUrl)\">{{ t('go_to_portal', 'Go to Portal') }} <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-external\"><\/use><\/svg><\/button>\n                        <\/aside>\n                    <\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'claims' }\">\n                <div class=\"uc-page-stack\">\n                    <section class=\"uc-banner uc-banner-claims\" aria-label=\"File a Claim Banner\">\n                        <div>\n                            <h2>{{ t('file_a_claim', 'File a Claim') }}<\/h2>\n                            <p>{{ t('claim_banner_desc', 'Submit medical bills and track reimbursement progress from one clean dashboard.') }}<\/p>\n                            <button type=\"button\" class=\"uc-button uc-button-white\" @click=\"claimFormOpen = !claimFormOpen\">\n                                <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use :href=\"claimFormOpen ? '#uc-i-x' : '#uc-i-plus'\"><\/use><\/svg>\n                                {{ claimFormOpen ? t('cancel_filing', 'Cancel Filing') : t('new_claim', 'New Claim') }}\n                            <\/button>\n                        <\/div>\n                        <div class=\"uc-checklist\">\n                            <h4>{{ t('required_checklist', 'Required Checklist') }}<\/h4>\n                            <ul>\n                                <li><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg> {{ t('claim_checklist_bill', 'Itemized bill from provider') }}<\/li>\n                                <li><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg> {{ t('claim_checklist_payment', 'Proof of payment') }}<\/li>\n                                <li><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg> {{ t('claim_checklist_notes', 'Diagnosis or visit notes') }}<\/li>\n                            <\/ul>\n                        <\/div>\n                    <\/section>\n\n                    <section class=\"uc-card uc-form-card\" :class=\"{ 'is-open': claimFormOpen }\">\n                        <div class=\"uc-card-head\">\n                            <h3>{{ t('file_new_claim', 'File a New Claim') }}<\/h3>\n                            <button type=\"button\" @click=\"claimFormOpen = false\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n                        <\/div>\n                        <div class=\"uc-claim-doc-tools\">\n                            <button type=\"button\" class=\"uc-claim-doc-link\" @click=\"openClaimInstructions\">\n                                <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-help\"><\/use><\/svg>\n                                {{ t('claims_instructions', 'Claims Instructions') }}\n                            <\/button>\n                            <button type=\"button\" class=\"uc-claim-doc-link\" @click=\"openClaimTemplate\">\n                                <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file\"><\/use><\/svg>\n                                {{ t('claim_template', 'Claim Template') }}\n                            <\/button>\n                            <p>{{ t('claim_template_hint', 'Please review the claim template before submitting your files.') }}<\/p>\n                        <\/div>\n                        <div class=\"uc-upload-section\">\n                            <input type=\"file\" id=\"fileUploadInput\" multiple accept=\".pdf,.jpg,.jpeg,.png\" style=\"display: none;\" @change=\"handleFileSelect\">\n                            <div class=\"uc-upload-box uc-form-wide\" @click=\"triggerFileSelect\" @dragover=\"handleDragOver\" @dragleave=\"handleDragLeave\" @drop=\"handleDrop\">\n                                <svg class=\"uc-icon\" width=\"28\" height=\"28\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-upload\"><\/use><\/svg>\n                                <strong>{{ t('upload_or_drag', 'Click to upload or drag and drop') }}<\/strong>\n                                <span>{{ t('claim_upload_hint', 'PDF, JPG, PNG (Max 10MB per file)') }}<\/span>\n                            <\/div>\n                            <div v-if=\"uploadedFiles.length > 0\" class=\"uc-file-list\">\n                                <div v-for=\"(file, index) in uploadedFiles\" :key=\"index\" class=\"uc-file-item\">\n                                    <div class=\"uc-file-info\">\n                                        <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file\"><\/use><\/svg>\n                                        <div>\n                                            <strong>{{ file.name }}<\/strong>\n                                            <small>{{ file.size }}<\/small>\n                                        <\/div>\n                                    <\/div>\n                                    <div class=\"uc-file-actions\">\n                                        <span v-if=\"file.status === 'loading'\" class=\"uc-upload-progress\">{{ file.percent }}%<\/span>\n                                        <span v-else-if=\"file.status === 'success'\" class=\"uc-status uc-status-green\">\n                                            <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg>\n                                            {{ t('ticket_uploaded', 'Uploaded') }}\n                                        <\/span>\n                                        <span v-else class=\"uc-status uc-status-red\">\n                                            <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n                                            {{ t('ticket_failed', 'Failed') }}\n                                        <\/span>\n                                        <button type=\"button\" class=\"uc-file-remove\" @click=\"removeFile(index)\">\n                                            <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n                                        <\/button>\n                                    <\/div>\n                                <\/div>\n                            <\/div>\n                            <div class=\"uc-form-actions uc-form-wide\">\n                                <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"claimFormOpen = false; uploadedFiles = []\">{{ t('cancel', 'Cancel') }}<\/button>\n                                <button type=\"button\" class=\"uc-button uc-button-primary\" @click=\"submitClaimFiles\">\n                                    <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-send\"><\/use><\/svg> {{ t('submit_files', 'Submit Files') }}\n                                <\/button>\n                            <\/div>\n                        <\/div>\n                    <\/section>\n\n                    <div class=\"uc-two-column uc-wide-left\" v-show=\"!claimFormOpen\">\n                        <section aria-label=\"Claims History\">\n                            <h3 class=\"uc-panel-heading\">{{ t('claims_history', 'Claims History') }}<\/h3>\n                            <div class=\"uc-card uc-claim-list\">\n                                <article v-for=\"(claim, index) in claimsForDisplay\" :key=\"claim.id\">\n                                    <div class=\"uc-claim-row\">\n                                        <button type=\"button\" class=\"uc-claim-toggle\" @click=\"toggleDetail('claim-' + index)\">\n                                            <span class=\"uc-claim-icon\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file\"><\/use><\/svg><\/span>\n                                            <span>\n                                                <strong>{{ claim.provider }}<\/strong>\n                                                <small>\n                                                    #{{ claim.id }} | {{ claim.date }}\n                                                    <em v-if=\"claim.isLocalPending\" class=\"uc-pending-sync-badge\">{{ t('pending_sync', 'Pending Sync') }}<\/em>\n                                                <\/small>\n                                            <\/span>\n                                            <span class=\"uc-claim-amount\"><strong>{{ claim.amount }}<\/strong><em class=\"uc-status\" :class=\"claim.statusClass\">{{ claim.status }}<\/em><\/span>\n                                            <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-down\"><\/use><\/svg>\n                                        <\/button>\n                                        <button\n                                            v-if=\"canDownloadClaimEob(claim)\"\n                                            type=\"button\"\n                                            class=\"uc-claim-eob-button\"\n                                            @click.stop=\"downloadClaimEob(claim)\"\n                                        >\n                                            <svg class=\"uc-icon\" width=\"15\" height=\"15\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-download\"><\/use><\/svg>\n                                            {{ t('download_eob', 'Download EOB') }}\n                                        <\/button>\n                                    <\/div>\n                                    <div class=\"uc-claim-detail\" :class=\"{ 'is-open': isDetailOpen('claim-' + index) }\">\n                                        <h5>{{ t('claim_details', 'Claim Details') }}<\/h5>\n                                        <div class=\"uc-detail-grid uc-claim-primary-grid\">\n                                            <div><span>{{ t('claim_id', 'Claim ID') }}<\/span><strong>{{ claim.id }}<\/strong><\/div>\n                                            <div><span>{{ t('patient', 'Patient') }}<\/span><strong>{{ claim.patientName }}<\/strong><\/div>\n                                            <div><span>{{ t('member_id', 'Member ID') }}<\/span><strong>{{ claim.memberId }}<\/strong><\/div>\n                                            <div><span>{{ t('claim_type', 'Claim Type') }}<\/span><strong>{{ claim.type }}<\/strong><\/div>\n                                            <div><span>{{ t('provider', 'Provider') }}<\/span><strong>{{ claim.provider }}<\/strong><\/div>\n                                            <div><span>{{ t('service_date', 'Service Date') }}<\/span><strong>{{ claim.serviceDateRange }}<\/strong><\/div>\n                                            <div><span>{{ t('status', 'Status') }}<\/span><strong>{{ claim.status }}<em v-if=\"claim.isLocalPending\" class=\"uc-pending-sync-badge\">{{ t('pending_sync', 'Pending Sync') }}<\/em><\/strong><\/div>\n                                            <div><span>{{ t('status_date', 'Status Date') }}<\/span><strong>{{ claim.statusDate }}<\/strong><\/div>\n                                        <\/div>\n                                        <h5 class=\"uc-claim-subheading\">{{ t('diagnosis', 'Diagnosis') }}<\/h5>\n                                        <div class=\"uc-detail-grid uc-claim-secondary-grid\">\n                                            <div><span>{{ t('dx_code', 'DX Code') }}<\/span><strong>{{ claim.diagnosisCode }}<\/strong><\/div>\n                                            <div><span>{{ t('description', 'Description') }}<\/span><strong>{{ claim.diagnosis }}<\/strong><\/div>\n                                            <div><span>{{ t('benefits_applied', 'Benefits Applied') }}<\/span><strong>{{ claim.benefitsApplied }}<\/strong><\/div>\n                                            <div><span>{{ t('eob_in_portal', 'EOB in Portal') }}<\/span><strong>{{ claim.eobInPortalText }}<\/strong><\/div>\n                                        <\/div>\n                                        <h5 class=\"uc-claim-subheading\">{{ t('financial_summary', 'Financial Summary') }}<\/h5>\n                                        <div class=\"uc-detail-grid uc-claim-financial-grid\">\n                                            <div><span>{{ t('claim_amount', 'Claim Amount') }}<\/span><strong>{{ claim.amount }}<\/strong><\/div>\n                                            <div><span>{{ t('reprice', 'Reprice') }}<\/span><strong>{{ claim.reprice }}<\/strong><\/div>\n                                            <div><span>{{ t('savings', 'Savings') }}<\/span><strong>{{ claim.savings }}<\/strong><\/div>\n                                            <div><span>{{ t('pay_to_provider', 'Pay to Provider') }}<\/span><strong>{{ claim.payProvider }}<\/strong><\/div>\n                                            <div><span>{{ t('member_paid', 'Member Paid') }}<\/span><strong>{{ claim.memberPaid }}<\/strong><\/div>\n                                            <div><span>{{ t('patient_responsibility', 'Patient Responsibility') }}<\/span><strong>{{ claim.patientResponsibility }}<\/strong><\/div>\n                                            <div><span>{{ t('non_covered', 'Non Covered') }}<\/span><strong>{{ claim.nonCovered }}<\/strong><\/div>\n                                            <div><span>{{ t('network', 'Network') }}<\/span><strong>{{ claim.networkDescription }}<\/strong><\/div>\n                                        <\/div>\n                                        <div class=\"uc-claim-detail-actions\">\n                                            <button\n                                                v-if=\"canDownloadClaimEob(claim)\"\n                                                type=\"button\"\n                                                class=\"uc-button uc-button-primary\"\n                                                @click=\"downloadClaimEob(claim)\"\n                                            >\n                                                {{ t('download_eob', 'Download EOB') }}\n                                            <\/button>\n                                        <\/div>\n                                    <\/div>\n                                <\/article>\n                                <div v-if=\"!claimsForDisplay.length\" class=\"uc-empty-state\">{{ t('no_claim_records', 'No claim records yet.') }}<\/div>\n                            <\/div>\n                        <\/section>\n\n                        <aside class=\"uc-card uc-info-card\">\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-info\"><\/use><\/svg>\n                            <h4>{{ t('processing_time', 'Processing Time') }}<\/h4>\n                            <p>{{ t('claim_processing_time_desc', 'Claims are usually reviewed within 14-21 business days after all documents are received.') }}<\/p>\n                        <\/aside>\n                    <\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'referrals' }\">\n                <div class=\"uc-page-stack\">\n                    <section class=\"uc-banner uc-banner-referrals\" aria-label=\"Referrals Banner\">\n                        <div class=\"uc-round-icon\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-gift\"><\/use><\/svg><\/div>\n                        <h2>{{ t('referral_banner_title', 'Refer Friends, Unlock Exciting Tiers!') }}<\/h2>\n                        <p>{{ t('referral_banner_desc', \"Share your exclusive code or direct link. When a friend buys a plan using your link, you'll earn rewards and climb the milestone ladder.\") }}<\/p>\n                        <div class=\"uc-referral-tools\">\n                            <div><span>{{ t('referral_code', 'Referral Code') }}<\/span><strong>{{ dashboardReferralCode }}<\/strong><button type=\"button\" @click=\"copyReferralValue(dashboardReferralCode)\"><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-copy\"><\/use><\/svg><\/button><\/div>\n                            <div><span>{{ t('exclusive_link', 'Exclusive Link') }}<\/span><strong>{{ referralLinkShort }}<\/strong><button type=\"button\" @click=\"copyReferralValue(referralLink)\"><svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-copy\"><\/use><\/svg> {{ t('copy_link', 'Copy Link') }}<\/button><\/div>\n                        <\/div>\n                    <\/section>\n\n                    <section class=\"uc-card uc-milestone-card\" aria-label=\"Milestone Progress\">\n                        <div class=\"uc-card-head\">\n                            <div>\n                                <h3>{{ t('milestone_progress_title', 'Your Milestone Progress') }}<\/h3>\n                                <p>{{ t('you_have', 'You have') }} <strong>{{ referralSuccessCount }}<\/strong> {{ t('successful_referrals', 'successful referrals.') }}<\/p>\n                                <p class=\"uc-milestone-note\">{{ referralCountStartDateNote }}<\/p>\n                            <\/div>\n                            <button type=\"button\" class=\"uc-soft-button\" @click=\"openRulesModal()\"><svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-info\"><\/use><\/svg> {{ t('rules_details', 'Rules & Details') }}<\/button>\n                        <\/div>\n                        <div v-if=\"milestoneNextGap > 0\" class=\"uc-milestone-reminder\">\n                            <span class=\"uc-milestone-reminder-star\" aria-hidden=\"true\">\u2b50<\/span>\n                            {{ milestoneNextGapText }}\n                        <\/div>\n                        <div class=\"uc-milestone-scroll\" @scroll=\"hideMilestoneFloatingTip\">\n                            <div class=\"uc-milestones\">\n                                <div class=\"uc-milestones-track\" aria-hidden=\"true\"><\/div>\n                                <div class=\"uc-milestones-track-active\" :style=\"{ width: milestoneProgressWidth }\" aria-hidden=\"true\"><\/div>\n                                <div\n                                    v-for=\"node in milestoneNodesForDisplay\"\n                                    :key=\"node.count\"\n                                    class=\"uc-milestone-node\"\n                                    :class=\"{ 'is-complete': isMilestoneNodeCompleted(node), 'is-big': !!node.isBig, 'is-next': !!node.isNext || milestoneNextNodeCount === node.count, 'is-current': !!node.isCurrent }\"\n                                    @mouseenter=\"showMilestoneFloatingTip(node, $event)\"\n                                    @mouseleave=\"hideMilestoneFloatingTip\"\n                                    @click.stop=\"showMilestoneFloatingTip(node, $event)\"\n                                >\n                                    <span>{{ node.count }}<\/span>\n                                    <strong v-if=\"node.tier\">{{ node.tier }}<\/strong>\n                                    <a\n                                        v-if=\"node.count === 5 && node.applyUrl && canShowMilestoneReward(node)\"\n                                        class=\"uc-milestone-ambassador-link\"\n                                        :href=\"node.applyUrl\"\n                                        target=\"_blank\"\n                                        rel=\"noopener noreferrer\"\n                                    >\n                                        {{ t('campus_ambassador_application', 'Campus Ambassador Application') }}\n                                    <\/a>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                        <div v-if=\"activeMilestoneTipNode\" class=\"uc-milestone-floating-tip\" :class=\"activeMilestoneTipClass\" :style=\"activeMilestoneTipStyle\">\n                            <p class=\"uc-milestone-tip-title\">{{ getTierDisplayName(activeMilestoneTipNode.tooltipTier || activeMilestoneTipNode.tier || 'Tier') }} {{ t('tier', 'Tier') }}<\/p>\n                            <p class=\"uc-milestone-tip-sub\">{{ t('requires', 'Requires') }}: {{ activeMilestoneTipNode.count }} {{ Number(activeMilestoneTipNode.count) > 1 ? t('referrals_unit', 'Referrals') : t('referral_unit', 'Referral') }}<\/p>\n                            <template v-if=\"canShowMilestoneReward(activeMilestoneTipNode)\">\n                                <p class=\"uc-milestone-tip-base\">{{ t('reward', 'Reward') }}: {{ localizeRewardText(getMilestoneBaseReward(activeMilestoneTipNode)) }}<\/p>\n                                <p v-if=\"activeMilestoneTipNode.extra && activeMilestoneTipNode.extra !== 'None'\" class=\"uc-milestone-tip-extra\">{{ activeMilestoneTipNode.extra }}<\/p>\n                            <\/template>\n                            <p v-else class=\"uc-milestone-tip-locked\">{{ t('pending_unlock', 'Pending unlock') }}<\/p>\n                        <\/div>\n                    <\/section>\n\n                    <div class=\"uc-two-column uc-narrow-left\">\n                        <section class=\"uc-page-stack\" aria-label=\"Earnings\">\n                            <div class=\"uc-earn-card\">\n                                <div><h4>{{ t('total_earnings', 'Total Earnings') }}<\/h4><p>{{ t('available_balance', 'Available Balance') }}<\/p><\/div>\n                                <button type=\"button\" class=\"uc-button uc-button-primary\" @click=\"openClaimRewardModal\">{{ t('claim_rewards', 'Claim Rewards') }}<\/button>\n                            <\/div>\n                            <div class=\"uc-card uc-earn-list\">\n                                <div><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-coffee\"><\/use><\/svg><span><small>{{ t('total_rewards', 'Total Rewards') }}<\/small><strong class=\"uc-reward-summary\">{{ referralHistoryRewardText }}<\/strong><\/span><\/div>\n                                <div><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-dollar\"><\/use><\/svg><span><small>{{ t('pending_rewards', 'Pending Rewards') }}<\/small><strong class=\"uc-reward-summary\">{{ referralPendingRewardText }}<\/strong><\/span><\/div>\n                            <\/div>\n                        <\/section>\n\n                        <section class=\"uc-card uc-referral-history\" aria-label=\"Referral History\">\n                            <h3>{{ t('referral_history', 'Referral History') }}<\/h3>\n                            <div v-for=\"(referral, index) in referrals\" :key=\"referral.id || referral.user + '-' + index\" class=\"uc-referral-history-row\" :class=\"referral.roleClass\">\n                                <span class=\"uc-referral-id\">{{ referral.enrollmentId }}<\/span>\n                                <strong class=\"uc-referral-main\">\n                                    <span><b>{{ referral.user }}<\/b><i class=\"uc-referral-role\">{{ referral.roleLabel }}<\/i><\/span>\n                                    <small>{{ referral.date }}<\/small>\n                                <\/strong>\n                                <span class=\"uc-referral-status-stack\">\n                                    <em v-for=\"(tag, tagIndex) in referral.statusTags\" :key=\"(referral.id || index) + '-tag-' + tagIndex\" class=\"uc-status\" :class=\"tag.className\"><svg class=\"uc-icon\" width=\"12\" height=\"12\" viewbox=\"0 0 24 24\"><use :href=\"tag.icon || '#uc-i-check-circle'\"><\/use><\/svg> {{ tag.label }}<\/em>\n                                <\/span>\n                            <\/div>\n                            <div class=\"uc-pagination\"><button type=\"button\" :disabled=\"referralCurrentPage <= 1\" @click=\"changeReferralPage(referralCurrentPage - 1)\"><svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-left\"><\/use><\/svg> {{ t('prev', 'Prev') }}<\/button><span>{{ referralCurrentPage }} \/ {{ referralPageCount }}<\/span><button type=\"button\" :disabled=\"referralCurrentPage >= referralPageCount\" @click=\"changeReferralPage(referralCurrentPage + 1)\">{{ t('next', 'Next') }} <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg><\/button><\/div>\n                        <\/section>\n                    <\/div>\n                <\/div>\n            <\/section>\n\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'ugc' }\">\n                <div class=\"uc-page-stack\">\n                    <section class=\"uc-banner uc-banner-ugc\" aria-label=\"UGC Banner\">\n                        <h2>{{ t('ugc_banner_title', 'Share Your Experience & Win Big!') }} \ud83c\udf89<\/h2>\n                        <p>{{ t('ugc_banner_desc', 'We value your feedback. Share your GoGlobalSafe experience on popular social platforms, submit your screenshot, and join our exclusive WeChat group for weekly lotteries and extra rewards.') }}<\/p>\n                    <\/section>\n\n                    <section class=\"uc-platform-grid\" aria-label=\"Supported Platforms\">\n                        <button\n                            v-for=\"platform in ugcPlatformsForDisplay\"\n                            :key=\"platform.id\"\n                            type=\"button\"\n                            class=\"uc-platform-card\"\n                            :class=\"{ 'is-selected': selectedPlatform === platform.id }\"\n                            @click=\"selectUgcPlatform(platform.id)\"\n                        >\n                            <span :class=\"platform.className\">\n                                <img v-if=\"platform.iconUrl\" :src=\"platform.iconUrl\" :alt=\"platform.name + ' icon'\" style=\"width:20px;height:20px;object-fit:cover;border-radius:4px;display:block;\">\n                                <svg v-else class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use :href=\"'#uc-i-' + platform.icon\"><\/use><\/svg>\n                            <\/span>\n                            <strong>{{ platform.name }}<\/strong>\n                            <p>{{ platform.rewardText }}<\/p>\n                            <em\n                                role=\"button\"\n                                tabindex=\"0\"\n                                @click.stop=\"openUgcPlatformByJumpUrl(platform)\"\n                                @keydown.enter.stop.prevent=\"openUgcPlatformByJumpUrl(platform)\"\n                            >\n                                {{ platform.actionText }} <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-external\"><\/use><\/svg>\n                            <\/em>\n                        <\/button>\n                        <div v-if=\"!ugcPlatformsForDisplay.length\" class=\"uc-empty-state\">{{ t('no_supported_platforms', 'No supported platforms available right now.') }}<\/div>\n                    <\/section>\n\n                    <section class=\"uc-card uc-upload-card\" aria-label=\"Upload Screenshot\">\n                        <div class=\"uc-card-head\">\n                            <h3>{{ t('submit_screenshot', 'Submit Screenshot') }}<\/h3>\n                            <span class=\"uc-muted-badge\">{{ ugcSelectedPlatform ? ugcSelectedPlatform.name : 'Select a platform first' }}<\/span>\n                        <\/div>\n                        <div class=\"uc-tip-box\">\n                            <div style=\"display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;\">\n                                <strong>{{ t('tips_templates', 'Tips & Templates') }}<\/strong>\n                                <button\n                                    type=\"button\"\n                                    class=\"uc-soft-button\"\n                                    :disabled=\"ugcGenerating || ugcGenerateTodayRemainingCount <= 0 || !ugcSelectedPlatform\"\n                                    @click=\"generateUgcTemplate\"\n                                >\n                                    {{ ugcGenerating ? t('generating', 'Generating...') : t('generate_copy', 'Generate Copy') }} ({{ ugcGenerateTodayRemainingCount }}\/3)\n                                <\/button>\n                            <\/div>\n                            <p v-if=\"!ugcSelectedPlatform\">{{ t('select_platform_first', 'Select a platform first, then click Generate Copy.') }}<\/p>\n                            <p v-else-if=\"ugcGeneratedTemplatesForDisplay.length === 0\">{{ t('no_generated_copy', 'No generated copy yet. You can generate up to 3 times per day.') }}<\/p>\n                            <div v-else style=\"display:grid;gap:10px;margin-top:8px;\">\n                                <div\n                                    v-for=\"item in ugcGeneratedTemplatesForDisplay\"\n                                    :key=\"item.localId\"\n                                    style=\"display:block;text-align:left;padding:10px;border:1px solid #bfd4ff;border-radius:10px;background:#fff;\"\n                                >\n                                    <div style=\"display:flex;align-items:flex-start;justify-content:space-between;gap:10px;\">\n                                        <strong style=\"display:block;margin-bottom:6px;\">{{ item.title || ('Template #' + item.templateId) }}<\/strong>\n                                        <button\n                                            type=\"button\"\n                                            class=\"uc-soft-button\"\n                                            style=\"padding:4px 10px;min-width:64px;line-height:1.2;\"\n                                            @click.stop=\"copyUgcTemplateContent(item)\"\n                                        >\n                                            Copy\n                                        <\/button>\n                                    <\/div>\n                                    <span style=\"display:block;line-height:1.6;color:#213656;\">{{ item.content }}<\/span>\n                                    <small style=\"display:block;margin-top:6px;color:#4b6185;\">{{ item.generatedAtText }}<\/small>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n\n                        <input type=\"file\" id=\"ugcScreenshotInput\" accept=\".png,.jpg,.jpeg,.pdf\" style=\"display:none;\" @change=\"handleUgcFileSelect\">\n                        <button type=\"button\" class=\"uc-upload-box\" @click=\"triggerUgcFileSelect\">\n                            <svg class=\"uc-icon\" width=\"28\" height=\"28\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-upload\"><\/use><\/svg>\n                            <strong>{{ ugcSelectedFileName || t('click_upload_screenshot', 'Click to upload screenshot') }}<\/strong>\n                            <span>{{ ugcSelectedFileSizeText || 'PNG, JPG, JPEG, PDF (Max 10MB)' }}<\/span>\n                        <\/button>\n\n                        <div v-if=\"ugcNeedShareLink\" class=\"uc-form uc-form-single uc-ugc-share-link\">\n                            <label>\n                                <span>{{ t('xiaohongshu_share_link', 'Xiaohongshu Share Link') }}<\/span>\n                                <input type=\"url\" v-model.trim=\"ugcForm.shareLink\" maxlength=\"500\" :placeholder=\"t('enter_xiaohongshu_share_link', 'Paste your Xiaohongshu post link')\">\n                                <small>{{ t('xiaohongshu_share_link_hint', 'Required for Xiaohongshu submissions.') }}<\/small>\n                            <\/label>\n                        <\/div>\n\n                        <div v-if=\"ugcNeedAlipayFields\" class=\"uc-form\">\n                            <label>\n                                <span>{{ t('alipay_account_short', 'Alipay Account') }}<\/span>\n                                <input type=\"text\" v-model.trim=\"ugcForm.alipayAccount\" maxlength=\"120\" :placeholder=\"t('enter_alipay_account', 'Enter your Alipay account')\">\n                            <\/label>\n                            <label>\n                                <span>{{ t('alipay_real_name', 'Alipay Real Name') }}<\/span>\n                                <input type=\"text\" v-model.trim=\"ugcForm.alipayRealName\" maxlength=\"120\" :placeholder=\"t('enter_alipay_real_name', 'Enter real name matching Alipay')\">\n                            <\/label>\n                        <\/div>\n\n                        <label class=\"uc-consent\">\n                            <input type=\"checkbox\" v-model=\"ugcForm.agreeTerms\">\n                            <span>{{ t('ugc_consent', 'I agree that GoGlobalSafe may review this screenshot for reward verification.') }}<\/span>\n                        <\/label>\n                        <button type=\"button\" class=\"uc-button uc-button-black uc-full\" :disabled=\"ugcSubmitting\" @click=\"submitUgcSubmission\">\n                            {{ ugcSubmitting ? t('submitting', 'Submitting...') : t('submit_screenshot', 'Submit Screenshot') }}\n                        <\/button>\n                    <\/section>\n\n                    <section class=\"uc-card uc-success-card\" :class=\"{ 'is-open': ugcSuccess }\">\n                        <button type=\"button\" class=\"uc-success-close\" :aria-label=\"t('close', 'Close')\" @click=\"ugcSuccess = false\">\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n                        <\/button>\n                        <div class=\"uc-success-copy\">\n                            <span class=\"uc-success-icon\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check\"><\/use><\/svg><\/span>\n                            <h3>{{ t('screenshot_uploaded_success', 'Screenshot Uploaded Successfully!') }}<\/h3>\n                            <p>{{ t('ugc_success_desc', 'Thank you for sharing your experience. We are reviewing your submission, and your reward will be sent soon.') }}<\/p>\n                            <div class=\"uc-success-wechat\">\n                                <h4>\n                                    <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-qrcode\"><\/use><\/svg>\n                                    {{ t('join_wechat_group', 'Join the WeChat Group') }}\n                                <\/h4>\n                                <ul>\n                                    <li>{{ t('wechat_group_benefit_1', 'Weekly lucky draws for active members.') }}<\/li>\n                                    <li>{{ t('wechat_group_benefit_2', 'Fast-track support from the GoGlobalSafe team.') }}<\/li>\n                                    <li>{{ t('wechat_group_benefit_3', 'Earn double rewards for future UGC events!') }}<\/li>\n                                <\/ul>\n                            <\/div>\n                        <\/div>\n                        <div class=\"uc-success-qr-panel\">\n                            <div class=\"uc-qr-box\">\n                                <img v-if=\"!ugcGroupQrFailed\" :src=\"ugcGroupQrUrl\" alt=\"UGC WeChat group QR\" @error=\"handleUgcGroupQrError\">\n                                <img v-else :src=\"ugcGroupQrFallbackUrl\" alt=\"UGC WeChat group QR\">\n                            <\/div>\n                            <span>{{ t('scan_to_join_group', 'Scan to Join Group') }}<\/span>\n                        <\/div>\n                    <\/section>\n\n                    <section class=\"uc-card uc-review-history\">\n                        <h3>{{ t('review_history', 'Review History') }}<\/h3>\n                        <div v-for=\"item in ugcHistoryForDisplay\" :key=\"item.id\">\n                            <img\n                                v-if=\"item.platformIconUrl\"\n                                :src=\"item.platformIconUrl\"\n                                :alt=\"item.platform + ' icon'\"\n                                style=\"width:24px;height:24px;object-fit:cover;border-radius:6px;\"\n                            >\n                            <svg v-else class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-book\"><\/use><\/svg>\n                            <span>\n                                <strong>{{ item.platform }}<\/strong>\n                                <small>{{ item.createdAtDisplay }} \u00b7 ID: {{ item.displayId }}<\/small>\n                                <small v-if=\"item.isReviewPending\">{{ item.rewardStatusLabel }}<\/small>\n                                <small v-if=\"item.rejectReason\">Reject reason: {{ item.rejectReason }}<\/small>\n                            <\/span>\n                            <em class=\"uc-status\" :class=\"item.reviewStatusClass\">{{ item.reviewStatusLabel }}<\/em>\n                        <\/div>\n                        <div v-if=\"!ugcHistoryForDisplay.length\" class=\"uc-empty-state\">{{ t('no_ugc_history', 'No UGC submission history yet.') }}<\/div>\n                    <\/section>\n                <\/div>\n            <\/section>\n\n            <section class=\"uc-panel\" :class=\"{ 'is-active': activeTab === 'help' }\">\n                <div class=\"uc-two-column uc-wide-left\">\n                    <div class=\"uc-page-stack\">\n                        <section class=\"uc-card uc-ticket-card\" aria-label=\"Submit a Ticket\">\n                            <div class=\"uc-panel-intro\">\n                                <span><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-message\"><\/use><\/svg><\/span>\n                                <div><h3>{{ t('ticket_submit_title', 'Submit a Ticket') }}<\/h3><p>{{ t('ticket_submit_desc', 'Our support team will help you with plan, billing, waiver, or claim questions.') }}<\/p><\/div>\n                            <\/div>\n                            <form class=\"uc-form uc-ticket-form\" action=\"\">\n                                <label>\n                                    <span>{{ t('ticket_category', 'Category') }} <b>*<\/b><\/span>\n                                    <select id=\"ticketCategory\" v-model=\"selectedParentId\" @change=\"selectedSubId = ''\">\n                                        <option value=\"\">{{ t('ticket_category_select', 'Select category') }}<\/option>\n                                        <option v-for=\"category in ticketCategories\" :key=\"category.id\" :value=\"category.id\">{{ formatTicketCategoryName(category) }}<\/option>\n                                    <\/select>\n                                <\/label>\n                                <div class=\"uc-ticket-subcategory\" :class=\"{ 'is-empty': subCategories.length === 0 }\">\n                                    <span>{{ t('ticket_subcategory', 'Subcategory') }} <b>*<\/b><\/span>\n                                    <div v-if=\"subCategories.length\" id=\"ticketSubcategory\" class=\"uc-ticket-radio-grid\">\n                                        <label v-for=\"sub in subCategories\" :key=\"sub.id\">\n                                            <input type=\"radio\" name=\"ticketSubcategory\" v-model=\"selectedSubId\" :value=\"sub.id\">\n                                            <span>{{ formatTicketCategoryName(sub) }}<\/span>\n                                        <\/label>\n                                    <\/div>\n                                    <small v-else>{{ t('ticket_subcategory_select', 'Select a category first.') }}<\/small>\n                                <\/div>\n                                <label class=\"uc-form-wide\"><span>{{ t('ticket_subject', 'Subject') }}<\/span><input type=\"text\" v-model=\"ticketSubject\" :placeholder=\"t('ticket_subject_placeholder', 'Briefly describe your question')\"><\/label>\n                                <label class=\"uc-form-wide\"><span>{{ t('ticket_description', 'Description') }}<\/span><textarea rows=\"6\" v-model=\"ticketDescription\" :placeholder=\"t('ticket_description_placeholder', 'Tell us what happened and what you need help with')\"><\/textarea><\/label>\n                                <label class=\"uc-form-wide\">\n                                    <span>{{ t('ticket_attachments', 'Attachments (Optional)') }}<\/span>\n                                    <input id=\"ticketFileUploadInput\" type=\"file\" multiple style=\"display:none;\" @change=\"handleTicketFileSelect\">\n                                    <div class=\"uc-ticket-attach-box\">\n                                        <button type=\"button\" class=\"uc-button uc-button-plain uc-ticket-upload-button\" @click=\"triggerTicketFileSelect\">\n                                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-upload\"><\/use><\/svg>\n                                            {{ t('ticket_add_files', 'Add Files') }}\n                                        <\/button>\n                                        <small>{{ t('ticket_upload_hint', 'PDF\/JPG\/PNG\/HEIC\/CSV, up to 10MB per file.') }}<\/small>\n                                    <\/div>\n                                <\/label>\n                                <div v-if=\"uploadedTicketFiles.length > 0\" class=\"uc-file-list\">\n                                    <div v-for=\"(file, index) in uploadedTicketFiles\" :key=\"'ticket-file-' + index\" class=\"uc-file-item\">\n                                        <div class=\"uc-file-info\">\n                                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file\"><\/use><\/svg>\n                                            <div>\n                                                <strong>{{ file.name }}<\/strong>\n                                                <small>{{ file.size || '-' }}<\/small>\n                                            <\/div>\n                                        <\/div>\n                                        <div class=\"uc-file-actions\">\n                                            <span v-if=\"file.status === 'loading'\" class=\"uc-upload-progress\">{{ file.percent || 0 }}%<\/span>\n                                            <span v-else-if=\"file.status === 'success'\" class=\"uc-status uc-status-green\">\n                                                <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg>\n                                                {{ t('ticket_uploaded', 'Uploaded') }}\n                                            <\/span>\n                                            <span v-else-if=\"file.status === 'fail' || file.status === 'error'\" class=\"uc-status uc-status-red\">\n                                                <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n                                                {{ t('ticket_failed', 'Failed') }}\n                                            <\/span>\n                                            <button type=\"button\" class=\"uc-file-remove\" @click=\"removeTicketFile(index)\">\n                                                <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n                                            <\/button>\n                                        <\/div>\n                                    <\/div>\n                                <\/div>\n                                <label class=\"uc-consent uc-form-wide\" style=\"margin-top:8px;margin-bottom:8px;\">\n                                    <input type=\"checkbox\" v-model=\"ticketConfirm\">\n                                    <span>{{ t('ticket_confirm', 'I confirm this information is accurate and support can contact me for follow-up.') }}<\/span>\n                                <\/label>\n                                <div class=\"uc-form-actions uc-form-wide\"><button type=\"button\" class=\"uc-button uc-button-primary\" @click=\"addTicket\"><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-send\"><\/use><\/svg> {{ t('submit', 'Submit') }}<\/button><\/div>\n                            <input type=\"hidden\" name=\"trp-form-language\" value=\"zh\"\/><\/form>\n                        <\/section>\n                        <section class=\"uc-card uc-recent-card uc-ticket-record-card\" aria-label=\"Ticket Records\">\n                            <div class=\"uc-ticket-record-head\">\n                                <h3>{{ t('ticket_record', 'Ticket Record') }}<\/h3>\n                                <span>{{ tk_total || ticket_list.length }} total<\/span>\n                            <\/div>\n                            <div v-if=\"ticket_list.length\" class=\"uc-ticket-table\">\n                                <button v-for=\"ticket in ticket_list\" :key=\"ticket.id || ticket.ticket_no\" type=\"button\" class=\"uc-ticket-row\" @click=\"openTicketDetail(ticket)\">\n                                    <span class=\"uc-ticket-id-pill\">{{ ticket.ticket_no || ticket.id || '-' }}<\/span>\n                                    <strong class=\"uc-ticket-main\">\n                                        <span><b>{{ ticket.subject || ticket.title || t('support_ticket', 'Support Ticket') }}<\/b><i>{{ getTicketCategoryLabel(ticket) }}<\/i><\/span>\n                                        <small>{{ formatDateShort(ticket.created_at || ticket.createdAt) || '-' }}<\/small>\n                                    <\/strong>\n                                    <span class=\"uc-ticket-status-stack\">\n                                        <em class=\"uc-status\" :class=\"getTicketStatusClass(ticket.status)\">{{ getTicketStatusLabel(ticket.status, ticket.status_text || ticket.statusText) }}<\/em>\n                                        <span class=\"uc-ticket-action\">\n                                        <i v-if=\"ticket.is_ticket\" class=\"uc-ticket-unread-dot\" aria-hidden=\"true\"><\/i>\n                                        {{ t('view', 'View') }}\n                                        <svg class=\"uc-icon\" width=\"14\" height=\"14\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-eye\"><\/use><\/svg>\n                                        <\/span>\n                                    <\/span>\n                                <\/button>\n                            <\/div>\n                            <div v-else class=\"uc-empty-state\">{{ t('no_ticket_records', 'No ticket records yet.') }}<\/div>\n                            <div v-if=\"ticketPageCount > 1\" class=\"uc-pagination uc-ticket-pagination\">\n                                <button type=\"button\" :disabled=\"tk_currentPage <= 1\" @click=\"TicketPageChange(tk_currentPage - 1)\"><svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-left\"><\/use><\/svg> {{ t('prev', 'Prev') }}<\/button>\n                                <span>{{ tk_currentPage }} \/ {{ ticketPageCount }}<\/span>\n                                <button type=\"button\" :disabled=\"tk_currentPage >= ticketPageCount\" @click=\"TicketPageChange(tk_currentPage + 1)\">{{ t('next', 'Next') }} <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg><\/button>\n                            <\/div>\n                        <\/section>\n                    <\/div>\n                    <aside class=\"uc-card uc-settings-card\">\n                        <div class=\"uc-panel-intro\">\n                            <span><svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-lock\"><\/use><\/svg><\/span>\n                            <h3>{{ t('account_settings', 'Account Settings') }}<\/h3>\n                        <\/div>\n                        <button type=\"button\" @click=\"openChangePasswordModal\"><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-lock\"><\/use><\/svg><span><strong>{{ t('change_password', 'Change Password') }}<\/strong><small>{{ locale === 'zh' ? '\u5b89\u5168\u66f4\u65b0\u8d26\u53f7\u5bc6\u7801' : 'Update account password securely' }}<\/small><\/span><\/button>\n                        <button type=\"button\" class=\"uc-settings-mfa-button\" @click=\"openMfaModal\">\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-shield\"><\/use><\/svg>\n                            <span>\n                                <strong>{{ t('two_step_verification', 'Two-Step Verification') }}<\/strong>\n                                <small>{{ mfaSettingsSummary }}<\/small>\n                            <\/span>\n                            <em class=\"uc-settings-status\" :class=\"{ 'is-on': isMfaEnabled }\">{{ mfaStatusBadge }}<\/em>\n                        <\/button>\n                    <\/aside>\n                <\/div>\n            <\/section>\n\n        <\/div>\n    <\/main>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'rules' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box\">\n            <div class=\"uc-card-head\"><h3>{{ t('reward_rules', 'Reward Rules') }}<\/h3><button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button><\/div>\n            <div class=\"uc-modal-body uc-rules-modal-body\">\n                <div class=\"uc-rules-grid\">\n                    <article v-for=\"region in visibleReferralRules\" :key=\"region.region\" class=\"uc-rule-region\" :class=\"`is-${region.key}`\">\n                        <div class=\"uc-rule-region-head\">\n                            <h4>{{ region.region }}<\/h4>\n                            <span class=\"uc-rule-badge\">{{ localizeRuleText(region.badge) }}<\/span>\n                        <\/div>\n                        <section v-for=\"section in region.sections\" :key=\"section.title\" class=\"uc-rule-section\" :class=\"{ 'is-highlight': section.highlight }\">\n                            <strong>{{ localizeRuleText(section.title) }}<\/strong>\n                            <ul>\n                                <li v-for=\"line in section.lines\" :key=\"line\">{{ localizeRuleText(line) }}<\/li>\n                            <\/ul>\n                        <\/section>\n                    <\/article>\n                <\/div>\n            <\/div>\n            <div class=\"uc-modal-foot\"><button type=\"button\" class=\"uc-button uc-button-black\" @click=\"openModal = ''\">{{ t('got_it', 'Got It') }}<\/button><\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal uc-onboarding-modal\" :class=\"{ 'is-open': openModal === 'onboardingGuide' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small uc-onboarding-box\">\n            <div class=\"uc-card-head\">\n                <h3>{{ t('onboarding_title', 'A quick start guide') }}<\/h3>\n                <button type=\"button\" @click=\"dismissOnboardingGuide\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body uc-onboarding-body\">\n                <p>{{ t('onboarding_desc', 'Three small things help you get set up faster.') }}<\/p>\n                <div class=\"uc-onboarding-steps\">\n                    <article>\n                        <span><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-shield\"><\/use><\/svg><\/span>\n                        <div><strong>{{ t('onboarding_step_plan', 'Check your plan') }}<\/strong><small>{{ t('onboarding_step_plan_desc', 'Review coverage dates and network details.') }}<\/small><\/div>\n                    <\/article>\n                    <article>\n                        <span><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-download\"><\/use><\/svg><\/span>\n                        <div><strong>{{ t('onboarding_step_docs', 'Download documents') }}<\/strong><small>{{ t('onboarding_step_docs_desc', 'Keep your certificate and policy files ready.') }}<\/small><\/div>\n                    <\/article>\n                    <article>\n                        <span><svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file-check\"><\/use><\/svg><\/span>\n                        <div><strong>{{ t('onboarding_step_waiver', 'Submit waiver') }}<\/strong><small>{{ t('onboarding_step_waiver_desc', 'Use the required documents before your school deadline.') }}<\/small><\/div>\n                    <\/article>\n                <\/div>\n            <\/div>\n            <div class=\"uc-modal-foot\">\n                <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"dismissOnboardingGuide\">{{ t('skip', 'Skip') }}<\/button>\n                <button type=\"button\" class=\"uc-button uc-button-primary\" @click=\"startOnboardingGuide\">{{ t('start_with_my_plan', 'Start with My Plan') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'claimReward' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small\">\n            <div class=\"uc-card-head uc-claim-reward-head\"><h3>{{ t('claim_rewards', 'Claim Your Rewards') }}<\/h3><button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button><\/div>\n            <div v-if=\"claimRewardStep === 'options'\" class=\"uc-modal-body uc-claim-reward-body\">\n                <p>{{ referralPendingRewardText }}<\/p>\n                <button v-if=\"hasPendingStarbucksReward\" type=\"button\" class=\"uc-reward-option\" @click=\"claimRewardStep = 'starbucks'\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-coffee\"><\/use><\/svg><span><strong>{{ t('starbucks_gift_card', 'Starbucks Gift Card') }}<\/strong><small>{{ t('digital_code_instant', 'Digital code sent instantly') }}<\/small><\/span><i aria-hidden=\"true\"><\/i><\/button>\n                <button v-if=\"hasPendingCashReward\" type=\"button\" class=\"uc-reward-option\" @click=\"claimRewardStep = 'alipay'\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-dollar\"><\/use><\/svg><span><strong>{{ t('cash_via_alipay', 'Cash via Alipay') }}<\/strong><small>{{ t('alipay_transfer_time', 'Transferred in 1-2 business days') }}<\/small><\/span><i aria-hidden=\"true\"><\/i><\/button>\n            <\/div>\n            <div v-else-if=\"claimRewardStep === 'starbucks'\" class=\"uc-modal-body uc-claim-reward-body uc-claim-generate-body\">\n                <button type=\"button\" class=\"uc-claim-back\" @click=\"claimRewardStep = 'options'\">\u2190 {{ t('back_to_options', 'Back to options') }}<\/button>\n                <div class=\"uc-claim-large-icon\"><svg class=\"uc-icon\" width=\"32\" height=\"32\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-coffee\"><\/use><\/svg><\/div>\n                <h4>{{ t('claim', 'Claim') }} {{ pendingStarbucksRewardAmountText }} {{ t('starbucks_card', 'Starbucks Card') }}<\/h4>\n                <p>{{ t('redeem_digital_card_prefix', 'You are about to redeem a') }} {{ pendingStarbucksRewardAmountText }} {{ t('redeem_digital_card_suffix', 'digital gift card.') }}<\/p>\n                <button type=\"button\" class=\"uc-claim-generate-btn\" :disabled=\"claimRewardSubmitting\" @click=\"submitRewardRedeem('reward')\">{{ t('generate_digital_link', 'Generate Digital Link') }} <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-external\"><\/use><\/svg><\/button>\n            <\/div>\n            <div v-else-if=\"claimRewardStep === 'alipay'\" class=\"uc-modal-body uc-claim-reward-body uc-claim-alipay-body\">\n                <button type=\"button\" class=\"uc-claim-back\" @click=\"claimRewardStep = 'options'\">\u2190 {{ t('back_to_options', 'Back to options') }}<\/button>\n                <div class=\"uc-claim-form-title\"><span><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-users\"><\/use><\/svg><\/span><div><h4>{{ t('withdraw_to_alipay', 'Withdraw to Alipay') }}<\/h4><p>{{ t('provide_account_details', 'Provide your account details.') }}<\/p><\/div><\/div>\n                <label class=\"uc-claim-field\"><span>{{ t('alipay_account', 'Alipay Account (Phone \/ Email)') }}<\/span><input type=\"text\" v-model.trim=\"claimRewardAlipayAccount\" :placeholder=\"t('enter_valid_account', 'Enter valid account')\"><\/label>\n                <label class=\"uc-claim-field\"><span>{{ t('real_name_alipay', 'Real Name (Matches Alipay)') }}<\/span><input type=\"text\" v-model.trim=\"claimRewardAlipayName\" :placeholder=\"t('real_name_placeholder', 'e.g. Zhang San')\"><\/label>\n                <button type=\"button\" class=\"uc-claim-submit-btn\" :disabled=\"claimRewardSubmitting\" @click=\"submitRewardRedeem('reward_cash')\">{{ t('submit_withdrawal_request', 'Submit Withdrawal Request') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'emergencySos' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small\">\n            <div class=\"uc-card-head\"><h3>{{ t('emergency_sos', 'Emergency SOS') }}<\/h3><button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button><\/div>\n            <div class=\"uc-modal-body uc-sos-body\">\n                <p>{{ t('emergency_assistance', '24\/7 Global Emergency Assistance') }}<\/p>\n                <div class=\"uc-sos-phone-card\">\n                    <strong>{{ t('emergency_hotline', 'Emergency Hotline') }}<\/strong>\n                    <a class=\"uc-sos-phone-number\" :href=\"emergencyPhoneHref\">{{ emergencyPhoneDisplay }}<\/a>\n                    <span>{{ t('tap_to_call', 'Tap to call immediately for urgent help.') }}<\/span>\n                <\/div>\n            <\/div>\n            <div class=\"uc-modal-foot\">\n                <a class=\"uc-button uc-button-primary\" :href=\"emergencyPhoneHref\">{{ t('call_now', 'Call Now') }}<\/a>\n                <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"openModal = ''\">{{ t('close', 'Close') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'logoutConfirm' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small\">\n            <div class=\"uc-card-head\"><h3>{{ t('confirm_logout', 'Confirm Logout') }}<\/h3><button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button><\/div>\n            <div class=\"uc-modal-body\">\n                <p>{{ t('confirm_logout_desc', 'Are you sure you want to log out?') }}<\/p>\n            <\/div>\n            <div class=\"uc-modal-foot\">\n                <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"openModal = ''\">{{ t('cancel', 'Cancel') }}<\/button>\n                <button type=\"button\" class=\"uc-button uc-button-black\" @click=\"confirmLogout\">{{ t('logout', 'Log out') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'notificationDetail' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box\">\n            <div class=\"uc-card-head\">\n                <h3>{{ selectedNotificationDetail.title || t('notification', 'Notification') }}<\/h3>\n                <button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body uc-notification-detail-body\">\n                <p v-if=\"selectedNotificationDetail.subtitle\">{{ selectedNotificationDetail.subtitle }}<\/p>\n                <p v-if=\"selectedNotificationDetail.sent_at\"><strong>{{ t('sent_at', 'Sent at') }}:<\/strong> {{ selectedNotificationDetail.sent_at }}<\/p>\n                <div v-if=\"isNotificationDetailLoading\" class=\"uc-notification-detail-block\">{{ t('loading', 'Loading...') }}<\/div>\n                <div v-else-if=\"selectedNotificationDetail.content\" class=\"uc-notification-detail-block\" v-html=\"formattedNotificationDetailContent\"><\/div>\n                <div v-else class=\"uc-notification-detail-block\">\n                    <p>{{ selectedNotificationDetail.summary || 'No detail content.' }}<\/p>\n                <\/div>\n            <\/div>\n            <div class=\"uc-modal-foot\">\n                <button type=\"button\" class=\"uc-button uc-button-black\" @click=\"openModal = ''\">{{ t('close', 'Close') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'oshcPayOptions' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small\">\n            <div class=\"uc-card-head\">\n                <h3>{{ t('payment_options', 'Payment Options') }}<\/h3>\n                <button type=\"button\" @click=\"closeOshcPayModal\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body uc-oshc-pay-body\">\n                <p>{{ selectedOshcPayOrderTitle }}<\/p>\n                <template v-if=\"selectedPaymentOrderRegion === 'usa'\">\n                    <div v-if=\"usPaymentStep === 'wechat'\" class=\"uc-oshc-wechat-pay\">\n                        <span class=\"uc-oshc-wechat-title\">{{ t('wechat_pay', 'WeChat Pay') }}<\/span>\n                        <img :src=\"selectedUsWechatPayUrl\" alt=\"WeChat Pay QR code\">\n                        <div class=\"uc-wechat-pay-actions\">\n                            <button type=\"button\" class=\"uc-pay-text-button\" @click=\"usPaymentStep = 'options'\">{{ t('back_to_options', 'Back to options') }}<\/button>\n                            <button type=\"button\" class=\"uc-pay-text-button\" @click=\"goToUsEnrollmentPayment(selectedOshcPayOrder)\">{{ t('qr_code_expired', 'QR code expired?') }}<\/button>\n                        <\/div>\n                    <\/div>\n                    <template v-else>\n                        <button type=\"button\" class=\"uc-pay-option\" :disabled=\"isOshcPaySubmitting\" @click=\"submitUsOrderCreditCardPayment\">\n                            <span class=\"uc-pay-option-icon\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-credit-card\"><\/use><\/svg><\/span>\n                            <span class=\"uc-pay-option-copy\"><strong>{{ t('credit_card_payment', 'Credit Card Payment') }}<\/strong><small>{{ t('credit_card_payment_desc', 'Pay directly with Mastercard, Visa, UnionPay and more.') }}<\/small><\/span>\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                        <\/button>\n                        <button type=\"button\" class=\"uc-pay-option\" :disabled=\"isOshcPaySubmitting\" @click=\"handleUsWechatPay\">\n                            <span class=\"uc-pay-option-icon\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-qrcode\"><\/use><\/svg><\/span>\n                            <span class=\"uc-pay-option-copy\"><strong>{{ t('wechat_pay', 'WeChat Pay') }}<\/strong><small>{{ t('wechat_pay_desc', 'Scan the QR code with WeChat to complete payment.') }}<\/small><\/span>\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                        <\/button>\n                    <\/template>\n                <\/template>\n                <template v-else>\n                    <div v-if=\"selectedOshcWechatPayUrl\" class=\"uc-oshc-wechat-pay\">\n                        <span class=\"uc-oshc-wechat-title\">{{ t('wechat_pay', 'WeChat Pay') }}<\/span>\n                        <img :src=\"selectedOshcWechatPayUrl\" alt=\"WeChat Pay QR code\">\n                        <small>{{ t('wechat_pay_desc', 'Scan the QR code with WeChat to complete payment.') }}<\/small>\n                    <\/div>\n                    <button type=\"button\" class=\"uc-pay-option\" :disabled=\"isOshcPaySubmitting\" @click=\"submitOshcOrderPayment(3)\">\n                        <span class=\"uc-pay-option-icon\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-send\"><\/use><\/svg><\/span>\n                        <span class=\"uc-pay-option-copy\"><strong>{{ t('email_link_credit_card', 'Email Link (Credit Card)') }}<\/strong><small>{{ t('email_link_credit_card_desc', 'Receive a secure payment link by email.') }}<\/small><\/span>\n                        <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                    <\/button>\n                    <button v-if=\"isSelectedOshcPayOrderMedibank\" type=\"button\" class=\"uc-pay-option\" :disabled=\"isOshcPaySubmitting\" @click=\"submitOshcOrderPayment(1)\">\n                        <span class=\"uc-pay-option-icon\"><svg class=\"uc-icon\" width=\"24\" height=\"24\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-credit-card\"><\/use><\/svg><\/span>\n                        <span class=\"uc-pay-option-copy\"><strong>{{ t('credit_card_payment', 'Credit Card Payment') }}<\/strong><small>{{ t('credit_card_payment_desc', 'Pay directly with Mastercard, Visa, UnionPay and more.') }}<\/small><\/span>\n                        <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-chevron-right\"><\/use><\/svg>\n                    <\/button>\n                <\/template>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'oshcEmailQueued' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small uc-oshc-email-box\">\n            <div class=\"uc-modal-body uc-oshc-email-body\">\n                <div class=\"uc-oshc-email-icon\"><svg class=\"uc-icon\" width=\"28\" height=\"28\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg><\/div>\n                <h3>{{ t('check_payment_email', 'Please check your payment email shortly') }}<\/h3>\n                <p>{{ oshcEmailRedirectMessage }}<\/p>\n                <button type=\"button\" class=\"uc-button uc-button-primary uc-full\" @click=\"goToOshcOrderListNow\">{{ t('go_to_order_list_now', 'Go to Order List Now') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'contactSupport' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box\">\n            <div class=\"uc-card-head\">\n                <h3>{{ t('contact_support', 'Contact Support') }}<\/h3>\n                <button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body\">\n                <p>{{ t('contact_support_desc', 'Below are two ways to contact us.') }}<\/p>\n                <div class=\"uc-support-card\">\n                    <strong>{{ t('email', 'Email') }}<\/strong>\n                    <a class=\"uc-support-email\" :href=\"`mailto:${supportEmail}`\">{{ supportEmail }}<\/a>\n                <\/div>\n                <div class=\"uc-support-card\">\n                    <strong>{{ t('enterprise_wechat_scan', 'Enterprise WeChat Scan') }}<\/strong>\n                    <span>{{ t('wechat_scan_desc', 'Use Enterprise WeChat to scan the QR code.') }}<\/span>\n                    <div class=\"uc-support-qr-box\">\n                        <img v-if=\"!supportQrFailed\" :src=\"supportQrUrl\" alt=\"Enterprise WeChat QR\" @error=\"handleSupportQrError\">\n                        <img v-else :src=\"supportQrFallbackUrl\" alt=\"Fallback QR code\">\n                    <\/div>\n                <\/div>\n            <\/div>\n            <div class=\"uc-modal-foot\">\n                <button type=\"button\" class=\"uc-button uc-button-black\" @click=\"openModal = ''\">{{ t('got_it', 'Got It') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal uc-ticket-detail-modal\" :class=\"{ 'is-open': openModal === 'ticketDetail' && selectTicketDetail }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-ticket-detail-box\">\n            <div class=\"uc-card-head\">\n                <div>\n                    <h3>{{ t('ticket_detail', 'Ticket Detail') }}<\/h3>\n                    <p>{{ selectTicketDetail ? (selectTicketDetail.ticket_no || selectTicketDetail.id || '') : '' }}<\/p>\n                <\/div>\n                <button type=\"button\" @click=\"closeTicketDetail\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div v-if=\"selectTicketDetail\" class=\"uc-modal-body uc-ticket-detail-body\">\n                <div class=\"uc-ticket-detail-summary\">\n                    <div class=\"uc-ticket-detail-fields\">\n                        <div><span>{{ t('ticket_id', 'Ticket ID') }}:<\/span><strong>{{ selectTicketDetail.ticket_no || selectTicketDetail.id || '-' }}<\/strong><\/div>\n                        <div><span>{{ t('ticket_submitted_date', 'Submitted Date') }}:<\/span><strong>{{ formatDateShort(selectTicketDetail.created_at || selectTicketDetail.createdAt) || '-' }}<\/strong><\/div>\n                        <div><span>{{ t('ticket_category', 'Category') }}:<\/span><strong>{{ getTicketCategoryLabel(selectTicketDetail) }}<\/strong><\/div>\n                        <div><span>{{ t('ticket_subject', 'Subject') }}:<\/span><strong>{{ selectTicketDetail.subject || '-' }}<\/strong><\/div>\n                        <div><span>{{ t('ticket_description', 'Description') }}:<\/span><strong>{{ selectTicketDetail.content || selectTicketDetail.description || '-' }}<\/strong><\/div>\n                    <\/div>\n                    <div class=\"uc-ticket-progress-panel\">\n                        <div class=\"uc-ticket-status-title\">\n                            <span>{{ t('ticket_status', 'Ticket status') }}:<\/span>\n                            <strong :class=\"getTicketStatusClass(selectTicketDetail.status)\">{{ getTicketStatusLabel(selectTicketDetail.status, selectTicketDetail.status_text || selectTicketDetail.statusText) }}<\/strong>\n                        <\/div>\n                        <div class=\"uc-ticket-progress\">\n                            <div class=\"is-complete\"><i><\/i><span>{{ t('ticket_step_submit', 'Submit a ticket') }}<\/span><small>{{ formatDateShort(selectTicketDetail.created_at || selectTicketDetail.createdAt) }}<\/small><\/div>\n                            <div class=\"is-complete\"><i><\/i><span>{{ t('ticket_step_review', 'Under review') }}<\/span><small>{{ formatDateShort(selectTicketDetail.created_at || selectTicketDetail.createdAt) }}<\/small><\/div>\n                            <div :class=\"{ 'is-complete': Number(selectTicketDetail.status) === 2 }\"><i><\/i><span>{{ t('ticket_step_resolved', 'Resolved') }}<\/span><small>{{ Number(selectTicketDetail.status) === 2 ? formatDateShort(selectTicketDetail.updated_at || selectTicketDetail.updatedAt) : '' }}<\/small><\/div>\n                        <\/div>\n                    <\/div>\n                    <div class=\"uc-ticket-detail-files\">\n                        <span>{{ t('ticket_attachments', 'Attachments') }}:<\/span>\n                        <div v-if=\"getTicketFileList(selectTicketDetail).length\" class=\"uc-ticket-attachment-list\">\n                            <a v-for=\"(file, index) in getTicketFileList(selectTicketDetail)\" :key=\"'ticket-detail-file-' + index\" :href=\"getTicketFileUrl(file)\" target=\"_blank\" rel=\"noopener\">\n                                <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-file\"><\/use><\/svg>\n                                {{ file }}\n                            <\/a>\n                        <\/div>\n                        <small v-else>{{ t('no_attachments', 'No attachments.') }}<\/small>\n                    <\/div>\n                <\/div>\n                <div class=\"uc-ticket-chat\">\n                    <div ref=\"ticketChatContent\" class=\"uc-ticket-chat-log\">\n                        <template v-if=\"getTicketChatLogs(selectTicketDetail).length\">\n                            <div v-for=\"(log, index) in getTicketChatLogs(selectTicketDetail)\" :key=\"log.id || ('ticket-log-' + index)\" class=\"uc-ticket-chat-message\" :class=\"{ 'is-user': Number(log.type) !== 0 }\">\n                                <strong>{{ Number(log.type) === 0 ? t('customer_service', 'Customer Service') : dashboardDisplayName }}<\/strong>\n                                <p>{{ log.content }}<\/p>\n                                <small>{{ log.create_time || log.created_at || log.createdAt || '' }}<\/small>\n                            <\/div>\n                        <\/template>\n                        <div v-else class=\"uc-empty-state\">{{ t('no_messages', 'No messages yet.') }}<\/div>\n                    <\/div>\n                    <input id=\"addTicketFileUploadInput\" type=\"file\" multiple style=\"display:none;\" @change=\"handleAddTicketFile\">\n                    <div class=\"uc-ticket-chat-input\">\n                        <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"triggerAddTicketFile\" :title=\"t('add_attachment', 'Add attachment')\">\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-plus\"><\/use><\/svg>\n                        <\/button>\n                        <input type=\"text\" v-model=\"chatMessage\" :placeholder=\"t('type_message', 'Type your message')\">\n                        <button type=\"button\" class=\"uc-button uc-button-primary\" @click=\"sendMessage(selectTicketDetail.id)\">\n                            <svg class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-send\"><\/use><\/svg>\n                            {{ t('send', 'Send') }}\n                        <\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': ticketSuccess }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small uc-ticket-success-box\">\n            <div class=\"uc-card-head\">\n                <h3>{{ t('ticket_submitted_success', 'Ticket Submitted') }}<\/h3>\n                <button type=\"button\" @click=\"ticketSuccess = false\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body\">\n                <span class=\"uc-ticket-success-icon\"><svg class=\"uc-icon\" width=\"28\" height=\"28\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg><\/span>\n                <p>{{ t('ticket_submitted_success_desc', 'Your ticket has been submitted successfully.') }}<\/p>\n                <div v-if=\"ticketId\" class=\"uc-ticket-success-id\">\n                    <strong>{{ t('ticket_id', 'Ticket ID') }}<\/strong>\n                    <span>{{ ticketId }}<\/span>\n                <\/div>\n            <\/div>\n            <div class=\"uc-modal-foot\">\n                <button type=\"button\" class=\"uc-button uc-button-black\" @click=\"ticketSuccess = false\">{{ t('got_it', 'Got It') }}<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal\" :class=\"{ 'is-open': openModal === 'changePassword' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-modal-small\">\n            <div class=\"uc-card-head\">\n                <h3>{{ t('change_password', 'Change Password') }}<\/h3>\n                <button type=\"button\" @click=\"openModal = ''\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body\">\n                <label class=\"uc-claim-field\">\n                    <span>{{ t('old_password', 'Old Password') }}<\/span>\n                    <input type=\"password\" v-model.trim=\"changePwdForm.oldPassword\" :placeholder=\"t('old_password_placeholder', 'Enter old password')\">\n                <\/label>\n                <label class=\"uc-claim-field\">\n                    <span>{{ t('new_password', 'New Password') }}<\/span>\n                    <input type=\"password\" v-model.trim=\"changePwdForm.newPassword\" :placeholder=\"t('new_password_placeholder', 'Enter new password')\">\n                <\/label>\n                <label class=\"uc-claim-field\">\n                    <span>{{ t('confirm_password', 'Confirm Password') }}<\/span>\n                    <input type=\"password\" v-model.trim=\"changePwdForm.confirmPassword\" :placeholder=\"t('confirm_password_placeholder', 'Re-enter new password')\">\n                <\/label>\n                <div class=\"uc-modal-foot\" style=\"padding:16px 0 0;\">\n                    <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"openForgetPassword\">{{ t('forget_password', 'Forget Password?') }}<\/button>\n                    <button type=\"button\" class=\"uc-button uc-button-black\" :disabled=\"changePwdSubmitting\" @click=\"submitChangePassword\">\n                        {{ changePwdSubmitting ? t('submitting', 'Submitting...') : t('save', 'Save') }}\n                    <\/button>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal uc-mfa-modal\" :class=\"{ 'is-open': openModal === 'mfa' }\" aria-hidden=\"true\">\n        <div class=\"uc-modal-box uc-mfa-box\">\n            <div class=\"uc-card-head\">\n                <h3>{{ mfaModalTitle }}<\/h3>\n                <button type=\"button\" @click=\"closeMfaModal\"><svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg><\/button>\n            <\/div>\n            <div class=\"uc-modal-body uc-mfa-body\">\n                <div v-if=\"mfaView === 'setup'\" class=\"uc-mfa-setup\">\n                    <p>{{ t('mfa_setup_intro', 'Use an Authenticator App to scan the QR code. If you cannot scan it, enter the key manually.') }}<\/p>\n                    <div class=\"uc-mfa-setup-grid\">\n                        <div class=\"uc-mfa-qr-card\">\n                            <div ref=\"mfaQrRoot\" class=\"uc-mfa-qr\"><\/div>\n                            <small v-if=\"mfaQrRenderError\">{{ t('mfa_qr_fallback', 'QR code is unavailable. Please use the manual key.') }}<\/small>\n                        <\/div>\n                        <div class=\"uc-mfa-secret-card\">\n                            <span>{{ t('mfa_manual_key', 'Manual Entry Key') }}<\/span>\n                            <strong>{{ mfaSetup.manual_entry_key || '-' }}<\/strong>\n                            <button type=\"button\" class=\"uc-mfa-copy\" @click=\"copyMfaText(mfaSetup.manual_entry_key, t('mfa_key_copied', 'Setup key copied.'))\">\n                                <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-copy\"><\/use><\/svg>\n                                {{ t('copy', 'Copy') }}\n                            <\/button>\n                        <\/div>\n                    <\/div>\n                    <label class=\"uc-claim-field\">\n                        <span>{{ t('mfa_auth_code', 'Authenticator Code') }}<\/span>\n                        <input type=\"text\" inputmode=\"numeric\" autocomplete=\"one-time-code\" maxlength=\"8\" v-model.trim=\"mfaForm.setupCode\" :placeholder=\"t('mfa_code_placeholder', 'Enter 6-digit code')\">\n                    <\/label>\n                    <div class=\"uc-mfa-hint\">{{ t('mfa_setup_hint', 'After the app shows a 6-digit code, enter it here to finish setup.') }}<\/div>\n                    <div class=\"uc-modal-foot uc-mfa-actions\">\n                        <button type=\"button\" class=\"uc-button uc-button-plain\" @click=\"closeMfaModal\">{{ t('cancel', 'Cancel') }}<\/button>\n                        <button type=\"button\" class=\"uc-button uc-button-black\" :disabled=\"mfaSubmitting\" @click=\"confirmMfaSetup\">\n                            {{ mfaSubmitting ? t('submitting', 'Submitting...') : t('enable_two_step', 'Enable Two-Step Verification') }}\n                        <\/button>\n                    <\/div>\n                <\/div>\n\n                <div v-else-if=\"mfaView === 'recovery'\" class=\"uc-mfa-recovery\">\n                    <div class=\"uc-mfa-recovery-intro\">\n                        <span class=\"uc-mfa-recovery-icon\">\n                            <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-shield\"><\/use><\/svg>\n                        <\/span>\n                        <div>\n                            <strong>{{ t('mfa_recovery_intro_title', 'Keep these codes somewhere safe') }}<\/strong>\n                            <p>{{ t('mfa_recovery_intro', 'Save these recovery codes now. Each code can be used once if you cannot access your Authenticator App.') }}<\/p>\n                        <\/div>\n                    <\/div>\n                    <div class=\"uc-mfa-recovery-grid\">\n                        <button v-for=\"code in mfaRecoveryCodes\" :key=\"code\" type=\"button\" @click=\"copyMfaText(code, t('mfa_recovery_code_copied', 'Recovery code copied.'))\">\n                            <span>{{ code }}<\/span>\n                            <em>\n                                <svg class=\"uc-icon\" width=\"15\" height=\"15\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-copy\"><\/use><\/svg>\n                            <\/em>\n                        <\/button>\n                    <\/div>\n                    <div class=\"uc-modal-foot uc-mfa-actions\">\n                        <button type=\"button\" class=\"uc-button uc-button-plain uc-mfa-copy-all\" @click=\"copyMfaText(mfaRecoveryCodesText, t('mfa_recovery_codes_copied', 'Recovery codes copied.'))\">\n                            <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-copy\"><\/use><\/svg>\n                            {{ t('copy_all', 'Copy All') }}\n                        <\/button>\n                        <button type=\"button\" class=\"uc-button uc-button-black uc-mfa-saved-button\" @click=\"acknowledgeMfaRecoveryCodes\">\n                            <svg class=\"uc-icon\" width=\"17\" height=\"17\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check\"><\/use><\/svg>\n                            {{ t('mfa_saved_codes', 'I Have Saved These Codes') }}\n                        <\/button>\n                    <\/div>\n                <\/div>\n\n                <div v-else class=\"uc-mfa-manage\">\n                    <div class=\"uc-mfa-status-card\" :class=\"{ 'is-on': isMfaEnabled }\">\n                        <span>{{ mfaStatusBadge }}<\/span>\n                        <strong>{{ mfaStatusHeadline }}<\/strong>\n                        <p>{{ mfaStatusDescription }}<\/p>\n                    <\/div>\n                    <div v-if=\"isMfaEnabled\" class=\"uc-mfa-manage-form\">\n                        <label class=\"uc-claim-field\">\n                            <span>{{ t('mfa_auth_code', 'Authenticator Code') }}<\/span>\n                            <input type=\"text\" inputmode=\"numeric\" autocomplete=\"one-time-code\" maxlength=\"8\" v-model.trim=\"mfaForm.manageCode\" :placeholder=\"t('mfa_code_placeholder', 'Enter 6-digit code')\">\n                        <\/label>\n                        <label class=\"uc-claim-field\">\n                            <span>{{ t('mfa_recovery_code_optional', 'Recovery Code (for turning off)') }}<\/span>\n                            <input type=\"text\" v-model.trim=\"mfaForm.manageRecoveryCode\" :placeholder=\"t('mfa_recovery_code_placeholder', 'ABCD-EFGH-JKLM')\">\n                        <\/label>\n                        <div class=\"uc-mfa-hint\">{{ t('mfa_manage_hint', 'Regenerating recovery codes requires a current Authenticator code. Turning off can use either an Authenticator code or a recovery code.') }}<\/div>\n                        <div class=\"uc-modal-foot uc-mfa-actions\">\n                            <button type=\"button\" class=\"uc-button uc-button-plain\" :disabled=\"mfaSubmitting\" @click=\"regenerateMfaRecoveryCodes\">{{ t('regenerate_recovery_codes', 'Regenerate Recovery Codes') }}<\/button>\n                            <button type=\"button\" class=\"uc-button uc-button-black\" :disabled=\"mfaSubmitting\" @click=\"disableMfa\">{{ t('turn_off_two_step', 'Turn Off') }}<\/button>\n                        <\/div>\n                    <\/div>\n                    <div v-else class=\"uc-mfa-offline\">\n                        <p>{{ t('mfa_offline_desc', 'Two-step verification is optional for student accounts. You can turn it on to require an Authenticator code at your next login.') }}<\/p>\n                        <button type=\"button\" class=\"uc-button uc-button-black\" :disabled=\"mfaSubmitting\" @click=\"startMfaSetup\">\n                            {{ mfaSubmitting ? t('loading', 'Loading...') : t('enable_two_step', 'Enable Two-Step Verification') }}\n                        <\/button>\n                    <\/div>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"uc-modal uc-renew-modal\" :class=\"{ 'is-open': renewModalOpen }\" aria-hidden=\"true\">\n        <div class=\"uc-renew-modal-box\">\n            <button type=\"button\" class=\"uc-renew-close\" aria-label=\"\u5173\u95ed\" @click=\"closeRenewReminder\">\n                <svg class=\"uc-icon\" width=\"22\" height=\"22\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n            <\/button>\n            <div class=\"uc-renew-modal-icon\">\n                <svg class=\"uc-icon\" width=\"32\" height=\"32\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-gift\"><\/use><\/svg>\n            <\/div>\n            <h2>{{ t('renew_modal_title', 'Time to Renew Your Protection!') }}<\/h2>\n            <p>{{ t('renew_modal_desc', 'Your current global student insurance plan is expiring soon. Renew now to maintain seamless coverage.') }}<\/p>\n            <div class=\"uc-renew-modal-reward\">\n                <svg class=\"uc-icon\" width=\"20\" height=\"20\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-info\"><\/use><\/svg>\n                <strong>{{ t('renew_modal_reward', 'Renew today and get 400 RMB cashback + a $15 Starbucks Gift Card!') }}<\/strong>\n            <\/div>\n            <button type=\"button\" class=\"uc-renew-now\" @click=\"goToRenewNow\">{{ t('renew_now', 'Renew Now') }}<\/button>\n            <button type=\"button\" class=\"uc-renew-later\" @click=\"closeRenewReminder\">{{ t('remind_me_later', 'Remind Me Later') }}<\/button>\n        <\/div>\n    <\/div>\n\n    <transition name=\"uc-loading\">\n        <div v-if=\"globalLoadingVisible\" class=\"uc-global-loading\" role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n            <div class=\"uc-global-loading-card\">\n                <div class=\"uc-global-loading-orbit\">\n                    <span><\/span><span><\/span><span><\/span>\n                    <img decoding=\"async\" src=\"http:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2026\/05\/logo-pure.webp\" alt=\"GoGlobalSafe\" class=\"uc-global-loading-logo\">\n                <\/div>\n                <strong>{{ globalLoadingTitle }}<\/strong>\n                <p>{{ globalLoadingMessage }}<\/p>\n            <\/div>\n        <\/div>\n    <\/transition>\n\n    <transition name=\"uc-toast\">\n        <div v-if=\"toast.visible\" class=\"uc-toast\" :class=\"`is-${toast.type}`\" role=\"status\" aria-live=\"polite\">\n            <span class=\"uc-toast-icon\">\n                <svg v-if=\"toast.type === 'success'\" class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-check-circle\"><\/use><\/svg>\n                <svg v-else class=\"uc-icon\" width=\"18\" height=\"18\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-alert\"><\/use><\/svg>\n            <\/span>\n            <div class=\"uc-toast-body\">\n                <strong>{{ toast.title }}<\/strong>\n                <p>{{ toast.message }}<\/p>\n            <\/div>\n            <button type=\"button\" class=\"uc-toast-close\" :aria-label=\"t('close_message', 'Close message')\" @click=\"hideToast\">\n                <svg class=\"uc-icon\" width=\"16\" height=\"16\" viewbox=\"0 0 24 24\"><use href=\"#uc-i-x\"><\/use><\/svg>\n            <\/button>\n        <\/div>\n    <\/transition>\n<\/div>\n\n<script>\nconst { createApp } = Vue;\n\ncreateApp({\n    computed: {\n        text() {\n            const dict = this.i18n && this.i18n[this.locale] ? this.i18n[this.locale] : this.i18n.en;\n            return dict || {};\n        },\n        isMfaEnabled() {\n            return !!(this.mfaStatus && this.mfaStatus.enabled);\n        },\n        mfaStatusBadge() {\n            if (this.mfaLoading && !this.mfaStatusLoaded) return this.t('loading', 'Loading...');\n            return this.isMfaEnabled ? this.t('enabled', 'Enabled') : this.t('not_enabled', 'Not Enabled');\n        },\n        mfaSettingsSummary() {\n            if (this.mfaLoading && !this.mfaStatusLoaded) return this.t('mfa_status_loading', 'Checking security status...');\n            if (this.isMfaEnabled) {\n                const remaining = Number(this.mfaStatus.recovery_codes_remaining || 0);\n                return this.locale === 'zh'\n                    ? `\u5df2\u5f00\u542f\uff0c\u5269\u4f59 ${remaining} \u4e2a\u6062\u590d\u7801`\n                    : `Enabled, ${remaining} recovery codes left`;\n            }\n            return this.t('mfa_settings_summary_off', 'Add an Authenticator App for safer sign-in');\n        },\n        mfaModalTitle() {\n            if (this.mfaView === 'setup') return this.t('set_up_two_step', 'Set Up Two-Step Verification');\n            if (this.mfaView === 'recovery') return this.t('save_recovery_codes', 'Save Recovery Codes');\n            return this.t('two_step_verification', 'Two-Step Verification');\n        },\n        mfaStatusHeadline() {\n            if (this.isMfaEnabled) return this.t('mfa_enabled_headline', 'Two-step verification is on');\n            return this.t('mfa_disabled_headline', 'Two-step verification is off');\n        },\n        mfaStatusDescription() {\n            if (!this.isMfaEnabled) {\n                return this.t('mfa_disabled_desc', 'Your current login works as usual until you turn this on.');\n            }\n            const enabledAt = this.formatDateShort(this.mfaStatus.enabled_at);\n            const remaining = Number(this.mfaStatus.recovery_codes_remaining || 0);\n            if (this.locale === 'zh') {\n                return `${enabledAt ? `\u5f00\u542f\u4e8e ${enabledAt}\uff0c` : ''}\u5269\u4f59 ${remaining} \u4e2a\u6062\u590d\u7801\u3002`;\n            }\n            return `${enabledAt ? `Enabled ${enabledAt}, ` : ''}${remaining} recovery codes remaining.`;\n        },\n        mfaRecoveryCodesText() {\n            return (this.mfaRecoveryCodes || []).join('\\n');\n        },\n        dashboardCurrentOrder() {\n            const user = this.userInfo || {};\n            if (this.dashboardRegion === 'au' && user.au_order) return user.au_order;\n            if (user.usa_order) return user.usa_order;\n            if (user.au_order) return user.au_order;\n            return null;\n        },\n        dashboardDisplayName() {\n            const user = this.userInfo || {};\n            if (this.dashboardRegion === 'au') {\n                const raw = user.au_order && (user.au_order.firstName || user.au_order.name || user.au_order.user_name);\n                return raw || 'Student';\n            }\n            const member = user.usa_order && Array.isArray(user.usa_order.members) ? user.usa_order.members[0] : null;\n            const firstName = member && member.firstName ? String(member.firstName) : '';\n            const lastName = member && member.lastName ? String(member.lastName) : '';\n            const fullName = (firstName + ' ' + lastName).trim();\n            if (fullName) return fullName;\n            return user.user_name || user.name || 'Student';\n        },\n        dashboardSchoolName() {\n            const user = this.userInfo || {};\n            if (this.dashboardRegion === 'au') {\n                return (user.au_order && user.au_order.au_order) || (user.au_order && user.au_order.destination_name) || 'Australia Student';\n            }\n            const member = user.usa_order && Array.isArray(user.usa_order.members) ? user.usa_order.members[0] : null;\n            const contacts = member && Array.isArray(member.contacts) ? member.contacts : [];\n            const schoolContact = contacts[2] && contacts[2].value ? String(contacts[2].value).trim() : '';\n            return schoolContact || 'United States Student';\n        },\n        dashboardPlanName() {\n            const user = this.userInfo || {};\n            const order = this.dashboardCurrentOrder;\n            if (!order || !this.canUsePlanBenefits) return this.t('no_active_plan', 'No Active GGS Plan');\n            if (this.dashboardRegion === 'au') {\n                const auPlanName = order.destination_name\n                    || user.destination_name\n                    || (user.au_order && user.au_order.destination_name)\n                    || order.product_name\n                    || 'AU Plan';\n                return this.formatPlanName(auPlanName);\n            }\n            const usaPlanName = user.planName\n                || order.planName\n                || order.plan_name\n                || (order.product && (order.product.planName || order.product.plan_name || order.product.name))\n                || (user.product && (user.product.planName || user.product.plan_name || user.product.name))\n                || 'USA Plan';\n            return this.formatPlanName(usaPlanName);\n        },\n        dashboardCoveragePeriod() {\n            const order = this.dashboardCurrentOrder;\n            if (!order || !this.canUsePlanBenefits) return '-';\n            if (this.dashboardRegion === 'au') {\n                return this.formatDateRange(order.policyStartDate, order.policyEndDate);\n            }\n            const member = Array.isArray(order.members) ? order.members[0] : null;\n            const coverage = member && member.enrollmentCoverage ? member.enrollmentCoverage : {};\n            return this.formatDateRange(coverage.coverageStartDate, coverage.coverageEndDate);\n        },\n        dashboardSecondaryLabel() {\n            return this.dashboardRegion === 'au' ? this.t('policy_number', 'Policy Number') : this.t('network', 'Network');\n        },\n        dashboardSecondaryValue() {\n            const user = this.userInfo || {};\n            if (!this.canUsePlanBenefits) return '-';\n            if (this.dashboardRegion === 'au') {\n                const order = user.au_order || {};\n                return order.id || order.au_order || '-';\n            }\n            const order = this.dashboardCurrentOrder || {};\n            const product = order.product || user.product || {};\n            const rawNetwork = product.network || product.medical_provider_network || 'UnitedHealthcare';\n            const network = String(rawNetwork || '').trim() || 'UnitedHealthcare';\n            return \/\\bPPO\\b\/i.test(network) ? network : `${network} PPO`;\n        },\n        dashboardStatusLabel() {\n            const order = this.dashboardCurrentOrder;\n            if (!order) return this.t('pending', 'Pending');\n            if (this.dashboardRegion === 'au') {\n                return this.getAuStatusText(order.pay_status);\n            }\n            return this.getUsStatusText(order.pay_status);\n        },\n        dashboardStatusClass() {\n            const order = this.dashboardCurrentOrder;\n            if (!order) return 'uc-status-orange';\n            const payStatus = Number(order.pay_status);\n            if (this.dashboardRegion === 'au') {\n                if (payStatus === 2) return 'uc-status-green';\n                if (payStatus === 1 || payStatus === -2) return 'uc-status-blue';\n                if (payStatus === 4 || payStatus === -3) return 'uc-status-gray';\n                if (payStatus === -1) return 'uc-status-yellow';\n                return 'uc-status-orange';\n            }\n            if (payStatus === 1) return 'uc-status-green';\n            if (payStatus === 0) return 'uc-status-yellow';\n            if (payStatus === -1 || payStatus === 4) return 'uc-status-gray';\n            return 'uc-status-blue';\n        },\n        dashboardStatusBadgeClass() {\n            const statusClass = this.dashboardStatusClass || '';\n            return statusClass ? statusClass.replace('uc-status-', 'uc-badge-') : 'uc-badge-orange';\n        },\n        dashboardNeedAction() {\n            const order = this.dashboardCurrentOrder;\n            if (!order) return true;\n            const payStatus = Number(order.pay_status);\n            if (this.dashboardRegion === 'au') {\n                return !(payStatus === 2 || payStatus === 1);\n            }\n            return payStatus !== 1;\n        },\n        dashboardReferralCode() {\n            const user = this.userInfo || {};\n            return user.code || (user.usa_order && user.usa_order.referral_code) || (user.au_order && user.au_order.referral_code) || 'N\/A';\n        },\n        dashboardInvitedCount() {\n            const user = this.userInfo || {};\n            const recommendedOrderCounts = user.recommended_order_counts || {};\n            const regionCount = this.dashboardRegion === 'au' ? recommendedOrderCounts.au : recommendedOrderCounts.us;\n            if (typeof regionCount === 'number' && Number.isFinite(regionCount)) return regionCount;\n            if (typeof regionCount === 'string' && regionCount.trim() !== '' && !Number.isNaN(Number(regionCount))) return Number(regionCount);\n            const candidates = [\n                user.invite_num,\n                user.issued_num,\n                user.paid_num,\n            ];\n            for (const value of candidates) {\n                if (typeof value === 'number' && Number.isFinite(value)) return value;\n                if (typeof value === 'string' && value.trim() !== '' && !Number.isNaN(Number(value))) return Number(value);\n            }\n            return 0;\n        },\n        dashboardWaiveDeadlineText() {\n            const user = this.userInfo || {};\n            if (this.dashboardRegion !== 'au') {\n                const deadline = user.us_school_deadline && user.us_school_deadline.waive_deadline\n                    ? String(user.us_school_deadline.waive_deadline).trim()\n                    : '';\n                if (deadline) {\n                    return this.locale === 'zh' ? `\u8bf7\u5728 ${deadline} \u524d\u63d0\u4ea4\u8c41\u514d\u3002` : `Submit your waiver before ${deadline}.`;\n                }\n            }\n            return this.locale === 'zh' ? '\u8bf7\u5c3d\u65e9\u63d0\u4ea4\u8c41\u514d\u3002' : 'Submit your waiver as early as possible.';\n        },\n        waiveDeadlineRaw() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            const user = this.userInfo || {};\n            return String(\n                schoolWaive.waive_deadline\n                || (user.us_school_deadline && user.us_school_deadline.waive_deadline)\n                || ''\n            ).trim();\n        },\n        waiveDeadlineDisplayDate() {\n            const raw = this.waiveDeadlineRaw;\n            if (!raw) return '';\n            return this.formatDateLong(raw) || raw;\n        },\n        waiveDeadlineIntroText() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            const coverageStart = String(schoolWaive.coverage_start_date || '').trim();\n            const term = this.getTermLabelByDate(coverageStart);\n            if (this.locale === 'zh') return term ? `${term} \u8c41\u514d\u622a\u6b62\u65e5\u671f\u4e3a ` : '\u8c41\u514d\u622a\u6b62\u65e5\u671f\u4e3a ';\n            if (term) return `The waiver deadline for ${term} is `;\n            return 'The waiver deadline is ';\n        },\n        dashboardReferralPromoText() {\n            if (this.dashboardRegion === 'au') return '';\n            const user = this.userInfo || {};\n            const identityReward = user.current_identity_reward || {};\n            const rewardText = String(identityReward.reward || '').trim();\n            const rewardCashText = String(identityReward.reward_cash || '').trim();\n            const selfReward = this.normalizeRewardTextForDisplay(rewardText || rewardCashText);\n            if (!selfReward) return this.locale === 'zh' ? '\u597d\u53cb\u53ef\u5f97 $20 \u661f\u5df4\u514b\u5361\u3002' : 'Friends get a $20 Starbucks card.';\n            return this.locale === 'zh'\n                ? `\u4f60\u53ef\u5f97 ${selfReward}\u3002\u597d\u53cb\u53ef\u5f97 $20 \u661f\u5df4\u514b\u5361\u3002`\n                : `You get ${selfReward}. Friends get a $20 Starbucks card.`;\n        },\n        currentIdentityRewardText() {\n            const user = this.userInfo || {};\n            const identityReward = user.current_identity_reward && typeof user.current_identity_reward === 'object'\n                ? user.current_identity_reward\n                : {};\n            const rewardText = String(identityReward.reward || '').trim();\n            const rewardCashText = String(identityReward.reward_cash || '').trim();\n            return this.normalizeRewardTextForDisplay(rewardText || rewardCashText);\n        },\n        dashboardTopActions() {\n            const source = Array.isArray(this.topActions) ? this.topActions : [];\n            if (this.dashboardRegion === 'au') {\n                return source.filter(action => action && action.id !== 'emergency_sos');\n            }\n            return source;\n        },\n        currentPlanHeaderActionLabel() {\n            if (this.dashboardRegion === 'au' && !this.canUsePlanBenefits) {\n                return this.t('explore_oshc_plans', 'Explore OSHC Plans');\n            }\n            return this.t('view_coverage_details', 'View Coverage Details');\n        },\n        currentPlanPrimaryActionLabel() {\n            if (this.dashboardRegion === 'au' && !this.canUsePlanBenefits) {\n                return this.t('explore_oshc_plans', 'Explore OSHC Plans');\n            }\n            return this.t('view_plan', 'View Plan');\n        },\n        currentPlanPrimaryActionIcon() {\n            return this.dashboardRegion === 'au' && !this.canUsePlanBenefits ? '#uc-i-external' : '#uc-i-file';\n        },\n        dashboardRegionOrders() {\n            const region = this.dashboardRegion === 'au' ? 'au' : 'usa';\n            return (Array.isArray(this.orders) ? this.orders : []).filter(order => order && order.region === region);\n        },\n        dashboardRecentRegionOrders() {\n            return this.dashboardRegionOrders.filter(order => this.isDashboardPaymentStatusOrder(order));\n        },\n        dashboardUnpaidOrderRow() {\n            return this.dashboardRecentRegionOrders.find(order => this.canShowOrderPayNow(order)) || null;\n        },\n        dashboardAnyOrderRow() {\n            return this.dashboardRegionOrders[0] || null;\n        },\n        dashboardCurrentOrderPayRow() {\n            if (this.dashboardUnpaidOrderRow) return this.dashboardUnpaidOrderRow;\n            const order = this.dashboardCurrentOrder;\n            if (!order) return this.dashboardAnyOrderRow;\n            const currentRow = this.dashboardRegion === 'au'\n                ? this.buildAuOrderRow(order, 0)\n                : this.buildUsaOrderRow(order, 0);\n            return currentRow || this.dashboardAnyOrderRow;\n        },\n        dashboardOrderStatusSignal() {\n            const unpaidOrder = this.dashboardUnpaidOrderRow;\n            if (unpaidOrder) return this.getOrderPayStatusRaw(unpaidOrder);\n            const loadedOrder = this.dashboardAnyOrderRow;\n            if (loadedOrder) return this.getOrderPayStatusRaw(loadedOrder);\n            const order = this.dashboardCurrentOrder || {};\n            return typeof order.pay_status !== 'undefined' ? order.pay_status : '';\n        },\n        dashboardHasOrderSignal() {\n            if (this.canUsePlanBenefits) return true;\n            if (this.dashboardRecentRegionOrders.length) return true;\n            const currentRow = this.dashboardCurrentOrderPayRow;\n            if (currentRow && this.isDashboardPaymentStatusOrder(currentRow)) return true;\n            const user = this.userInfo || {};\n            if (this.dashboardRegion === 'au') return this.isTruthyRegionFlag(user.pay_status_au);\n            return this.isTruthyRegionFlag(typeof user.pay_status_us !== 'undefined' ? user.pay_status_us : user.pay_status_usa);\n        },\n        dashboardHasUnpaidOrder() {\n            const row = this.dashboardUnpaidOrderRow || this.dashboardCurrentOrderPayRow;\n            return !!(row && this.canShowOrderPayNow(row) && this.isDashboardPaymentStatusOrder(row));\n        },\n        dashboardNextStep() {\n            const order = this.dashboardCurrentOrder;\n            const isAu = this.dashboardRegion === 'au';\n            if (this.dashboardHasUnpaidOrder) {\n                return {\n                    kicker: this.t('next_step', 'Next Step'),\n                    title: this.t('next_payment_title', 'Complete Payment'),\n                    desc: this.t('next_payment_desc', 'Your order is saved. Finish payment to unlock documents and benefits.'),\n                    actionLabel: this.t('view_order_history', 'View Order History'),\n                    actionType: 'plans',\n                    className: 'is-warning',\n                };\n            }\n            if (!this.dashboardHasOrderSignal) {\n                return {\n                    kicker: this.t('next_step', 'Next Step'),\n                    title: isAu ? this.t('next_explore_oshc_title', 'Explore OSHC Plans') : this.t('next_choose_plan_title', 'Choose Your Student Plan'),\n                    desc: isAu\n                        ? this.t('next_explore_oshc_desc', 'Compare OSHC options and start a new order when you are ready.')\n                        : this.t('next_choose_plan_desc', 'Start an enrollment so your policy documents can be prepared.'),\n                    actionLabel: isAu ? this.t('explore_oshc_plans', 'Explore OSHC Plans') : this.t('start_enrollment', 'Start Enrollment'),\n                    actionType: isAu ? 'explore_au' : 'start_us',\n                    className: 'is-info',\n                };\n            }\n            if (!this.canUsePlanBenefits) {\n                return {\n                    kicker: this.t('next_step', 'Next Step'),\n                    title: this.t('next_confirmation_title', 'Wait for Confirmation'),\n                    desc: this.t('next_confirmation_desc', 'We are processing this order. Check your email and order history for updates.'),\n                    actionLabel: this.t('view_order_history', 'View Order History'),\n                    actionType: 'orders',\n                    className: 'is-info',\n                };\n            }\n            if (this.canShowRenewEntry()) {\n                return {\n                    kicker: this.t('next_step', 'Next Step'),\n                    title: this.t('next_renew_title', 'Renew Your Protection'),\n                    desc: this.t('next_renew_desc', 'Your plan is close to renewal. Renew now to keep coverage uninterrupted.'),\n                    actionLabel: this.t('renew_now', 'Renew Now'),\n                    actionType: 'renew',\n                    className: 'is-warning',\n                };\n            }\n            if (!isAu && this.canShowWaiveCenter && !this.hasWaiverApprovalUploaded) {\n                return {\n                    kicker: this.t('next_step', 'Next Step'),\n                    title: this.t('next_waiver_title', 'Submit Your School Waiver'),\n                    desc: this.t('next_waiver_desc', 'Download the required documents and submit them before your school deadline.'),\n                    actionLabel: this.t('go_to_waive_center', 'Go to Waive Center'),\n                    actionType: 'waive',\n                    className: 'is-success',\n                };\n            }\n            return {\n                kicker: this.t('next_step', 'Next Step'),\n                title: isAu ? this.t('next_use_oshc_title', 'Use Your OSHC Cover') : this.t('next_keep_docs_title', 'Keep Your Insurance Handy'),\n                desc: isAu\n                    ? this.t('next_use_oshc_desc', 'Find a provider, keep support close, and use your policy when care is needed.')\n                    : this.t('next_keep_docs_desc', 'Keep your ID card and policy documents ready for visits or school requests.'),\n                actionLabel: this.t('view_plan', 'View Plan'),\n                actionType: 'plans',\n                className: 'is-success',\n            };\n        },\n        dashboardStatusTimeline() {\n            const hasOrder = !!this.dashboardHasOrderSignal;\n            const active = !!this.canUsePlanBenefits;\n            const unpaid = !!this.dashboardHasUnpaidOrder;\n            const pendingOrder = hasOrder && !active && !unpaid;\n            if (this.dashboardRegion === 'au') {\n                return [\n                    {\n                        key: 'choose',\n                        title: this.t('timeline_au_choose_title', 'Choose OSHC'),\n                        desc: this.t('timeline_au_choose_desc', 'Pick a plan'),\n                        state: hasOrder ? 'done' : 'current',\n                    },\n                    {\n                        key: 'payment',\n                        title: this.t('timeline_payment_title', 'Payment'),\n                        desc: this.t('timeline_payment_desc', 'Finish payment'),\n                        state: (active || pendingOrder) ? 'done' : (hasOrder ? 'current' : 'locked'),\n                    },\n                    {\n                        key: 'policy',\n                        title: pendingOrder ? this.t('next_confirmation_title', 'Wait for Confirmation') : this.t('timeline_au_policy_title', 'Policy Issued'),\n                        desc: pendingOrder ? this.t('next_confirmation_desc', 'We are processing this order. Check your email and order history for updates.') : this.t('timeline_au_policy_desc', 'Documents ready'),\n                        state: active ? 'done' : (pendingOrder ? 'current' : 'locked'),\n                    },\n                    {\n                        key: 'benefits',\n                        title: this.t('timeline_benefits_title', 'Use Benefits'),\n                        desc: this.t('timeline_benefits_desc', 'Care and support'),\n                        state: active ? 'done' : 'locked',\n                    },\n                ];\n            }\n            return [\n                {\n                    key: 'choose',\n                    title: this.t('timeline_us_choose_title', 'Choose Plan'),\n                    desc: this.t('timeline_us_choose_desc', 'Start enrollment'),\n                    state: hasOrder ? 'done' : 'current',\n                },\n                {\n                    key: 'payment',\n                    title: this.t('timeline_payment_title', 'Payment'),\n                    desc: this.t('timeline_payment_desc', 'Finish payment'),\n                    state: (active || pendingOrder) ? 'done' : (hasOrder ? 'current' : 'locked'),\n                },\n                {\n                    key: 'confirmation',\n                    title: this.t('next_confirmation_title', 'Wait for Confirmation'),\n                    desc: this.t('next_confirmation_desc', 'We are processing this order. Check your email and order history for updates.'),\n                    state: active ? 'done' : (pendingOrder ? 'current' : 'locked'),\n                },\n                {\n                    key: 'waiver',\n                    title: this.t('timeline_waiver_title', 'Waiver'),\n                    desc: this.t('timeline_waiver_desc', 'Submit to school'),\n                    state: active ? (this.hasWaiverApprovalUploaded ? 'done' : 'current') : 'locked',\n                },\n                {\n                    key: 'coverage',\n                    title: this.t('timeline_coverage_title', 'Coverage'),\n                    desc: this.t('timeline_coverage_desc', 'Use your plan'),\n                    state: active ? 'done' : 'locked',\n                },\n            ];\n        },\n        dashboardCurrentTimelineStep() {\n            const steps = Array.isArray(this.dashboardStatusTimeline) ? this.dashboardStatusTimeline : [];\n            const currentStep = steps.find(step => step && step.state === 'current');\n            if (currentStep) return currentStep;\n            const nextStep = this.dashboardNextStep || {};\n            return {\n                key: String(nextStep.actionType || 'status'),\n                title: nextStep.title || this.dashboardStatusLabel || this.t('current_status', 'Current Status'),\n                desc: nextStep.desc || this.t('what_happens_next', 'What happens next'),\n                state: 'current',\n            };\n        },\n        dashboardCurrentFlowStatusClass() {\n            const step = this.dashboardCurrentTimelineStep || {};\n            if (step.key === 'payment' || step.state === 'current' && this.dashboardHasUnpaidOrder) return 'uc-status-yellow';\n            if (step.key === 'waiver') return 'uc-status-orange';\n            if (step.key === 'coverage' || step.key === 'benefits') return 'uc-status-green';\n            if (step.key === 'choose') return 'uc-status-blue';\n            if (step.key === 'policy' || step.key === 'confirmation') return 'uc-status-blue';\n            return this.dashboardStatusClass || 'uc-status-blue';\n        },\n        formattedNotificationDetailContent() {\n            return this.formatNotificationContent(this.selectedNotificationDetail.content || '');\n        },\n        selectedOshcPayOrderTitle() {\n            const order = this.selectedOshcPayOrder || {};\n            const plan = order.plan ? this.formatPlanName(order.plan) : this.t('oshc_order', 'OSHC Order');\n            const total = order.total ? ` \u00b7 ${order.total}` : '';\n            return `${plan}${total}`;\n        },\n        selectedPaymentOrderRegion() {\n            const order = this.selectedOshcPayOrder || {};\n            return String(order.region || '').trim().toLowerCase() === 'usa' ? 'usa' : 'au';\n        },\n        isSelectedOshcPayOrderMedibank() {\n            const order = this.selectedOshcPayOrder || {};\n            const raw = order.raw || {};\n            return this.getUnbrandedPlanName(raw.destination_name || order.plan || '') === 'Medibank';\n        },\n        selectedOshcWechatPayUrl() {\n            const order = this.selectedOshcPayOrder || {};\n            const raw = order.raw || {};\n            const payment = raw.payment || order.payment || {};\n            const paymentData = payment.payment_data || payment.paymentData || {};\n            return String(paymentData.pay_url || paymentData.payUrl || payment.pay_url || payment.payUrl || '').trim();\n        },\n        selectedUsWechatPayUrl() {\n            return this.getUsOrderWechatPayUrl(this.selectedOshcPayOrder);\n        },\n        oshcEmailRedirectMessage() {\n            return this.t(\n                'payment_email_queue_desc',\n                'The payment link has entered the sending queue. Please wait for the email to arrive. Redirecting to the order list in {seconds} seconds.'\n            ).replace('{seconds}', this.oshcEmailRedirectSeconds);\n        },\n        dashboardBottomActions() {\n            const source = this.dashboardRegion === 'au' ? this.dashboardBottomActionsAu : this.dashboardBottomActionsUsa;\n            return source.filter((action) => {\n                if (!action) return false;\n                if (action.id === 'waive_guide') return this.canShowWaiveCenter;\n                return this.canShowBottomAction(action);\n            });\n        },\n        isUsPurchaseComplete() {\n            const user = this.userInfo || {};\n            const order = user.usa_order || {};\n            return Number(order.pay_status) === 1;\n        },\n        isAuPurchaseComplete() {\n            const user = this.userInfo || {};\n            const order = user.au_order || {};\n            return Number(order.pay_status) === 2;\n        },\n        canUsePlanBenefits() {\n            return this.dashboardRegion === 'au' ? this.isAuPurchaseComplete : this.isUsPurchaseComplete;\n        },\n        canShowWaiveCenter() {\n            return this.dashboardRegion !== 'au' && this.isUsPurchaseComplete;\n        },\n        canShowClaimsCenter() {\n            return this.dashboardRegion !== 'au' && this.isUsPurchaseComplete;\n        },\n        currentPlanName() {\n            return this.dashboardPlanName;\n        },\n        currentPlanCoveragePeriod() {\n            return this.dashboardCoveragePeriod;\n        },\n        currentPlanSecondaryLabel() {\n            return this.dashboardSecondaryLabel;\n        },\n        currentPlanSecondaryValue() {\n            return this.dashboardSecondaryValue;\n        },\n        currentPlanBadgeLabel() {\n            return this.canShowRenewEntry() ? this.t('action_required', 'Action Required') : '';\n        },\n        currentPlanProduct() {\n            const user = this.userInfo || {};\n            const order = this.dashboardCurrentOrder || {};\n            return order.product || user.product || {};\n        },\n        currentPlanCoverageItems() {\n            const product = this.currentPlanProduct || {};\n            if (!this.canUsePlanBenefits) {\n                return [\n                    { label: this.t('deductible', 'Deductible'), value: '-' },\n                    { label: this.t('coinsurance', 'Coinsurance'), value: '-' },\n                    { label: this.t('out_of_pocket_max', 'Out-of-pocket Max'), value: '-' },\n                    { label: this.t('rx_copay', 'Rx Copay'), value: '-' },\n                ];\n            }\n            return [\n                {\n                    label: this.t('deductible', 'Deductible'),\n                    value: this.formatCoverageValue(product.deductible_in || product.deductible || product.in_network_deductible, '$0'),\n                },\n                {\n                    label: this.t('coinsurance', 'Coinsurance'),\n                    value: this.formatPercentValue(product.coinsurance_in || product.coinsurance || product.in_network_coinsurance, '100%'),\n                },\n                {\n                    label: this.t('out_of_pocket_max', 'Out-of-pocket Max'),\n                    value: this.formatCoverageValue(product.out_of_pocket_maximum_in_network || product.out_of_pocket_max || product.oop_max, '$6000'),\n                },\n                {\n                    label: this.t('rx_copay', 'Rx Copay'),\n                    value: this.formatCoverageValue(product.prescription || product.rx_copay || product.rx, '$10, $20, $40'),\n                },\n            ];\n        },\n        claimsForDisplay() {\n            return Array.isArray(this.claim_list) ? this.claim_list : [];\n        },\n        ugcMarket() {\n            return this.dashboardRegion === 'au' ? 'AU' : 'US';\n        },\n        ugcPlatformsForDisplay() {\n            const source = this.ugcConfig && Array.isArray(this.ugcConfig.platforms) ? this.ugcConfig.platforms : [];\n            return source.map((platform, index) => {\n                const item = platform && typeof platform === 'object' ? platform : {};\n                const rewardConfig = item.reward_config && typeof item.reward_config === 'object' ? item.reward_config : {};\n                const rewardType = String(rewardConfig.reward_type || '').trim().toLowerCase();\n                const amount = String(rewardConfig.reward_amount || '').trim();\n                const currency = String(rewardConfig.reward_currency || '').trim().toUpperCase();\n                const rawIcon = String(item.icon || '').trim();\n                let iconUrl = '';\n                if (rawIcon) {\n                    if (\/^https?:\\\/\\\/\/i.test(rawIcon)) {\n                        iconUrl = rawIcon;\n                    } else if (rawIcon.startsWith('\/storage\/')) {\n                        iconUrl = `https:\/\/agent.goglobalsafe.com${rawIcon}`;\n                    } else {\n                        iconUrl = `https:\/\/agent.goglobalsafe.com\/storage\/${rawIcon.replace(\/^\\\/+\/, '')}`;\n                    }\n                }\n                let rewardText = this.t('reward_available', 'Reward available');\n                if (rewardType === 'cash') {\n                    rewardText = amount\n                        ? `${this.t('cash_reward', 'Cash reward')}: ${amount} ${currency || ''}`.trim()\n                        : this.t('cash_reward', 'Cash reward');\n                } else if (rewardType === 'starbucks_card') {\n                    rewardText = amount\n                        ? `${this.t('starbucks_card', 'Starbucks card')}: ${amount} ${currency || ''}`.trim()\n                        : this.t('starbucks_gift_reward', 'Starbucks gift card reward');\n                }\n                return {\n                    id: Number(item.id || 0),\n                    name: String(item.name || `${this.t('platform', 'Platform')} ${index + 1}`),\n                    iconUrl,\n                    jumpUrl: String(item.jump_url || '').trim(),\n                    rewardType: rewardType || 'starbucks_card',\n                    rewardText,\n                    actionText: item.jump_url ? this.t('open_platform', 'Open Platform') : this.t('platform_ready', 'Platform Ready'),\n                    icon: index % 2 === 0 ? 'map-pin' : 'book',\n                    className: index % 3 === 0 ? 'uc-platform-red' : (index % 3 === 1 ? 'uc-platform-red-dark' : 'uc-platform-orange'),\n                    rewardConfig,\n                    raw: item,\n                };\n            });\n        },\n        ugcSelectedPlatform() {\n            const selectedId = Number(this.selectedPlatform || 0);\n            return this.ugcPlatformsForDisplay.find(item => Number(item.id) === selectedId) || null;\n        },\n        ugcCurrentRewardType() {\n            const platform = this.ugcSelectedPlatform;\n            return platform && platform.rewardType ? platform.rewardType : '';\n        },\n        ugcGenerateStorageKey() {\n            const user = this.userInfo || {};\n            const uid = String(user.id || user.student_id || 'guest').trim();\n            return `${this.ugcGenerateStorageKeyPrefix}:${uid}`;\n        },\n        ugcGeneratedTemplatesForDisplay() {\n            const list = Array.isArray(this.ugcGeneratedTemplates) ? this.ugcGeneratedTemplates : [];\n            const today = this.getTodayDateKey();\n            return list\n                .filter(item => String(item.dayKey || '') === today && Number(item.platformId || 0) === Number(this.selectedPlatform || 0))\n                .map((item, index) => ({\n                    localId: item.localId || `${item.templateId || 'tpl'}-${index}`,\n                    templateId: Number(item.templateId || 0),\n                    rewardType: String(item.rewardType || '').trim().toLowerCase(),\n                    title: String(item.title || '').trim(),\n                    content: String(item.content || '').trim(),\n                    generatedAt: String(item.generatedAt || '').trim(),\n                    generatedAtText: this.formatDateShort(item.generatedAt) || String(item.generatedAt || '').replace('T', ' ').slice(0, 19) || '-',\n                    dayKey: String(item.dayKey || '').trim(),\n                    market: String(item.market || '').trim(),\n                    platformId: Number(item.platformId || 0),\n                    raw: item,\n                }))\n                .sort((a, b) => String(b.generatedAt).localeCompare(String(a.generatedAt)));\n        },\n        ugcAutoTemplateIdForSubmit() {\n            const list = this.ugcGeneratedTemplatesForDisplay;\n            if (!Array.isArray(list) || !list.length) return 0;\n            return Number(list[0].templateId || 0);\n        },\n        ugcGenerateTodayCount() {\n            const today = this.getTodayDateKey();\n            const list = Array.isArray(this.ugcGeneratedTemplates) ? this.ugcGeneratedTemplates : [];\n            const platformId = Number(this.selectedPlatform || 0);\n            return list.filter((item) => {\n                const dayKey = String(item && item.dayKey ? item.dayKey : '');\n                const rowPlatformId = Number(item && item.platformId ? item.platformId : 0);\n                return dayKey === today && rowPlatformId === platformId;\n            }).length;\n        },\n        ugcGenerateTodayRemainingCount() {\n            return Math.max(0, 3 - Number(this.ugcGenerateTodayCount || 0));\n        },\n        ugcNeedAlipayFields() {\n            return this.ugcCurrentRewardType === 'cash';\n        },\n        ugcNeedShareLink() {\n            const platform = this.ugcSelectedPlatform || {};\n            const raw = platform.raw && typeof platform.raw === 'object' ? platform.raw : {};\n            const text = [\n                platform.name,\n                raw.name,\n                raw.slug,\n                raw.key,\n                raw.platform,\n                raw.platform_name,\n            ].map(value => String(value || '').trim().toLowerCase()).filter(Boolean).join(' ');\n            return \/xiaohongshu|xhs|\u5c0f\u7ea2\u4e66\/.test(text);\n        },\n        ugcSelectedFileName() {\n            const file = this.ugcForm.screenshotFile;\n            return file && file.name ? String(file.name) : '';\n        },\n        ugcSelectedFileSizeText() {\n            const file = this.ugcForm.screenshotFile;\n            if (!file || !file.size) return '';\n            const sizeMb = Number(file.size) \/ 1024 \/ 1024;\n            return `${sizeMb.toFixed(2)} MB`;\n        },\n        ugcHistoryForDisplay() {\n            const list = Array.isArray(this.ugcHistory) ? this.ugcHistory : [];\n            const platforms = this.ugcPlatformsForDisplay;\n            return list.map((item, index) => {\n                const row = item && typeof item === 'object' ? item : {};\n                const reviewStatus = String(row.review_status || '').trim().toLowerCase();\n                const isReviewPending = reviewStatus === 'pending';\n                const reviewMapped = this.mapUgcReviewStatus(reviewStatus);\n                const rewardType = String(row.reward_type || '').trim().toLowerCase();\n                const rewardStatusLabel = this.mapUgcRewardStatus(rewardType, row.cash_status, row.starbucks_status);\n                const createdRaw = String(row.created_at || '').trim();\n                const platformName = String(row.platform || '').trim();\n                const historyPlatformId = Number(row.platform_id || 0);\n                let matchedPlatform = null;\n                if (historyPlatformId > 0) {\n                    matchedPlatform = platforms.find(p => Number(p.id || 0) === historyPlatformId) || null;\n                }\n                if (!matchedPlatform && platformName) {\n                    const platformNameLower = platformName.toLowerCase();\n                    matchedPlatform = platforms.find((p) => {\n                        const candidate = String((p && p.name) || '').trim().toLowerCase();\n                        return candidate && candidate === platformNameLower;\n                    }) || null;\n                }\n                return {\n                    id: row.id || `ugc-${index}`,\n                    displayId: row.id || `UGC-${index + 1}`,\n                    platform: platformName || 'Unknown Platform',\n                    platformIconUrl: matchedPlatform && matchedPlatform.iconUrl ? matchedPlatform.iconUrl : '',\n                    rewardType,\n                    reviewStatus,\n                    isReviewPending,\n                    reviewStatusLabel: reviewMapped.label,\n                    reviewStatusClass: reviewMapped.className,\n                    rewardStatusLabel,\n                    rejectReason: String(row.reject_reason || '').trim(),\n                    screenshotUrl: String(row.screenshot_url || '').trim(),\n                    createdAtDisplay: this.formatDateShort(createdRaw) || createdRaw || '-',\n                    raw: row,\n                };\n            });\n        },\n        referralLink() {\n            const code = this.dashboardReferralCode;\n            if (!code || code === 'N\/A') return 'https:\/\/www.goglobalsafe.com';\n            return `https:\/\/www.goglobalsafe.com?reff=${encodeURIComponent(code)}`;\n        },\n        referralLinkShort() {\n            const link = this.referralLink;\n            return link.length > 28 ? link.slice(0, 25) + '...' : link;\n        },\n        referralPageCount() {\n            const total = Number(this.referralTotal || 0);\n            const size = Math.max(1, Number(this.referralPageSize || 10));\n            return Math.max(1, Math.ceil(total \/ size));\n        },\n        subCategories() {\n            const selected = String(this.selectedParentId || '');\n            const parent = (Array.isArray(this.ticketCategories) ? this.ticketCategories : []).find((category) => {\n                return String(category && category.id) === selected;\n            });\n            return parent && Array.isArray(parent.children) ? parent.children : [];\n        },\n        ticketPageCount() {\n            const total = Number(this.tk_total || 0);\n            const size = Math.max(1, Number(this.tk_pageSize || 10));\n            return Math.max(1, Math.ceil(total \/ size));\n        },\n        referralSuccessCount() {\n            const summary = this.rewardCenterSummary && typeof this.rewardCenterSummary === 'object' ? this.rewardCenterSummary : {};\n            const rewardCenterCount = Number(summary.successful_referral_order_count);\n            if (!Number.isNaN(rewardCenterCount)) return Math.max(0, rewardCenterCount);\n            if (this.dashboardRegion !== 'au') return 0;\n            const issued = Number(this.referralIssuedCount || 0);\n            const invited = Number(this.dashboardInvitedCount || 0);\n            return Math.max(0, Number.isFinite(invited) ? invited : issued);\n        },\n        referralHistoryRewardText() {\n            const stats = this.rewardCenterStats && typeof this.rewardCenterStats === 'object' ? this.rewardCenterStats : {};\n            return this.formatRewardStatsText(stats.history, this.referralIssuedCount, 'total');\n        },\n        referralPendingRewardText() {\n            const stats = this.rewardCenterStats && typeof this.rewardCenterStats === 'object' ? this.rewardCenterStats : {};\n            return this.formatRewardStatsText(stats.pending, this.referralProcessingCount, 'pending');\n        },\n        referralCountStartDateNote() {\n            const summary = this.rewardCenterSummary && typeof this.rewardCenterSummary === 'object' ? this.rewardCenterSummary : {};\n            const startDate = String(summary.referral_count_start_date || '2026-05-01').trim();\n            return this.t('referral_campaign_after', 'This referral campaign only counts referred orders placed after {date}.').replace('{date}', startDate);\n        },\n        milestoneNextGapText() {\n            return this.t('milestone_next_gap', 'Just {count} more to reach the next milestone!').replace('{count}', this.milestoneNextGap);\n        },\n        pendingRewardStats() {\n            const stats = this.rewardCenterStats && typeof this.rewardCenterStats === 'object' ? this.rewardCenterStats : {};\n            return stats.pending && typeof stats.pending === 'object' ? stats.pending : {};\n        },\n        hasPendingStarbucksReward() {\n            const card = this.pendingRewardStats.starbucks_card && typeof this.pendingRewardStats.starbucks_card === 'object' ? this.pendingRewardStats.starbucks_card : {};\n            return Number(card.count || 0) > 0 || Number(card.amount || 0) > 0;\n        },\n        hasPendingCashReward() {\n            const stats = this.pendingRewardStats;\n            const primary = stats.primary_cash && typeof stats.primary_cash === 'object' ? stats.primary_cash : {};\n            const primaryAmounts = primary.amounts && typeof primary.amounts === 'object' ? primary.amounts : {};\n            const hasPrimary = Object.keys(primaryAmounts).some(currency => Number(primaryAmounts[currency] || 0) > 0);\n            const extra = stats.extra_cash && typeof stats.extra_cash === 'object' ? stats.extra_cash : {};\n            return hasPrimary || Number(extra.amount || 0) > 0;\n        },\n        pendingStarbucksRewardAmountText() {\n            const card = this.pendingRewardStats.starbucks_card && typeof this.pendingRewardStats.starbucks_card === 'object' ? this.pendingRewardStats.starbucks_card : {};\n            const amount = Number(card.amount || 0);\n            const currency = String(card.currency || 'USD').toUpperCase();\n            if (!Number.isFinite(amount) || amount <= 0) return 'Starbucks';\n            const formatted = this.formatRewardAmount(amount);\n            if (currency === 'USD') return `$${formatted}`;\n            if (currency === 'CNY') return `${formatted} RMB`;\n            return `${formatted} ${currency}`;\n        },\n        milestoneNodesForDisplay() {\n            const all = Array.isArray(this.milestones) ? this.milestones : [];\n            return all.slice();\n        },\n        milestoneProgressPercent() {\n            const nodes = this.milestoneNodesForDisplay;\n            if (!Array.isArray(nodes) || nodes.length <= 1) return 0;\n            const refs = Number(this.referralSuccessCount || 0);\n            const completedCount = nodes.filter(node => this.isMilestoneNodeCompleted(node)).length;\n            const lastIndex = completedCount - 1;\n            if (lastIndex < 0) return 0;\n            if (lastIndex >= nodes.length - 1) return 100;\n            const lastCount = Number(nodes[lastIndex].count || 0);\n            const nextCount = Number(nodes[lastIndex + 1].count || lastCount || 1);\n            const gap = Math.max(1, nextCount - lastCount);\n            const intra = Math.max(0, Math.min(1, (refs - lastCount) \/ gap));\n            return ((lastIndex + intra) \/ (nodes.length - 1)) * 100;\n        },\n        milestoneProgressWidth() {\n            const percent = Math.max(0, Math.min(100, Number(this.milestoneProgressPercent || 0)));\n            return `calc((100% - 172px) * ${percent \/ 100})`;\n        },\n        milestoneNextGap() {\n            const summary = this.rewardCenterSummary && typeof this.rewardCenterSummary === 'object' ? this.rewardCenterSummary : {};\n            const nextMilestone = summary.next_milestone && typeof summary.next_milestone === 'object' ? summary.next_milestone : null;\n            const remaining = Number(nextMilestone && nextMilestone.remaining_count);\n            if (!Number.isNaN(remaining)) return Math.max(0, remaining);\n            const nodes = this.milestoneNodesForDisplay;\n            const refs = Number(this.referralSuccessCount || 0);\n            const next = nodes.find(node => refs < Number(node.count || 0));\n            if (!next) return 0;\n            return Math.max(0, Number(next.count || 0) - refs);\n        },\n        milestoneNextNodeCount() {\n            const summary = this.rewardCenterSummary && typeof this.rewardCenterSummary === 'object' ? this.rewardCenterSummary : {};\n            const nextMilestone = summary.next_milestone && typeof summary.next_milestone === 'object' ? summary.next_milestone : null;\n            const nextCount = Number(nextMilestone && nextMilestone.order_count);\n            if (!Number.isNaN(nextCount) && nextCount > 0) return nextCount;\n            const nodes = this.milestoneNodesForDisplay;\n            const refs = Number(this.referralSuccessCount || 0);\n            const next = nodes.find(node => refs < Number(node.count || 0));\n            return next ? Number(next.count || 0) : 0;\n        },\n        milestoneCurrentNodeCount() {\n            const nodes = this.milestoneNodesForDisplay.slice().sort((a, b) => Number(a.count || 0) - Number(b.count || 0));\n            const current = nodes.find(node => node && node.isCurrent === true);\n            if (current) return Number(current.count || 0);\n            const completed = nodes.filter(node => this.isMilestoneNodeCompleted(node));\n            if (completed.length) return Math.max(...completed.map(node => Number(node.count || 0)));\n            return 0;\n        },\n        milestoneRewardVisibleMaxCount() {\n            const nodes = this.milestoneNodesForDisplay.slice().sort((a, b) => Number(a.count || 0) - Number(b.count || 0));\n            const currentCount = Number(this.milestoneCurrentNodeCount || 0);\n            const nextNamedTier = nodes.find(node => Number(node.count || 0) > currentCount && this.hasMilestoneNamedTier(node));\n            if (nextNamedTier) return Number(nextNamedTier.count || 0);\n            return currentCount;\n        },\n        milestoneRewardVisibleCounts() {\n            const nodes = this.milestoneNodesForDisplay.slice().sort((a, b) => Number(a.count || 0) - Number(b.count || 0));\n            const currentCount = Number(this.milestoneCurrentNodeCount || 0);\n            if (!nodes.length) return [];\n\n            const visible = new Set();\n            const groups = [];\n            nodes.forEach((node) => {\n                const count = Number(node && node.count ? node.count : 0);\n                if (!count) return;\n                const identityKey = this.getMilestoneIdentityKey(node) || `count-${count}`;\n                let group = groups.find(item => item.key === identityKey);\n                if (!group) {\n                    group = { key: identityKey, counts: [] };\n                    groups.push(group);\n                }\n                group.counts.push(count);\n            });\n            groups.forEach(group => group.counts.sort((a, b) => a - b));\n\n            \/\/ Always keep already reached milestones visible.\n            nodes.forEach((node) => {\n                const count = Number(node && node.count ? node.count : 0);\n                if (count > 0 && count <= currentCount) {\n                    visible.add(count);\n                }\n            });\n\n            \/\/ If user has 0 referral, show first identity's first reward directly.\n            if (currentCount <= 0) {\n                if (groups.length && groups[0].counts.length) {\n                    visible.add(Number(groups[0].counts[0]));\n                }\n                return Array.from(visible.values());\n            }\n\n            \/\/ Locate current identity by the highest reached milestone node.\n            let currentIdentityIndex = -1;\n            const reachedNodes = nodes.filter(node => Number(node && node.count ? node.count : 0) <= currentCount);\n            const currentNode = reachedNodes.length ? reachedNodes[reachedNodes.length - 1] : null;\n            if (currentNode) {\n                const key = this.getMilestoneIdentityKey(currentNode) || `count-${Number(currentNode.count || 0)}`;\n                currentIdentityIndex = groups.findIndex(group => group.key === key);\n            }\n\n            if (currentIdentityIndex >= 0) {\n                const currentGroup = groups[currentIdentityIndex];\n                \/\/ Same identity: show remaining rewards in this identity.\n                currentGroup.counts.forEach((count) => {\n                    if (count > currentCount) {\n                        visible.add(Number(count));\n                    }\n                });\n                \/\/ Next identity: show entry reward only.\n                const nextGroup = groups[currentIdentityIndex + 1];\n                if (nextGroup && nextGroup.counts.length) {\n                    visible.add(Number(nextGroup.counts[0]));\n                }\n            }\n\n            return Array.from(visible.values());\n        },\n        visibleReferralRules() {\n            const key = this.dashboardRegion === 'au' ? 'au' : 'usa';\n            const current = this.referralRules.find(region => region.key === key);\n            if (current) return [current];\n            return this.referralRules.slice(0, 1);\n        },\n        supportQrUrl() {\n            return this.dashboardRegion === 'au' ? this.supportQrAuUrl : this.supportQrUsUrl;\n        },\n        supportQrFallbackUrl() {\n            return this.supportQrUrl;\n        },\n        dashboardMaterials() {\n            const base = Array.isArray(this.materials) ? this.materials.slice() : [];\n            if (this.dashboardRegion !== 'au' && this.isCurrentPlanElite) {\n                const exists = base.some(item => item && item.id === 'summary_benefits');\n                if (!exists) {\n                    base.push({\n                        id: 'summary_benefits',\n                        title: 'Summary of Benefits',\n                        desc: 'School-specific waiver summary document.',\n                        icon: 'book',\n                        className: 'uc-material-teal',\n                    });\n                }\n            }\n            return base;\n        },\n        isCurrentPlanElite() {\n            const user = this.userInfo || {};\n            const order = this.dashboardCurrentOrder || {};\n            const product = order.product || user.product || {};\n            const candidates = [\n                user.planName,\n                user.plan_name,\n                order.planName,\n                order.plan_name,\n                product.planName,\n                product.plan_name,\n                product.name,\n                this.dashboardPlanName,\n            ];\n            return candidates.some((value) => {\n                const text = this.getUnbrandedPlanName(value || '');\n                return \/\\belite\\b\/i.test(text);\n            });\n        },\n        waiveGuideStepItems() {\n            const fallback = (Array.isArray(this.waiveSteps) ? this.waiveSteps : []).map((title, index) => ({\n                title: String(title || '').trim() || `Step ${index + 1}`,\n                detail: String((this.waiveInstructions && this.waiveInstructions[index]) || title || '').trim() || '-',\n            }));\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            const source = Array.isArray(schoolWaive.waiver_guide_steps) ? schoolWaive.waiver_guide_steps : [];\n            if (!source.length) return fallback;\n\n            const normalized = source.map((item, index) => {\n                if (typeof item === 'string') {\n                    const text = String(item || '').trim();\n                    return {\n                        title: text || `Step ${index + 1}`,\n                        detail: text || '-',\n                    };\n                }\n                const title = this.pickClaimValue(item.title, item.name, item.label, item.step_title, item.step, item.heading);\n                const detail = this.pickClaimValue(item.description, item.desc, item.content, item.text, item.instruction, item.subtitle, title);\n                return {\n                    title: String(title || `Step ${index + 1}`).trim() || `Step ${index + 1}`,\n                    detail: String(detail || '-').trim() || '-',\n                };\n            }).filter(step => step && step.title);\n\n            return normalized.length ? normalized : fallback;\n        },\n        waiveFaqArticles() {\n            const categories = Array.isArray(this.waiveFaqCategories) ? this.waiveFaqCategories : [];\n            const articles = [];\n            categories.forEach((category) => {\n                const list = category && Array.isArray(category.articles) ? category.articles : [];\n                list.forEach((article, index) => {\n                    const title = String((article && article.title) || '').trim();\n                    if (!title) return;\n                    articles.push({\n                        id: article.id || `${category.id || 'faq'}-${index}`,\n                        title,\n                        content: String((article && article.content) || '').trim(),\n                    });\n                });\n            });\n            if (articles.length) return articles;\n            return [\n                { id: 'fallback-1', title: 'How long does waiver approval take?', content: 'Most schools review waiver submissions within 3-7 business days.' },\n                { id: 'fallback-2', title: 'What if the school asks for more documents?', content: 'Contact support and we will help you prepare the required materials.' },\n            ];\n        },\n        waiveGuideTitle() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            return String(schoolWaive.waiver_guide_title || '').trim() || this.t('waive_guide', 'Waive Guide');\n        },\n        waiveGuideSubtitle() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            return String(schoolWaive.waiver_guide_subtitle || '').trim() || this.t('waive_guide_subtitle', 'Step-by-step visual instructions');\n        },\n        waiveGuideLinkUrl() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            const link = String(schoolWaive.waiver_guide_link_url || '').trim();\n            return link;\n        },\n        waivePortalLinkUrl() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            return String(schoolWaive.compliance_intro_link_url || '').trim();\n        },\n        schoolWaiveLinkUrl() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            return String(schoolWaive.school_waive_link_url || '').trim();\n        },\n        currentWaiverApprovalUrl() {\n            const order = (this.userInfo && this.userInfo.usa_order) || {};\n            const candidates = [\n                this.waiverApprovalUrl,\n                order.waiver_approval,\n                order.waiverApproval,\n                order.waiver_approval_url,\n                order.waiverApprovalUrl,\n            ];\n            for (const value of candidates) {\n                const text = String(value || '').trim();\n                if (text) return text;\n            }\n            return '';\n        },\n        hasWaiverApprovalUploaded() {\n            return !!this.currentWaiverApprovalUrl;\n        },\n        waiverGuideProgressRatio() {\n            const steps = Array.isArray(this.waiveGuideStepItems) ? this.waiveGuideStepItems : [];\n            if (steps.length <= 1) return 0;\n            const completed = steps.reduce((count, step, index) => count + (this.isWaiverGuideStepComplete(index) ? 1 : 0), 0);\n            if (completed <= 0) return 0;\n            const lastCompletedIndex = Math.min(completed - 1, steps.length - 1);\n            return Math.max(0, Math.min(1, lastCompletedIndex \/ (steps.length - 1)));\n        },\n        waiveFaqUpdatedBadgeText() {\n            const schoolWaive = this.schoolWaiveData && typeof this.schoolWaiveData === 'object' ? this.schoolWaiveData : {};\n            const updatedAt = String(schoolWaive.updated_at || '').trim();\n            if (!updatedAt) return this.locale === 'zh' ? '\u5df2\u66f4\u65b0' : 'Updated';\n            const formatted = this.formatMonthYear(updatedAt) || updatedAt;\n            return this.locale === 'zh' ? `\u66f4\u65b0\u4e8e ${formatted}` : `Updated ${formatted}`;\n        },\n        orderPageCount() {\n            const total = Array.isArray(this.orders) ? this.orders.length : 0;\n            return Math.max(1, Math.ceil(total \/ this.orderPageSize));\n        },\n        orderCurrentPage() {\n            return Math.min(this.orderPageCount, Math.max(1, Number(this.orderPage) || 1));\n        },\n        pagedOrders() {\n            const source = Array.isArray(this.orders) ? this.orders : [];\n            const start = (this.orderCurrentPage - 1) * this.orderPageSize;\n            return source.slice(start, start + this.orderPageSize);\n        },\n        showPlusCrown() {\n            return \/plus\/i.test(String(this.dashboardPlanName || ''));\n        },\n        canShowUgcCenter() {\n            return this.isUsPurchaseComplete || this.isAuPurchaseComplete;\n        },\n        sidebarNavItems() {\n            const source = Array.isArray(this.navItems) ? this.navItems : [];\n            return source.filter((item) => {\n                if (!item) return false;\n                if (item.id === 'ugc' && !this.canShowUgcCenter) return false;\n                if (item.id === 'waive' && !this.canShowWaiveCenter) return false;\n                if (item.id === 'claims' && !this.canShowClaimsCenter) return false;\n                if (item.id === 'referrals' && this.dashboardRegion === 'au') return false;\n                return true;\n            });\n        },\n        hasUnreadTicketMessage() {\n            const user = this.userInfo && typeof this.userInfo === 'object' ? this.userInfo : {};\n            const userFlag = Number(user.is_ticket || 0) === 1 || user.is_ticket === true;\n            const ticketFlag = (Array.isArray(this.ticket_list) ? this.ticket_list : []).some(ticket => {\n                return Number(ticket && ticket.is_ticket || 0) === 1 || (ticket && ticket.is_ticket === true);\n            });\n            return userFlag || ticketFlag;\n        },\n    },\n    data() {\n        return {\n            locale: 'en',\n            i18n: {\n                en: {\n                    nav_referrals: 'Referral & Rewards',\n                    nav_dashboard: 'Dashboard',\n                    nav_plans: 'My Plans',\n                    nav_waive: 'Waive Center',\n                    nav_claims: 'Claims',\n                    nav_ugc: 'Creator Center',\n                    nav_help: 'Help & Settings',\n                    ticket_submit_title: 'Submit a Ticket',\n                    ticket_submit_desc: 'Our support team will help you with plan, billing, waiver, or claim questions.',\n                    ticket_category: 'Category',\n                    ticket_category_select: 'Select category',\n                    ticket_subcategory: 'Subcategory',\n                    ticket_subcategory_select: 'Select a category first.',\n                    ticket_subject: 'Subject',\n                    ticket_subject_placeholder: 'Briefly describe your question',\n                    ticket_description: 'Description',\n                    ticket_description_placeholder: 'Tell us what happened and what you need help with',\n                    ticket_attachments: 'Attachments (Optional)',\n                    ticket_add_files: 'Add Files',\n                    ticket_upload_hint: 'PDF\/JPG\/PNG\/HEIC\/CSV, up to 10MB per file.',\n                    ticket_uploaded: 'Uploaded',\n                    ticket_failed: 'Failed',\n                    ticket_confirm: 'I confirm this information is accurate and support can contact me for follow-up.',\n                    submit: 'Submit',\n                    ticket_record: 'Ticket Record',\n                    support_ticket: 'Support Ticket',\n                    view: 'View',\n                    prev: 'Prev',\n                    next: 'Next',\n                    account_settings: 'Account Settings',\n                    change_password: 'Change Password',\n                    two_step_verification: 'Two-Step Verification',\n                    set_up_two_step: 'Set Up Two-Step Verification',\n                    enable_two_step: 'Enable Two-Step Verification',\n                    turn_off_two_step: 'Turn Off',\n                    enabled: 'Enabled',\n                    not_enabled: 'Not Enabled',\n                    mfa_status_loading: 'Checking security status...',\n                    mfa_settings_summary_off: 'Add an Authenticator App for safer sign-in',\n                    mfa_enabled_headline: 'Two-step verification is on',\n                    mfa_disabled_headline: 'Two-step verification is off',\n                    mfa_disabled_desc: 'Your current login works as usual until you turn this on.',\n                    mfa_setup_intro: 'Use an Authenticator App to scan the QR code. If you cannot scan it, enter the key manually.',\n                    mfa_setup_hint: 'After the app shows a 6-digit code, enter it here to finish setup.',\n                    mfa_qr_fallback: 'QR code is unavailable. Please use the manual key.',\n                    mfa_manual_key: 'Manual Entry Key',\n                    mfa_auth_code: 'Authenticator Code',\n                    mfa_code_placeholder: 'Enter 6-digit code',\n                    mfa_recovery_code_optional: 'Recovery Code (for turning off)',\n                    mfa_recovery_code_placeholder: 'ABCD-EFGH-JKLM',\n                    mfa_manage_hint: 'Regenerating recovery codes requires a current Authenticator code. Turning off can use either an Authenticator code or a recovery code.',\n                    mfa_offline_desc: 'Two-step verification is optional for student accounts. You can turn it on to require an Authenticator code at your next login.',\n                    save_recovery_codes: 'Save Recovery Codes',\n                    mfa_recovery_intro_title: 'Keep these codes somewhere safe',\n                    mfa_recovery_intro: 'Save these recovery codes now. Each code can be used once if you cannot access your Authenticator App.',\n                    regenerate_recovery_codes: 'Regenerate Recovery Codes',\n                    mfa_saved_codes: 'I Have Saved These Codes',\n                    mfa_key_copied: 'Setup key copied.',\n                    mfa_recovery_code_copied: 'Recovery code copied.',\n                    mfa_recovery_codes_copied: 'Recovery codes copied.',\n                    mfa_enabled_success: 'Two-step verification enabled.',\n                    mfa_disabled_success: 'Two-step verification turned off.',\n                    mfa_codes_regenerated: 'Recovery codes regenerated.',\n                    mfa_setup_loading: 'Preparing Authenticator setup...',\n                    mfa_confirm_loading: 'Verifying Authenticator code...',\n                    mfa_status_failed: 'Failed to load two-step verification status.',\n                    mfa_setup_failed: 'Failed to start two-step verification setup.',\n                    mfa_confirm_failed: 'Failed to enable two-step verification.',\n                    mfa_regenerate_failed: 'Failed to regenerate recovery codes.',\n                    mfa_disable_failed: 'Failed to turn off two-step verification.',\n                    mfa_enter_code: 'Please enter the Authenticator code.',\n                    mfa_enter_code_or_recovery: 'Please enter an Authenticator code or recovery code.',\n                    mfa_turn_off_confirm: 'Turn off two-step verification for this account?',\n                    copy: 'Copy',\n                    copy_all: 'Copy All',\n                    ticket_detail: 'Ticket Detail',\n                    ticket_id: 'Ticket ID',\n                    ticket_submitted_date: 'Submitted Date',\n                    ticket_status: 'Ticket status',\n                    ticket_step_submit: 'Submit a ticket',\n                    ticket_step_review: 'Under review',\n                    ticket_step_resolved: 'Resolved',\n                    no_attachments: 'No attachments.',\n                    customer_service: 'Customer Service',\n                    no_messages: 'No messages yet.',\n                    add_attachment: 'Add attachment',\n                    type_message: 'Type your message',\n                    send: 'Send',\n                    ticket_submitted_success: 'Ticket Submitted',\n                    ticket_submitted_success_desc: 'Your ticket has been submitted successfully.',\n                    got_it: 'Got It',\n                    old_password: 'Old Password',\n                    new_password: 'New Password',\n                    confirm_password: 'Confirm Password',\n                    old_password_placeholder: 'Enter old password',\n                    new_password_placeholder: 'Enter new password',\n                    confirm_password_placeholder: 'Re-enter new password',\n                    forget_password: 'Forget Password?',\n                    save: 'Save',\n                    submitting: 'Submitting...',\n                    loading_title: 'Loading',\n                    loading_dashboard: 'Loading your dashboard...',\n                    status_submitted: 'Submitted',\n                    status_checking: 'Checking',\n                    status_resolved: 'Resolved',\n                    menu: 'Menu',\n                    hello: 'Hello',\n                    current_status: 'Current Status',\n                    click_view_progress: 'Click to view progress',\n                    click_to_continue: 'Click',\n                    onboarding_title: 'A quick start guide',\n                    onboarding_desc: 'Three small things help you get set up faster.',\n                    onboarding_step_plan: 'Check your plan',\n                    onboarding_step_plan_desc: 'Review coverage dates and network details.',\n                    onboarding_step_docs: 'Download documents',\n                    onboarding_step_docs_desc: 'Keep your certificate and policy files ready.',\n                    onboarding_step_waiver: 'Submit waiver',\n                    onboarding_step_waiver_desc: 'Use the required documents before your school deadline.',\n                    skip: 'Skip',\n                    start_with_my_plan: 'Start with My Plan',\n                    current_plan: 'Current Plan',\n                    no_active_plan: 'No Active GGS Plan',\n                    view_coverage_details: 'View Coverage Details',\n                    explore_oshc_plans: 'Explore OSHC Plans',\n                    next_step: 'Next Step',\n                    plan_progress: 'Plan Progress',\n                    what_happens_next: 'What happens next',\n                    start_enrollment: 'Start Enrollment',\n                    view_order_history: 'View Order History',\n                    go_to_waive_center: 'Go to Waive Center',\n                    next_choose_plan_title: 'Choose Your Student Plan',\n                    next_choose_plan_desc: 'Start an enrollment so your policy documents can be prepared.',\n                    next_explore_oshc_title: 'Explore OSHC Plans',\n                    next_explore_oshc_desc: 'Compare OSHC options and start a new order when you are ready.',\n                    next_payment_title: 'Complete Payment',\n                    next_payment_desc: 'Your order is saved. Finish payment to unlock documents and benefits.',\n                    next_confirmation_title: 'Wait for Confirmation',\n                    next_confirmation_desc: 'We are processing this order. Check your email and order history for updates.',\n                    next_renew_title: 'Renew Your Protection',\n                    next_renew_desc: 'Your plan is close to renewal. Renew now to keep coverage uninterrupted.',\n                    next_waiver_title: 'Submit Your School Waiver',\n                    next_waiver_desc: 'Download the required documents and submit them before your school deadline.',\n                    next_use_oshc_title: 'Use Your OSHC Cover',\n                    next_use_oshc_desc: 'Find a provider, keep support close, and use your policy when care is needed.',\n                    next_keep_docs_title: 'Keep Your Insurance Handy',\n                    next_keep_docs_desc: 'Keep your ID card and policy documents ready for visits or school requests.',\n                    timeline_us_choose_title: 'Choose Plan',\n                    timeline_us_choose_desc: 'Start enrollment',\n                    timeline_au_choose_title: 'Choose OSHC',\n                    timeline_au_choose_desc: 'Pick a plan',\n                    timeline_payment_title: 'Payment',\n                    timeline_payment_desc: 'Finish payment',\n                    timeline_documents_title: 'Documents',\n                    timeline_documents_desc: 'ID card ready',\n                    timeline_waiver_title: 'Waiver',\n                    timeline_waiver_desc: 'Submit to school',\n                    timeline_coverage_title: 'Coverage',\n                    timeline_coverage_desc: 'Use your plan',\n                    timeline_au_policy_title: 'Policy Issued',\n                    timeline_au_policy_desc: 'Documents ready',\n                    timeline_benefits_title: 'Use Benefits',\n                    timeline_benefits_desc: 'Care and support',\n                    plus_benefits_title: 'Plus Exclusive Benefits',\n                    plus_benefit_lounge: 'Airport VIP Lounge access',\n                    plus_benefit_travel: 'Up to 2 weeks free travel insurance',\n                    plus_benefit_merch: 'Exclusive GGS member merch',\n                    plus_benefits_claim_hint: 'Please add customer service WeChat to claim.',\n                    action_required: 'Action Required',\n                    waive_deadline_approaching: 'Waive Deadline Approaching',\n                    complete_waiver_now: 'Complete Waiver Now',\n                    view_plan: 'View Plan',\n                    renew: 'Renew',\n                    quick_actions: 'Quick Actions',\n                    refer_earn: 'Refer & Earn',\n                    your_referral_code: 'Your Referral Code',\n                    view_rewards: 'View Rewards',\n                    activity_rules: 'Activity Rules',\n                    invited: 'Invited',\n                    notifications: 'Notifications',\n                    waive_center: 'GGS Waiver Center',\n                    detected_school: 'Detected School',\n                    waiver_steps: 'Waiver Steps',\n                    detailed_instructions: 'Detailed Instructions',\n                    step: 'Step',\n                    waiver_faq: 'Waiver FAQ',\n                    question_prefix: 'Q',\n                    waive_guide: 'Waive Guide',\n                    waive_guide_subtitle: 'Step-by-step visual instructions',\n                    important_deadline: 'Important Deadline',\n                    required_documents: 'Required Documents',\n                    more_files: 'More Files',\n                    waiver_details: 'Waiver Details',\n                    address: 'Address',\n                    phone: 'Phone',\n                    go_to_portal: 'Go to Portal',\n                    file_a_claim: 'File a Claim',\n                    claim_banner_desc: 'Submit medical bills and track reimbursement progress from one clean dashboard.',\n                    cancel_filing: 'Cancel Filing',\n                    new_claim: 'New Claim',\n                    required_checklist: 'Required Checklist',\n                    claim_checklist_bill: 'Itemized bill from provider',\n                    claim_checklist_payment: 'Proof of payment',\n                    claim_checklist_notes: 'Claim Form',\n                    file_new_claim: 'File a New Claim',\n                    claims_instructions: 'Claims Instructions',\n                    claim_template: 'Claim Template',\n                    claim_template_hint: 'Please review the claim template before submitting your files.',\n                    upload_or_drag: 'Click to upload or drag and drop',\n                    claim_upload_hint: 'PDF, JPG, PNG (Max 10MB per file)',\n                    cancel: 'Cancel',\n                    submit_files: 'Submit Files',\n                    claims_history: 'Claims History',\n                    pending_sync: 'Pending Sync',\n                    claim_details: 'Claim Details',\n                    claim_id: 'Claim ID',\n                    patient: 'Patient',\n                    member_id: 'Member ID',\n                    claim_type: 'Claim Type',\n                    provider: 'Provider',\n                    service_date: 'Service Date',\n                    status: 'Status',\n                    status_date: 'Status Date',\n                    diagnosis: 'Diagnosis',\n                    dx_code: 'DX Code',\n                    benefits_applied: 'Benefits Applied',\n                    eob_in_portal: 'EOB in Portal',\n                    financial_summary: 'Financial Summary',\n                    claim_amount: 'Claim Amount',\n                    reprice: 'Reprice',\n                    savings: 'Savings',\n                    pay_to_provider: 'Pay to Provider',\n                    member_paid: 'Member Paid',\n                    patient_responsibility: 'Patient Responsibility',\n                    non_covered: 'Non Covered',\n                    network: 'Network',\n                    download_eob: 'Download EOB',\n                    no_claim_records: 'No claim records yet.',\n                    processing_time: 'Processing Time',\n                    claim_processing_time_desc: 'Claims are usually reviewed within 14-21 business days after all documents are received.',\n                    referral_banner_title: 'Refer Friends, Unlock Exciting Tiers!',\n                    referral_banner_desc: \"Share your exclusive code or direct link. When a friend buys a plan using your link, you'll earn rewards and climb the milestone ladder.\",\n                    referral_code: 'Referral Code',\n                    exclusive_link: 'Exclusive Link',\n                    copy_link: 'Copy Link',\n                    milestone_progress_title: 'Your Milestone Progress',\n                    you_have: 'You have',\n                    successful_referrals: 'successful referrals.',\n                    rules_details: 'Rules & Details',\n                    campus_ambassador_application: 'Campus Ambassador Application',\n                    tier: 'Tier',\n                    requires: 'Requires',\n                    referral_unit: 'Referral',\n                    referrals_unit: 'Referrals',\n                    reward: 'Reward',\n                    pending_unlock: 'Pending unlock',\n                    total_earnings: 'Total Earnings',\n                    available_balance: 'Available Balance',\n                    claim_rewards: 'Claim Your Rewards',\n                    total_rewards: 'Total Rewards',\n                    pending_rewards: 'Pending Rewards',\n                    referral_history: 'Referral History',\n                    starbucks_gift_card: 'Starbucks Gift Card',\n                    digital_code_instant: 'Digital code sent instantly',\n                    cash_via_alipay: 'Cash via Alipay',\n                    alipay_transfer_time: 'Transferred in 1-2 business days',\n                    back_to_options: 'Back to options',\n                    claim: 'Claim',\n                    starbucks_card: 'Starbucks Card',\n                    redeem_digital_card_prefix: 'You are about to redeem a',\n                    redeem_digital_card_suffix: 'digital gift card.',\n                    generate_digital_link: 'Generate Digital Link',\n                    withdraw_to_alipay: 'Withdraw to Alipay',\n                    provide_account_details: 'Provide your account details.',\n                    alipay_account: 'Alipay Account (Phone \/ Email)',\n                    enter_valid_account: 'Enter valid account',\n                    real_name_alipay: 'Real Name (Matches Alipay)',\n                    real_name_placeholder: 'e.g. Zhang San',\n                    submit_withdrawal_request: 'Submit Withdrawal Request',\n                    emergency_sos: 'Emergency SOS',\n                    emergency_assistance: '24\/7 Global Emergency Assistance',\n                    emergency_hotline: 'Emergency Hotline',\n                    tap_to_call: 'Tap to call immediately for urgent help.',\n                    call_now: 'Call Now',\n                    close: 'Close',\n                    confirm_logout: 'Confirm Logout',\n                    confirm_logout_desc: 'Are you sure you want to log out?',\n                    logout: 'Log out',\n                    notification: 'Notification',\n                    sent_at: 'Sent at',\n                    loading: 'Loading...',\n                    renew_modal_title: 'Time to Renew Your Protection!',\n                    renew_modal_desc: 'Your current global student insurance plan is expiring soon. Renew now to maintain seamless coverage.',\n                    renew_modal_reward: 'Renew today and get 400 RMB cashback + a $15 Starbucks Gift Card!',\n                    renew_now: 'Renew Now',\n                    remind_me_later: 'Remind Me Later',\n                    close_message: 'Close message',\n                    referral_campaign_after: 'This referral campaign only counts referred orders placed after {date}.',\n                    milestone_next_gap: 'Just {count} more to reach the next milestone!',\n                    base_pending: 'Base Pending',\n                    base_issued: 'Base Issued',\n                    extra_pending: 'Extra Pending',\n                    extra_issued: 'Extra Issued',\n                    not_redeemed: 'Not Redeemed',\n                    processing: 'Processing',\n                    issued: 'Issued',\n                    paid: 'Paid',\n                    rejected: 'Rejected',\n                    pending: 'Pending',\n                    buyer: 'Buyer',\n                    referral: 'Referral',\n                    starbucks_card_label: 'Starbucks card',\n                    primary_cash_label: 'primary cash',\n                    extra_cash_label: 'extra cash',\n                    top_emergency_title: 'Emergency SOS',\n                    top_emergency_desc: '24\/7 Global emergency medical assistance and evacuation.',\n                    top_ai_title: 'AI Symptom Checker',\n                    top_ai_desc: '24\/7 smart triage and hospital recommendations based on your symptoms.',\n                    top_bill_title: 'Bill Analyzer',\n                    top_bill_desc: 'Upload your hospital bill directly to understand your coverage and out-of-pocket costs.',\n                    bottom_find_pharmacy: 'Find Pharmacy',\n                    bottom_find_provider: 'Find Provider',\n                    bottom_waive_guide: 'Waive Guide',\n                    bottom_add_dental_vision: 'Add Dental\/Vision',\n                    bottom_contact_support: 'Contact Support',\n                    material_id_card_title: 'Insurance ID Card',\n                    material_id_card_desc: 'Download your digital ID card',\n                    material_policy_title: 'Policy & Terms',\n                    material_policy_desc: 'View your full coverage details',\n                    material_waiver_title: 'Waive Documents',\n                    material_waiver_desc: 'Documents needed for school waiver',\n                    material_summary_title: 'Summary of Benefits',\n                    material_summary_desc: 'School-specific waiver summary document.',\n                    material_waiver_form_title: 'Waiver Form',\n                    material_waiver_form_desc: 'Download your NYU waiver form.',\n                    material_id_image_title: 'ID Card Image',\n                    material_id_image_desc: 'Download your ID card image for waiver.',\n                    material_certificate_title: 'Waiver Certificate',\n                    material_certificate_desc: 'Download your waiver certificate for school submission.',\n                    material_id_card_usage: 'Use for doctor visits, provider check-in, and school waiver uploads.',\n                    material_policy_usage: 'Use to confirm benefits, exclusions, network rules, and coverage dates.',\n                    material_summary_usage: 'Use when your school asks for a summary of benefits.',\n                    material_waiver_form_usage: 'Upload this form to the school waiver portal.',\n                    material_id_image_usage: 'Upload this image where the school asks for insurance proof.',\n                    material_certificate_usage: 'Upload this certificate for school waiver submission.',\n                    coverage_period: 'Coverage Period',\n                    add_to_apple_wallet: 'Add to Apple Wallet',\n                    key_coverage: 'Key Coverage',\n                    important_materials: 'Important Materials',\n                    documents: 'Documents',\n                    download_all_zip: 'Download All (ZIP)',\n                    order_history: 'Order History',\n                    plan: 'Plan',\n                    period: 'Period',\n                    total: 'Total',\n                    actions: 'Actions',\n                    details: 'Details',\n                    pay_now: 'Pay Now',\n                    payment_options: 'Payment Options',\n                    email_link_credit_card: 'Email Link (Credit Card)',\n                    email_link_credit_card_desc: 'Receive a secure payment link by email.',\n                    wechat_pay: 'WeChat Pay',\n                    wechat_pay_desc: 'Scan the QR code with WeChat to complete payment.',\n                    qr_code_expired: 'QR code expired?',\n                    us_payment_link_missing: 'Payment link is not available. Please continue on the enrollment page.',\n                    credit_card_payment: 'Credit Card Payment',\n                    credit_card_payment_desc: 'Pay directly with Mastercard, Visa, UnionPay and more.',\n                    check_payment_email: 'Please check your payment email shortly',\n                    payment_email_queue_desc: 'The payment link has entered the sending queue. Please wait for the email to arrive. Redirecting to the order list in {seconds} seconds.',\n                    go_to_order_list_now: 'Go to Order List Now',\n                    oshc_order: 'OSHC Order',\n                    payment_link_missing: 'Payment link is not available yet. Please try again later.',\n                    sending_payment_email: 'Sending payment email...',\n                    preparing_payment_link: 'Preparing payment link...',\n                    order_id: 'Order ID',\n                    insurance_name: 'Insurance Name',\n                    insurance_time: 'Insurance Time',\n                    member: 'Member',\n                    email: 'Email',\n                    order_status: 'Order Status',\n                    coverage_type: 'Coverage Type',\n                    school: 'School',\n                    visa: 'Visa',\n                    policy_number: 'Policy Number',\n                    deductible: 'Deductible',\n                    coinsurance: 'Coinsurance',\n                    out_of_pocket_max: 'Out-of-pocket Max',\n                    rx_copay: 'Rx Copay',\n                    status_active: 'Active',\n                    status_unpaid: 'Unpaid',\n                    status_refunded: 'Refunded',\n                    status_expired: 'Expired',\n                    status_waiting: 'Waiting',\n                    status_initiated: 'Initiated',\n                    status_cancelled: 'Cancelled',\n                    waive_center_after_purchase: 'Waive Center is available after your purchase is complete.',\n                    claims_after_purchase: 'Claims are available after your purchase is complete.',\n                    feature_unlock_after_purchase: 'This feature will unlock after your purchase is complete.',\n                    apple_wallet_unavailable: 'Apple Wallet is not available yet.',\n                    status_processed: 'Processed',\n                    completed: 'Completed',\n                    status_completed: 'Completed',\n                    status_approved: 'Approved',\n                    status_denied: 'Denied',\n                    status_in_review: 'In Review',\n                    ugc_banner_title: 'Share Your Experience & Win Big!',\n                    ugc_banner_desc: 'We value your feedback. Share your GoGlobalSafe experience on popular social platforms, submit your screenshot, and join our exclusive WeChat group for weekly lotteries and extra rewards.',\n                    no_supported_platforms: 'No supported platforms available right now.',\n                    submit_screenshot: 'Submit Screenshot',\n                    tips_templates: 'Tips & Templates',\n                    select_platform_first: 'Select a platform first, then click Generate Copy.',\n                    no_generated_copy: 'No generated copy yet. You can generate up to 3 times per day.',\n                    alipay_account_short: 'Alipay Account',\n                    alipay_real_name: 'Alipay Real Name',\n                    xiaohongshu_share_link: 'Xiaohongshu Share Link',\n                    enter_xiaohongshu_share_link: 'Paste your Xiaohongshu post link',\n                    xiaohongshu_share_link_hint: 'Required for Xiaohongshu submissions.',\n                    xiaohongshu_share_link_required: 'Please enter your Xiaohongshu share link.',\n                    ugc_consent: 'I agree that GoGlobalSafe may review this screenshot for reward verification.',\n                    screenshot_uploaded_success: 'Screenshot Uploaded Successfully!',\n                    scan_to_join_group: 'Scan to Join Group',\n                    join_wechat_group: 'Join the WeChat Group',\n                    wechat_group_benefit_1: 'Weekly lucky draws for active members.',\n                    wechat_group_benefit_2: 'Fast-track support from the GoGlobalSafe team.',\n                    wechat_group_benefit_3: 'Earn double rewards for future UGC events!',\n                    review_history: 'Review History',\n                    no_ugc_history: 'No UGC submission history yet.',\n                    no_ticket_records: 'No ticket records yet.',\n                    reward_rules: 'Reward Rules',\n                    contact_support: 'Contact Support',\n                    contact_support_desc: 'Below are two ways to contact us.',\n                    enterprise_wechat_scan: 'Enterprise WeChat Scan',\n                    wechat_scan_desc: 'Use Enterprise WeChat to scan the QR code.',\n                    view_detailed_guide: 'View detailed guide',\n                    waive_step_guide_alt: 'Waiver guide',\n                    waive_step_guide_hint: 'Follow the highlighted area in the guide and make sure the information matches your policy.',\n                    upload_approval_image: 'Upload Approval Image',\n                    complete_waiver_step: 'Complete Waiver Step',\n                    complete_last_step: 'Complete Last Step',\n                    waiver_approval_upload_hint: 'Upload your waiver approval screenshot to complete the final step.',\n                    waiver_all_done_desc: 'Your approval screenshot is saved. All waiver steps are complete.',\n                    upload_approval_image_short: 'Upload',\n                    view_approval_image: 'View Image',\n                    uploading: 'Uploading',\n                    waiver_approval_uploaded: 'Waiver approval image uploaded.',\n                    invalid_waiver_approval_file: 'Please upload a JPG, PNG, or WebP image.',\n                    waiver_approval_too_large: 'Image size cannot exceed 10MB.',\n                    waiver_approval_missing_order: 'No USA enrollment found for this waiver.',\n                    generating: 'Generating...',\n                    generate_copy: 'Generate Copy',\n                    click_upload_screenshot: 'Click to upload screenshot',\n                    enter_alipay_account: 'Enter your Alipay account',\n                    enter_alipay_real_name: 'Enter real name matching Alipay',\n                    ugc_success_desc: 'Thank you for sharing your experience. We are reviewing your submission, and your reward will be sent soon.',\n                    reward_available: 'Reward available',\n                    cash_reward: 'Cash reward',\n                    starbucks_gift_reward: 'Starbucks gift card reward',\n                    platform: 'Platform',\n                    open_platform: 'Open Platform',\n                    platform_ready: 'Platform Ready',\n                    no_template_content: 'No template content to copy.',\n                    template_copied: 'Template copied.',\n                    copy_failed_manual: 'Copy failed. Please press and hold to copy manually.',\n                    please_select_platform: 'Please select a platform first.',\n                    generate_limit_tip: 'You can generate copy up to 3 times per day.',\n                    loading_generating_ugc: 'Generating your UGC copy...',\n                    success: 'Success',\n                    notice: 'Notice',\n                },\n                zh: {\n                    nav_referrals: '\u63a8\u8350\u5956\u52b1',\n                    nav_dashboard: '\u4eea\u8868\u76d8',\n                    nav_plans: '\u6211\u7684\u8ba1\u5212',\n                    nav_waive: '\u8c41\u514d\u4e2d\u5fc3',\n                    nav_claims: '\u7406\u8d54',\n                    nav_ugc: '\u521b\u4f5c\u4e2d\u5fc3',\n                    nav_help: '\u5e2e\u52a9\u4e0e\u8bbe\u7f6e',\n                    ticket_submit_title: '\u63d0\u4ea4\u5de5\u5355',\n                    ticket_submit_desc: '\u6211\u4eec\u7684\u5ba2\u670d\u56e2\u961f\u5c06\u5e2e\u52a9\u4f60\u5904\u7406\u5957\u9910\u3001\u8d26\u5355\u3001\u8c41\u514d\u548c\u7406\u8d54\u95ee\u9898\u3002',\n                    ticket_category: '\u95ee\u9898\u5206\u7c7b',\n                    ticket_category_select: '\u8bf7\u9009\u62e9\u5206\u7c7b',\n                    ticket_subcategory: '\u5b50\u5206\u7c7b',\n                    ticket_subcategory_select: '\u8bf7\u5148\u9009\u62e9\u5206\u7c7b',\n                    ticket_subject: '\u4e3b\u9898',\n                    ticket_subject_placeholder: '\u8bf7\u7b80\u8981\u63cf\u8ff0\u4f60\u7684\u95ee\u9898',\n                    ticket_description: '\u95ee\u9898\u63cf\u8ff0',\n                    ticket_description_placeholder: '\u8bf7\u8be6\u7ec6\u8bf4\u660e\u4f60\u9047\u5230\u7684\u95ee\u9898\u548c\u8bc9\u6c42',\n                    ticket_attachments: '\u9644\u4ef6\uff08\u53ef\u9009\uff09',\n                    ticket_add_files: '\u6dfb\u52a0\u6587\u4ef6',\n                    ticket_upload_hint: '\u652f\u6301 PDF\/JPG\/PNG\/HEIC\/CSV\uff0c\u5355\u4e2a\u6587\u4ef6\u4e0d\u8d85\u8fc7 10MB\u3002',\n                    ticket_uploaded: '\u5df2\u4e0a\u4f20',\n                    ticket_failed: '\u5931\u8d25',\n                    ticket_confirm: '\u6211\u786e\u8ba4\u4ee5\u4e0a\u4fe1\u606f\u771f\u5b9e\u6709\u6548\uff0c\u5e76\u540c\u610f\u5ba2\u670d\u5c31\u6b64\u8054\u7cfb\u6211\u3002',\n                    submit: '\u63d0\u4ea4',\n                    ticket_record: '\u5de5\u5355\u8bb0\u5f55',\n                    support_ticket: '\u652f\u6301\u5de5\u5355',\n                    view: '\u67e5\u770b',\n                    prev: '\u4e0a\u4e00\u9875',\n                    next: '\u4e0b\u4e00\u9875',\n                    account_settings: '\u8d26\u53f7\u8bbe\u7f6e',\n                    change_password: '\u4fee\u6539\u5bc6\u7801',\n                    two_step_verification: '\u4e24\u6b65\u9a8c\u8bc1',\n                    set_up_two_step: '\u8bbe\u7f6e\u4e24\u6b65\u9a8c\u8bc1',\n                    enable_two_step: '\u5f00\u542f\u4e24\u6b65\u9a8c\u8bc1',\n                    turn_off_two_step: '\u5173\u95ed',\n                    enabled: '\u5df2\u5f00\u542f',\n                    not_enabled: '\u672a\u5f00\u542f',\n                    mfa_status_loading: '\u6b63\u5728\u68c0\u67e5\u5b89\u5168\u72b6\u6001...',\n                    mfa_settings_summary_off: '\u6dfb\u52a0 Authenticator App\uff0c\u8ba9\u767b\u5f55\u66f4\u5b89\u5168',\n                    mfa_enabled_headline: '\u4e24\u6b65\u9a8c\u8bc1\u5df2\u5f00\u542f',\n                    mfa_disabled_headline: '\u4e24\u6b65\u9a8c\u8bc1\u672a\u5f00\u542f',\n                    mfa_disabled_desc: '\u5f00\u542f\u524d\uff0c\u4f60\u5f53\u524d\u7684\u767b\u5f55\u65b9\u5f0f\u4fdd\u6301\u4e0d\u53d8\u3002',\n                    mfa_setup_intro: '\u8bf7\u4f7f\u7528 Authenticator App \u626b\u63cf\u4e8c\u7ef4\u7801\u3002\u65e0\u6cd5\u626b\u7801\u65f6\uff0c\u53ef\u624b\u52a8\u8f93\u5165\u4e0b\u65b9\u5bc6\u94a5\u3002',\n                    mfa_setup_hint: 'App \u663e\u793a 6 \u4f4d\u52a8\u6001\u9a8c\u8bc1\u7801\u540e\uff0c\u5728\u8fd9\u91cc\u8f93\u5165\u5373\u53ef\u5b8c\u6210\u5f00\u542f\u3002',\n                    mfa_qr_fallback: '\u4e8c\u7ef4\u7801\u6682\u4e0d\u53ef\u7528\uff0c\u8bf7\u4f7f\u7528\u624b\u52a8\u5bc6\u94a5\u6dfb\u52a0\u3002',\n                    mfa_manual_key: '\u624b\u52a8\u8f93\u5165\u5bc6\u94a5',\n                    mfa_auth_code: 'Authenticator \u9a8c\u8bc1\u7801',\n                    mfa_code_placeholder: '\u8bf7\u8f93\u5165 6 \u4f4d\u9a8c\u8bc1\u7801',\n                    mfa_recovery_code_optional: '\u6062\u590d\u7801\uff08\u7528\u4e8e\u5173\u95ed\uff09',\n                    mfa_recovery_code_placeholder: 'ABCD-EFGH-JKLM',\n                    mfa_manage_hint: '\u91cd\u65b0\u751f\u6210\u6062\u590d\u7801\u9700\u8981\u5f53\u524d Authenticator \u9a8c\u8bc1\u7801\u3002\u5173\u95ed\u4e24\u6b65\u9a8c\u8bc1\u53ef\u4f7f\u7528\u9a8c\u8bc1\u7801\u6216\u6062\u590d\u7801\u3002',\n                    mfa_offline_desc: '\u5b66\u751f\u8d26\u53f7\u53ef\u81ea\u884c\u9009\u62e9\u662f\u5426\u5f00\u542f\u4e24\u6b65\u9a8c\u8bc1\u3002\u5f00\u542f\u540e\uff0c\u4e0b\u6b21\u767b\u5f55\u9700\u8981\u8f93\u5165 Authenticator \u52a8\u6001\u9a8c\u8bc1\u7801\u3002',\n                    save_recovery_codes: '\u4fdd\u5b58\u6062\u590d\u7801',\n                    mfa_recovery_intro_title: '\u8bf7\u59a5\u5584\u4fdd\u5b58\u8fd9\u4e9b\u6062\u590d\u7801',\n                    mfa_recovery_intro: '\u8bf7\u7acb\u5373\u4fdd\u5b58\u8fd9\u4e9b\u6062\u590d\u7801\u3002\u5f53\u4f60\u65e0\u6cd5\u4f7f\u7528 Authenticator App \u65f6\uff0c\u6bcf\u4e2a\u6062\u590d\u7801\u53ef\u767b\u5f55\u4e00\u6b21\u3002',\n                    regenerate_recovery_codes: '\u91cd\u65b0\u751f\u6210\u6062\u590d\u7801',\n                    mfa_saved_codes: '\u6211\u5df2\u4fdd\u5b58\u8fd9\u4e9b\u6062\u590d\u7801',\n                    mfa_key_copied: '\u5bc6\u94a5\u5df2\u590d\u5236\u3002',\n                    mfa_recovery_code_copied: '\u6062\u590d\u7801\u5df2\u590d\u5236\u3002',\n                    mfa_recovery_codes_copied: '\u6062\u590d\u7801\u5df2\u590d\u5236\u3002',\n                    mfa_enabled_success: '\u4e24\u6b65\u9a8c\u8bc1\u5df2\u5f00\u542f\u3002',\n                    mfa_disabled_success: '\u4e24\u6b65\u9a8c\u8bc1\u5df2\u5173\u95ed\u3002',\n                    mfa_codes_regenerated: '\u6062\u590d\u7801\u5df2\u91cd\u65b0\u751f\u6210\u3002',\n                    mfa_setup_loading: '\u6b63\u5728\u51c6\u5907\u4e24\u6b65\u9a8c\u8bc1\u8bbe\u7f6e...',\n                    mfa_confirm_loading: '\u6b63\u5728\u9a8c\u8bc1\u52a8\u6001\u9a8c\u8bc1\u7801...',\n                    mfa_status_failed: '\u4e24\u6b65\u9a8c\u8bc1\u72b6\u6001\u52a0\u8f7d\u5931\u8d25\u3002',\n                    mfa_setup_failed: '\u4e24\u6b65\u9a8c\u8bc1\u8bbe\u7f6e\u542f\u52a8\u5931\u8d25\u3002',\n                    mfa_confirm_failed: '\u4e24\u6b65\u9a8c\u8bc1\u5f00\u542f\u5931\u8d25\u3002',\n                    mfa_regenerate_failed: '\u6062\u590d\u7801\u91cd\u65b0\u751f\u6210\u5931\u8d25\u3002',\n                    mfa_disable_failed: '\u4e24\u6b65\u9a8c\u8bc1\u5173\u95ed\u5931\u8d25\u3002',\n                    mfa_enter_code: '\u8bf7\u8f93\u5165 Authenticator \u9a8c\u8bc1\u7801\u3002',\n                    mfa_enter_code_or_recovery: '\u8bf7\u8f93\u5165 Authenticator \u9a8c\u8bc1\u7801\u6216\u6062\u590d\u7801\u3002',\n                    mfa_turn_off_confirm: '\u786e\u5b9a\u8981\u5173\u95ed\u8be5\u8d26\u53f7\u7684\u4e24\u6b65\u9a8c\u8bc1\u5417\uff1f',\n                    copy: '\u590d\u5236',\n                    copy_all: '\u5168\u90e8\u590d\u5236',\n                    ticket_detail: '\u5de5\u5355\u8be6\u60c5',\n                    ticket_id: '\u5de5\u5355ID',\n                    ticket_submitted_date: '\u63d0\u4ea4\u65f6\u95f4',\n                    ticket_status: '\u5de5\u5355\u72b6\u6001',\n                    ticket_step_submit: '\u63d0\u4ea4\u5de5\u5355',\n                    ticket_step_review: '\u5ba1\u6838\u4e2d',\n                    ticket_step_resolved: '\u5df2\u5904\u7406',\n                    no_attachments: '\u6682\u65e0\u9644\u4ef6',\n                    customer_service: '\u5ba2\u670d',\n                    no_messages: '\u6682\u65e0\u6d88\u606f',\n                    add_attachment: '\u6dfb\u52a0\u9644\u4ef6',\n                    type_message: '\u8bf7\u8f93\u5165\u6d88\u606f',\n                    send: '\u53d1\u9001',\n                    ticket_submitted_success: '\u5de5\u5355\u63d0\u4ea4\u6210\u529f',\n                    ticket_submitted_success_desc: '\u4f60\u7684\u5de5\u5355\u5df2\u63d0\u4ea4\u6210\u529f\u3002',\n                    got_it: '\u77e5\u9053\u4e86',\n                    old_password: '\u65e7\u5bc6\u7801',\n                    new_password: '\u65b0\u5bc6\u7801',\n                    confirm_password: '\u786e\u8ba4\u5bc6\u7801',\n                    old_password_placeholder: '\u8bf7\u8f93\u5165\u65e7\u5bc6\u7801',\n                    new_password_placeholder: '\u8bf7\u8f93\u5165\u65b0\u5bc6\u7801',\n                    confirm_password_placeholder: '\u8bf7\u518d\u6b21\u8f93\u5165\u65b0\u5bc6\u7801',\n                    forget_password: '\u5fd8\u8bb0\u5bc6\u7801\uff1f',\n                    save: '\u4fdd\u5b58',\n                    submitting: '\u63d0\u4ea4\u4e2d...',\n                    loading_title: '\u52a0\u8f7d\u4e2d',\n                    loading_dashboard: '\u6b63\u5728\u52a0\u8f7d\u4e2a\u4eba\u4e2d\u5fc3...',\n                    status_submitted: '\u5df2\u63d0\u4ea4',\n                    status_checking: '\u5ba1\u6838\u4e2d',\n                    status_resolved: '\u5df2\u5904\u7406',\n                    menu: '\u83dc\u5355',\n                    hello: '\u4f60\u597d',\n                    current_status: '\u5f53\u524d\u72b6\u6001',\n                    click_view_progress: '\u70b9\u51fb\u67e5\u770b\u8fdb\u5ea6',\n                    click_to_continue: '\u70b9\u51fb',\n                    onboarding_title: '\u5feb\u901f\u5f00\u59cb\u6307\u5357',\n                    onboarding_desc: '\u5b8c\u6210\u8fd9 3 \u4ef6\u5c0f\u4e8b\uff0c\u53ef\u4ee5\u66f4\u5feb\u7528\u597d\u4f60\u7684\u8ba1\u5212\u3002',\n                    onboarding_step_plan: '\u67e5\u770b\u8ba1\u5212',\n                    onboarding_step_plan_desc: '\u786e\u8ba4\u4fdd\u969c\u65e5\u671f\u3001\u7f51\u7edc\u548c\u8ba1\u5212\u4fe1\u606f\u3002',\n                    onboarding_step_docs: '\u4e0b\u8f7d\u6587\u4ef6',\n                    onboarding_step_docs_desc: '\u63d0\u524d\u4fdd\u5b58\u4fdd\u9669\u8bc1\u660e\u548c\u4fdd\u5355\u6587\u4ef6\u3002',\n                    onboarding_step_waiver: '\u63d0\u4ea4\u8c41\u514d',\n                    onboarding_step_waiver_desc: '\u5728\u5b66\u6821\u622a\u6b62\u65e5\u671f\u524d\u4f7f\u7528\u6240\u9700\u6587\u4ef6\u5b8c\u6210\u63d0\u4ea4\u3002',\n                    skip: '\u8df3\u8fc7',\n                    start_with_my_plan: '\u4ece\u6211\u7684\u8ba1\u5212\u5f00\u59cb',\n                    current_plan: '\u5f53\u524d\u8ba1\u5212',\n                    no_active_plan: '\u6682\u65e0\u751f\u6548GGS\u8ba1\u5212',\n                    view_coverage_details: '\u67e5\u770b\u4fdd\u969c\u8be6\u60c5',\n                    explore_oshc_plans: '\u6d4f\u89c8 OSHC \u8ba1\u5212',\n                    plus_benefits_title: 'Plus \u4e13\u5c5e\u6743\u76ca',\n                    plus_benefit_lounge: '\u673a\u573a\u8d35\u5bbe\u5385\u6743\u76ca',\n                    plus_benefit_travel: '\u6700\u9ad8 2 \u5468\u514d\u8d39\u65c5\u884c\u4fdd\u9669',\n                    plus_benefit_merch: 'GGS \u4f1a\u5458\u4e13\u5c5e\u5468\u8fb9',\n                    plus_benefits_claim_hint: '\u8bf7\u6dfb\u52a0\u5ba2\u670d\u4f01\u4e1a\u5fae\u4fe1\u9886\u53d6\u3002',\n                    action_required: '\u9700\u8981\u5904\u7406',\n                    waive_deadline_approaching: '\u8c41\u514d\u622a\u6b62\u65e5\u671f\u4e34\u8fd1',\n                    complete_waiver_now: '\u7acb\u5373\u5b8c\u6210\u8c41\u514d',\n                    view_plan: '\u67e5\u770b\u8ba1\u5212',\n                    renew: '\u7eed\u4fdd',\n                    quick_actions: '\u5feb\u6377\u64cd\u4f5c',\n                    refer_earn: '\u63a8\u8350\u8d5a\u5956\u52b1',\n                    your_referral_code: '\u4f60\u7684\u63a8\u8350\u7801',\n                    view_rewards: '\u67e5\u770b\u5956\u52b1',\n                    activity_rules: '\u6d3b\u52a8\u89c4\u5219',\n                    invited: '\u5df2\u9080\u8bf7',\n                    notifications: '\u901a\u77e5',\n                    waive_center: 'GGS \u8c41\u514d\u4e2d\u5fc3',\n                    detected_school: '\u8bc6\u522b\u5b66\u6821',\n                    waiver_steps: '\u8c41\u514d\u6b65\u9aa4',\n                    detailed_instructions: '\u8be6\u7ec6\u8bf4\u660e',\n                    step: '\u6b65\u9aa4',\n                    waiver_faq: '\u8c41\u514d\u95ee\u7b54',\n                    question_prefix: '\u95ee',\n                    waive_guide: '\u8c41\u514d\u6307\u5357',\n                    waive_guide_subtitle: '\u5206\u6b65\u9aa4\u56fe\u6587\u8bf4\u660e',\n                    important_deadline: '\u91cd\u8981\u622a\u6b62\u65e5\u671f',\n                    required_documents: '\u6240\u9700\u6587\u4ef6',\n                    more_files: '\u66f4\u591a\u6587\u4ef6',\n                    waiver_details: '\u8c41\u514d\u8be6\u60c5',\n                    address: '\u5730\u5740',\n                    phone: '\u7535\u8bdd',\n                    go_to_portal: '\u524d\u5f80\u5b66\u6821\u7cfb\u7edf',\n                    file_a_claim: '\u63d0\u4ea4\u7406\u8d54',\n                    claim_banner_desc: '\u63d0\u4ea4\u533b\u7597\u8d26\u5355\uff0c\u5e76\u5728\u4e2a\u4eba\u4e2d\u5fc3\u8ddf\u8e2a\u62a5\u9500\u8fdb\u5ea6\u3002',\n                    cancel_filing: '\u53d6\u6d88\u63d0\u4ea4',\n                    new_claim: '\u65b0\u589e\u7406\u8d54',\n                    required_checklist: '\u6240\u9700\u6750\u6599\u6e05\u5355',\n                    claim_checklist_bill: '\u533b\u7597\u673a\u6784\u660e\u7ec6\u8d26\u5355',\n                    claim_checklist_payment: '\u4ed8\u6b3e\u51ed\u8bc1',\n                    claim_checklist_notes: '\u7406\u8d54\u8868\u683c',\n                    file_new_claim: '\u63d0\u4ea4\u65b0\u7684\u7406\u8d54',\n                    claims_instructions: '\u7406\u8d54\u8bf4\u660e',\n                    claim_template: '\u7406\u8d54\u6a21\u677f',\n                    claim_template_hint: '\u63d0\u4ea4\u6587\u4ef6\u524d\u8bf7\u5148\u67e5\u770b\u7406\u8d54\u6a21\u677f\u3002',\n                    upload_or_drag: '\u70b9\u51fb\u4e0a\u4f20\u6216\u62d6\u62fd\u6587\u4ef6\u5230\u6b64\u5904',\n                    claim_upload_hint: 'PDF\u3001JPG\u3001PNG\uff08\u5355\u4e2a\u6587\u4ef6\u4e0d\u8d85\u8fc7 10MB\uff09',\n                    cancel: '\u53d6\u6d88',\n                    submit_files: '\u63d0\u4ea4\u6587\u4ef6',\n                    claims_history: '\u7406\u8d54\u8bb0\u5f55',\n                    pending_sync: '\u7b49\u5f85\u540c\u6b65',\n                    claim_details: '\u7406\u8d54\u8be6\u60c5',\n                    claim_id: '\u7406\u8d54ID',\n                    patient: '\u60a3\u8005',\n                    member_id: '\u4f1a\u5458ID',\n                    claim_type: '\u7406\u8d54\u7c7b\u578b',\n                    provider: '\u670d\u52a1\u673a\u6784',\n                    service_date: '\u670d\u52a1\u65e5\u671f',\n                    status: '\u72b6\u6001',\n                    status_date: '\u72b6\u6001\u65e5\u671f',\n                    diagnosis: '\u8bca\u65ad\u4fe1\u606f',\n                    dx_code: '\u8bca\u65ad\u4ee3\u7801',\n                    benefits_applied: '\u6743\u76ca\u5e94\u7528',\n                    eob_in_portal: 'EOB \u72b6\u6001',\n                    financial_summary: '\u8d39\u7528\u6c47\u603b',\n                    claim_amount: '\u7406\u8d54\u91d1\u989d',\n                    reprice: '\u8bae\u4ef7\u91d1\u989d',\n                    savings: '\u8282\u7701\u91d1\u989d',\n                    pay_to_provider: '\u652f\u4ed8\u7ed9\u673a\u6784',\n                    member_paid: '\u4f1a\u5458\u5df2\u4ed8',\n                    patient_responsibility: '\u60a3\u8005\u81ea\u4ed8',\n                    non_covered: '\u4e0d\u627f\u4fdd\u91d1\u989d',\n                    network: '\u7f51\u7edc',\n                    download_eob: '\u4e0b\u8f7d EOB',\n                    no_claim_records: '\u6682\u65e0\u7406\u8d54\u8bb0\u5f55\u3002',\n                    processing_time: '\u5904\u7406\u65f6\u95f4',\n                    claim_processing_time_desc: '\u8d44\u6599\u9f50\u5168\u540e\uff0c\u7406\u8d54\u901a\u5e38\u4f1a\u5728 14-21 \u4e2a\u5de5\u4f5c\u65e5\u5185\u5ba1\u6838\u3002',\n                    referral_banner_title: '\u63a8\u8350\u597d\u53cb\uff0c\u89e3\u9501\u66f4\u591a\u5956\u52b1\u7b49\u7ea7\uff01',\n                    referral_banner_desc: '\u5206\u4eab\u4f60\u7684\u4e13\u5c5e\u63a8\u8350\u7801\u6216\u94fe\u63a5\u3002\u597d\u53cb\u901a\u8fc7\u94fe\u63a5\u8d2d\u4e70\u8ba1\u5212\u540e\uff0c\u4f60\u5c06\u83b7\u5f97\u5956\u52b1\u5e76\u63d0\u5347\u91cc\u7a0b\u7891\u7b49\u7ea7\u3002',\n                    referral_code: '\u63a8\u8350\u7801',\n                    exclusive_link: '\u4e13\u5c5e\u94fe\u63a5',\n                    copy_link: '\u590d\u5236\u94fe\u63a5',\n                    milestone_progress_title: '\u91cc\u7a0b\u7891\u8fdb\u5ea6',\n                    you_have: '\u4f60\u5df2\u6709',\n                    successful_referrals: '\u4e2a\u6210\u529f\u63a8\u8350\u3002',\n                    rules_details: '\u89c4\u5219\u8be6\u60c5',\n                    campus_ambassador_application: '\u6821\u56ed\u5927\u4f7f\u7533\u8bf7',\n                    tier: '\u7b49\u7ea7',\n                    requires: '\u9700\u8981',\n                    referral_unit: '\u4e2a\u63a8\u8350',\n                    referrals_unit: '\u4e2a\u63a8\u8350',\n                    reward: '\u5956\u52b1',\n                    pending_unlock: '\u5f85\u89e3\u9501',\n                    total_earnings: '\u5956\u52b1\u603b\u89c8',\n                    available_balance: '\u53ef\u9886\u53d6\u4f59\u989d',\n                    claim_rewards: '\u9886\u53d6\u5956\u52b1',\n                    total_rewards: '\u5386\u53f2\u5956\u52b1',\n                    pending_rewards: '\u5f85\u53d1\u653e\u5956\u52b1',\n                    referral_history: '\u63a8\u8350\u8bb0\u5f55',\n                    starbucks_gift_card: '\u661f\u5df4\u514b\u793c\u54c1\u5361',\n                    digital_code_instant: '\u6570\u5b57\u5151\u6362\u7801\u5373\u65f6\u53d1\u9001',\n                    cash_via_alipay: '\u652f\u4ed8\u5b9d\u63d0\u73b0',\n                    alipay_transfer_time: '\u9884\u8ba1 1-2 \u4e2a\u5de5\u4f5c\u65e5\u5230\u8d26',\n                    back_to_options: '\u8fd4\u56de\u9009\u9879',\n                    claim: '\u9886\u53d6',\n                    starbucks_card: '\u661f\u5df4\u514b\u5361',\n                    redeem_digital_card_prefix: '\u4f60\u5c06\u9886\u53d6\u4e00\u5f20',\n                    redeem_digital_card_suffix: '\u6570\u5b57\u793c\u54c1\u5361\u3002',\n                    generate_digital_link: '\u751f\u6210\u5151\u6362\u94fe\u63a5',\n                    withdraw_to_alipay: '\u63d0\u73b0\u5230\u652f\u4ed8\u5b9d',\n                    provide_account_details: '\u8bf7\u586b\u5199\u4f60\u7684\u8d26\u6237\u4fe1\u606f\u3002',\n                    alipay_account: '\u652f\u4ed8\u5b9d\u8d26\u53f7\uff08\u624b\u673a\u53f7\/\u90ae\u7bb1\uff09',\n                    enter_valid_account: '\u8bf7\u8f93\u5165\u6709\u6548\u8d26\u53f7',\n                    real_name_alipay: '\u771f\u5b9e\u59d3\u540d\uff08\u4e0e\u652f\u4ed8\u5b9d\u4e00\u81f4\uff09',\n                    real_name_placeholder: '\u4f8b\u5982\uff1a\u5f20\u4e09',\n                    submit_withdrawal_request: '\u63d0\u4ea4\u63d0\u73b0\u7533\u8bf7',\n                    emergency_sos: '\u7d27\u6025\u6551\u63f4',\n                    emergency_assistance: '7x24 \u5168\u7403\u7d27\u6025\u63f4\u52a9',\n                    emergency_hotline: '\u7d27\u6025\u70ed\u7ebf',\n                    tap_to_call: '\u5982\u9047\u7d27\u6025\u60c5\u51b5\uff0c\u8bf7\u7acb\u5373\u62e8\u6253\u3002',\n                    call_now: '\u7acb\u5373\u62e8\u6253',\n                    close: '\u5173\u95ed',\n                    confirm_logout: '\u786e\u8ba4\u9000\u51fa\u767b\u5f55',\n                    confirm_logout_desc: '\u786e\u5b9a\u8981\u9000\u51fa\u5f53\u524d\u8d26\u53f7\u5417\uff1f',\n                    logout: '\u9000\u51fa\u767b\u5f55',\n                    notification: '\u901a\u77e5',\n                    sent_at: '\u53d1\u9001\u65f6\u95f4',\n                    loading: '\u52a0\u8f7d\u4e2d...',\n                    renew_modal_title: '\u662f\u65f6\u5019\u7eed\u4fdd\u5566\uff01',\n                    renew_modal_desc: '\u4f60\u7684\u5168\u7403\u5b66\u751f\u4fdd\u9669\u8ba1\u5212\u5373\u5c06\u5230\u671f\u3002\u7acb\u5373\u7eed\u4fdd\uff0c\u4fdd\u6301\u4fdd\u969c\u4e0d\u65ad\u6863\u3002',\n                    renew_modal_reward: '\u73b0\u5728\u7eed\u4fdd\u53ef\u83b7\u5f97 400 RMB \u8fd4\u73b0 + $15 \u661f\u5df4\u514b\u793c\u54c1\u5361\uff01',\n                    renew_now: '\u7acb\u5373\u7eed\u4fdd',\n                    remind_me_later: '\u7a0d\u540e\u63d0\u9192\u6211',\n                    close_message: '\u5173\u95ed\u6d88\u606f',\n                    referral_campaign_after: '\u672c\u6b21\u63a8\u8350\u6d3b\u52a8\u4ec5\u7edf\u8ba1 {date} \u4e4b\u540e\u7684\u63a8\u8350\u8ba2\u5355\u3002',\n                    milestone_next_gap: '\u518d\u63a8\u8350 {count} \u4e2a\u5373\u53ef\u5230\u8fbe\u4e0b\u4e00\u4e2a\u91cc\u7a0b\u7891\uff01',\n                    base_pending: '\u57fa\u7840\u5956\u52b1\u5f85\u53d1\u653e',\n                    base_issued: '\u57fa\u7840\u5956\u52b1\u5df2\u53d1\u653e',\n                    extra_pending: '\u989d\u5916\u5956\u52b1\u5f85\u53d1\u653e',\n                    extra_issued: '\u989d\u5916\u5956\u52b1\u5df2\u53d1\u653e',\n                    not_redeemed: '\u672a\u5151\u5956',\n                    processing: '\u5904\u7406\u4e2d',\n                    issued: '\u5df2\u53d1\u653e',\n                    paid: '\u5df2\u652f\u4ed8',\n                    rejected: '\u5df2\u62d2\u7edd',\n                    pending: '\u5f85\u5904\u7406',\n                    buyer: '\u8d2d\u4e70\u5956\u52b1',\n                    referral: '\u63a8\u8350\u5956\u52b1',\n                    starbucks_card_label: '\u661f\u5df4\u514b\u5361',\n                    primary_cash_label: '\u57fa\u7840\u73b0\u91d1',\n                    extra_cash_label: '\u989d\u5916\u73b0\u91d1',\n                    top_emergency_title: '\u7d27\u6025\u6551\u63f4',\n                    top_emergency_desc: '7x24 \u5168\u7403\u7d27\u6025\u533b\u7597\u63f4\u52a9\u4e0e\u8f6c\u8fd0\u652f\u6301\u3002',\n                    top_ai_title: 'AI \u75c7\u72b6\u68c0\u67e5',\n                    top_ai_desc: '\u6839\u636e\u75c7\u72b6\u667a\u80fd\u5206\u8bca\uff0c\u5e76\u63a8\u8350\u5408\u9002\u7684\u5c31\u533b\u8d44\u6e90\u3002',\n                    top_bill_title: '\u8d26\u5355\u5206\u6790',\n                    top_bill_desc: '\u4e0a\u4f20\u533b\u9662\u8d26\u5355\uff0c\u5feb\u901f\u4e86\u89e3\u4fdd\u969c\u8303\u56f4\u548c\u81ea\u4ed8\u8d39\u7528\u3002',\n                    bottom_find_pharmacy: '\u67e5\u627e\u836f\u623f',\n                    bottom_find_provider: '\u67e5\u627e\u533b\u751f',\n                    bottom_waive_guide: '\u8c41\u514d\u6307\u5357',\n                    bottom_add_dental_vision: '\u6dfb\u52a0\u7259\u79d1\/\u773c\u79d1',\n                    bottom_contact_support: '\u8054\u7cfb\u5ba2\u670d',\n                    material_id_card_title: '\u4fdd\u9669 ID \u5361',\n                    material_id_card_desc: '\u4e0b\u8f7d\u4f60\u7684\u7535\u5b50 ID \u5361',\n                    material_policy_title: '\u4fdd\u5355\u6761\u6b3e',\n                    material_policy_desc: '\u67e5\u770b\u5b8c\u6574\u4fdd\u969c\u8be6\u60c5',\n                    material_waiver_title: '\u8c41\u514d\u6587\u4ef6',\n                    material_waiver_desc: '\u5b66\u6821\u8c41\u514d\u6240\u9700\u6587\u4ef6',\n                    material_summary_title: '\u798f\u5229\u6458\u8981',\n                    material_summary_desc: '\u5b66\u6821\u8c41\u514d\u4e13\u7528\u6458\u8981\u6587\u4ef6\u3002',\n                    material_waiver_form_title: '\u8c41\u514d\u8868\u683c',\n                    material_waiver_form_desc: '\u4e0b\u8f7d NYU \u8c41\u514d\u8868\u683c\u3002',\n                    material_id_image_title: 'ID \u5361\u56fe\u7247',\n                    material_id_image_desc: '\u4e0b\u8f7d\u7528\u4e8e\u8c41\u514d\u7684 ID \u5361\u56fe\u7247\u3002',\n                    material_certificate_title: '\u8c41\u514d\u8bc1\u660e',\n                    material_certificate_desc: '\u4e0b\u8f7d\u7528\u4e8e\u5b66\u6821\u63d0\u4ea4\u7684\u8c41\u514d\u8bc1\u660e\u3002',\n                    coverage_period: '\u4fdd\u969c\u671f\u95f4',\n                    add_to_apple_wallet: '\u6dfb\u52a0\u5230 Apple Wallet',\n                    key_coverage: '\u6838\u5fc3\u4fdd\u969c',\n                    important_materials: '\u91cd\u8981\u6750\u6599',\n                    documents: '\u6587\u4ef6',\n                    download_all_zip: '\u4e0b\u8f7d\u5168\u90e8\uff08ZIP\uff09',\n                    order_history: '\u8ba2\u5355\u8bb0\u5f55',\n                    plan: '\u8ba1\u5212',\n                    period: '\u671f\u95f4',\n                    total: '\u603b\u8ba1',\n                    actions: '\u64cd\u4f5c',\n                    details: '\u8be6\u60c5',\n                    pay_now: '\u7acb\u5373\u652f\u4ed8',\n                    payment_options: '\u652f\u4ed8\u65b9\u5f0f',\n                    email_link_credit_card: '\u90ae\u7bb1\u94fe\u63a5\uff08\u4fe1\u7528\u5361\uff09',\n                    email_link_credit_card_desc: '\u901a\u8fc7\u90ae\u7bb1\u6536\u5230\u4e13\u5c5e\u5b89\u5168\u652f\u4ed8\u94fe\u63a5\u3002',\n                    wechat_pay: '\u5fae\u4fe1\u652f\u4ed8',\n                    wechat_pay_desc: '\u4f7f\u7528\u5fae\u4fe1\u626b\u63cf\u4e8c\u7ef4\u7801\u5b8c\u6210\u652f\u4ed8\u3002',\n                    qr_code_expired: '\u4e8c\u7ef4\u7801\u5931\u6548\uff1f',\n                    us_payment_link_missing: '\u6682\u672a\u83b7\u53d6\u5230\u652f\u4ed8\u94fe\u63a5\uff0c\u8bf7\u524d\u5f80\u6295\u4fdd\u9875\u9762\u7ee7\u7eed\u652f\u4ed8\u3002',\n                    credit_card_payment: '\u4fe1\u7528\u5361\u652f\u4ed8',\n                    credit_card_payment_desc: '\u652f\u6301 Mastercard\u3001VISA\u3001\u94f6\u8054\u7b49\u3002',\n                    check_payment_email: '\u8bf7\u7a0d\u540e\u67e5\u6536\u652f\u4ed8\u90ae\u4ef6',\n                    payment_email_queue_desc: '\u652f\u4ed8\u94fe\u63a5\u5df2\u8fdb\u5165\u53d1\u9001\u961f\u5217\uff0c\u8bf7\u8010\u5fc3\u7b49\u5f85\u90ae\u4ef6\u9001\u8fbe\u3002{seconds} \u79d2\u540e\u8df3\u8f6c\u5230\u8ba2\u5355\u5217\u8868\u3002',\n                    go_to_order_list_now: '\u7acb\u5373\u524d\u5f80\u8ba2\u5355\u5217\u8868',\n                    oshc_order: 'OSHC \u8ba2\u5355',\n                    payment_link_missing: '\u6682\u672a\u83b7\u53d6\u5230\u652f\u4ed8\u94fe\u63a5\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5\u3002',\n                    sending_payment_email: '\u6b63\u5728\u53d1\u9001\u652f\u4ed8\u90ae\u4ef6...',\n                    preparing_payment_link: '\u6b63\u5728\u51c6\u5907\u652f\u4ed8\u94fe\u63a5...',\n                    order_id: '\u8ba2\u5355ID',\n                    insurance_name: '\u4fdd\u9669\u540d\u79f0',\n                    insurance_time: '\u4fdd\u9669\u65f6\u95f4',\n                    member: '\u6210\u5458',\n                    email: '\u90ae\u7bb1',\n                    order_status: '\u8ba2\u5355\u72b6\u6001',\n                    coverage_type: '\u4fdd\u969c\u7c7b\u578b',\n                    school: '\u5b66\u6821',\n                    visa: '\u7b7e\u8bc1',\n                    policy_number: '\u4fdd\u5355\u53f7',\n                    deductible: '\u514d\u8d54\u989d',\n                    coinsurance: '\u5171\u540c\u4fdd\u9669',\n                    out_of_pocket_max: '\u81ea\u4ed8\u4e0a\u9650',\n                    rx_copay: '\u5904\u65b9\u836f\u81ea\u4ed8',\n                    status_active: '\u751f\u6548\u4e2d',\n                    status_unpaid: '\u672a\u652f\u4ed8',\n                    status_refunded: '\u5df2\u9000\u6b3e',\n                    status_expired: '\u5df2\u8fc7\u671f',\n                    status_waiting: '\u7b49\u5f85\u4e2d',\n                    status_initiated: '\u5df2\u53d1\u8d77',\n                    status_cancelled: '\u5df2\u53d6\u6d88',\n                    waive_center_after_purchase: '\u8d2d\u4e70\u5b8c\u6210\u540e\u53ef\u4f7f\u7528\u8c41\u514d\u4e2d\u5fc3\u3002',\n                    claims_after_purchase: '\u8d2d\u4e70\u5b8c\u6210\u540e\u53ef\u4f7f\u7528\u7406\u8d54\u529f\u80fd\u3002',\n                    feature_unlock_after_purchase: '\u5f85\u8d2d\u4e70\u5b8c\u6210\u540e\u89e3\u9501\u3002',\n                    apple_wallet_unavailable: 'Apple Wallet \u529f\u80fd\u6682\u672a\u5f00\u653e\u3002',\n                    status_processed: '\u5df2\u5904\u7406',\n                    completed: '\u5df2\u5b8c\u6210',\n                    status_completed: '\u5df2\u5b8c\u6210',\n                    status_approved: '\u5df2\u6279\u51c6',\n                    status_denied: '\u5df2\u62d2\u7edd',\n                    status_in_review: '\u5ba1\u6838\u4e2d',\n                    ugc_banner_title: '\u5206\u4eab\u4f53\u9a8c\uff0c\u8d62\u53d6\u5956\u52b1\uff01',\n                    ugc_banner_desc: '\u5206\u4eab\u4f60\u7684 GoGlobalSafe \u4f7f\u7528\u4f53\u9a8c\uff0c\u4e0a\u4f20\u622a\u56fe\u5e76\u52a0\u5165\u4e13\u5c5e\u5fae\u4fe1\u7fa4\uff0c\u5373\u53ef\u53c2\u4e0e\u6bcf\u5468\u62bd\u5956\u548c\u989d\u5916\u5956\u52b1\u3002',\n                    no_supported_platforms: '\u5f53\u524d\u6682\u65e0\u53ef\u7528\u5e73\u53f0\u3002',\n                    submit_screenshot: '\u63d0\u4ea4\u622a\u56fe',\n                    tips_templates: '\u6587\u6848\u63d0\u793a',\n                    select_platform_first: '\u8bf7\u5148\u9009\u62e9\u5e73\u53f0\uff0c\u518d\u751f\u6210\u6587\u6848\u3002',\n                    no_generated_copy: '\u6682\u65e0\u751f\u6210\u6587\u6848\u3002\u6bcf\u5929\u6700\u591a\u53ef\u751f\u6210 3 \u6b21\u3002',\n                    alipay_account_short: '\u652f\u4ed8\u5b9d\u8d26\u53f7',\n                    alipay_real_name: '\u652f\u4ed8\u5b9d\u771f\u5b9e\u59d3\u540d',\n                    xiaohongshu_share_link: '\u5c0f\u7ea2\u4e66\u5206\u4eab\u94fe\u63a5',\n                    enter_xiaohongshu_share_link: '\u7c98\u8d34\u4f60\u7684\u5c0f\u7ea2\u4e66\u7b14\u8bb0\u94fe\u63a5',\n                    xiaohongshu_share_link_hint: '\u5c0f\u7ea2\u4e66\u63d0\u4ea4\u5fc5\u586b\u3002',\n                    xiaohongshu_share_link_required: '\u8bf7\u586b\u5199\u5c0f\u7ea2\u4e66\u5206\u4eab\u94fe\u63a5\u3002',\n                    ugc_consent: '\u6211\u540c\u610f GoGlobalSafe \u5ba1\u6838\u8be5\u622a\u56fe\u7528\u4e8e\u5956\u52b1\u6838\u9a8c\u3002',\n                    screenshot_uploaded_success: '\u622a\u56fe\u4e0a\u4f20\u6210\u529f\uff01',\n                    scan_to_join_group: '\u626b\u7801\u52a0\u5165\u7fa4\u804a',\n                    join_wechat_group: '\u52a0\u5165\u5fae\u4fe1\u7fa4',\n                    wechat_group_benefit_1: '\u6d3b\u8dc3\u6210\u5458\u6bcf\u5468\u5e78\u8fd0\u62bd\u5956\u3002',\n                    wechat_group_benefit_2: 'GoGlobalSafe \u56e2\u961f\u5feb\u901f\u652f\u6301\u3002',\n                    wechat_group_benefit_3: '\u672a\u6765 UGC \u6d3b\u52a8\u53ef\u83b7\u5f97\u53cc\u500d\u5956\u52b1\u3002',\n                    review_history: '\u5ba1\u6838\u8bb0\u5f55',\n                    no_ugc_history: '\u6682\u65e0 UGC \u63d0\u4ea4\u8bb0\u5f55\u3002',\n                    no_ticket_records: '\u6682\u65e0\u5de5\u5355\u8bb0\u5f55\u3002',\n                    reward_rules: '\u5956\u52b1\u89c4\u5219',\n                    contact_support: '\u8054\u7cfb\u5ba2\u670d',\n                    contact_support_desc: '\u4f60\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u4e24\u79cd\u65b9\u5f0f\u8054\u7cfb\u6211\u4eec\u3002',\n                    enterprise_wechat_scan: '\u4f01\u4e1a\u5fae\u4fe1\u626b\u7801',\n                    wechat_scan_desc: '\u4f7f\u7528\u4f01\u4e1a\u5fae\u4fe1\u626b\u63cf\u4e8c\u7ef4\u7801\u3002',\n                    view_detailed_guide: '\u67e5\u770b\u8be6\u7ec6\u6307\u5f15 (View Guide)',\n                    waive_step_guide_alt: '\u8c41\u514d\u8be6\u7ec6\u6307\u5f15',\n                    waive_step_guide_hint: '\u6309\u7167\u6307\u5f15\u4e2d\u7684\u9ad8\u4eae\u533a\u57df\u586b\u5199\u5065\u5eb7\u4fdd\u9669\u8c41\u514d\u4fe1\u606f\uff0c\u8bf7\u786e\u4fdd\u4fe1\u606f\u4e0e\u4fdd\u5355\u4e00\u81f4\u3002',\n                    generating: '\u751f\u6210\u4e2d...',\n                    generate_copy: '\u751f\u6210\u6587\u6848',\n                    click_upload_screenshot: '\u70b9\u51fb\u4e0a\u4f20\u622a\u56fe',\n                    enter_alipay_account: '\u8bf7\u8f93\u5165\u652f\u4ed8\u5b9d\u8d26\u53f7',\n                    enter_alipay_real_name: '\u8bf7\u8f93\u5165\u4e0e\u652f\u4ed8\u5b9d\u4e00\u81f4\u7684\u771f\u5b9e\u59d3\u540d',\n                    ugc_success_desc: '\u611f\u8c22\u4f60\u7684\u5206\u4eab\u3002\u6211\u4eec\u6b63\u5728\u5ba1\u6838\u4f60\u7684\u63d0\u4ea4\uff0c\u5956\u52b1\u4f1a\u5c3d\u5feb\u53d1\u653e\u3002',\n                    reward_available: '\u53ef\u83b7\u5f97\u5956\u52b1',\n                    cash_reward: '\u73b0\u91d1\u5956\u52b1',\n                    starbucks_gift_reward: '\u661f\u5df4\u514b\u793c\u54c1\u5361\u5956\u52b1',\n                    platform: '\u5e73\u53f0',\n                    open_platform: '\u6253\u5f00\u5e73\u53f0',\n                    platform_ready: '\u5e73\u53f0\u5df2\u5c31\u7eea',\n                    no_template_content: '\u6ca1\u6709\u53ef\u590d\u5236\u7684\u6587\u6848\u3002',\n                    template_copied: '\u6587\u6848\u5df2\u590d\u5236\u3002',\n                    copy_failed_manual: '\u590d\u5236\u5931\u8d25\uff0c\u8bf7\u957f\u6309\u624b\u52a8\u590d\u5236\u3002',\n                    please_select_platform: '\u8bf7\u5148\u9009\u62e9\u5e73\u53f0\u3002',\n                    generate_limit_tip: '\u6bcf\u5929\u6700\u591a\u53ef\u751f\u6210 3 \u6b21\u6587\u6848\u3002',\n                    loading_generating_ugc: '\u6b63\u5728\u751f\u6210 UGC \u6587\u6848...',\n                    upload_approval_image: '\u4e0a\u4f20\u8c41\u514d\u901a\u8fc7\u622a\u56fe',\n                    complete_waiver_step: '\u5b8c\u6210\u8c41\u514d\u6b65\u9aa4',\n                    complete_last_step: '\u5b8c\u6210\u6700\u540e\u4e00\u6b65',\n                    waiver_approval_upload_hint: '\u4e0a\u4f20\u4f60\u7684\u8c41\u514d\u901a\u8fc7\u622a\u56fe\u6765\u5b8c\u6210\u6700\u540e\u4e00\u6b65\u3002',\n                    waiver_all_done_desc: '\u4f60\u7684\u8c41\u514d\u901a\u8fc7\u622a\u56fe\u5df2\u4fdd\u5b58\uff0c\u5168\u90e8\u6b65\u9aa4\u5df2\u5b8c\u6210\u3002',\n                    upload_approval_image_short: '\u4e0a\u4f20',\n                    view_approval_image: '\u67e5\u770b\u56fe\u7247',\n                    uploading: '\u4e0a\u4f20\u4e2d',\n                    waiver_approval_uploaded: '\u8c41\u514d\u901a\u8fc7\u622a\u56fe\u5df2\u4e0a\u4f20\u3002',\n                    invalid_waiver_approval_file: '\u8bf7\u4e0a\u4f20 JPG\u3001PNG \u6216 WebP \u56fe\u7247\u3002',\n                    waiver_approval_too_large: '\u56fe\u7247\u5927\u5c0f\u4e0d\u80fd\u8d85\u8fc7 10MB\u3002',\n                    waiver_approval_missing_order: '\u672a\u627e\u5230\u53ef\u7528\u7684\u7f8e\u56fd\u8ba2\u5355\u3002',\n                    success: '\u6210\u529f',\n                    notice: '\u63d0\u793a',\n                },\n            },\n            activeTab: 'dashboard',\n            claimFormOpen: false,\n            renewModalOpen: false,\n            mobileMenuOpen: false,\n            isLoadingDashboard: false,\n            openModal: '',\n            statusFlowOpen: false,\n            plusBenefitsOpen: false,\n            waiveStepGuideImageFailed: false,\n            openDetails: {},\n            selectedPlatform: '',\n            ugcSuccess: false,\n            authToken: '',\n            redirectingToLogin: false,\n            userInfo: {},\n            dashboardRegion: 'usa',\n            apiBase: 'https:\/\/agent.goglobalsafe.com',\n            api: {\n                renewTrackLoginStatus: '\/api\/v1\/renew\/track\/login-status',\n                renewTrackAction: '\/api\/v1\/renew\/track\/action',\n                userInfo: '\/api\/v1\/student\/user\/userinfo',\n                oshcOrders: '\/api\/v1\/student\/order\/orderlist',\n                oshcPayForm: '\/api\/v1\/h5\/oshc\/submit\/payForm',\n                usaOrders: '\/api\/v1\/student\/order\/usorderlist',\n                usPaymentLink: '\/api\/v1\/student\/order\/uspayment-link',\n                usWaiverApproval: '\/api\/v1\/student\/order\/uswaiver-approval',\n                files: '\/api\/v1\/wechat\/user\/files',\n                downloadOshcPolicy: '\/api\/v1\/student\/order\/downloadPDF',\n                downloadUsaCertificate: '\/api\/v1\/student\/wellaway\/downloadCard',\n                downloadUsaIdCard: '\/api\/v1\/student\/wellaway\/downloadUSACardImage',\n                downloadWaiverForm: '\/api\/v1\/student\/wellaway\/downloadWaiverForm',\n                downloadWaiverCertificate: '\/api\/v1\/student\/wellaway\/downloadWaiverCertificate',\n                downloadEob: '\/api\/v1\/student\/wellaway\/downloadEob',\n                rewards: '\/api\/v1\/student\/user\/rewards',\n                rewardActivation: '\/api\/v1\/student\/user\/reward\/activation',\n                requestRewardCode: '\/api\/v1\/student\/user\/reward\/request_code',\n                ausRewards: '\/api\/v1\/student\/user\/aus\/rewards',\n                usaRewardCenter: '\/api\/v1\/student\/user\/usa\/reward-center',\n                logout: '\/api\/v1\/student\/user\/logout',\n                redeem: '\/api\/v1\/student\/user\/usa\/redeem',\n                editEnrollment: '\/api\/v1\/student\/wellaway\/editEnrollment',\n                resetPasswordOld: '\/api\/v1\/student\/user\/resetPasswordOld',\n                mfaStatus: '\/api\/v1\/student\/mfa\/status',\n                mfaSetup: '\/api\/v1\/student\/mfa\/setup',\n                mfaConfirm: '\/api\/v1\/student\/mfa\/confirm',\n                mfaDisable: '\/api\/v1\/student\/mfa\/disable',\n                mfaRecoveryCodesRegenerate: '\/api\/v1\/student\/mfa\/recovery-codes\/regenerate',\n                claims: '\/api\/v1\/student\/wellaway\/getClaimList',\n                claimUpload: '\/api\/v1\/student\/wellaway\/claimUpload',\n                claimSubmit: '\/api\/v1\/student\/wellaway\/submitClaimFile',\n                addComment: '\/api\/v1\/student\/user\/addComment',\n                shareImg: '\/api\/v1\/student\/user\/shareImg',\n                messages: '\/api\/v1\/student\/user\/messages',\n                productSchoolWaiveFaq: '\/api\/v1\/insurance\/baoxian\/product_school_waive_faq',\n                tickets: '\/api\/v1\/student\/user\/getTickets',\n                addTickets: '\/api\/v1\/student\/user\/addTickets',\n                ticketDetails: '\/api\/v1\/student\/user\/getTicketDetails',\n                updateTicket: '\/api\/v1\/student\/user\/updateTicket',\n                addChat: '\/api\/v1\/student\/user\/addChatLogs',\n                shareCount: '\/api\/v1\/student\/user\/shareCount',\n                ugcConfig: '\/api\/v1\/student\/user\/ugc\/config',\n                ugcTemplateGenerate: '\/api\/v1\/student\/user\/ugc\/template\/generate',\n                ugcSubmit: '\/api\/v1\/student\/user\/ugc\/submit',\n                ugcHistory: '\/api\/v1\/student\/user\/ugc\/history',\n            },\n            \/\/ Claim related\n            claim_list: [],\n            activeClaimId: 0,\n            uploadedFiles: [],\n            claimInstructionsUrl: 'https:\/\/goglobalsafe.com\/wp-content\/uploads\/2025\/08\/Understanding_U.S._Claim_Form.png',\n            claimTemplateUrl: 'https:\/\/goglobalsafe.com\/wp-content\/uploads\/2025\/08\/U.S._Claim_Form.pdf',\n            schoolWaiveData: null,\n            waiveFaqCategories: [],\n            waiverApprovalUploading: false,\n            waiverApprovalUrl: '',\n            plansDataLoaded: false,\n            claimsDataLoaded: false,\n            waiverDataLoaded: false,\n            plansDataLoadingPromise: null,\n            claimsDataLoadingPromise: null,\n            waiverDataLoadingPromise: null,\n            referralDataLoaded: false,\n            referralDataLoadingPromise: null,\n            dashboardBackgroundPreloadStarted: false,\n            dashboardBackgroundPreloadTimer: null,\n            referralCurrentPage: 1,\n            referralPageSize: 10,\n            referralTotal: 0,\n            referralIssuedCount: 0,\n            referralProcessingCount: 0,\n            activeMilestoneTipNode: null,\n            activeMilestoneTipClass: 'is-center',\n            activeMilestoneTipStyle: {},\n            rewardCenterSummary: null,\n            rewardCenterStats: null,\n            claimRewardStep: 'options',\n            claimRewardSubmitting: false,\n            claimRewardAlipayAccount: '',\n            claimRewardAlipayName: '',\n            ticketDataLoaded: false,\n            ticketDataLoadingPromise: null,\n            ugcDataLoaded: false,\n            ugcLoadingPromise: null,\n            dashboardPaymentCutoffDate: '2026-05-01',\n            ugcConfig: {\n                market: '',\n                platforms: [],\n            },\n            ugcHistory: [],\n            ugcGeneratedTemplates: [],\n            ugcGenerating: false,\n            ugcSubmitting: false,\n            ugcSuccessMessage: '',\n            ugcGenerateStorageKeyPrefix: 'ugc_generate_history_v1',\n            ugcForm: {\n                agreeTerms: false,\n                alipayAccount: '',\n                alipayRealName: '',\n                shareLink: '',\n                screenshotFile: null,\n            },\n            \/\/ Ticket related\n            ticket_list: [],\n            ticketCategories: [],\n            selectedParentId: '',\n            selectedSubId: '',\n            ticketSubject: '',\n            ticketDescription: '',\n            ticketConfirm: false,\n            uploadedTicketFiles: [],\n            ticketSuccess: false,\n            ticketId: '',\n            changePwdSubmitting: false,\n            changePwdForm: {\n                oldPassword: '',\n                newPassword: '',\n                confirmPassword: '',\n            },\n            mfaStatusLoaded: false,\n            mfaLoading: false,\n            mfaSubmitting: false,\n            mfaView: 'status',\n            mfaStatus: {\n                required: false,\n                enabled: false,\n                setup_required: false,\n                method: 'totp',\n                enabled_at: '',\n                recovery_codes_remaining: 0,\n            },\n            mfaSetup: {\n                otpauth_uri: '',\n                manual_entry_key: '',\n            },\n            mfaRecoveryCodes: [],\n            mfaForm: {\n                setupCode: '',\n                manageCode: '',\n                manageRecoveryCode: '',\n            },\n            mfaQrRenderError: false,\n            mfaQrScriptPromise: null,\n            isTicketDetail: false,\n            selectTicketDetail: null,\n            chatMessage: '',\n            tk_currentPage: 1,\n            tk_pageSize: 10,\n            tk_total: 0,\n            supportEmail: 'info@goglobalsafe.com',\n            supportQrUsUrl: 'https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/05\/\u4f01\u4e1a\u5fae\u4fe1\u5ba2\u670d-150x150.png',\n            supportQrAuUrl: 'https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2026\/05\/au-service.png',\n            supportQrFailed: false,\n            plusBenefitsQrFailed: false,\n            ugcGroupQrUrl: 'https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2026\/05\/ugc-group.png',\n            ugcGroupQrFallbackUrl: 'https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2026\/05\/ugc-group.png',\n            ugcGroupQrFailed: false,\n            unreadMessageCount: 0,\n            notificationPagination: {\n                current_page: 1,\n                per_page: 20,\n                total: 0,\n                last_page: 1,\n            },\n            selectedNotificationDetail: {},\n            isNotificationDetailLoading: false,\n            selectedOshcPayOrder: null,\n            isOshcPaySubmitting: false,\n            usPaymentStep: 'options',\n            oshcEmailRedirectSeconds: 5,\n            oshcEmailRedirectTimer: null,\n            toastTimer: null,\n            toast: {\n                visible: false,\n                type: 'success',\n                title: '',\n                message: '',\n            },\n            globalLoadingVisible: false,\n            globalLoadingCount: 0,\n            globalLoadingTitle: 'Processing',\n            globalLoadingMessage: 'Please wait a moment...',\n            globalLoadingShowTimer: null,\n            globalLoadingHideTimer: null,\n            renewPromoStorageKey: 'renewal_reward_rule',\n            renewPopupLastDismissTsKey: 'renew_popup_last_dismiss_ts',\n            renewPopupSuppressMs: 2 * 60 * 60 * 1000,\n            renewPopupRecheckTimer: null,\n            onboardingGuideTimer: null,\n            renewTrackPendingKey: 'renew_track_pending',\n            renewTrackActionPendingKey: 'renew_track_action_pending',\n            renewTrackLoginStatusApi: 'https:\/\/agent.goglobalsafe.com\/api\/v1\/renew\/track\/login-status',\n            renewTrackActionApi: 'https:\/\/agent.goglobalsafe.com\/api\/v1\/renew\/track\/action',\n            renewTrackState: {\n                fromUrl: '',\n                pending: '',\n                actionPending: '',\n                hasReportedLoggedIn: false,\n            },\n            renewalRewardRule: null,\n            emergencyPhoneDisplay: '+1-855-773-7810',\n            emergencyPhoneHref: 'tel:+18557737810',\n            navItems: [\n                { id: 'dashboard', label: 'Dashboard', labelKey: 'nav_dashboard', icon: 'dashboard' },\n                { id: 'plans', label: 'My Plans', labelKey: 'nav_plans', icon: 'shield' },\n                { id: 'waive', label: 'Waive Center', labelKey: 'nav_waive', icon: 'file-check' },\n                { id: 'claims', label: 'Claims', labelKey: 'nav_claims', icon: 'file' },\n                { id: 'referrals', label: 'Referral & Rewards', labelKey: 'nav_referrals', icon: 'gift' },\n                { id: 'ugc', label: 'Creator Center', labelKey: 'nav_ugc', icon: 'message' },\n                { id: 'help', label: 'Help & Settings', labelKey: 'nav_help', icon: 'help' },\n            ],\n            topActions: [\n                { id: 'emergency_sos', title: 'Emergency SOS', desc: '24\/7 Global emergency medical assistance and evacuation.', icon: 'shield', className: 'uc-gradient-blue' },\n                { id: 'ai_symptom_checker', title: 'AI Symptom Checker', desc: '24\/7 smart triage and hospital recommendations based on your symptoms.', icon: 'activity', className: 'uc-gradient-green' },\n                { id: 'bill_analyzer', title: 'Bill Analyzer', desc: 'Upload your hospital bill directly to understand your coverage and out-of-pocket costs.', icon: 'file', className: 'uc-gradient-purple' },\n            ],\n            dashboardBottomActionsUsa: [\n                { id: 'find_pharmacy', label: 'Find Pharmacy', icon: 'search', color: 'uc-text-emerald' },\n                { id: 'find_provider', label: 'Find Provider', icon: 'map-pin', color: 'uc-text-blue' },\n                { id: 'waive_guide', label: 'Waive Guide', icon: 'file-check', color: 'uc-text-purple' },\n                { id: 'add_dental_vision', label: 'Add Dental\/Vision', icon: 'plus', color: 'uc-text-orange' },\n                { id: 'contact_support', label: 'Contact Support', icon: 'message', color: 'uc-text-pink' },\n            ],\n            dashboardBottomActionsAu: [\n                { id: 'find_provider', label: 'Find Provider', icon: 'map-pin', color: 'uc-text-blue' },\n                { id: 'contact_support', label: 'Contact Support', icon: 'message', color: 'uc-text-pink' },\n            ],\n            notifications: [],\n            materials: [\n                { id: 'id_card', title: 'Insurance ID Card', desc: 'Download your digital ID card', icon: 'credit-card', className: 'uc-material-blue' },\n                { id: 'policy', title: 'Policy & Terms', desc: 'View your full coverage details', icon: 'shield', className: 'uc-material-purple' },\n                { id: 'waiver', title: 'Waive Documents', desc: 'Documents needed for school waiver', icon: 'file-check', className: 'uc-material-green' },\n            ],\n            documents: [\n                { name: 'Policy Terms', size: '2.4 MB' },\n                { name: 'Plan Brochure', size: '1.1 MB' },\n                { name: 'Member Guide', size: '850 KB' },\n                { name: 'Certificate', size: '120 KB' },\n                { name: 'Teladoc Guide', size: '1.2 MB' },\n            ],\n            orders: [\n                { plan: 'Royal Plus', period: '2025-08-01\\\\nto 2026-07-31', total: '$1843.25', status: 'Unpaid', className: 'uc-status-yellow', policy: '888-2025-2026-1' },\n                { plan: 'Royal Plus', period: '2025-08-01\\\\nto 2026-07-31', total: '$2602.45', status: 'Unpaid', className: 'uc-status-yellow', policy: '888-2025-2026-2' },\n                { plan: 'Royal Plus', period: '2025-01-09\\\\nto 2025-08-20', total: '$1131.20', status: 'Expired', className: 'uc-status-gray', policy: '888-2024-2025-1' },\n            ],\n            orderPage: 1,\n            orderPageSize: 8,\n            waiveSteps: ['Buy Plan', 'Download Docs', 'Submit Waiver', 'Wait Approval'],\n            waiveInstructions: [\n                'Choose a plan that meets your school waiver requirements.',\n                'Download policy confirmation and ID card.',\n                'Log in to your school portal and upload the documents.',\n                'Wait for approval and keep checking your school email.',\n            ],\n            claims: [\n                { id: 'CLM-2025-001', provider: 'General Hospital', date: 'Oct 12, 2025', amount: '$150.00', status: 'In Review', statusRaw: 'In Review', statusClass: 'uc-status-blue', type: 'Medical', diagnosis: 'Routine Checkup', patientName: '-', memberId: '-' },\n                { id: 'CLM-2025-002', provider: 'City Clinic', date: 'Jul 04, 2025', amount: '$85.00', status: 'Approved', statusRaw: 'Approved', statusClass: 'uc-status-green', type: 'Dental', diagnosis: 'Tooth Extraction', patientName: '-', memberId: '-' },\n            ],\n            milestones: [\n                { count: 1, tier: 'Starter', tooltipTier: 'Starter', base: '$20 Starbucks', extra: '', isBig: true },\n                { count: 2, tier: 'Connector', tooltipTier: 'Connector', base: '$20 Starbucks', extra: '\u00a550', isBig: true },\n                { count: 3, tier: '', tooltipTier: 'Connector', base: '$20 Starbucks', extra: '\u00a5300', isBig: false },\n                { count: 5, tier: 'Explorer', tooltipTier: 'Explorer', base: '$20 Starbucks', extra: '\u00a5300', isBig: true },\n                { count: 8, tier: '', tooltipTier: 'Explorer', base: '$20 Starbucks', extra: '\u00a5300', isBig: false },\n                { count: 12, tier: '', tooltipTier: 'Explorer', base: '$20 Starbucks', extra: '\u00a5500', isBig: false },\n                { count: 20, tier: 'Navigator', tooltipTier: 'Navigator', base: '$20 Starbucks', extra: '\u00a51000', isBig: true },\n                { count: 50, tier: 'Pinnacle', tooltipTier: 'Pinnacle', base: '$20 Starbucks', extra: '', isBig: true },\n            ],\n            referrals: Array.from({ length: 8 }).map((_, index) => ({\n                id: 'seed-' + index,\n                user: 'User_928' + (4 + index) + '****',\n                date: 'Aug ' + (11 + index) + ', 2025',\n                statusLabel: 'Completed',\n                statusClass: 'uc-status-green',\n            })),\n            platforms: [\n                { id: 'google', title: 'Google Maps', desc: 'Share your honest experience on Google Maps.', action: 'Open Google Maps', icon: 'map-pin', className: 'uc-platform-red' },\n                { id: 'xhs', title: 'Xiaohongshu', desc: 'Post a student-friendly review on Xiaohongshu.', action: 'Open Xiaohongshu', icon: 'book', className: 'uc-platform-red-dark' },\n                { id: 'reddit', title: 'Reddit', desc: 'Help other international students on Reddit.', action: 'Open Reddit', icon: 'message', className: 'uc-platform-orange' },\n            ],\n            referralRules: [\n                {\n                    key: 'usa',\n                    region: 'USA Referral Campaign Rules',\n                    badge: 'May 1 - Oct 30, 2026',\n                    sections: [\n                        {\n                            title: 'Campaign Period',\n                            highlight: true,\n                            lines: [\n                                'The current referral campaign is valid from May 1, 2026 to October 30, 2026.',\n                                'Only successful referrals completed within the campaign period will be counted toward this referral program.',\n                                'Referrals submitted after October 30, 2026 will return to \u00a550 rewards per successful referral.',\n                            ],\n                        },\n                        {\n                            title: 'Referrer Rewards',\n                            highlight: true,\n                            lines: [\n                                'For each friend who purchases using your referral code:',\n                                'Referrers who successfully enroll in a GGS plan for the 2026 Fall intake (Season Period: May 01, 2026-Oct 30, 2026) will receive a $20 Starbucks gift card for each successful referral.',\n                                'Referrers who do not enroll in a GGS plan for the 2026 Fall intake will instead receive a RMB 50 cash reward per successful referral.',\n                                'No upper limit on successful referrals.',\n                            ],\n                        },\n                        {\n                            title: 'Friend Rewards',\n                            highlight: true,\n                            lines: [\n                                'Friend must enter your referral code correctly during checkout.',\n                                'During this campaign period, friends can receive a $20 Starbucks gift card plus a \u00a5300 Flywire tuition coupon. Please contact WeChat customer support for the Flywire tuition coupon.',\n                            ],\n                        },\n                        {\n                            title: 'How It Works',\n                            lines: [\n                                '1) Copy your referral code or referral link from the Personal Account Center.',\n                                '2) Share it with your friends.',\n                                '3) Your friend enters the referral code during the quote\/purchase process. They can also use your referral link to purchase.',\n                                '4) Rewards are granted after successful purchase completion and waiver approval.',\n                            ],\n                        },\n                        {\n                            title: 'Important Notes Before you Refer',\n                            lines: [\n                                'Successful referrals are defined as completed purchases with approved waiver results.',\n                                'If the referred user later cancels or refunds the policy, both parties\u2019 referral rewards may be revoked.',\n                                'Failure to enter a referral code during purchase will be considered a voluntary waiver of referral rewards and campaign benefits.',\n                                'Referral rewards cannot be combined with other GGS campaigns or promotional offers unless otherwise stated.',\n                                'GGS reserves the right to investigate suspicious referral activities and revoke any related rewards in cases of abuse, fraud, duplicate accounts, self-referrals, or other violations of the campaign rules.',\n                            ],\n                        },\n                    ],\n                },\n                {\n                    key: 'au',\n                    region: 'Australia OSHC Referral Program',\n                    badge: 'OSHC',\n                    sections: [\n                        {\n                            title: 'How to Earn',\n                            highlight: true,\n                            lines: [\n                                '1) Share your referral code with friends.',\n                                '2) Your friend purchases an eligible OSHC plan (minimum coverage period: 1 year) using your referral code.',\n                                '3) After successful payment and qualification review, the reward will be credited to your account center for redemption.',\n                            ],\n                        },\n                        {\n                            title: 'Reward',\n                            highlight: true,\n                            lines: [\n                                'Each successful referral will receive a RMB 100 JD Gift Card reward.',\n                            ],\n                        },\n                        {\n                            title: 'Reward Rules',\n                            lines: [\n                                'Only orders with a coverage period of 1 year or longer are eligible for referral rewards.',\n                                'Rewards can be redeemed directly through the account center after qualification approval.',\n                                'Australia OSHC and U.S. insurance referral campaigns are managed separately. Referral codes are not interchangeable across regions. If an Australia OSHC order uses a U.S. referral code (or vice versa), the referral reward will be deemed invalid.',\n                                'Orders that are canceled, refunded, or fail qualification review will not be eligible for rewards.',\n                                'Referral rewards cannot be combined with other conflicting promotions unless otherwise stated.',\n                            ],\n                        },\n                        {\n                            title: 'Validity',\n                            lines: [\n                                'The referral code must be entered and remain valid at the time of order purchase.',\n                            ],\n                        },\n                    ],\n                },\n            ],\n        };\n    },\n    methods: {\n        formatTicketCategoryName(category) {\n            if (!category || typeof category !== 'object') return '-';\n            return category.title || category.label || category.display_name || category.name || '-';\n        },\n        getTicketCategoryLabel(ticket) {\n            const row = ticket && typeof ticket === 'object' ? ticket : {};\n            if (row.category && typeof row.category === 'object') {\n                return this.formatTicketCategoryName(row.category);\n            }\n            const categoryId = String(row.category_id || row.categoryId || '');\n            if (categoryId) {\n                const categories = Array.isArray(this.ticketCategories) ? this.ticketCategories : [];\n                for (let i = 0; i < categories.length; i += 1) {\n                    const category = categories[i] || {};\n                    if (String(category.id) === categoryId) return this.formatTicketCategoryName(category);\n                    const children = Array.isArray(category.children) ? category.children : [];\n                    const child = children.find(item => String(item && item.id) === categoryId);\n                    if (child) return this.formatTicketCategoryName(child);\n                }\n            }\n            return row.category_name || row.categoryName || '-';\n        },\n        getTicketStatusLabel(status, fallback = '') {\n            const text = String(fallback || '').trim();\n            if (text && Number.isNaN(Number(text))) return text;\n            const code = Number(status);\n            if (code === 0) return this.text.status_submitted || 'Submitted';\n            if (code === 1) return this.text.status_checking || 'Checking';\n            if (code === 2) return this.text.status_resolved || 'Resolved';\n            return text || (this.locale === 'zh' ? '\u5904\u7406\u4e2d' : 'In Progress');\n        },\n        getTicketStatusClass(status) {\n            const code = Number(status);\n            if (code === 2) return 'uc-status-green';\n            if (code === 1) return 'uc-status-red';\n            return 'uc-status-blue';\n        },\n        getTicketFileList(ticket) {\n            const row = ticket && typeof ticket === 'object' ? ticket : {};\n            const raw = row.file_list || row.files || [];\n            if (Array.isArray(raw)) return raw.filter(Boolean);\n            if (typeof raw === 'string' && raw.trim()) {\n                try {\n                    const parsed = JSON.parse(raw);\n                    if (Array.isArray(parsed)) return parsed.filter(Boolean);\n                } catch (error) {}\n                return raw.split(',').map(item => item.trim()).filter(Boolean);\n            }\n            return [];\n        },\n        getTicketFileUrl(file) {\n            const text = String(file || '').trim();\n            if (!text) return '#';\n            if (\/^https?:\\\/\\\/\/i.test(text)) return text;\n            return `${this.apiBase}\/storage\/uploads\/${text.replace(\/^\\\/+\/, '')}`;\n        },\n        getTicketChatLogs(ticket) {\n            const row = ticket && typeof ticket === 'object' ? ticket : {};\n            return Array.isArray(row.chat_log) ? row.chat_log : [];\n        },\n        scrollTicketChatToBottom() {\n            this.$nextTick(() => {\n                const el = this.$refs.ticketChatContent;\n                if (el) el.scrollTop = el.scrollHeight;\n            });\n        },\n        shouldShowNavUnreadDot(item) {\n            const navItem = item && typeof item === 'object' ? item : {};\n            if (navItem.id === 'help') return this.hasUnreadTicketMessage;\n            return false;\n        },\n        getUsStatusText(status) {\n            const code = Number(status);\n            const text = String(status === null || typeof status === 'undefined' ? '' : status).trim().toLowerCase();\n            if (code === 1) return this.t('status_active', 'Active');\n            if (code === 0) return this.t('status_unpaid', 'Unpaid');\n            if (['paid', 'active', 'complete', 'completed'].includes(text)) return this.t('status_active', 'Active');\n            if (this.isUnpaidOrderStatus(status, 'usa')) return this.t('status_unpaid', 'Unpaid');\n            if (code === -1) return this.t('status_refunded', 'Refunded');\n            if (code === 4) return this.t('status_expired', 'Expired');\n            return this.t('pending', 'Pending');\n        },\n        getAuStatusText(status) {\n            const code = Number(status);\n            const text = String(status === null || typeof status === 'undefined' ? '' : status).trim().toLowerCase();\n            if (code === 2) return this.t('status_active', 'Active');\n            if (code === 1) return this.t('status_waiting', 'Waiting');\n            if (code === -1) return this.t('status_unpaid', 'Unpaid');\n            if (['paid', 'active', 'complete', 'completed'].includes(text)) return this.t('status_active', 'Active');\n            if (this.isUnpaidOrderStatus(status, 'au')) return this.t('status_unpaid', 'Unpaid');\n            if (code === -2) return this.t('status_initiated', 'Initiated');\n            if (code === -3) return this.t('status_cancelled', 'Cancelled');\n            if (code === 4) return this.t('status_expired', 'Expired');\n            return this.t('pending', 'Pending');\n        },\n        formatDateShort(value) {\n            if (!value) return '';\n            const date = new Date(value);\n            if (Number.isNaN(date.getTime())) return '';\n            return date.toLocaleDateString(this.locale === 'zh' ? 'zh-CN' : 'en-US', {\n                month: 'short',\n                day: '2-digit',\n                year: 'numeric',\n            });\n        },\n        formatMonthYear(value) {\n            if (!value) return '';\n            const date = new Date(value);\n            if (Number.isNaN(date.getTime())) return '';\n            return date.toLocaleDateString(this.locale === 'zh' ? 'zh-CN' : 'en-US', {\n                month: 'short',\n                year: 'numeric',\n            });\n        },\n        formatDateLong(value) {\n            if (!value) return '';\n            const date = new Date(value);\n            if (Number.isNaN(date.getTime())) return '';\n            return date.toLocaleDateString(this.locale === 'zh' ? 'zh-CN' : 'en-US', {\n                month: 'long',\n                day: 'numeric',\n                year: 'numeric',\n            });\n        },\n        getTermLabelByDate(value) {\n            const date = new Date(value);\n            if (Number.isNaN(date.getTime())) return '';\n            const month = date.getMonth() + 1;\n            const year = date.getFullYear();\n            if (this.locale === 'zh') {\n                if (month >= 8 && month <= 12) return `${year} \u79cb\u5b63`;\n                if (month >= 1 && month <= 5) return `${year} \u6625\u5b63`;\n                return `${year} \u590f\u5b63`;\n            }\n            if (month >= 8 && month <= 12) return `Fall ${year}`;\n            if (month >= 1 && month <= 5) return `Spring ${year}`;\n            return `Summer ${year}`;\n        },\n        formatDateRange(start, end) {\n            const startText = this.formatDateShort(start);\n            const endText = this.formatDateShort(end);\n            if (startText && endText) return `${startText} ~ ${endText}`;\n            return startText || endText || '-';\n        },\n        normalizeDateYmd(value) {\n            const text = String(value || '').trim();\n            if (!text) return '';\n            if (text.includes('T')) return text.split('T')[0];\n            return text;\n        },\n        formatOrderPeriod(start, end) {\n            const startText = this.normalizeDateYmd(start);\n            const endText = this.normalizeDateYmd(end);\n            if (startText && endText) return `${startText}\\nto ${endText}`;\n            return startText || endText || '-';\n        },\n        formatCoverageValue(value, fallback = '-') {\n            if (value === null || typeof value === 'undefined') return fallback;\n            const text = String(value).trim();\n            return text || fallback;\n        },\n        isTruthyRegionFlag(value) {\n            if (value === true) return true;\n            if (value === false || value === null || typeof value === 'undefined') return false;\n            const text = String(value).trim().toLowerCase();\n            return ['true', '1', 'yes', 'y'].includes(text);\n        },\n        formatPercentValue(value, fallback = '-') {\n            if (value === null || typeof value === 'undefined' || value === '') return fallback;\n            const number = Number(value);\n            if (!Number.isNaN(number)) {\n                const percent = number > 0 && number <= 1 ? number * 100 : number;\n                return `${percent}%`;\n            }\n            const text = String(value).trim();\n            if (!text) return fallback;\n            return text.includes('%') ? text : `${text}%`;\n        },\n        pickDashboardRegion(user) {\n            const info = user || {};\n            const usOrder = info.usa_order && typeof info.usa_order === 'object' ? info.usa_order : null;\n            const auOrder = info.au_order && typeof info.au_order === 'object' ? info.au_order : null;\n            const usFlagRaw = typeof info.pay_status_us !== 'undefined' ? info.pay_status_us : info.pay_status_usa;\n            const auFlagRaw = info.pay_status_au;\n            const hasUsRegionFlag = this.isTruthyRegionFlag(usFlagRaw);\n            const hasAuRegionFlag = this.isTruthyRegionFlag(auFlagRaw);\n            if (hasUsRegionFlag) return 'usa';\n            if (hasAuRegionFlag) return 'au';\n\n            const regionText = String(info.region || info.market || info.country || info.order_region || '').trim().toLowerCase();\n            if (['us', 'usa', 'united states', 'united states student', 'wellaway'].includes(regionText)) return 'usa';\n            if (['au', 'australia', 'australia student', 'oshc'].includes(regionText)) return 'au';\n\n            if (usOrder && !auOrder) return 'usa';\n            if (auOrder && !usOrder) return 'au';\n            if (usOrder && auOrder) {\n                const usTime = this.getOrderTimestampForRegionPick(usOrder);\n                const auTime = this.getOrderTimestampForRegionPick(auOrder);\n                if (usTime || auTime) return usTime >= auTime ? 'usa' : 'au';\n                return 'usa';\n            }\n\n            const auSignals = [\n                info.au_order_id,\n                info.au_id,\n                info.oshc_order_id,\n                info.destination_name,\n                info.au_product_name,\n            ].some(value => value !== null && typeof value !== 'undefined' && String(value).trim() !== '');\n            if (auSignals) return 'au';\n            return 'usa';\n        },\n        getOrderTimestampForRegionPick(order) {\n            const item = order && typeof order === 'object' ? order : {};\n            const candidates = [\n                item.updated_at,\n                item.created_at,\n                item.purchaseDate,\n                item.purchase_date,\n                item.paid_at,\n                item.pay_at,\n                item.policyStartDate,\n                item.start_date,\n            ];\n            for (const value of candidates) {\n                const text = String(value || '').trim();\n                if (!text) continue;\n                const timestamp = Date.parse(text);\n                if (!Number.isNaN(timestamp)) return timestamp;\n            }\n            return 0;\n        },\n        getApiClient() {\n            if (window.ApiClient && typeof window.ApiClient.get === 'function') {\n                return window.ApiClient;\n            }\n            if (window.apiClient && typeof window.apiClient.get === 'function') {\n                return window.apiClient;\n            }\n            if (window.axios && typeof window.axios.get === 'function') {\n                return window.axios;\n            }\n            return null;\n        },\n        waitForApiClient(timeout = 4000) {\n            const readyClient = this.getApiClient();\n            if (readyClient) {\n                return Promise.resolve(readyClient);\n            }\n            const startedAt = Date.now();\n            return new Promise((resolve) => {\n                const checkClient = () => {\n                    const client = this.getApiClient();\n                    if (client) {\n                        resolve(client);\n                        return;\n                    }\n                    if (Date.now() - startedAt >= timeout) {\n                        resolve(null);\n                        return;\n                    }\n                    window.setTimeout(checkClient, 50);\n                };\n                checkClient();\n            });\n        },\n        authHeaders(headers = {}) {\n            this.authToken = this.authToken || localStorage.getItem('student_token') || '';\n            return {\n                Authorization: 'Bearer ' + this.authToken,\n                Accept: 'application\/json',\n                'x-authentication-key': 'HSxZK8nHniLzZtv0Qtfk87wvNvXpJZ5K',\n                ...headers,\n            };\n        },\n        getAuthFailureStatus(source) {\n            const candidates = [\n                source && source.status,\n                source && source.code,\n                source && source.response && source.response.status,\n                source && source.response && source.response.data && source.response.data.status,\n                source && source.response && source.response.data && source.response.data.code,\n                source && source.data && source.data.status,\n                source && source.data && source.data.code,\n            ];\n            let firstStatus = 0;\n            for (const value of candidates) {\n                const status = Number(value || 0);\n                if (status === 401 || status === 419) return status;\n                if (!firstStatus && status) firstStatus = status;\n            }\n            return firstStatus;\n        },\n        getAuthFailureMessage(source) {\n            const data = source && source.response && source.response.data ? source.response.data : (source && source.data ? source.data : source);\n            const values = [\n                source && source.message,\n                data && data.message,\n                data && data.error,\n                data && data.msg,\n                data && data.data && data.data.message,\n                data && data.data && data.data.error,\n            ];\n            return values.filter(Boolean).map(value => String(value)).join(' ').toLowerCase();\n        },\n        isAuthFailure(source) {\n            const status = this.getAuthFailureStatus(source);\n            if (status === 401 || status === 419) return true;\n            const message = this.getAuthFailureMessage(source);\n            if (!message) return false;\n            return \/unauthenticated|unauthorized|unauthorised|token\\s*(expired|invalid|missing)|invalid\\s*token|expired\\s*token|login\\s*expired|session\\s*expired|please\\s*login|please\\s*log\\s*in\/i.test(message);\n        },\n        redirectToStudentLogin() {\n            if (this.redirectingToLogin) return;\n            this.redirectingToLogin = true;\n            this.authToken = '';\n            localStorage.removeItem('student_token');\n            localStorage.removeItem('user_info');\n            const path = String((window.location && window.location.pathname) || '').replace(\/\\\/+$\/, '\/');\n            if (path !== '\/student-login\/') {\n                \/\/ window.location.href = '\/student-login\/';\n            }\n        },\n        handleAuthFailure(source) {\n            if (!this.isAuthFailure(source)) return false;\n            this.redirectToStudentLogin();\n            return true;\n        },\n        validateAuthResponse(response) {\n            if (this.handleAuthFailure(response)) {\n                throw new Error('Authentication expired. Please sign in again.');\n            }\n            return response;\n        },\n        async apiGet(url, config = {}) {\n            const apiClient = await this.waitForApiClient();\n            if (!apiClient || typeof apiClient.get !== 'function') {\n                throw new Error('API client not available');\n            }\n            const requestUrl = String(url || '').startsWith('\/') ? this.apiBase + url : url;\n            try {\n                const response = await apiClient.get(requestUrl, {\n                    ...config,\n                    headers: this.authHeaders(config.headers || {}),\n                });\n                return this.validateAuthResponse(response);\n            } catch (error) {\n                this.handleAuthFailure(error);\n                throw error;\n            }\n        },\n        async apiPost(url, data = {}, config = {}) {\n            const apiClient = await this.waitForApiClient();\n            if (!apiClient || typeof apiClient.post !== 'function') {\n                throw new Error('API client not available');\n            }\n            const requestUrl = String(url || '').startsWith('\/') ? this.apiBase + url : url;\n            try {\n                const response = await apiClient.post(requestUrl, data, {\n                    ...config,\n                    headers: this.authHeaders(config.headers || {}),\n                });\n                return this.validateAuthResponse(response);\n            } catch (error) {\n                this.handleAuthFailure(error);\n                throw error;\n            }\n        },\n        getPayloadData(response) {\n            const payload = response && response.data ? response.data : {};\n            return payload && Object.prototype.hasOwnProperty.call(payload, 'data') ? payload.data : payload;\n        },\n        showToast(type, message, title = '') {\n            const toastType = type === 'error' ? 'error' : 'success';\n            const toastTitle = title || (toastType === 'error' ? 'Action failed' : 'Success');\n            if (this.toastTimer) {\n                window.clearTimeout(this.toastTimer);\n                this.toastTimer = null;\n            }\n            this.toast = {\n                visible: true,\n                type: toastType,\n                title: toastTitle,\n                message: String(message || '').trim() || (toastType === 'error' ? 'Something went wrong.' : 'Done.'),\n            };\n            this.toastTimer = window.setTimeout(() => {\n                this.hideToast();\n            }, 2600);\n        },\n        hideToast() {\n            if (this.toastTimer) {\n                window.clearTimeout(this.toastTimer);\n                this.toastTimer = null;\n            }\n            this.toast.visible = false;\n        },\n        notifySuccess(message) {\n            this.showToast('success', this.localizeMessage(message), this.t('success', 'Success'));\n        },\n        notifyError(message) {\n            this.showToast('error', this.localizeMessage(message), this.t('notice', 'Notice'));\n        },\n        localizeMessage(message) {\n            const text = String(message || '').trim();\n            if (!text || this.locale !== 'zh') return text;\n            const map = {\n                'Please enter your Alipay account.': '\u8bf7\u8f93\u5165\u652f\u4ed8\u5b9d\u8d26\u53f7\u3002',\n                'Please enter the real name that matches your Alipay account.': '\u8bf7\u8f93\u5165\u4e0e\u652f\u4ed8\u5b9d\u4e00\u81f4\u7684\u771f\u5b9e\u59d3\u540d\u3002',\n                'Digital link generated.': '\u5151\u6362\u94fe\u63a5\u5df2\u751f\u6210\u3002',\n                'Withdrawal request submitted.': '\u63d0\u73b0\u7533\u8bf7\u5df2\u63d0\u4ea4\u3002',\n                'Unable to load message detail': '\u65e0\u6cd5\u52a0\u8f7d\u6d88\u606f\u8be6\u60c5',\n                'Referral code requested': '\u63a8\u8350\u7801\u5df2\u7533\u8bf7',\n                'Referral code application failed. Please contact customer service.': '\u63a8\u8350\u7801\u7533\u8bf7\u5931\u8d25\uff0c\u8bf7\u8054\u7cfb\u5ba2\u670d\u3002',\n                'UGC Center is available after purchasing insurance.': '\u8d2d\u4e70\u4fdd\u9669\u540e\u53ef\u4f7f\u7528 UGC \u4e2d\u5fc3\u3002',\n                'Download successful': '\u4e0b\u8f7d\u6210\u529f',\n                'Summary of Benefits is not available yet.': '\u798f\u5229\u6458\u8981\u6682\u4e0d\u53ef\u7528\u3002',\n                'No USA enrollment found for this document': '\u672a\u627e\u5230\u53ef\u7528\u4e8e\u8be5\u6587\u4ef6\u7684\u7f8e\u56fd\u8ba2\u5355\u3002',\n                'Platform link is not available.': '\u5e73\u53f0\u94fe\u63a5\u6682\u4e0d\u53ef\u7528\u3002',\n                'No template available.': '\u6682\u65e0\u53ef\u7528\u6587\u6848\u3002',\n                'Copy generated. Click the item to select it for submission.': '\u6587\u6848\u5df2\u751f\u6210\uff0c\u70b9\u51fb\u6587\u6848\u5373\u53ef\u7528\u4e8e\u63d0\u4ea4\u3002',\n                'Only png, jpg, jpeg, and pdf files are allowed.': '\u4ec5\u652f\u6301 png\u3001jpg\u3001jpeg \u548c pdf \u6587\u4ef6\u3002',\n                'File size cannot exceed 10MB.': '\u6587\u4ef6\u5927\u5c0f\u4e0d\u80fd\u8d85\u8fc7 10MB\u3002',\n                'Failed to load UGC configuration.': 'UGC \u914d\u7f6e\u52a0\u8f7d\u5931\u8d25\u3002',\n                'Failed to load UGC history.': 'UGC \u5386\u53f2\u8bb0\u5f55\u52a0\u8f7d\u5931\u8d25\u3002',\n                'Please generate copy first.': '\u8bf7\u5148\u751f\u6210\u6587\u6848\u3002',\n                'Please upload a screenshot file.': '\u8bf7\u4e0a\u4f20\u622a\u56fe\u6587\u4ef6\u3002',\n                'Please agree to the terms before submitting.': '\u63d0\u4ea4\u524d\u8bf7\u5148\u540c\u610f\u76f8\u5173\u786e\u8ba4\u3002',\n                'Alipay account and real name are required for cash reward.': '\u73b0\u91d1\u5956\u52b1\u9700\u8981\u586b\u5199\u652f\u4ed8\u5b9d\u8d26\u53f7\u548c\u771f\u5b9e\u59d3\u540d\u3002',\n                'UGC submit failed. Please try again.': 'UGC \u63d0\u4ea4\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5\u3002',\n                'Referral link copied': '\u63a8\u8350\u94fe\u63a5\u5df2\u590d\u5236',\n                'Referral code copied': '\u63a8\u8350\u7801\u5df2\u590d\u5236',\n                'Claims instructions are not available right now.': '\u7406\u8d54\u8bf4\u660e\u6682\u4e0d\u53ef\u7528\u3002',\n                'Claim template is not available right now.': '\u7406\u8d54\u6a21\u677f\u6682\u4e0d\u53ef\u7528\u3002',\n                'File upload failed': '\u6587\u4ef6\u4e0a\u4f20\u5931\u8d25',\n                'Please upload at least one file': '\u8bf7\u81f3\u5c11\u4e0a\u4f20\u4e00\u4e2a\u6587\u4ef6',\n                'Member ID is required before submitting claim files': '\u63d0\u4ea4\u7406\u8d54\u6587\u4ef6\u524d\u9700\u8981\u4f1a\u5458 ID\u3002',\n                'Please wait until files upload successfully': '\u8bf7\u7b49\u5f85\u6587\u4ef6\u4e0a\u4f20\u6210\u529f\u540e\u518d\u63d0\u4ea4\u3002',\n                'Files submitted successfully!': '\u6587\u4ef6\u63d0\u4ea4\u6210\u529f\uff01',\n                'Failed to submit files': '\u6587\u4ef6\u63d0\u4ea4\u5931\u8d25',\n                'EOB is not available yet': 'EOB \u6682\u4e0d\u53ef\u7528',\n                'Missing claim download parameters': '\u7f3a\u5c11\u7406\u8d54\u4e0b\u8f7d\u53c2\u6570',\n                'EOB download successful': 'EOB \u4e0b\u8f7d\u6210\u529f',\n                'Please enter a message': '\u8bf7\u8f93\u5165\u6d88\u606f',\n                'Sent success': '\u53d1\u9001\u6210\u529f',\n                'Failed to send message': '\u53d1\u9001\u6d88\u606f\u5931\u8d25',\n                'Ticket detail is not ready': '\u5de5\u5355\u8be6\u60c5\u6682\u672a\u5c31\u7eea',\n                'Failed to upload files': '\u6587\u4ef6\u4e0a\u4f20\u5931\u8d25',\n                'Files uploaded successfully!': '\u6587\u4ef6\u4e0a\u4f20\u6210\u529f\uff01',\n                'Please select category': '\u8bf7\u9009\u62e9\u5206\u7c7b',\n                'Please select subcategory': '\u8bf7\u9009\u62e9\u5b50\u5206\u7c7b',\n                'Please enter ticket subject': '\u8bf7\u8f93\u5165\u5de5\u5355\u4e3b\u9898',\n                'Please enter ticket description': '\u8bf7\u8f93\u5165\u5de5\u5355\u63cf\u8ff0',\n                'Please confirm support follow-up agreement': '\u8bf7\u786e\u8ba4\u5ba2\u670d\u8ddf\u8fdb\u6388\u6743',\n                'Submit success': '\u63d0\u4ea4\u6210\u529f',\n                'Error, please try again later': '\u51fa\u9519\u4e86\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5',\n                'Network error, please try again later': '\u7f51\u7edc\u9519\u8bef\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5',\n                'Please enter old password.': '\u8bf7\u8f93\u5165\u65e7\u5bc6\u7801\u3002',\n                'Password cannot be less than 6 characters.': '\u5bc6\u7801\u4e0d\u80fd\u5c11\u4e8e 6 \u4f4d\u3002',\n                'Password cannot contain Chinese characters.': '\u5bc6\u7801\u4e0d\u80fd\u5305\u542b\u4e2d\u6587\u5b57\u7b26\u3002',\n                'The password you entered is inconsistent.': '\u4e24\u6b21\u8f93\u5165\u7684\u5bc6\u7801\u4e0d\u4e00\u81f4\u3002',\n                'Change success': '\u4fee\u6539\u6210\u529f',\n                'Failed to change password.': '\u4fee\u6539\u5bc6\u7801\u5931\u8d25\u3002',\n                'Processing': '\u5904\u7406\u4e2d',\n                'Loading': '\u52a0\u8f7d\u4e2d',\n                'Generating': '\u751f\u6210\u4e2d',\n                'Submitting': '\u63d0\u4ea4\u4e2d',\n                'Please wait a moment...': '\u8bf7\u7a0d\u5019...',\n                'Loading UGC center...': '\u6b63\u5728\u52a0\u8f7d UGC \u4e2d\u5fc3...',\n                'Submitting your UGC screenshot...': '\u6b63\u5728\u63d0\u4ea4 UGC \u622a\u56fe...',\n                'Loading claims...': '\u6b63\u5728\u52a0\u8f7d\u7406\u8d54\u8bb0\u5f55...',\n                'Loading plans...': '\u6b63\u5728\u52a0\u8f7d\u8ba1\u5212...',\n            };\n            return map[text] || text;\n        },\n        localizeRuleText(value) {\n            const text = String(value || '').trim();\n            if (!text || this.locale !== 'zh') return text;\n            const map = {\n                Popular: '\u70ed\u95e8',\n                'USA Referral Campaign Rules': '\u7f8e\u56fd\u63a8\u8350\u6d3b\u52a8\u89c4\u5219',\n                'Australia OSHC Referral Program': '\u6fb3\u6d32 OSHC \u63a8\u8350\u6d3b\u52a8\u89c4\u5219',\n                'May 1 - Oct 30, 2026': '2026\u5e745\u67081\u65e5 - 10\u670830\u65e5',\n                'Campaign Period': '\u6d3b\u52a8\u65f6\u95f4',\n                'Referrer Rewards': '\u63a8\u8350\u4eba\u5956\u52b1',\n                'Friend Rewards': '\u597d\u53cb\u5956\u52b1',\n                'How It Works': '\u53c2\u4e0e\u65b9\u5f0f',\n                'Important Notes': '\u91cd\u8981\u8bf4\u660e',\n                'Important Notes Before you Refer': '\u63a8\u8350\u524d\u91cd\u8981\u8bf4\u660e',\n                '3 Steps to Earn': '\u4e09\u6b65\u9886\u53d6\u5956\u52b1',\n                'How to Earn': '\u5982\u4f55\u83b7\u5f97\u5956\u52b1',\n                Reward: '\u5956\u52b1',\n                'Reward Rules': '\u5956\u52b1\u89c4\u5219',\n                Validity: '\u6709\u6548\u6027',\n                'The current referral campaign is valid from May 1, 2026 to October 30, 2026.': '\u5f53\u524d\u63a8\u8350\u6d3b\u52a8\u6709\u6548\u671f\u4e3a 2026\u5e745\u67081\u65e5\u81f32026\u5e7410\u670830\u65e5\u3002',\n                'Only successful referrals completed within the campaign period will be counted toward this referral program.': '\u4ec5\u6d3b\u52a8\u671f\u5185\u5b8c\u6210\u7684\u6210\u529f\u63a8\u8350\u4f1a\u8ba1\u5165\u672c\u6b21\u63a8\u8350\u6d3b\u52a8\u3002',\n                'Referrals submitted after October 30, 2026 will return to \u00a550 rewards per successful referral.': '2026\u5e7410\u670830\u65e5\u540e\u63d0\u4ea4\u7684\u63a8\u8350\uff0c\u5c06\u6062\u590d\u4e3a\u6bcf\u6210\u529f\u63a8\u8350 \u00a550 \u5956\u52b1\u3002',\n                'For each friend who purchases using your referral code:': '\u597d\u53cb\u4f7f\u7528\u4f60\u7684\u63a8\u8350\u7801\u8d2d\u4e70\u540e\uff1a',\n                'Referrers who successfully enroll in a GGS plan for the 2026 Fall intake (Season Period: May 01, 2026-Oct 30, 2026) will receive a $20 Starbucks gift card for each successful referral.': '\u63a8\u8350\u4eba\u82e5\u6210\u529f\u8d2d\u4e70\u5e76 enroll 2026 Fall \u5165\u5b66\u5b63\u7684 GGS \u8ba1\u5212\uff08Season Period: 2026\u5e745\u67081\u65e5-2026\u5e7410\u670830\u65e5\uff09\uff0c\u6bcf\u4e2a\u6210\u529f\u63a8\u8350\u53ef\u83b7\u5f97\u4e00\u5f20 $20 Starbucks gift card\u3002',\n                'Referrers who do not enroll in a GGS plan for the 2026 Fall intake will instead receive a RMB 50 cash reward per successful referral.': '\u63a8\u8350\u4eba\u82e5\u672a\u8d2d\u4e70 2026 Fall \u5165\u5b66\u5b63\u7684 GGS \u8ba1\u5212\uff0c\u5219\u6bcf\u4e2a\u6210\u529f\u63a8\u8350\u53ef\u83b7\u5f97 RMB 50 \u73b0\u91d1\u5956\u52b1\u3002',\n                'Friend must enter your referral code correctly during checkout.': '\u597d\u53cb\u5fc5\u987b\u5728\u7ed3\u8d26\u65f6\u6b63\u786e\u586b\u5199\u4f60\u7684\u63a8\u8350\u7801\u3002',\n                'During this campaign period, friends can receive a $20 Starbucks gift card plus a \u00a5300 Flywire tuition coupon. Please contact WeChat customer support for the Flywire tuition coupon.': '\u6d3b\u52a8\u671f\u95f4\uff0c\u597d\u53cb\u53ef\u83b7\u5f97\u4e00\u5f20 $20 Starbucks gift card\uff0c\u5e76\u989d\u5916\u83b7\u5f97 \u00a5300 Flywire \u5b66\u8d39\u4f18\u60e0\u5238\u3002Flywire \u5b66\u8d39\u4f18\u60e0\u5238\u8bf7\u8054\u7cfb\u5fae\u4fe1\u5ba2\u670d\u9886\u53d6\u3002',\n                '1) Copy your referral code or referral link from the Personal Account Center.': '1\uff09\u5728 Personal Account Center \u590d\u5236\u4f60\u7684\u63a8\u8350\u7801\u6216\u63a8\u8350\u94fe\u63a5\u3002',\n                '2) Share it with your friends.': '2\uff09\u5206\u4eab\u7ed9\u4f60\u7684\u670b\u53cb\u3002',\n                '3) Your friend enters the referral code during the quote\/purchase process. They can also use your referral link to purchase.': '3\uff09\u670b\u53cb\u5728\u62a5\u4ef7\u6216\u8d2d\u4e70\u6d41\u7a0b\u4e2d\u586b\u5199\u63a8\u8350\u7801\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u4f60\u7684\u63a8\u8350\u94fe\u63a5\u76f4\u63a5\u8d2d\u4e70\u3002',\n                '4) Rewards are granted after successful purchase completion and waiver approval.': '4\uff09\u5956\u52b1\u5c06\u5728\u597d\u53cb\u5b8c\u6210\u8d2d\u4e70\u5e76\u901a\u8fc7 waiver approval \u540e\u53d1\u653e\u3002',\n                'Successful referrals are defined as completed purchases with approved waiver results.': '\u6210\u529f\u63a8\u8350\u6307\uff1a\u597d\u53cb\u5df2\u5b8c\u6210\u8d2d\u4e70\uff0c\u4e14 waiver \u7ed3\u679c\u5df2\u901a\u8fc7\u5ba1\u6838\u3002',\n                'If the referred user later cancels or refunds the policy, both parties\u2019 referral rewards may be revoked.': '\u5982\u679c\u88ab\u63a8\u8350\u7528\u6237\u540e\u7eed\u53d6\u6d88\u6216\u9000\u6b3e\u4fdd\u5355\uff0c\u53cc\u65b9\u63a8\u8350\u5956\u52b1\u53ef\u80fd\u4f1a\u88ab\u64a4\u9500\u3002',\n                'Failure to enter a referral code during purchase will be considered a voluntary waiver of referral rewards and campaign benefits.': '\u8d2d\u4e70\u65f6\u672a\u586b\u5199\u63a8\u8350\u7801\uff0c\u5c06\u89c6\u4e3a\u81ea\u613f\u653e\u5f03\u63a8\u8350\u5956\u52b1\u548c\u672c\u6b21\u6d3b\u52a8\u6743\u76ca\u3002',\n                'Referral rewards cannot be combined with other GGS campaigns or promotional offers unless otherwise stated.': '\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u63a8\u8350\u5956\u52b1\u4e0d\u53ef\u4e0e\u5176\u4ed6 GGS \u6d3b\u52a8\u6216\u4fc3\u9500\u4f18\u60e0\u53e0\u52a0\u4f7f\u7528\u3002',\n                'GGS reserves the right to investigate suspicious referral activities and revoke any related rewards in cases of abuse, fraud, duplicate accounts, self-referrals, or other violations of the campaign rules.': '\u5982\u53d1\u73b0\u6ee5\u7528\u3001\u6b3a\u8bc8\u3001\u91cd\u590d\u8d26\u53f7\u3001\u81ea\u6211\u63a8\u8350\u6216\u5176\u4ed6\u8fdd\u53cd\u6d3b\u52a8\u89c4\u5219\u7684\u884c\u4e3a\uff0cGGS \u4fdd\u7559\u8c03\u67e5\u5e76\u64a4\u9500\u76f8\u5173\u5956\u52b1\u7684\u6743\u5229\u3002',\n                '2) Your friend purchases an eligible OSHC plan (minimum coverage period: 1 year) using your referral code.': '2\uff09\u4f60\u7684\u670b\u53cb\u4f7f\u7528\u4f60\u7684\u63a8\u8350\u7801\u8d2d\u4e70\u7b26\u5408\u6761\u4ef6\u7684 OSHC \u8ba1\u5212\uff08\u6700\u4f4e\u4fdd\u969c\u671f\u9650\uff1a1\u5e74\uff09\u3002',\n                '3) After successful payment and qualification review, the reward will be credited to your account center for redemption.': '3\uff09\u6210\u529f\u4ed8\u6b3e\u5e76\u901a\u8fc7\u8d44\u683c\u5ba1\u6838\u540e\uff0c\u5956\u52b1\u5c06\u8ba1\u5165\u4f60\u7684 Account Center\uff0c\u53ef\u7528\u4e8e\u5151\u6362\u3002',\n                'Each successful referral will receive a RMB 100 JD Gift Card reward.': '\u6bcf\u4e2a\u6210\u529f\u63a8\u8350\u53ef\u83b7\u5f97 RMB 100 \u4eac\u4e1c\u793c\u54c1\u5361\u5956\u52b1\u3002',\n                'Only orders with a coverage period of 1 year or longer are eligible for referral rewards.': '\u4ec5\u4fdd\u969c\u671f\u9650\u4e3a 1 \u5e74\u6216\u66f4\u957f\u7684\u8ba2\u5355\u7b26\u5408\u63a8\u8350\u5956\u52b1\u8d44\u683c\u3002',\n                'Rewards can be redeemed directly through the account center after qualification approval.': '\u8d44\u683c\u5ba1\u6838\u901a\u8fc7\u540e\uff0c\u53ef\u5728 Account Center \u76f4\u63a5\u5151\u6362\u5956\u52b1\u3002',\n                'Australia OSHC and U.S. insurance referral campaigns are managed separately. Referral codes are not interchangeable across regions. If an Australia OSHC order uses a U.S. referral code (or vice versa), the referral reward will be deemed invalid.': '\u6fb3\u6d32 OSHC \u4e0e\u7f8e\u56fd\u4fdd\u9669\u63a8\u8350\u6d3b\u52a8\u5206\u522b\u7ba1\u7406\u3002\u63a8\u8350\u7801\u4e0d\u53ef\u8de8\u5730\u533a\u4e92\u7528\u3002\u5982\u679c\u6fb3\u6d32 OSHC \u8ba2\u5355\u4f7f\u7528\u7f8e\u56fd\u63a8\u8350\u7801\uff08\u6216\u53cd\u5411\u4f7f\u7528\uff09\uff0c\u8be5\u63a8\u8350\u5956\u52b1\u5c06\u88ab\u89c6\u4e3a\u65e0\u6548\u3002',\n                'Orders that are canceled, refunded, or fail qualification review will not be eligible for rewards.': '\u5df2\u53d6\u6d88\u3001\u5df2\u9000\u6b3e\u6216\u672a\u901a\u8fc7\u8d44\u683c\u5ba1\u6838\u7684\u8ba2\u5355\u4e0d\u7b26\u5408\u5956\u52b1\u8d44\u683c\u3002',\n                'Referral rewards cannot be combined with other conflicting promotions unless otherwise stated.': '\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u63a8\u8350\u5956\u52b1\u4e0d\u53ef\u4e0e\u5176\u4ed6\u51b2\u7a81\u4fc3\u9500\u6d3b\u52a8\u53e0\u52a0\u4f7f\u7528\u3002',\n                'The referral code must be entered and remain valid at the time of order purchase.': '\u63a8\u8350\u7801\u5fc5\u987b\u5728\u8ba2\u5355\u8d2d\u4e70\u65f6\u586b\u5199\uff0c\u5e76\u5728\u8d2d\u4e70\u65f6\u4fdd\u6301\u6709\u6548\u3002',\n                'For each friend who purchases with your referral code: existing GGS insured users receive a $20 Starbucks gift card.': '\u597d\u53cb\u4f7f\u7528\u4f60\u7684\u63a8\u8350\u7801\u8d2d\u4e70\u540e\uff0c\u5df2\u6295\u4fdd GGS \u7684\u7528\u6237\u53ef\u83b7\u5f97 $20 \u661f\u5df4\u514b\u5361\u3002',\n                'If you are not yet insured with GGS, you receive a RMB 50 cash reward per successful referral.': '\u5982\u679c\u4f60\u5c1a\u672a\u6295\u4fdd GGS\uff0c\u6bcf\u4e2a\u6210\u529f\u63a8\u8350\u53ef\u83b7\u5f97 50 RMB \u73b0\u91d1\u5956\u52b1\u3002',\n                'No upper limit on successful referrals.': '\u6210\u529f\u63a8\u8350\u6b21\u6570\u4e0d\u8bbe\u4e0a\u9650\u3002',\n                'Friend must enter your referral code correctly at purchase checkout.': '\u597d\u53cb\u9700\u5728\u8d2d\u4e70\u7ed3\u8d26\u65f6\u6b63\u786e\u586b\u5199\u4f60\u7684\u63a8\u8350\u7801\u3002',\n                'During the campaign upgrade period: friend can receive a $20 Starbucks gift card plus a Flywire coupon package.': '\u6d3b\u52a8\u5347\u7ea7\u671f\u95f4\uff0c\u597d\u53cb\u53ef\u83b7\u5f97 $20 \u661f\u5df4\u514b\u5361\u53ca Flywire \u4f18\u60e0\u5238\u5305\u3002',\n                'After campaign period, reward reverts to the standard gift card offer.': '\u6d3b\u52a8\u7ed3\u675f\u540e\uff0c\u597d\u53cb\u5956\u52b1\u6062\u590d\u4e3a\u6807\u51c6\u793c\u54c1\u5361\u3002',\n                '1) Copy your referral code in Personal Center.': '1\uff09\u5728\u4e2a\u4eba\u4e2d\u5fc3\u590d\u5236\u4f60\u7684\u63a8\u8350\u7801\u3002',\n                '2) Share it, and your friend enters it on the quote\/purchase flow.': '2\uff09\u5206\u4eab\u7ed9\u597d\u53cb\uff0c\u597d\u53cb\u5728\u62a5\u4ef7\/\u8d2d\u4e70\u6d41\u7a0b\u4e2d\u586b\u5199\u3002',\n                '3) Rewards are granted after purchase completion and waiver success.': '3\uff09\u8d2d\u4e70\u5b8c\u6210\u4e14\u8c41\u514d\u6210\u529f\u540e\u53d1\u653e\u5956\u52b1\u3002',\n                'Wrong or missing referral code cannot be matched retroactively.': '\u63a8\u8350\u7801\u586b\u5199\u9519\u8bef\u6216\u9057\u6f0f\uff0c\u65e0\u6cd5\u4e8b\u540e\u8865\u767b\u3002',\n                'Rewards may be adjusted for refunded\/cancelled orders.': '\u9000\u6b3e\u6216\u53d6\u6d88\u8ba2\u5355\u7684\u5956\u52b1\u53ef\u80fd\u4f1a\u88ab\u8c03\u6574\u3002',\n                'Share your referral code with friends buying eligible AU OSHC plans.': '\u5c06\u4f60\u7684\u63a8\u8350\u7801\u5206\u4eab\u7ed9\u8d2d\u4e70\u7b26\u5408\u6761\u4ef6 AU OSHC \u8ba1\u5212\u7684\u597d\u53cb\u3002',\n                'Reward is issued after the order is confirmed and policy is active.': '\u8ba2\u5355\u786e\u8ba4\u4e14\u4fdd\u5355\u751f\u6548\u540e\u53d1\u653e\u5956\u52b1\u3002',\n                'Referral rewards follow current campaign settlement rules.': '\u63a8\u8350\u5956\u52b1\u6309\u5f53\u524d\u6d3b\u52a8\u7ed3\u7b97\u89c4\u5219\u53d1\u653e\u3002',\n                '1) Share your referral code with friends.': '1\uff09\u5206\u4eab\u4f60\u7684\u63a8\u8350\u7801\u7ed9\u597d\u53cb\u3002',\n                '2) Friend purchases eligible OSHC plan (normally 1 year or longer) using your code.': '2\uff09\u597d\u53cb\u4f7f\u7528\u4f60\u7684\u63a8\u8350\u7801\u8d2d\u4e70\u7b26\u5408\u6761\u4ef6\u7684 OSHC \u8ba1\u5212\uff08\u901a\u5e38\u4e3a 1 \u5e74\u6216\u66f4\u957f\uff09\u3002',\n                '3) Reward is issued after order confirmation and qualification checks.': '3\uff09\u8ba2\u5355\u786e\u8ba4\u5e76\u5b8c\u6210\u8d44\u683c\u5ba1\u6838\u540e\u53d1\u653e\u5956\u52b1\u3002',\n                'Each qualified referral can receive campaign-defined gift card\/cash reward.': '\u6bcf\u4e2a\u5408\u683c\u63a8\u8350\u53ef\u83b7\u5f97\u6d3b\u52a8\u89c4\u5b9a\u7684\u793c\u54c1\u5361\u6216\u73b0\u91d1\u5956\u52b1\u3002',\n                'Rewards are settled monthly; issuance usually occurs in the next cycle.': '\u5956\u52b1\u6309\u6708\u7ed3\u7b97\uff0c\u901a\u5e38\u5728\u4e0b\u4e00\u4e2a\u5468\u671f\u53d1\u653e\u3002',\n                'Referral rewards cannot be stacked with other conflicting promotions unless explicitly stated.': '\u9664\u975e\u7279\u522b\u8bf4\u660e\uff0c\u63a8\u8350\u5956\u52b1\u4e0d\u53ef\u4e0e\u51b2\u7a81\u6d3b\u52a8\u53e0\u52a0\u3002',\n                'Referral code must be valid at order creation time.': '\u63a8\u8350\u7801\u5fc5\u987b\u5728\u8ba2\u5355\u521b\u5efa\u65f6\u6709\u6548\u3002',\n                'Orders canceled\/refunded before qualification are not rewarded.': '\u8d44\u683c\u786e\u8ba4\u524d\u53d6\u6d88\u6216\u9000\u6b3e\u7684\u8ba2\u5355\u4e0d\u53d1\u653e\u5956\u52b1\u3002',\n            };\n            return map[text] || text;\n        },\n        t(key, fallback = '') {\n            if (!key) return fallback;\n            const text = this.text && Object.prototype.hasOwnProperty.call(this.text, key) ? this.text[key] : '';\n            return text || fallback;\n        },\n        getUnbrandedPlanName(value) {\n            const text = String(value === null || typeof value === 'undefined' ? '' : value).trim();\n            return text.replace(\/^(?:GGS|GGS)\\s*\/i, '').trim();\n        },\n        formatPlanName(value) {\n            const text = String(value === null || typeof value === 'undefined' ? '' : value).trim();\n            if (!text || text === '-') return text || '-';\n            const noActiveLabels = [\n                'No Active Plan',\n                'No Active GGS Plan',\n                '\u6682\u65e0\u751f\u6548\u8ba1\u5212',\n                '\u6682\u65e0\u751f\u6548GGS\u8ba1\u5212',\n                this.t('no_active_plan', 'No Active GGS Plan'),\n            ];\n            if (noActiveLabels.includes(text)) return text;\n            const base = this.getUnbrandedPlanName(text);\n            if (!base) return text;\n            const prefix = this.locale === 'zh' ? 'GGS' : 'GGS';\n            return `${prefix} ${base}`;\n        },\n        getActionTitle(action) {\n            const id = String(action && action.id || '');\n            const map = {\n                emergency_sos: 'top_emergency_title',\n                ai_symptom_checker: 'top_ai_title',\n                bill_analyzer: 'top_bill_title',\n            };\n            return this.t(map[id], action && action.title ? action.title : '');\n        },\n        getActionDesc(action) {\n            const id = String(action && action.id || '');\n            const map = {\n                emergency_sos: 'top_emergency_desc',\n                ai_symptom_checker: 'top_ai_desc',\n                bill_analyzer: 'top_bill_desc',\n            };\n            return this.t(map[id], action && action.desc ? action.desc : '');\n        },\n        getActionLabel(action) {\n            const id = String(action && action.id || '');\n            const map = {\n                find_pharmacy: 'bottom_find_pharmacy',\n                find_provider: 'bottom_find_provider',\n                waive_guide: 'bottom_waive_guide',\n                add_dental_vision: 'bottom_add_dental_vision',\n                contact_support: 'bottom_contact_support',\n            };\n            return this.t(map[id], action && action.label ? action.label : '');\n        },\n        getApiErrorMessage(error, fallback = 'Request failed. Please try again.') {\n            if (!error) return fallback;\n            const response = error.response && error.response.data ? error.response.data : null;\n            if (response && typeof response === 'object') {\n                if (response.message) return String(response.message);\n                if (response.error) return String(response.error);\n                if (response.data && response.data.message) return String(response.data.message);\n            }\n            const message = error.message ? String(error.message) : '';\n            return message || fallback;\n        },\n        getUploadPayloadErrorMessage(payload, fallback = 'File upload failed') {\n            const body = payload && typeof payload === 'object' ? payload : {};\n            const status = Number(body.status || 0);\n            const success = body.success;\n            const message = String(\n                body.message\n                || body.error\n                || (body.data && body.data.message)\n                || ''\n            ).trim();\n            if (success === false || (status >= 400 && status !== 0)) {\n                return message || fallback;\n            }\n            return '';\n        },\n        clearGlobalLoadingTimers() {\n            if (this.globalLoadingShowTimer) {\n                window.clearTimeout(this.globalLoadingShowTimer);\n                this.globalLoadingShowTimer = null;\n            }\n            if (this.globalLoadingHideTimer) {\n                window.clearTimeout(this.globalLoadingHideTimer);\n                this.globalLoadingHideTimer = null;\n            }\n        },\n        beginGlobalLoading(message = 'Please wait a moment...', title = 'Processing') {\n            this.globalLoadingCount += 1;\n            this.globalLoadingTitle = this.localizeMessage(String(title || 'Processing'));\n            this.globalLoadingMessage = this.localizeMessage(String(message || 'Please wait a moment...'));\n            if (this.globalLoadingHideTimer) {\n                window.clearTimeout(this.globalLoadingHideTimer);\n                this.globalLoadingHideTimer = null;\n            }\n            if (this.globalLoadingVisible) return;\n            if (this.globalLoadingShowTimer) return;\n            this.globalLoadingShowTimer = window.setTimeout(() => {\n                this.globalLoadingShowTimer = null;\n                if (this.globalLoadingCount > 0) {\n                    this.globalLoadingVisible = true;\n                }\n            }, 90);\n        },\n        endGlobalLoading() {\n            this.globalLoadingCount = Math.max(0, Number(this.globalLoadingCount || 0) - 1);\n            if (this.globalLoadingCount > 0) return;\n            if (this.globalLoadingShowTimer) {\n                window.clearTimeout(this.globalLoadingShowTimer);\n                this.globalLoadingShowTimer = null;\n            }\n            if (!this.globalLoadingVisible) return;\n            if (this.globalLoadingHideTimer) {\n                window.clearTimeout(this.globalLoadingHideTimer);\n            }\n            this.globalLoadingHideTimer = window.setTimeout(() => {\n                this.globalLoadingHideTimer = null;\n                if (this.globalLoadingCount === 0) {\n                    this.globalLoadingVisible = false;\n                }\n            }, 180);\n        },\n        async withGlobalLoading(message, task, title = 'Processing') {\n            this.beginGlobalLoading(message, title);\n            try {\n                return await task();\n            } finally {\n                this.endGlobalLoading();\n            }\n        },\n        copyTextLegacy(text) {\n            const textarea = document.createElement('textarea');\n            textarea.value = text;\n            textarea.setAttribute('readonly', 'readonly');\n            textarea.setAttribute('aria-hidden', 'true');\n            textarea.style.position = 'fixed';\n            textarea.style.top = '-9999px';\n            textarea.style.left = '-9999px';\n            textarea.style.opacity = '0';\n            document.body.appendChild(textarea);\n            textarea.focus();\n            textarea.select();\n            textarea.setSelectionRange(0, textarea.value.length);\n\n            let copied = false;\n            try {\n                copied = document.execCommand('copy');\n            } catch (error) {\n                copied = false;\n            }\n\n            document.body.removeChild(textarea);\n            return copied;\n        },\n        normalizeMfaStatus(data = {}) {\n            const payload = data && typeof data === 'object' ? data : {};\n            return {\n                required: !!payload.required,\n                enabled: !!payload.enabled,\n                setup_required: !!payload.setup_required,\n                method: payload.method || 'totp',\n                enabled_at: payload.enabled_at || '',\n                recovery_codes_remaining: Number(payload.recovery_codes_remaining || 0),\n            };\n        },\n        async fetchMfaStatus(options = {}) {\n            const silent = !!options.silent;\n            this.authToken = this.authToken || localStorage.getItem('student_token') || '';\n            if (!this.authToken) return null;\n            this.mfaLoading = true;\n            try {\n                const response = await this.apiGet(this.api.mfaStatus);\n                const data = this.getPayloadData(response) || {};\n                this.mfaStatus = this.normalizeMfaStatus(data);\n                this.mfaStatusLoaded = true;\n                return this.mfaStatus;\n            } catch (error) {\n                if (!silent) {\n                    this.notifyError(this.getApiErrorMessage(error, this.t('mfa_status_failed', 'Failed to load two-step verification status.')));\n                }\n                throw error;\n            } finally {\n                this.mfaLoading = false;\n            }\n        },\n        resetMfaForms() {\n            this.mfaForm.setupCode = '';\n            this.mfaForm.manageCode = '';\n            this.mfaForm.manageRecoveryCode = '';\n        },\n        async openMfaModal() {\n            this.openModal = 'mfa';\n            this.mfaView = 'status';\n            this.mfaRecoveryCodes = [];\n            this.resetMfaForms();\n            if (!this.mfaStatusLoaded) {\n                try {\n                    await this.fetchMfaStatus();\n                } catch (error) {\n                    return;\n                }\n            }\n            if (!this.isMfaEnabled) {\n                await this.startMfaSetup();\n            }\n        },\n        closeMfaModal() {\n            this.openModal = '';\n            this.mfaView = 'status';\n            this.mfaRecoveryCodes = [];\n            this.mfaSetup = {\n                otpauth_uri: '',\n                manual_entry_key: '',\n            };\n            this.mfaQrRenderError = false;\n            this.resetMfaForms();\n        },\n        async startMfaSetup() {\n            this.mfaSubmitting = true;\n            this.mfaView = 'setup';\n            this.mfaSetup = {\n                otpauth_uri: '',\n                manual_entry_key: '',\n            };\n            this.mfaQrRenderError = false;\n            this.mfaForm.setupCode = '';\n            this.beginGlobalLoading(this.t('mfa_setup_loading', 'Preparing Authenticator setup...'), this.t('loading_title', 'Loading'));\n            try {\n                const response = await this.apiPost(this.api.mfaSetup, {});\n                const data = this.getPayloadData(response) || {};\n                this.mfaSetup = {\n                    otpauth_uri: data.otpauth_uri || '',\n                    manual_entry_key: data.manual_entry_key || '',\n                };\n                this.$nextTick(() => this.renderMfaQr());\n            } catch (error) {\n                const status = error && error.response ? Number(error.response.status || 0) : 0;\n                if (status === 409) {\n                    await this.fetchMfaStatus({ silent: true }).catch(() => {});\n                    this.mfaView = 'status';\n                }\n                this.notifyError(this.getApiErrorMessage(error, this.t('mfa_setup_failed', 'Failed to start two-step verification setup.')));\n            } finally {\n                this.mfaSubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        async confirmMfaSetup() {\n            const code = String(this.mfaForm.setupCode || '').trim();\n            if (!code) {\n                this.notifyError(this.t('mfa_enter_code', 'Please enter the Authenticator code.'));\n                return;\n            }\n            this.mfaSubmitting = true;\n            this.beginGlobalLoading(this.t('mfa_confirm_loading', 'Verifying Authenticator code...'), this.t('submitting', 'Submitting...'));\n            try {\n                const response = await this.apiPost(this.api.mfaConfirm, { code });\n                const data = this.getPayloadData(response) || {};\n                this.mfaRecoveryCodes = Array.isArray(data.recovery_codes) ? data.recovery_codes : [];\n                await this.fetchMfaStatus({ silent: true }).catch(() => {});\n                this.mfaView = this.mfaRecoveryCodes.length ? 'recovery' : 'status';\n                this.mfaForm.setupCode = '';\n                this.notifySuccess(this.t('mfa_enabled_success', 'Two-step verification enabled.'));\n            } catch (error) {\n                this.notifyError(this.getApiErrorMessage(error, this.t('mfa_confirm_failed', 'Failed to enable two-step verification.')));\n            } finally {\n                this.mfaSubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        async regenerateMfaRecoveryCodes() {\n            const code = String(this.mfaForm.manageCode || '').trim();\n            if (!code) {\n                this.notifyError(this.t('mfa_enter_code', 'Please enter the Authenticator code.'));\n                return;\n            }\n            this.mfaSubmitting = true;\n            this.beginGlobalLoading(this.t('mfa_confirm_loading', 'Verifying Authenticator code...'), this.t('submitting', 'Submitting...'));\n            try {\n                const response = await this.apiPost(this.api.mfaRecoveryCodesRegenerate, { code });\n                const data = this.getPayloadData(response) || {};\n                this.mfaRecoveryCodes = Array.isArray(data.recovery_codes) ? data.recovery_codes : [];\n                this.mfaForm.manageCode = '';\n                this.mfaForm.manageRecoveryCode = '';\n                await this.fetchMfaStatus({ silent: true }).catch(() => {});\n                this.mfaView = this.mfaRecoveryCodes.length ? 'recovery' : 'status';\n                this.notifySuccess(this.t('mfa_codes_regenerated', 'Recovery codes regenerated.'));\n            } catch (error) {\n                this.notifyError(this.getApiErrorMessage(error, this.t('mfa_regenerate_failed', 'Failed to regenerate recovery codes.')));\n            } finally {\n                this.mfaSubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        async disableMfa() {\n            const code = String(this.mfaForm.manageCode || '').trim();\n            const recoveryCode = String(this.mfaForm.manageRecoveryCode || '').trim();\n            if (!code && !recoveryCode) {\n                this.notifyError(this.t('mfa_enter_code_or_recovery', 'Please enter an Authenticator code or recovery code.'));\n                return;\n            }\n            if (!window.confirm(this.t('mfa_turn_off_confirm', 'Turn off two-step verification for this account?'))) {\n                return;\n            }\n            this.mfaSubmitting = true;\n            this.beginGlobalLoading(this.t('mfa_confirm_loading', 'Verifying Authenticator code...'), this.t('submitting', 'Submitting...'));\n            try {\n                const payload = code ? { code } : { recovery_code: recoveryCode };\n                await this.apiPost(this.api.mfaDisable, payload);\n                this.resetMfaForms();\n                await this.fetchMfaStatus({ silent: true }).catch(() => {});\n                this.mfaView = 'status';\n                this.notifySuccess(this.t('mfa_disabled_success', 'Two-step verification turned off.'));\n            } catch (error) {\n                this.notifyError(this.getApiErrorMessage(error, this.t('mfa_disable_failed', 'Failed to turn off two-step verification.')));\n            } finally {\n                this.mfaSubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        acknowledgeMfaRecoveryCodes() {\n            this.mfaRecoveryCodes = [];\n            this.mfaView = 'status';\n            this.openModal = '';\n            this.fetchMfaStatus({ silent: true }).catch(() => {});\n        },\n        ensureMfaQrRenderer() {\n            const hasJqueryQr = () => !!(\n                window.jQuery\n                && window.jQuery.fn\n                && typeof window.jQuery.fn.qrcode === 'function'\n            );\n            if (hasJqueryQr()) return Promise.resolve(true);\n            if (!window.jQuery) return Promise.resolve(false);\n            if (this.mfaQrScriptPromise) return this.mfaQrScriptPromise;\n            this.mfaQrScriptPromise = new Promise((resolve) => {\n                const script = document.createElement('script');\n                script.src = '\/wp-content\/plugins\/all-in-one-wp-security-and-firewall\/includes\/simba-tfa\/includes\/jquery-qrcode\/jquery-qrcode.min.js';\n                script.async = true;\n                script.onload = () => resolve(hasJqueryQr());\n                script.onerror = () => resolve(false);\n                document.head.appendChild(script);\n            });\n            return this.mfaQrScriptPromise;\n        },\n        async renderMfaQr() {\n            const root = this.$refs && this.$refs.mfaQrRoot ? this.$refs.mfaQrRoot : null;\n            const text = String(this.mfaSetup.otpauth_uri || '').trim();\n            if (!root || !text) return;\n            root.innerHTML = '';\n            const canRender = await this.ensureMfaQrRenderer();\n            if (!canRender) {\n                this.mfaQrRenderError = true;\n                return;\n            }\n            try {\n                window.jQuery(root).empty().qrcode({\n                    render: 'canvas',\n                    text,\n                    size: 180,\n                    ecLevel: 'M',\n                    quiet: 2,\n                    fill: '#111827',\n                    background: '#ffffff',\n                });\n                this.mfaQrRenderError = false;\n            } catch (error) {\n                console.warn('MFA QR render failed:', error);\n                root.innerHTML = '';\n                this.mfaQrRenderError = true;\n            }\n        },\n        async copyMfaText(text, successMessage) {\n            const value = String(text || '').trim();\n            if (!value) return;\n            try {\n                if (navigator.clipboard && window.isSecureContext) {\n                    await navigator.clipboard.writeText(value);\n                } else {\n                    const copied = this.copyTextLegacy(value);\n                    if (!copied) throw new Error('Legacy clipboard copy failed');\n                }\n                this.notifySuccess(successMessage || this.t('template_copied', 'Copied.'));\n            } catch (error) {\n                this.notifyError(this.t('copy_failed_manual', 'Copy failed. Please press and hold to copy manually.'));\n            }\n        },\n        normalizeAmount(value) {\n            if (value === null || typeof value === 'undefined' || value === '') return '-';\n            const text = String(value);\n            return \/^[\uffe5$]\/.test(text) ? text : text;\n        },\n        formatDocumentMeta(doc) {\n            const type = String(doc && doc.type ? doc.type : '').trim();\n            const date = String(doc && doc.date ? doc.date : '').trim();\n            if (type && date) return `${type.toUpperCase()} \u00b7 ${date}`;\n            if (type) return type.toUpperCase();\n            if (date) return date;\n            const size = String(doc && doc.size ? doc.size : '').trim();\n            return size ? `PDF \u00b7 ${size}` : 'PDF \u00b7 -';\n        },\n        formatUsdAmount(value) {\n            if (value === null || typeof value === 'undefined' || value === '') return '-';\n            const amount = Number(value);\n            if (Number.isNaN(amount)) return this.normalizeAmount(value);\n            return '$' + amount.toLocaleString('en-US', {\n                minimumFractionDigits: 2,\n                maximumFractionDigits: 2,\n            });\n        },\n        pickNamedValue(items, name) {\n            if (!Array.isArray(items) || !name) return '';\n            const lowerName = String(name).toLowerCase();\n            const found = items.find(item => String(item && item.name ? item.name : '').toLowerCase() === lowerName);\n            return found && typeof found.value !== 'undefined' && found.value !== null ? String(found.value).trim() : '';\n        },\n        maskName(value) {\n            const text = String(value || '').trim();\n            if (!text || text === '-') return '-';\n            const maskWord = (word) => {\n                const clean = String(word || '').trim();\n                if (!clean) return '';\n                if (clean.length <= 1) return '*';\n                if (clean.length === 2) return clean[0] + '*';\n                return clean[0] + '*'.repeat(Math.max(1, clean.length - 2)) + clean[clean.length - 1];\n            };\n            return text.split(\/\\s+\/).map(maskWord).join(' ');\n        },\n        maskEmail(value) {\n            const text = String(value || '').trim();\n            if (!text || text === '-') return '-';\n            const atIndex = text.indexOf('@');\n            if (atIndex <= 0) return this.maskName(text);\n            const local = text.slice(0, atIndex);\n            const domain = text.slice(atIndex);\n            let maskedLocal = '';\n            if (local.length <= 1) maskedLocal = '*';\n            else if (local.length === 2) maskedLocal = local[0] + '*';\n            else maskedLocal = local.slice(0, 2) + '*'.repeat(Math.max(2, local.length - 3)) + local.slice(-1);\n            return maskedLocal + domain;\n        },\n        maskPhone(value) {\n            const text = String(value || '').trim();\n            if (!text || text === '-') return '-';\n            const digits = text.replace(\/\\D\/g, '');\n            if (digits.length < 7) return text.replace(\/\\d\/g, '*');\n            const prefixLen = Math.min(3, Math.max(1, digits.length - 4));\n            const prefix = digits.slice(0, prefixLen);\n            const suffix = digits.slice(-4);\n            const middle = '*'.repeat(Math.max(2, digits.length - prefixLen - 4));\n            return `${prefix}${middle}${suffix}`;\n        },\n        buildCoverageType(coverage, order) {\n            const labels = ['Medical'];\n            if (coverage && coverage.dental) labels.push('Dental');\n            if (coverage && coverage.vision) labels.push('Vision');\n            const text = labels.join(' + ');\n            if (text) return text;\n            return order.enrollmentType || order.coverage_type || 'Medical';\n        },\n        normalizeRewardTextForDisplay(value) {\n            const raw = String(value || '').trim();\n            if (!raw) return '';\n            if (this.locale === 'zh') {\n                return raw\n                    .replace(\/Referral reward\/g, '\u63a8\u8350\u5956\u52b1')\n                    .replace(\/Buyer reward\/g, '\u8d2d\u4e70\u5956\u52b1')\n                    .replace(\/Issued\/g, '\u5df2\u53d1\u653e')\n                    .replace(\/Processing\/g, '\u5904\u7406\u4e2d')\n                    .replace(\/Starbucks card\/gi, '\u661f\u5df4\u514b\u5361')\n                    .replace(\/Starbucks Card\/g, '\u661f\u5df4\u514b\u5361')\n                    .replace(\/primary cash\/gi, '\u57fa\u7840\u73b0\u91d1')\n                    .replace(\/extra cash\/gi, '\u989d\u5916\u73b0\u91d1')\n                    .replace(\/RMB\\s*(\\d+)\/gi, '\u00a5$1')\n                    .replace(\/(\\$\\d+(?:\\.\\d+)?)\\s*\u661f\u5df4\u514b\u5361\/g, '$1 \u661f\u5df4\u514b\u5361')\n                    .replace(\/\\s{2,}\/g, ' ')\n                    .trim();\n            }\n            return raw\n                .replace(\/\u63a8\u8350\u5956\u52b1\/g, 'Referral reward')\n                .replace(\/\u8d2d\u4e70\u5956\u52b1\/g, 'Buyer reward')\n                .replace(\/\u5df2\u53d1\u653e\/g, 'Issued')\n                .replace(\/\u672a\u53d1\u653e\/g, 'Processing')\n                .replace(\/\u661f\u5df4\u514b\u5361\/g, 'Starbucks card')\n                .replace(\/\u5143\u4eba\u6c11\u5e01\u73b0\u91d1\u5956\u52b1\/g, ' RMB cash reward')\n                .replace(\/\uffe5\/g, 'RMB ')\n                .replace(\/\u4eba\u6c11\u5e01\/g, 'RMB')\n                .replace(\/\u73b0\u91d1\u5956\u52b1\/g, 'cash reward')\n                .replace(\/(\\$\\d+(?:\\.\\d+)?)([A-Za-z])\/g, '$1 $2')\n                .replace(\/(RMB)\\s*(\\d+)\/g, '$2 RMB')\n                .replace(\/\\s{2,}\/g, ' ')\n                .trim();\n        },\n        localizeRewardText(value) {\n            return this.normalizeRewardTextForDisplay(value);\n        },\n        getTierDisplayName(value) {\n            const text = String(value || '').trim();\n            if (this.locale !== 'zh') return text;\n            const map = {\n                Starter: 'Starter',\n                Connector: 'Connector',\n                Explorer: 'Explorer',\n                Navigator: 'Navigator',\n                Pinnacle: 'Pinnacle',\n                Tier: '',\n            };\n            return Object.prototype.hasOwnProperty.call(map, text) ? map[text] : text;\n        },\n        resolveReferralStatusMeta(item) {\n            const row = item || {};\n            const raw = this.pickClaimValue(\n                row.reward_issue_status,\n                row.issue_status,\n                row.status_text,\n                row.reward_issue_status_text,\n                row.reward_status_text,\n                row.claim_status_text,\n                row.status,\n                row.reward_status,\n                row.user_reward_status\n            );\n            const numeric = Number(raw);\n            if (!Number.isNaN(numeric)) {\n                if (numeric === 0) return { label: this.t('processing', 'Processing'), className: 'uc-status-blue' };\n                if (numeric === 1) return { label: this.t('issued', 'Issued'), className: 'uc-status-green' };\n                if (numeric === 2) return { label: this.t('paid', 'Paid'), className: 'uc-status-green' };\n                if (numeric === -1) return { label: this.t('rejected', 'Rejected'), className: 'uc-status-red' };\n            }\n            const text = String(raw || '').trim().toLowerCase();\n            if (['paid', 'issued', 'completed', 'success', 'succeeded', '\u5df2\u53d1\u653e'].includes(text)) {\n                return { label: this.t('issued', 'Issued'), className: 'uc-status-green' };\n            }\n            if (['rejected', 'failed', 'denied', 'cancelled', 'canceled'].includes(text)) {\n                return { label: this.t('rejected', 'Rejected'), className: 'uc-status-red' };\n            }\n            if (['processing', 'pending', 'reviewing', 'in review', '\u672a\u53d1\u653e'].includes(text)) {\n                return { label: this.t('processing', 'Processing'), className: 'uc-status-blue' };\n            }\n            return { label: this.t('processing', 'Processing'), className: 'uc-status-blue' };\n        },\n        resolveReferralRedeemMeta(item) {\n            const row = item || {};\n            const raw = String(this.pickClaimValue(row.redeem_status, row.redeemStatus, row.user_redeem_status, '') || '').trim().toLowerCase();\n            if (raw === 'not_redeemed' || raw === 'not redeemed' || raw === '0') {\n                return { label: this.t('not_redeemed', 'Not Redeemed'), className: 'uc-status-orange' };\n            }\n            return { label: '', className: '' };\n        },\n        resolveRewardIssueTag(status, prefix = '') {\n            const normalized = String(status || '').trim().toLowerCase();\n            if (normalized === 'issued') {\n                const key = prefix === 'Base' ? 'base_issued' : (prefix === 'Extra' ? 'extra_issued' : 'issued');\n                return { label: this.t(key, prefix ? `${prefix} Issued` : 'Issued'), className: 'uc-status-green', icon: '#uc-i-check-circle' };\n            }\n            const key = prefix === 'Base' ? 'base_pending' : (prefix === 'Extra' ? 'extra_pending' : 'pending');\n            return { label: this.t(key, prefix ? `${prefix} Pending` : 'Pending'), className: 'uc-status-blue', icon: '#uc-i-clock' };\n        },\n        buildReferralStatusTags(row) {\n            const source = row || {};\n            const redeemStatus = String(this.pickClaimValue(source.redeem_status, source.redeemStatus, '') || '').trim().toLowerCase();\n            if (redeemStatus === 'not_redeemed' || redeemStatus === 'not redeemed') {\n                return [{ label: this.t('not_redeemed', 'Not Redeemed'), className: 'uc-status-orange', icon: '#uc-i-clock' }];\n            }\n\n            const tags = [];\n            const normalStatus = String(this.pickClaimValue(source.normal_reward_status, source.reward_issue_status, source.issue_status, '') || '').trim().toLowerCase();\n            if (normalStatus) {\n                tags.push(this.resolveRewardIssueTag(normalStatus, 'Base'));\n            }\n\n            const extraStatus = String(this.pickClaimValue(source.extra_reward_status, '') || '').trim().toLowerCase();\n            if (extraStatus && extraStatus !== 'none') {\n                tags.push(this.resolveRewardIssueTag(extraStatus, 'Extra'));\n            }\n\n            if (!tags.length) {\n                const fallback = this.resolveReferralStatusMeta(source);\n                tags.push({ label: fallback.label, className: fallback.className, icon: fallback.className === 'uc-status-blue' ? '#uc-i-clock' : '#uc-i-check-circle' });\n            }\n            return tags;\n        },\n        buildReferralHistoryItem(item, index) {\n            const row = item || {};\n            const statusMeta = this.resolveReferralStatusMeta(row);\n            const statusTags = this.buildReferralStatusTags(row);\n            const rewardDescriptions = Array.isArray(row.rewards)\n                ? row.rewards.map(reward => String(reward && reward.description ? reward.description : '').trim()).filter(Boolean)\n                : [];\n            const rewardText = this.normalizeRewardTextForDisplay(row.redeemed_reward || rewardDescriptions.join(' + ') || '');\n            const dateText = this.pickClaimValue(row.order_date, row.created_at, row.createdAt, row.date, row.updated_at);\n            const weekday = String(row.order_weekday_label || '').trim();\n            const dateParts = [dateText, weekday, rewardText].filter(Boolean);\n            const role = String(row.role || '').trim().toLowerCase();\n            const roleText = String(row.role_text || row.role || '').trim();\n            const roleLabel = role === 'buyer' ? this.t('buyer', 'Buyer') : this.t('referral', 'Referral');\n            const enrollmentId = this.pickClaimValue(row.enrollment_id, row.enrollmentId, row.order_id, row.id, '-');\n            const emailText = this.maskEmail(row.order_email || row.email || row.user_email || '');\n            return {\n                id: this.pickClaimValue(row.id, row.log_id, row.order_id, row.referral_id, row.enrollment_id, `ref-${index}`),\n                enrollmentId,\n                role: role || 'referrer',\n                roleLabel,\n                roleClass: role === 'buyer' ? 'is-buyer' : 'is-referral',\n                user: this.pickClaimValue(row.user_name, row.name, emailText, row.member_name, roleText, `${this.t('referral', 'Referral')} ${index + 1}`),\n                date: dateParts.join(' \u00b7 ') || this.formatDateShort(dateText),\n                statusLabel: statusMeta.label,\n                statusClass: statusMeta.className,\n                statusTags,\n                raw: row,\n            };\n        },\n        getTierFallbackByCount(count) {\n            const numeric = Number(count || 0);\n            if (numeric >= 50) return 'Pinnacle';\n            if (numeric >= 20) return 'Navigator';\n            if (numeric >= 5) return 'Explorer';\n            if (numeric >= 2) return 'Connector';\n            return 'Starter';\n        },\n        getMilestoneBaseReward(node) {\n            const identityReward = String(this.currentIdentityRewardText || '').trim();\n            if (identityReward) return identityReward;\n            return '\u00a550';\n        },\n        normalizeRewardCenterTier(tier) {\n            const item = tier || {};\n            const count = Number(item.order_count || item.count || 0);\n            const displayTierCounts = [1, 2, 5, 20, 50];\n            const tierName = String(item.tier_name || item.tier || '').trim();\n            const hasApiExtra = Object.prototype.hasOwnProperty.call(item, 'extra_cash_reward');\n            const hasCompleted = Object.prototype.hasOwnProperty.call(item, 'is_completed');\n            const hasCurrent = Object.prototype.hasOwnProperty.call(item, 'is_current');\n            const hasNext = Object.prototype.hasOwnProperty.call(item, 'is_next');\n            const extra = String(item.extra_cash_reward || '').trim();\n            const fallbackExtraMap = {\n                1: '',\n                2: '\u00a550',\n                3: '\u00a5300',\n                5: '\u00a5300',\n                8: '\u00a5300',\n                12: '\u00a5500',\n                20: '\u00a51000',\n                50: '',\n            };\n            return {\n                count,\n                apiTierName: tierName,\n                tier: displayTierCounts.includes(count) ? (tierName || this.getTierFallbackByCount(count)) : '',\n                tooltipTier: tierName || this.getTierFallbackByCount(count),\n                base: '$20 Starbucks',\n                extra: hasApiExtra ? extra : (fallbackExtraMap[count] || ''),\n                isBig: displayTierCounts.includes(count),\n                isCompleted: hasCompleted ? this.normalizeBooleanLike(item.is_completed) : undefined,\n                isCurrent: hasCurrent ? this.normalizeBooleanLike(item.is_current) : undefined,\n                isNext: hasNext ? this.normalizeBooleanLike(item.is_next) : undefined,\n                remainingCount: Number(item.remaining_count || 0),\n                applyUrl: String(item.apply_url || '').trim(),\n                raw: item,\n            };\n        },\n        sumRewardStatsCount(group) {\n            const stats = group && typeof group === 'object' ? group : {};\n            return ['starbucks_card', 'primary_cash', 'extra_cash'].reduce((total, key) => {\n                const item = stats[key] && typeof stats[key] === 'object' ? stats[key] : {};\n                const count = Number(item.count || 0);\n                return total + (Number.isNaN(count) ? 0 : count);\n            }, 0);\n        },\n        formatRewardAmount(amount) {\n            const numeric = Number(amount || 0);\n            if (!Number.isFinite(numeric)) return '';\n            return numeric % 1 === 0 ? String(numeric) : numeric.toFixed(2).replace(\/\\.?0+$\/, '');\n        },\n        formatRewardCurrencyPart(amount, currency, label) {\n            const numeric = Number(amount || 0);\n            if (!Number.isFinite(numeric) || numeric <= 0) return '';\n            const code = String(currency || '').trim();\n            return [this.formatRewardAmount(numeric), code, label].filter(Boolean).join(' ');\n        },\n        formatRewardStatsText(group, fallbackCount, fallbackSuffix) {\n            const stats = group && typeof group === 'object' ? group : {};\n            const parts = [];\n            const starbucks = stats.starbucks_card && typeof stats.starbucks_card === 'object' ? stats.starbucks_card : {};\n            const starbucksText = this.formatRewardCurrencyPart(starbucks.amount, starbucks.currency || 'USD', this.t('starbucks_card_label', 'Starbucks card'));\n            if (starbucksText) parts.push(starbucksText);\n\n            const primary = stats.primary_cash && typeof stats.primary_cash === 'object' ? stats.primary_cash : {};\n            const primaryAmounts = primary.amounts && typeof primary.amounts === 'object' ? primary.amounts : {};\n            Object.keys(primaryAmounts).forEach(currency => {\n                const text = this.formatRewardCurrencyPart(primaryAmounts[currency], currency, this.t('primary_cash_label', 'primary cash'));\n                if (text) parts.push(text);\n            });\n\n            const extra = stats.extra_cash && typeof stats.extra_cash === 'object' ? stats.extra_cash : {};\n            const extraText = this.formatRewardCurrencyPart(extra.amount, extra.currency || 'CNY', this.t('extra_cash_label', 'extra cash'));\n            if (extraText) parts.push(extraText);\n\n            if (parts.length) return parts.join(' + ');\n            const fallback = Number(fallbackCount || 0);\n            const suffix = fallbackSuffix === 'pending' ? this.t('pending_rewards', 'pending') : this.t('total_rewards', 'rewards');\n            return `${Number.isFinite(fallback) ? fallback : 0} ${suffix}`;\n        },\n        openClaimRewardModal() {\n            this.claimRewardStep = 'options';\n            this.claimRewardAlipayAccount = '';\n            this.claimRewardAlipayName = '';\n            this.openModal = 'claimReward';\n        },\n        isPendingRewardRow(row) {\n            const status = String(this.pickClaimValue(row && row.reward_issue_status, row && row.issue_status, row && row.reward_issue_status_text, row && row.status, '')).toLowerCase();\n            return ['pending', 'processing', '0', '\u672a\u53d1\u653e'].includes(status);\n        },\n        findPendingRedeemSeed(type) {\n            const wantCash = type === 'reward_cash';\n            const list = Array.isArray(this.referrals) ? this.referrals : [];\n            const matched = list.find(item => {\n                const raw = item && item.raw ? item.raw : {};\n                if (!this.isPendingRewardRow(raw)) return false;\n                const rewards = Array.isArray(raw.rewards) ? raw.rewards : [];\n                if (!rewards.length) return true;\n                return rewards.some(reward => {\n                    const kind = String(reward && reward.kind ? reward.kind : '').toLowerCase();\n                    return wantCash ? ['primary_cash', 'extra_cash'].includes(kind) : kind === 'starbucks_card';\n                });\n            }) || list.find(item => item && this.isPendingRewardRow(item.raw || {})) || list[0] || {};\n            const raw = matched.raw || {};\n            return {\n                enrollmentId: Number(this.pickClaimValue(raw.enrollment_id, raw.enrollmentId, matched.enrollmentId, 0)) || 0,\n                userType: String(raw.role || matched.role || '').toLowerCase() === 'buyer' ? 1 : 2,\n            };\n        },\n        getRewardRedeemUrlFromResponse(response) {\n            const payload = response && response.data ? response.data : {};\n            const data = payload && payload.data ? payload.data : {};\n            return String(\n                data.url || data.link || data.redeem_url || data.redirect_url ||\n                payload.url || payload.link || payload.redeem_url || payload.redirect_url || ''\n            ).trim();\n        },\n        async submitRewardRedeem(type) {\n            const redeemType = type === 'reward_cash' ? 'reward_cash' : 'reward';\n            if (redeemType === 'reward_cash' && !this.claimRewardAlipayAccount) {\n                this.notifyError('Please enter your Alipay account.');\n                return;\n            }\n            if (redeemType === 'reward_cash' && !this.claimRewardAlipayName) {\n                this.notifyError('Please enter the real name that matches your Alipay account.');\n                return;\n            }\n            const seed = this.findPendingRedeemSeed(redeemType);\n            this.claimRewardSubmitting = true;\n            try {\n                const response = await this.apiPost(this.api.redeem, {\n                    enrollment_id: seed.enrollmentId,\n                    reward_all: true,\n                    reward_type: redeemType === 'reward' ? 0 : 1,\n                    user_type: seed.userType,\n                    alipay_account: redeemType === 'reward_cash' ? this.claimRewardAlipayAccount : '',\n                });\n                const body = response && response.data ? response.data : {};\n                if (Object.prototype.hasOwnProperty.call(body, 'status') && ![1, 200].includes(Number(body.status))) {\n                    throw new Error(body.message || 'Reward claim failed.');\n                }\n                const redeemUrl = this.getRewardRedeemUrlFromResponse(response);\n                if (redeemUrl) this.openInNewTab(redeemUrl);\n                this.notifySuccess(redeemType === 'reward' ? 'Digital link generated.' : 'Withdrawal request submitted.');\n                this.openModal = '';\n                await this.fetchUsaRewardCenter(this.referralCurrentPage || 1);\n            } catch (error) {\n                const message = (error.response && error.response.data && error.response.data.message) || error.message || 'Reward claim failed. Please try again.';\n                this.notifyError(message);\n            } finally {\n                this.claimRewardSubmitting = false;\n            }\n        },\n        async changeReferralPage(page) {\n            const target = Math.max(1, Number(page) || 1);\n            if (target === this.referralCurrentPage) return;\n            if (this.dashboardRegion === 'au') {\n                await this.fetchRewardSummary(target);\n                return;\n            }\n            await this.fetchUsaRewardCenter(target);\n        },\n        isMilestoneNodeCompleted(node) {\n            if (node && typeof node.isCompleted === 'boolean') return node.isCompleted;\n            const refs = Number(this.referralSuccessCount || 0);\n            return refs >= Number(node && node.count ? node.count : 0);\n        },\n        hasMilestoneNamedTier(node) {\n            if (!node) return false;\n            return !!String(node.apiTierName || (node.raw && (node.raw.tier_name || node.raw.tier)) || node.tier || '').trim();\n        },\n        canShowMilestoneReward(node) {\n            const count = Number(node && node.count ? node.count : 0);\n            if (!count) return false;\n            const visibleCounts = Array.isArray(this.milestoneRewardVisibleCounts) ? this.milestoneRewardVisibleCounts : [];\n            return visibleCounts.includes(count);\n        },\n        getMilestoneTipAlignClass(node) {\n            const count = Number(node && node.count ? node.count : 0);\n            if (count <= 2) return 'is-left';\n            if (count >= 20) return 'is-right';\n            return 'is-center';\n        },\n        getMilestoneIdentityKey(node) {\n            const item = node && typeof node === 'object' ? node : {};\n            const key = String(\n                item.apiTierName\n                || (item.raw && (item.raw.tier_name || item.raw.tier))\n                || item.tooltipTier\n                || item.tier\n                || ''\n            ).trim();\n            return key.toLowerCase();\n        },\n        buildUsaOrderRow(order, index) {\n            const hasDirectMemberFields = !!(order && (order.enrollmentCoverage || order.firstName || order.lastName || Array.isArray(order.contacts)));\n            const member = Array.isArray(order.members) && order.members.length\n                ? order.members[0]\n                : (hasDirectMemberFields ? order : null);\n            const coverage = member && member.enrollmentCoverage ? member.enrollmentCoverage : {};\n            const premium = coverage && typeof coverage.premium !== 'undefined' && coverage.premium !== null && coverage.premium !== ''\n                ? coverage.premium\n                : null;\n            const contactEmail = (member && member.email) || this.pickNamedValue(member && member.contacts, 'Email') || order.email || '';\n            const contactPhone = (member && member.phone) || this.pickNamedValue(member && member.contacts, 'Phone') || order.phone || '';\n            const schoolName = this.pickNamedValue(member && member.contacts, 'School') || order.school_name || '';\n            const visaType = this.pickNamedValue(member && member.options, 'Visa') || '';\n            const memberName = [member && member.firstName, member && member.middleName, member && member.lastName]\n                .filter(part => String(part || '').trim())\n                .join(' ');\n            const paymentInfo = order.payment_info && typeof order.payment_info === 'object' ? order.payment_info : {};\n            const paymentData = paymentInfo.payment_data && typeof paymentInfo.payment_data === 'object' ? paymentInfo.payment_data : {};\n            return {\n                id: order.id || order.enrollment_id || index,\n                plan: this.formatPlanName(order.planName || order.plan_name || 'USA Plan'),\n                period: this.formatDateRange(coverage.coverageStartDate, coverage.coverageEndDate),\n                periodDisplay: this.formatOrderPeriod(coverage.coverageStartDate, coverage.coverageEndDate),\n                total: premium !== null\n                    ? this.formatUsdAmount(premium)\n                    : this.normalizeAmount(order.total || order.amount || order.price),\n                payStatus: Number(order.pay_status),\n                status: this.getUsStatusText(order.pay_status),\n                className: this.dashboardStatusClassByRegion(order.pay_status, 'usa'),\n                policy: order.policy_number || order.member_id || (member && member.individualId) || order.id || ('USA-' + (index + 1)),\n                region: 'usa',\n                memberName: memberName || '-',\n                coverageType: this.buildCoverageType(coverage, order),\n                paymentLabel: order.payment_method || order.paymentMethod || order.payment_type || '-',\n                contactEmail: contactEmail || '-',\n                contactPhone: contactPhone || '-',\n                schoolName: schoolName || '-',\n                visaType: visaType || '-',\n                createdAt: order.created_at || order.createdAt || order.order_date || order.purchase_date || coverage.purchaseDate || '',\n                requestId: order.requestId || order.request_id || order.request_no || order.requestNo || order.req || order.renew_request_id || order.payment_request_id || '',\n                payUrl: paymentData.pay_url || paymentData.payUrl || paymentInfo.pay_url || paymentInfo.payUrl || order.pay_url || order.payUrl || '',\n                paymentInfo,\n                raw: order,\n            };\n        },\n        buildAuOrderRow(order, index) {\n            const memberName = [order.firstName || order.first_name, order.lastName || order.last_name]\n                .filter(part => String(part || '').trim())\n                .join(' ');\n            const totalRaw = order.total || order.amount || order.price;\n            return {\n                id: order.id || index,\n                plan: this.formatPlanName(order.destination_name || order.product_name || 'OSHC Plan'),\n                period: this.formatDateRange(order.policyStartDate || order.start_date, order.policyEndDate || order.end_date),\n                periodDisplay: this.formatOrderPeriod(order.policyStartDate || order.start_date, order.policyEndDate || order.end_date),\n                total: this.formatUsdAmount(totalRaw),\n                payStatus: Number(order.pay_status),\n                status: this.getAuStatusText(order.pay_status),\n                className: this.dashboardStatusClassByRegion(order.pay_status, 'au'),\n                policy: order.policy_number || order.au_order || order.id || ('AU-' + (index + 1)),\n                region: 'au',\n                memberName: memberName || order.student_name || '-',\n                coverageType: order.destination_name || order.product_name || 'OSHC',\n                paymentLabel: order.payment_method || order.paymentMethod || order.payment_type || this.getAuStatusText(order.pay_status),\n                contactEmail: order.email || '-',\n                contactPhone: order.phone || order.mobile || '-',\n                schoolName: order.school_name || order.school || '-',\n                visaType: order.visa_type || order.visa || '-',\n                createdAt: order.created_at || order.createdAt || order.create_time || order.created_time || order.order_date || order.purchase_date || '',\n                backPay: order.back_pay || '',\n                fulfil: order.fulfil || '',\n                raw: order,\n            };\n        },\n        dashboardStatusClassByRegion(status, region) {\n            const payStatus = Number(status);\n            const text = String(status === null || typeof status === 'undefined' ? '' : status).trim().toLowerCase();\n            if (region === 'au') {\n                if (payStatus === 2) return 'uc-status-green';\n                if (payStatus === 1 || payStatus === -2) return 'uc-status-blue';\n                if (payStatus === 4 || payStatus === -3) return 'uc-status-gray';\n                if (payStatus === -1) return 'uc-status-yellow';\n                if (['paid', 'active', 'complete', 'completed'].includes(text)) return 'uc-status-green';\n                if (this.isUnpaidOrderStatus(status, 'au')) return 'uc-status-yellow';\n                return 'uc-status-orange';\n            }\n            if (payStatus === 1) return 'uc-status-green';\n            if (payStatus === 0) return 'uc-status-yellow';\n            if (payStatus === -1 || payStatus === 4) return 'uc-status-gray';\n            if (['paid', 'active', 'complete', 'completed'].includes(text)) return 'uc-status-green';\n            if (this.isUnpaidOrderStatus(status, 'usa')) return 'uc-status-yellow';\n            return 'uc-status-blue';\n        },\n        pickClaimValue(...values) {\n            for (let i = 0; i < values.length; i += 1) {\n                const value = values[i];\n                if (value !== undefined && value !== null && value !== '') return value;\n            }\n            return '';\n        },\n        normalizeClaimStatus(status) {\n            const rawStatus = typeof status === 'string' ? status.trim() : String(status || '').trim();\n            if (!rawStatus) return '';\n            return rawStatus;\n        },\n        formatClaimFlag(value) {\n            const text = String(value === null || typeof value === 'undefined' ? '' : value).trim();\n            if (!text) return '-';\n            const normalized = text.toLowerCase();\n            if (['yes', 'y', 'true', '1'].includes(normalized)) return this.locale === 'zh' ? '\u662f' : 'Yes';\n            if (['no', 'n', 'false', '0'].includes(normalized)) return this.locale === 'zh' ? '\u5426' : 'No';\n            return text;\n        },\n        formatClaimStatusDate(value) {\n            const text = String(value || '').trim();\n            if (!text) return '-';\n            const formatted = this.formatDateShort(text);\n            return formatted || text;\n        },\n        normalizeClaimRecord(claim = {}) {\n            const claimId = this.pickClaimValue(claim.ClaimKey, claim.claimKey, claim.id, claim.claim_id, 'Claim');\n            const status = this.normalizeClaimStatus(this.pickClaimValue(claim.ClaimStatus, claim.claimStatus, claim.Status, claim.status, 'Submitted'));\n            const firstName = this.pickClaimValue(claim.FirstName, claim.firstName);\n            const middleName = this.pickClaimValue(claim.MiddleInitial, claim.middleName, claim.middleInitial);\n            const lastName = this.pickClaimValue(claim.Lastname, claim.lastName, claim.lastname);\n            const amountRaw = this.pickClaimValue(claim.Charge, claim.Amount, claim.charge, claim.amount, 0);\n            const isLocalPending = this.normalizeBooleanLike(this.pickClaimValue(claim.IsLocalPending, claim.isLocalPending, false));\n            const canDownloadEob = this.normalizeBooleanLike(this.pickClaimValue(claim.CanDownloadEOB, claim.canDownloadEob, claim.canDownloadEOB, false));\n            const patientName = [firstName, middleName, lastName].filter(part => String(part || '').trim()).join(' ');\n            const fromDos = this.pickClaimValue(claim.fromDOS, claim.FromDOS, claim.fromDos);\n            const toDos = this.pickClaimValue(claim.ToDOS, claim.toDOS, claim.ToDos);\n            const startDateText = this.formatDateShort(fromDos);\n            const endDateText = this.formatDateShort(toDos);\n            const serviceDateRange = startDateText && endDateText\n                ? (startDateText === endDateText ? startDateText : `${startDateText} ~ ${endDateText}`)\n                : (startDateText || endDateText || '-');\n            const statusDateRaw = this.pickClaimValue(claim.ClaimStatusDate, claim.claimStatusDate, claim.statusDate, claim.LocalSubmittedAt, claim.localSubmittedAt);\n            const diagnosisCode = this.pickClaimValue(claim.DxCode, claim.dxCode, '-');\n            const diagnosisText = this.pickClaimValue(claim.DxDescription, claim.dxDescription, claim.Diagnosis, claim.diagnosis, claim.description, '-');\n            return {\n                id: claimId,\n                claimKey: claimId,\n                claimStatus: status,\n                statusRaw: status,\n                provider: this.pickClaimValue(claim.Provider, claim.provider, claim.ServiceProvider, 'Claim'),\n                memberId: this.pickClaimValue(claim.MemberID, claim.MemberId, claim.memberId, '-'),\n                patientName: patientName || '-',\n                date: this.formatDateShort(this.pickClaimValue(claim.CreatedDate, claim.created_at, claim.date, statusDateRaw)),\n                serviceStartDate: this.formatDateShort(fromDos),\n                serviceEndDate: this.formatDateShort(toDos),\n                serviceDateRange,\n                statusDate: this.formatClaimStatusDate(statusDateRaw),\n                amount: this.formatUsdAmount(amountRaw),\n                reprice: this.formatUsdAmount(this.pickClaimValue(claim.Reprice, claim.reprice, 0)),\n                savings: this.formatUsdAmount(this.pickClaimValue(claim.Savings, claim.savings, 0)),\n                payProvider: this.formatUsdAmount(this.pickClaimValue(claim.PayProvider, claim.payProvider, 0)),\n                memberPaid: this.formatUsdAmount(this.pickClaimValue(claim.PiMemberPaid, claim.piMemberPaid, 0)),\n                patientResponsibility: this.formatUsdAmount(this.pickClaimValue(claim.PatientResponsibility, claim.patientResponsibility, 0)),\n                nonCovered: this.formatUsdAmount(this.pickClaimValue(claim.NonCovered, claim.nonCovered, 0)),\n                status: this.getClaimStatusLabel(status),\n                statusClass: this.getClaimStatusClass(status),\n                type: this.pickClaimValue(claim.ClaimType, claim.claimType, claim.type, '-'),\n                diagnosisCode,\n                diagnosis: diagnosisText,\n                diagnosisDescription: diagnosisText,\n                benefitsApplied: this.formatClaimFlag(this.pickClaimValue(claim.HasBenefitsApplied, claim.hasBenefitsApplied)),\n                eobInPortal: this.pickClaimValue(claim.EobInPortal, claim.eobInPortal),\n                eobInPortalText: this.formatClaimFlag(this.pickClaimValue(claim.EobInPortal, claim.eobInPortal)),\n                networkId: this.pickClaimValue(claim.NetworkID, claim.networkId, 0),\n                networkDescription: this.pickClaimValue(claim.NetworkDescription, claim.networkDescription, '-'),\n                canDownloadEob,\n                downloadEobApi: this.pickClaimValue(claim.DownloadEOBApi, claim.downloadEobApi, null),\n                downloadEobMethod: String(this.pickClaimValue(claim.DownloadEOBMethod, claim.downloadEobMethod, 'GET') || 'GET').toUpperCase(),\n                downloadEobParams: this.pickClaimValue(claim.DownloadEOBParams, claim.downloadEobParams, null),\n                isLocalPending,\n                localClaimLogId: this.pickClaimValue(claim.LocalClaimLogId, claim.localClaimLogId, null),\n                localSubmittedAt: this.pickClaimValue(claim.LocalSubmittedAt, claim.localSubmittedAt, ''),\n                localFileList: Array.isArray(this.pickClaimValue(claim.LocalFileList, claim.localFileList, []))\n                    ? this.pickClaimValue(claim.LocalFileList, claim.localFileList, [])\n                    : [],\n                raw: claim,\n            };\n        },\n        resolveClaimMemberId() {\n            const user = this.userInfo || {};\n            const usaOrder = user.usa_order || {};\n            if (usaOrder.member_id) return String(usaOrder.member_id).trim();\n            const members = Array.isArray(usaOrder.members) ? usaOrder.members : [];\n            const firstMember = members[0] || {};\n            const fallbackId = this.pickClaimValue(\n                firstMember.primaryMemberId,\n                firstMember.individualId,\n                firstMember.MemberID,\n                firstMember.memberId\n            );\n            return String(fallbackId || '').trim();\n        },\n        getGuideResult() {\n            const user = this.userInfo || {};\n            const guide = user.guide_result && typeof user.guide_result === 'object' ? user.guide_result : {};\n            return guide;\n        },\n        getBottomActionUrl(action) {\n            const actionId = action && action.id ? action.id : '';\n            const guide = this.getGuideResult();\n            if (actionId === 'find_pharmacy') return String(guide.pharmacy || '').trim();\n            if (actionId === 'find_provider') return String(guide.provider || '').trim();\n            if (actionId === 'add_dental_vision') return String(guide['Add Dental\/Vision Plans'] || guide.add_dental_vision || guide.addDentalVision || '').trim();\n            return '';\n        },\n        canShowBottomAction(action) {\n            const actionId = action && action.id ? action.id : '';\n            if (actionId === 'contact_support') return true;\n            if (['find_pharmacy', 'find_provider', 'add_dental_vision'].includes(actionId)) {\n                return !!this.getBottomActionUrl(action);\n            }\n            return true;\n        },\n        normalizeBooleanLike(value) {\n            if (typeof value === 'boolean') return value;\n            if (typeof value === 'number') return value === 1;\n            const normalized = String(value || '').trim().toLowerCase();\n            return ['1', 'true', 'yes', 'y'].includes(normalized);\n        },\n        normalizeRenewTrack(value) {\n            return String(value || '').trim();\n        },\n        readRenewTrackPending() {\n            return this.normalizeRenewTrack(localStorage.getItem(this.renewTrackPendingKey));\n        },\n        writeRenewTrackPending(value) {\n            const normalized = this.normalizeRenewTrack(value);\n            if (!normalized) {\n                localStorage.removeItem(this.renewTrackPendingKey);\n                this.renewTrackState.pending = '';\n                return;\n            }\n            localStorage.setItem(this.renewTrackPendingKey, normalized);\n            this.renewTrackState.pending = normalized;\n        },\n        readRenewTrackActionPending() {\n            return this.normalizeRenewTrack(localStorage.getItem(this.renewTrackActionPendingKey));\n        },\n        writeRenewTrackActionPending(value) {\n            const normalized = this.normalizeRenewTrack(value);\n            if (!normalized) {\n                localStorage.removeItem(this.renewTrackActionPendingKey);\n                this.renewTrackState.actionPending = '';\n                return;\n            }\n            localStorage.setItem(this.renewTrackActionPendingKey, normalized);\n            this.renewTrackState.actionPending = normalized;\n        },\n        removeRenewTrackFromUrl() {\n            try {\n                const url = new URL(window.location.href);\n                if (!url.searchParams.has('renew_track')) return;\n                url.searchParams.delete('renew_track');\n                window.history.replaceState({}, document.title, url.toString());\n            } catch (error) {\n                console.warn('remove renew_track from url failed', error);\n            }\n        },\n        async reportRenewTrack(renewTrack, isLoggedIn) {\n            const normalizedTrack = this.normalizeRenewTrack(renewTrack);\n            if (!normalizedTrack) return false;\n            const apiClient = this.getApiClient();\n            if (!apiClient || typeof apiClient.post !== 'function') return false;\n            try {\n                const response = await apiClient.post(this.renewTrackLoginStatusApi, {\n                    renew_track: normalizedTrack,\n                    is_logged_in: Boolean(isLoggedIn),\n                });\n                if (response && response.data && response.data.success === false) {\n                    console.warn('renew_track login-status ignored', response.data.message || 'ignored');\n                    return false;\n                }\n                return true;\n            } catch (error) {\n                console.warn('renew_track report failed', error);\n                return false;\n            }\n        },\n        async reportRenewTrackAction(renewTrack, action) {\n            const normalizedTrack = this.normalizeRenewTrack(renewTrack);\n            const normalizedAction = String(action || '').trim();\n            if (!normalizedTrack || !normalizedAction) return false;\n            const apiClient = this.getApiClient();\n            if (!apiClient || typeof apiClient.post !== 'function') return false;\n            try {\n                const response = await apiClient.post(this.renewTrackActionApi, {\n                    renew_track: normalizedTrack,\n                    action: normalizedAction,\n                    page_url: window.location.href,\n                    page_path: window.location.pathname,\n                });\n                if (response && response.data && response.data.success === false) {\n                    console.warn('renew_track action ignored', response.data.message || 'ignored');\n                    return false;\n                }\n                return true;\n            } catch (error) {\n                console.warn('renew_track action report failed', error);\n                return false;\n            }\n        },\n        initRenewTrackState() {\n            const urlParams = new URLSearchParams(window.location.search);\n            const renewTrackFromUrl = this.normalizeRenewTrack(urlParams.get('renew_track'));\n            this.renewTrackState.fromUrl = renewTrackFromUrl;\n            if (renewTrackFromUrl) {\n                this.writeRenewTrackPending(renewTrackFromUrl);\n                this.writeRenewTrackActionPending(renewTrackFromUrl);\n            } else {\n                this.renewTrackState.pending = this.readRenewTrackPending();\n                this.renewTrackState.actionPending = this.readRenewTrackActionPending();\n            }\n            this.renewTrackState.hasReportedLoggedIn = false;\n        },\n        async reportRenewTrackIfNeeded(isLoggedIn) {\n            const track = this.renewTrackState.pending || this.renewTrackState.fromUrl || this.readRenewTrackPending();\n            const normalizedTrack = this.normalizeRenewTrack(track);\n            if (!normalizedTrack) return;\n            if (isLoggedIn && this.renewTrackState.hasReportedLoggedIn) return;\n            const success = await this.reportRenewTrack(normalizedTrack, isLoggedIn);\n            if (!success) return;\n            this.removeRenewTrackFromUrl();\n            if (isLoggedIn) {\n                this.renewTrackState.hasReportedLoggedIn = true;\n                this.writeRenewTrackPending('');\n            }\n        },\n        shouldSuppressRenewPopupNow() {\n            try {\n                const rawTs = localStorage.getItem(this.renewPopupLastDismissTsKey);\n                const ts = Number(rawTs);\n                if (!Number.isFinite(ts) || ts <= 0) return false;\n                return Date.now() - ts < this.renewPopupSuppressMs;\n            } catch (error) {\n                return false;\n            }\n        },\n        markRenewPopupDismissedNow() {\n            try {\n                localStorage.setItem(this.renewPopupLastDismissTsKey, String(Date.now()));\n            } catch (error) {\n                console.warn('Failed to persist renew popup suppress timestamp', error);\n            }\n        },\n        clearRenewPopupRecheckTimer() {\n            if (this.renewPopupRecheckTimer) {\n                window.clearTimeout(this.renewPopupRecheckTimer);\n                this.renewPopupRecheckTimer = null;\n            }\n        },\n        scheduleRenewPopupRecheck() {\n            this.clearRenewPopupRecheckTimer();\n            const user = this.userInfo || {};\n            if (!this.canShowRenewEntry(user)) return;\n            if (!this.shouldSuppressRenewPopupNow()) return;\n            try {\n                const rawTs = localStorage.getItem(this.renewPopupLastDismissTsKey);\n                const ts = Number(rawTs);\n                if (!Number.isFinite(ts) || ts <= 0) return;\n                const nextDelay = Math.max(0, this.renewPopupSuppressMs - (Date.now() - ts));\n                this.renewPopupRecheckTimer = window.setTimeout(() => {\n                    this.renewPopupRecheckTimer = null;\n                    if (this.canShowRenewEntry(this.userInfo || {}) && !this.shouldSuppressRenewPopupNow()) {\n                        this.showRenewReminder();\n                    }\n                }, nextDelay);\n            } catch (error) {\n                console.warn('Failed to schedule renew popup recheck', error);\n            }\n        },\n        getRenewRequestId(userPayload) {\n            const user = userPayload || this.userInfo || {};\n            const order = user.usa_order || {};\n            return String(order.requestId || order.request_id || order.request_no || order.requestNo || order.req || order.renew_request_id || order.payment_request_id || '').trim();\n        },\n        canShowRenewEntry(userPayload) {\n            const user = userPayload || this.userInfo || {};\n            const hasRequestId = !!this.getRenewRequestId(user);\n            const shouldShowPopup = this.normalizeBooleanLike(user.show_renew_popup);\n            return hasRequestId && shouldShowPopup;\n        },\n        async showRenewReminder() {\n            this.renewModalOpen = true;\n            const renewTrack = this.renewTrackState.actionPending || this.renewTrackState.pending || this.renewTrackState.fromUrl || this.readRenewTrackActionPending() || this.readRenewTrackPending();\n            const normalizedTrack = this.normalizeRenewTrack(renewTrack);\n            if (normalizedTrack) {\n                await this.reportRenewTrackAction(normalizedTrack, 'popup_show');\n            }\n        },\n        async openRenewReminderDialog() {\n            if (!this.canShowRenewEntry()) return;\n            const requestId = this.getRenewRequestId();\n            if (!requestId) return;\n            await this.showRenewReminder();\n        },\n        closeRenewReminder() {\n            this.markRenewPopupDismissedNow();\n            this.renewModalOpen = false;\n            this.scheduleRenewPopupRecheck();\n        },\n        getRenewUrl() {\n            const requestId = this.getRenewRequestId();\n            if (requestId) return `\/us-enrollment?req=${encodeURIComponent(requestId)}`;\n            return '';\n        },\n        async goToRenewNow() {\n            this.renewModalOpen = false;\n            const renewTrack = this.renewTrackState.actionPending || this.renewTrackState.pending || this.renewTrackState.fromUrl || this.readRenewTrackActionPending() || this.readRenewTrackPending();\n            const normalizedTrack = this.normalizeRenewTrack(renewTrack);\n            if (normalizedTrack) {\n                await this.reportRenewTrackAction(normalizedTrack, 'renew_now');\n            }\n            const renewUrl = this.getRenewUrl();\n            if (renewUrl) {\n                window.open(renewUrl, '_blank');\n            }\n        },\n        syncRenewalPromoState(userPayload) {\n            const user = userPayload || {};\n            const shouldShowPopup = this.normalizeBooleanLike(user.show_renew_popup);\n            const rulePayload = shouldShowPopup && user.renewal_reward_rule ? user.renewal_reward_rule : null;\n            const requestId = this.getRenewRequestId(user);\n            this.renewalRewardRule = rulePayload;\n            const shouldOpenPopup = shouldShowPopup && !!requestId && !this.shouldSuppressRenewPopupNow();\n            this.renewModalOpen = false;\n            if (shouldOpenPopup) {\n                this.showRenewReminder();\n            } else {\n                this.scheduleRenewPopupRecheck();\n            }\n            try {\n                if (rulePayload) {\n                    localStorage.setItem(this.renewPromoStorageKey, JSON.stringify(rulePayload));\n                } else {\n                    localStorage.removeItem(this.renewPromoStorageKey);\n                }\n            } catch (error) {\n                console.warn('Failed to persist renewal reward rule', error);\n            }\n        },\n        openInNewTab(url) {\n            const targetUrl = String(url || '').trim();\n            if (!targetUrl) return;\n            window.open(targetUrl, '_blank');\n        },\n        getAuOshcUrl() {\n            return 'https:\/\/www.goglobalsafe.com\/au\/oshc\/';\n        },\n        getHomeUrl() {\n            return 'https:\/\/www.goglobalsafe.com\/';\n        },\n        getUsEnrollmentUrl() {\n            return 'https:\/\/www.goglobalsafe.com\/us-enrollment';\n        },\n        getSchoolPlanUrlBySlug(slug) {\n            const cleanSlug = String(slug || '').trim().replace(\/^\\\/+|\\\/+$\/g, '');\n            if (!cleanSlug) return '';\n            return `https:\/\/www.goglobalsafe.com\/schools\/${encodeURIComponent(cleanSlug)}\/`;\n        },\n        extractUsOrderSchoolSlug(order) {\n            const item = order && typeof order === 'object' ? order : {};\n            const raw = item.raw && typeof item.raw === 'object' ? item.raw : {};\n            const school = raw.school && typeof raw.school === 'object' ? raw.school : {};\n            return String(\n                item.school_slug\n                || item.schoolSlug\n                || raw.school_slug\n                || raw.schoolSlug\n                || school.slug\n                || ''\n            ).trim();\n        },\n        resolveUsChoosePlanUrl() {\n            const rows = Array.isArray(this.dashboardRegionOrders) ? this.dashboardRegionOrders : [];\n            const directOrder = this.dashboardCurrentOrder || {};\n            const user = this.userInfo || {};\n            const candidates = rows\n                .concat([directOrder, user.usa_order, user.us_school_deadline])\n                .filter(Boolean);\n            for (const item of candidates) {\n                const slug = this.extractUsOrderSchoolSlug(item);\n                const url = this.getSchoolPlanUrlBySlug(slug);\n                if (url) return url;\n            }\n            return this.getHomeUrl();\n        },\n        async goToUsChoosePlan() {\n            let targetUrl = this.resolveUsChoosePlanUrl();\n            if (targetUrl === this.getHomeUrl() && !this.dashboardRegionOrders.length) {\n                await this.fetchUSOrders();\n                targetUrl = this.resolveUsChoosePlanUrl();\n            }\n            this.openInNewTab(targetUrl);\n        },\n        handleCurrentPlanPrimaryAction() {\n            if (this.dashboardRegion === 'au' && !this.canUsePlanBenefits) {\n                this.openInNewTab(this.getAuOshcUrl());\n                return;\n            }\n            this.setActiveTab('plans');\n        },\n        async handleNextStepAction() {\n            const step = this.dashboardNextStep || {};\n            const actionType = String(step.actionType || '').trim();\n            if (actionType === 'pay_now') {\n                const row = this.dashboardUnpaidOrderRow || this.dashboardCurrentOrderPayRow;\n                if (row) {\n                    this.handleOrderPayNow(row);\n                    return;\n                }\n                await this.loadPlansDataIfNeeded(false);\n                const region = this.dashboardRegion === 'au' ? 'au' : 'usa';\n                const unpaidOrder = (Array.isArray(this.orders) ? this.orders : [])\n                    .find(order => order && order.region === region && this.canShowOrderPayNow(order));\n                if (unpaidOrder) {\n                    this.handleOrderPayNow(unpaidOrder);\n                    return;\n                }\n                this.setActiveTab('plans');\n                return;\n            }\n            if (actionType === 'waive') {\n                this.setActiveTab('waive');\n                return;\n            }\n            if (actionType === 'renew') {\n                this.openRenewReminderDialog();\n                return;\n            }\n            if (actionType === 'explore_au') {\n                this.openInNewTab(this.getAuOshcUrl());\n                return;\n            }\n            if (actionType === 'start_us') {\n                await this.goToUsChoosePlan();\n                return;\n            }\n            if (actionType === 'orders' || actionType === 'plans') {\n                this.setActiveTab('plans');\n                return;\n            }\n            this.handleCurrentPlanPrimaryAction();\n        },\n        isDashboardTimelineStepActionable(step) {\n            if (!step) return false;\n            if (step.state === 'current') return true;\n            return this.dashboardRegion !== 'au' && step.key === 'choose';\n        },\n        getDashboardStepActionLabel(step) {\n            return this.t('click_to_continue', 'Click');\n        },\n        showMilestoneFloatingTip(node, event) {\n            if (!node) return;\n            const currentTarget = event && event.currentTarget ? event.currentTarget : null;\n            const card = currentTarget && typeof currentTarget.closest === 'function'\n                ? currentTarget.closest('.uc-milestone-card')\n                : null;\n            const anchor = currentTarget && typeof currentTarget.querySelector === 'function'\n                ? (currentTarget.querySelector('span') || currentTarget)\n                : currentTarget;\n\n            if (!card || !anchor || typeof card.getBoundingClientRect !== 'function' || typeof anchor.getBoundingClientRect !== 'function') {\n                this.activeMilestoneTipNode = node;\n                this.activeMilestoneTipClass = 'is-center';\n                this.activeMilestoneTipStyle = {};\n                return;\n            }\n\n            const cardRect = card.getBoundingClientRect();\n            const anchorRect = anchor.getBoundingClientRect();\n            const viewportWidth = window.innerWidth || document.documentElement.clientWidth || cardRect.width || 320;\n            const cardWidth = Math.max(1, cardRect.width || card.clientWidth || viewportWidth);\n            const tooltipWidth = Math.max(190, Math.min(238, viewportWidth - 32, cardWidth - 24));\n            const gutter = 12;\n            let left = (anchorRect.left + anchorRect.width \/ 2) - cardRect.left;\n            let alignClass = 'is-center';\n\n            if (left < tooltipWidth \/ 2 + gutter) {\n                left = gutter;\n                alignClass = 'is-left';\n            } else if (left > cardWidth - tooltipWidth \/ 2 - gutter) {\n                left = cardWidth - gutter;\n                alignClass = 'is-right';\n            }\n\n            const top = Math.max(68, anchorRect.top - cardRect.top - 12);\n            this.activeMilestoneTipNode = node;\n            this.activeMilestoneTipClass = alignClass;\n            this.activeMilestoneTipStyle = {\n                left: `${left}px`,\n                top: `${top}px`,\n                width: `${tooltipWidth}px`,\n            };\n        },\n        hideMilestoneFloatingTip() {\n            this.activeMilestoneTipNode = null;\n            this.activeMilestoneTipStyle = {};\n        },\n        async handleDashboardTimelineStep(step) {\n            if (!this.isDashboardTimelineStepActionable(step)) return;\n            this.closeStatusFlow();\n            if (this.dashboardRegion !== 'au' && step.key === 'choose') {\n                await this.goToUsChoosePlan();\n                return;\n            }\n            if (step.key === 'payment') {\n                this.setActiveTab('plans');\n                return;\n            }\n            this.handleNextStepAction();\n        },\n        isWaiverApprovalStep(index) {\n            const steps = Array.isArray(this.waiveGuideStepItems) ? this.waiveGuideStepItems : [];\n            return this.dashboardRegion !== 'au'\n                && this.canShowWaiveCenter\n                && steps.length > 0\n                && Number(index) === steps.length - 1;\n        },\n        isWaiverGuideStepComplete(index) {\n            if (this.dashboardRegion === 'au' || !this.canShowWaiveCenter) return false;\n            const steps = Array.isArray(this.waiveGuideStepItems) ? this.waiveGuideStepItems : [];\n            if (!steps.length) return false;\n            const stepIndex = Number(index);\n            if (!Number.isFinite(stepIndex)) return false;\n            if (this.hasWaiverApprovalUploaded) return true;\n            return stepIndex <= 1;\n        },\n        getWaiverGuideCompletedCount() {\n            const steps = Array.isArray(this.waiveGuideStepItems) ? this.waiveGuideStepItems : [];\n            if (!steps.length) return 0;\n            return steps.reduce((count, step, index) => count + (this.isWaiverGuideStepComplete(index) ? 1 : 0), 0);\n        },\n        getCurrentUsEnrollmentId() {\n            const order = (this.userInfo && this.userInfo.usa_order) || {};\n            return Number(order.enrollment_id || order.enrollmentId || order.id || 0) || 0;\n        },\n        triggerWaiverApprovalFileSelect() {\n            if (!this.canShowWaiveCenter) {\n                this.notifyLockedUntilPurchase();\n                return;\n            }\n            if (this.waiverApprovalUploading) return;\n            const fileInput = document.getElementById('waiverApprovalUploadInput');\n            if (fileInput) {\n                fileInput.value = '';\n                fileInput.click();\n            }\n        },\n        handleWaiverApprovalFileSelect(event) {\n            const files = event && event.target && event.target.files ? Array.from(event.target.files) : [];\n            const file = files[0] || null;\n            if (event && event.target) event.target.value = '';\n            if (!file) return;\n            this.uploadWaiverApprovalImage(file);\n        },\n        setLocalWaiverApprovalUrl(url) {\n            const text = String(url || '').trim();\n            if (!text) return;\n            const user = this.userInfo || {};\n            const order = user.usa_order || {};\n            this.waiverApprovalUrl = text;\n            this.userInfo = {\n                ...user,\n                usa_order: {\n                    ...order,\n                    waiver_approval: text,\n                },\n            };\n        },\n        async refreshUserInfoOnly() {\n            const response = await this.apiGet(this.api.userInfo);\n            const user = this.getPayloadData(response) || {};\n            if (user && typeof user === 'object') {\n                this.userInfo = user;\n                this.dashboardRegion = this.pickDashboardRegion(user);\n                this.syncRenewalPromoState(user);\n            }\n            return user;\n        },\n        async uploadWaiverApprovalImage(file) {\n            const type = String(file && file.type || '').toLowerCase();\n            const name = String(file && file.name || '').toLowerCase();\n            const isImage = \/image\\\/(jpeg|png|webp)\/.test(type) || \/\\.(jpe?g|png|webp)$\/i.test(name);\n            if (!isImage) {\n                this.notifyError(this.t('invalid_waiver_approval_file', 'Please upload a JPG, PNG, or WebP image.'));\n                return;\n            }\n            if (Number(file.size || 0) > 10 * 1024 * 1024) {\n                this.notifyError(this.t('waiver_approval_too_large', 'Image size cannot exceed 10MB.'));\n                return;\n            }\n            const enrollmentId = this.getCurrentUsEnrollmentId();\n            if (!enrollmentId) {\n                this.notifyError(this.t('waiver_approval_missing_order', 'No USA enrollment found for this waiver.'));\n                return;\n            }\n            const formData = new FormData();\n            formData.append('image', file);\n            this.waiverApprovalUploading = true;\n            this.beginGlobalLoading(this.t('uploading', 'Uploading'), this.t('uploading', 'Uploading'));\n            try {\n                const response = await this.apiPost(`${this.api.usWaiverApproval}\/${encodeURIComponent(enrollmentId)}`, formData);\n                const payload = response && response.data ? response.data : {};\n                const uploadError = this.getUploadPayloadErrorMessage(payload);\n                if (uploadError) {\n                    throw new Error(uploadError);\n                }\n                const data = payload && payload.data && typeof payload.data === 'object' ? payload.data : payload;\n                const url = String(data.url || data.waiver_approval || '').trim();\n                if (url) {\n                    this.setLocalWaiverApprovalUrl(url);\n                }\n                await this.refreshUserInfoOnly().catch(() => {});\n                if (url && !this.currentWaiverApprovalUrl) {\n                    this.setLocalWaiverApprovalUrl(url);\n                }\n                this.notifySuccess(this.t('waiver_approval_uploaded', 'Waiver approval image uploaded.'));\n            } catch (error) {\n                this.notifyError(this.getApiErrorMessage(error, 'File upload failed'));\n            } finally {\n                this.waiverApprovalUploading = false;\n                this.endGlobalLoading();\n            }\n        },\n        handleDashboardReferralRewardsClick() {\n            if (this.dashboardRegion === 'au') {\n                this.openRulesModal();\n                return;\n            }\n            this.setActiveTab('referrals');\n        },\n        escapeHtml(value) {\n            return String(value || '')\n                .replace(\/&\/g, '&amp;')\n                .replace(\/<\/g, '&lt;')\n                .replace(\/>\/g, '&gt;')\n                .replace(\/\"\/g, '&quot;')\n                .replace(\/'\/g, '&#039;');\n        },\n        formatNotificationContent(content) {\n            const value = String(content || '').trim();\n            if (!value) return '';\n            const hasBlockHtml = \/<(p|div|ul|ol|li|table|blockquote|h[1-6])[\\s>]\/i.test(value);\n            if (hasBlockHtml) return value;\n            const hasInlineHtml = \/<[a-z][\\s\\S]*>\/i.test(value);\n            return value\n                .split(\/\\r?\\n\\s*\\r?\\n\/)\n                .map(block => block.trim())\n                .filter(Boolean)\n                .map((block) => {\n                    const lines = block\n                        .split(\/\\r?\\n\/)\n                        .map(line => line.trim())\n                        .filter(Boolean)\n                        .map(line => hasInlineHtml ? line : this.escapeHtml(line));\n                    return `<p>${lines.join('<br>')}<\/p>`;\n                })\n                .join('');\n        },\n        notifyLockedUntilPurchase() {\n            this.notifyError(this.t('feature_unlock_after_purchase', 'This feature will unlock after your purchase is complete.'));\n        },\n        isDashboardActionLocked(action) {\n            const actionId = action && action.id ? action.id : '';\n            return actionId !== 'contact_support' && !this.canUsePlanBenefits;\n        },\n        handleAppleWalletClick() {\n            if (!this.canUsePlanBenefits) {\n                this.notifyLockedUntilPurchase();\n                return;\n            }\n            this.notifyError(this.t('apple_wallet_unavailable', 'Apple Wallet is not available yet.'));\n        },\n        handleTopAction(action) {\n            const actionId = action && action.id ? action.id : '';\n            if (!this.canUsePlanBenefits) {\n                this.notifyLockedUntilPurchase();\n                return;\n            }\n            if (actionId === 'emergency_sos') {\n                this.openModal = 'emergencySos';\n                return;\n            }\n            if (actionId === 'ai_symptom_checker') {\n                this.openInNewTab('https:\/\/meditriage.goglobalsafe.com\/');\n                return;\n            }\n            if (actionId === 'bill_analyzer') {\n                this.openInNewTab('https:\/\/medibill.goglobalsafe.com\/');\n                return;\n            }\n        },\n        handleBottomAction(action) {\n            const actionId = action && action.id ? action.id : '';\n            const guide = this.getGuideResult();\n            if (actionId === 'waive_guide') {\n                this.setActiveTab('waive');\n                return;\n            }\n            if (actionId !== 'contact_support' && !this.canUsePlanBenefits) {\n                this.notifyLockedUntilPurchase();\n                return;\n            }\n            if (actionId === 'find_pharmacy') {\n                this.openInNewTab(this.getBottomActionUrl(action));\n                return;\n            }\n            if (actionId === 'find_provider') {\n                this.openInNewTab(this.getBottomActionUrl(action));\n                return;\n            }\n            if (actionId === 'add_dental_vision') {\n                this.openInNewTab(this.getBottomActionUrl(action));\n                return;\n            }\n            if (actionId === 'contact_support') {\n                this.openModal = 'contactSupport';\n                return;\n            }\n        },\n        handleSupportQrError() {\n            this.supportQrFailed = true;\n        },\n        handleUgcGroupQrError() {\n            this.ugcGroupQrFailed = true;\n        },\n        handlePlusBenefitsQrError() {\n            this.plusBenefitsQrFailed = true;\n        },\n        openRulesModal() {\n            this.openModal = 'rules';\n        },\n        getOnboardingGuideStorageKey() {\n            const user = this.userInfo || {};\n            const order = user.usa_order || {};\n            const identity = String(\n                user.id\n                || user.user_id\n                || user.email\n                || user.code\n                || order.id\n                || 'student'\n            ).trim();\n            return `ggs_usercenter_onboarding_seen_${identity}`;\n        },\n        hasSeenOnboardingGuide() {\n            try {\n                return localStorage.getItem(this.getOnboardingGuideStorageKey()) === '1';\n            } catch (error) {\n                return true;\n            }\n        },\n        markOnboardingGuideSeen() {\n            try {\n                localStorage.setItem(this.getOnboardingGuideStorageKey(), '1');\n            } catch (error) {}\n        },\n        maybeShowOnboardingGuide() {\n            if (this.dashboardRegion === 'au' || !this.isUsPurchaseComplete || this.hasSeenOnboardingGuide()) return;\n            if (this.onboardingGuideTimer) {\n                window.clearTimeout(this.onboardingGuideTimer);\n                this.onboardingGuideTimer = null;\n            }\n            this.onboardingGuideTimer = window.setTimeout(() => {\n                this.onboardingGuideTimer = null;\n                if (this.dashboardRegion === 'au' || !this.isUsPurchaseComplete || this.hasSeenOnboardingGuide()) return;\n                if (this.openModal || this.renewModalOpen) return;\n                this.openModal = 'onboardingGuide';\n            }, 420);\n        },\n        dismissOnboardingGuide() {\n            this.markOnboardingGuideSeen();\n            this.openModal = '';\n        },\n        startOnboardingGuide() {\n            this.markOnboardingGuideSeen();\n            this.openModal = '';\n            this.setActiveTab('plans');\n        },\n        async fetchDashboardUserInfo() {\n            this.authToken = localStorage.getItem('student_token') || '';\n            if (!this.authToken) {\n                this.userInfo = {};\n                this.dashboardRegion = 'usa';\n                window.location.href = '\/student-login\/';\n                return;\n            }\n            this.isLoadingDashboard = true;\n            let loadingClosed = false;\n            this.beginGlobalLoading('Loading your dashboard...', 'Loading');\n            const messagesPromise = this.fetchMessages().catch(() => {});\n            try {\n                const response = await this.apiGet(this.api.userInfo);\n                const user = this.getPayloadData(response) || {};\n                this.userInfo = user || {};\n                this.dashboardRegion = this.pickDashboardRegion(user);\n                this.syncRenewalPromoState(user);\n                const userCache = JSON.parse(JSON.stringify(user || {}));\n                delete userCache.guide_result;\n                delete userCache.au_order;\n                delete userCache.usa_order;\n                delete userCache.product;\n                localStorage.setItem('user_info', JSON.stringify(userCache));\n                this.fetchMfaStatus({ silent: true }).catch(() => {});\n\n                this.plansDataLoaded = false;\n                this.claimsDataLoaded = false;\n                this.waiverDataLoaded = false;\n                this.plansDataLoadingPromise = null;\n                this.claimsDataLoadingPromise = null;\n                this.waiverDataLoadingPromise = null;\n                this.referralDataLoaded = false;\n                this.referralDataLoadingPromise = null;\n                this.ticketDataLoaded = false;\n                this.ticketDataLoadingPromise = null;\n                this.ugcDataLoaded = false;\n                this.ugcLoadingPromise = null;\n                this.dashboardBackgroundPreloadStarted = false;\n                this.loadUgcGeneratedTemplatesFromStorage();\n\n                await this.loadDashboardCurrentPageData(messagesPromise);\n\n                this.isLoadingDashboard = false;\n                this.endGlobalLoading();\n                loadingClosed = true;\n\n                if (!this.canShowUgcCenter && this.activeTab === 'ugc') {\n                    this.activeTab = 'dashboard';\n                }\n                if (!this.canShowClaimsCenter && this.activeTab === 'claims') {\n                    this.activeTab = 'dashboard';\n                }\n                if (!this.canShowWaiveCenter && this.activeTab === 'waive') {\n                    this.activeTab = 'dashboard';\n                }\n                if (this.dashboardRegion === 'au' && this.activeTab === 'referrals') {\n                    this.activeTab = 'dashboard';\n                }\n                this.scheduleDashboardBackgroundPreload();\n                this.maybeShowOnboardingGuide();\n                this.reportRenewTrackIfNeeded(true).catch(() => {});\n            } catch (error) {\n                console.error('Dashboard userinfo fetch failed:', error);\n                if (this.handleAuthFailure(error)) return;\n                this.userInfo = {};\n                this.dashboardRegion = 'usa';\n            } finally {\n                if (!loadingClosed) {\n                    this.isLoadingDashboard = false;\n                    this.endGlobalLoading();\n                }\n            }\n        },\n        async loadDashboardCurrentPageData(messagesPromise = null) {\n            const tasks = [];\n            if (messagesPromise && typeof messagesPromise.then === 'function') {\n                tasks.push(messagesPromise);\n            } else {\n                tasks.push(this.fetchMessages());\n            }\n            tasks.push(this.fetchDashboardCurrentRegionOrders());\n            if (this.canShowWaiveCenter) {\n                tasks.push(this.loadWaiverDataIfNeeded(false, false));\n            }\n            await Promise.allSettled(tasks);\n        },\n        async fetchDashboardCurrentRegionOrders() {\n            if (this.dashboardRegion === 'au') {\n                await this.fetchOrders();\n                return;\n            }\n            await this.fetchUSOrders();\n        },\n        scheduleDashboardBackgroundPreload() {\n            if (this.dashboardBackgroundPreloadStarted) return;\n            this.dashboardBackgroundPreloadStarted = true;\n            if (this.dashboardBackgroundPreloadTimer) {\n                window.clearTimeout(this.dashboardBackgroundPreloadTimer);\n            }\n            this.dashboardBackgroundPreloadTimer = window.setTimeout(() => {\n                this.dashboardBackgroundPreloadTimer = null;\n                this.preloadDashboardSecondaryPages().catch((error) => {\n                    console.error('Dashboard background preload failed:', error);\n                });\n            }, 250);\n        },\n        async preloadDashboardSecondaryPages() {\n            const jobs = [\n                () => this.loadPlansDataIfNeeded(false, false),\n                () => this.canShowWaiveCenter ? this.loadWaiverDataIfNeeded(false, false) : Promise.resolve(),\n                () => this.dashboardRegion !== 'au' ? this.loadReferralDataIfNeeded(false, false) : Promise.resolve(),\n                () => this.canShowClaimsCenter ? this.loadClaimsDataIfNeeded(false, false) : Promise.resolve(),\n                () => this.canShowUgcCenter ? this.loadUgcDataIfNeeded(false, false) : Promise.resolve(),\n                () => this.loadTicketDataIfNeeded(false, false),\n            ];\n            for (const job of jobs) {\n                try {\n                    await job();\n                } catch (error) {\n                    console.error('Background preload job failed:', error);\n                }\n                await new Promise(resolve => window.setTimeout(resolve, 80));\n            }\n        },\n        async fetchOrders() {\n            try {\n                const response = await this.apiGet(this.api.oshcOrders, {\n                    params: { page: 1, per_page: 10 },\n                });\n                const data = this.getPayloadData(response);\n                const list = Array.isArray(data && data.data) ? data.data : (Array.isArray(data) ? data : []);\n                const auRows = list.map((order, index) => this.buildAuOrderRow(order, index));\n                if (this.dashboardRegion === 'au') {\n                    this.orders = auRows;\n                    this.resetOrderPagination();\n                }\n            } catch (error) {\n                console.error('Fetch OSHC orders failed:', error);\n            }\n        },\n        resolveWaiveFaqPayload() {\n            const user = this.userInfo || {};\n            if (this.dashboardRegion === 'au') return null;\n            const usaOrder = user.usa_order || {};\n            const members = Array.isArray(usaOrder.members) ? usaOrder.members : [];\n            const firstMember = members[0] || {};\n\n            const schoolSlug = String(\n                user.school_slug\n                || (user.us_school_deadline && user.us_school_deadline.school_slug)\n                || usaOrder.school_slug\n                || ''\n            ).trim();\n            if (schoolSlug) {\n                return { school_slug: schoolSlug };\n            }\n\n            const schoolIdRaw = this.pickClaimValue(\n                user.us_school_deadline && user.us_school_deadline.school_id,\n                usaOrder.school_id,\n                firstMember.school_id\n            );\n            const schoolId = Number(schoolIdRaw);\n            if (!Number.isNaN(schoolId) && schoolId > 0) {\n                return { school_id: schoolId };\n            }\n            return null;\n        },\n        async fetchWaiveFaqData() {\n            const payload = this.resolveWaiveFaqPayload();\n            if (!payload) {\n                this.schoolWaiveData = null;\n                this.waiveFaqCategories = [];\n                this.waiveStepGuideImageFailed = false;\n                return;\n            }\n            try {\n                const response = await this.apiPost(this.api.productSchoolWaiveFaq, payload);\n                const body = response && response.data ? response.data : {};\n                const data = body && body.data ? body.data : {};\n                this.schoolWaiveData = data && typeof data.school_waive === 'object' ? data.school_waive : null;\n                this.waiveFaqCategories = Array.isArray(data.faq_categories) ? data.faq_categories : [];\n                this.waiveStepGuideImageFailed = false;\n            } catch (error) {\n                console.error('Fetch school waive faq failed:', error);\n                this.schoolWaiveData = null;\n                this.waiveFaqCategories = [];\n                this.waiveStepGuideImageFailed = false;\n            }\n        },\n        async fetchMessages(perPage = 20) {\n            try {\n                const response = await this.apiGet(this.api.messages, {\n                    params: { per_page: perPage },\n                });\n                const payload = response && response.data ? response.data : {};\n                const messageList = Array.isArray(payload.data) ? payload.data : [];\n                this.notifications = messageList.map(item => ({\n                    id: item.id,\n                    title: item.title || 'Notification',\n                    subtitle: item.subtitle || '',\n                    summary: item.summary || '',\n                    is_read: !!item.is_read,\n                    read_at: item.read_at || null,\n                    sent_at: item.sent_at || item.created_at || '',\n                    created_at: item.created_at || '',\n                }));\n                this.unreadMessageCount = Number(payload.unread_count || 0);\n                const pagination = payload.pagination || {};\n                this.notificationPagination = {\n                    current_page: Number(pagination.current_page || 1),\n                    per_page: Number(pagination.per_page || perPage),\n                    total: Number(pagination.total || this.notifications.length),\n                    last_page: Number(pagination.last_page || 1),\n                };\n            } catch (error) {\n                console.error('Fetch messages failed:', error);\n                this.notifications = [];\n                this.unreadMessageCount = 0;\n            }\n        },\n        async openNotificationDetail(item) {\n            const messageId = item && item.id ? Number(item.id) : 0;\n            if (!messageId) return;\n            this.openModal = 'notificationDetail';\n            this.isNotificationDetailLoading = true;\n            this.selectedNotificationDetail = {\n                ...item,\n                content: '',\n            };\n            try {\n                const response = await this.apiGet(`${this.api.messages}\/${messageId}`);\n                const payload = response && response.data ? response.data : {};\n                const detail = payload.data || {};\n                this.selectedNotificationDetail = {\n                    id: detail.id,\n                    title: detail.title || item.title || 'Notification',\n                    subtitle: detail.subtitle || item.subtitle || '',\n                    summary: detail.summary || item.summary || '',\n                    content: detail.content || '',\n                    is_read: !!detail.is_read,\n                    read_at: detail.read_at || null,\n                    sent_at: detail.sent_at || detail.created_at || '',\n                    created_at: detail.created_at || '',\n                    updated_at: detail.updated_at || '',\n                };\n                const index = this.notifications.findIndex(msg => Number(msg.id) === messageId);\n                if (index !== -1) {\n                    const wasUnread = !this.notifications[index].is_read;\n                    this.notifications[index] = {\n                        ...this.notifications[index],\n                        is_read: true,\n                        read_at: this.selectedNotificationDetail.read_at || this.notifications[index].read_at,\n                    };\n                    if (wasUnread && this.unreadMessageCount > 0) {\n                        this.unreadMessageCount -= 1;\n                    }\n                }\n            } catch (error) {\n                console.error('Fetch message detail failed:', error);\n                this.notifyError('Unable to load message detail');\n                this.openModal = '';\n            } finally {\n                this.isNotificationDetailLoading = false;\n            }\n        },\n        async fetchUSOrders() {\n            try {\n                const response = await this.apiGet(this.api.usaOrders, {\n                    params: { page: 1, per_page: 10 },\n                });\n                const data = this.getPayloadData(response);\n                const paged = Array.isArray(data) ? data[0] : data;\n                const list = Array.isArray(paged && paged.data) ? paged.data : (Array.isArray(paged) ? paged : []);\n                const usaRows = list.map((order, index) => this.buildUsaOrderRow(order, index));\n                if (this.dashboardRegion !== 'au') {\n                    this.orders = usaRows;\n                    this.resetOrderPagination();\n                }\n            } catch (error) {\n                console.error('Fetch USA orders failed:', error);\n            }\n        },\n        async fetchFiles(enrollmentId) {\n            if (!enrollmentId) return [];\n            try {\n                const response = await this.apiPost(this.api.files, {\n                    type: 1,\n                    enrollment_id: enrollmentId,\n                }, {\n                    headers: {\n                        'x-authentication-key': 'HSxZK8nHniLzZtv0Qtfk87wvNvXpJZ5K',\n                    },\n                });\n                const payload = this.getPayloadData(response);\n                const files = payload && payload.files ? payload.files : [];\n                this.documents = (Array.isArray(files) ? files : Object.values(files)).map((file, index) => ({\n                    name: file.name || file.file_name || file.title || ('Document ' + (index + 1)),\n                    size: file.size || '',\n                    type: file.type || file.file_type || '',\n                    date: file.date || file.created_at || file.updated_at || '',\n                    url: file.url || file.path || file.file_url || '',\n                    raw: file,\n                }));\n                return this.documents;\n            } catch (error) {\n                console.error('Fetch files failed:', error);\n                return [];\n            }\n        },\n        async loadWaiverDataIfNeeded(force = false, useLoading = true) {\n            if (this.waiverDataLoaded && !force) return;\n            if (this.waiverDataLoadingPromise && !force) {\n                if (useLoading) {\n                    this.beginGlobalLoading('Loading waiver details...', 'Loading');\n                    try {\n                        await this.waiverDataLoadingPromise;\n                    } finally {\n                        this.endGlobalLoading();\n                    }\n                } else {\n                    await this.waiverDataLoadingPromise;\n                }\n                return;\n            }\n            const runner = async () => {\n                await this.fetchWaiveFaqData();\n                this.waiverDataLoaded = true;\n            };\n            this.waiverDataLoadingPromise = useLoading\n                ? this.withGlobalLoading('Loading waiver details...', runner, 'Loading')\n                : runner();\n            try {\n                await this.waiverDataLoadingPromise;\n            } finally {\n                this.waiverDataLoadingPromise = null;\n            }\n        },\n        async loadReferralDataIfNeeded(force = false, useLoading = true) {\n            if (this.referralDataLoaded && !force) return;\n            if (this.referralDataLoadingPromise && !force) {\n                if (useLoading) {\n                    this.beginGlobalLoading('Loading referral rewards...', 'Loading');\n                    try {\n                        await this.referralDataLoadingPromise;\n                    } finally {\n                        this.endGlobalLoading();\n                    }\n                } else {\n                    await this.referralDataLoadingPromise;\n                }\n                return;\n            }\n            const runner = async () => {\n                if (this.dashboardRegion === 'au') {\n                    await Promise.allSettled([\n                        this.fetchRewardSummary(1),\n                        this.fetchAusRewards(),\n                    ]);\n                } else {\n                    await this.fetchUsaRewardCenter(this.referralCurrentPage || 1);\n                }\n                this.referralDataLoaded = true;\n            };\n            this.referralDataLoadingPromise = useLoading\n                ? this.withGlobalLoading('Loading referral rewards...', runner, 'Loading')\n                : runner();\n            try {\n                await this.referralDataLoadingPromise;\n            } finally {\n                this.referralDataLoadingPromise = null;\n            }\n        },\n        async loadPlansDataIfNeeded(force = false, useLoading = true) {\n            if (this.plansDataLoaded && !force) return;\n            if (this.plansDataLoadingPromise && !force) {\n                if (useLoading) {\n                    this.beginGlobalLoading('Loading your plan details...', 'Loading');\n                    try {\n                        await this.plansDataLoadingPromise;\n                    } finally {\n                        this.endGlobalLoading();\n                    }\n                } else {\n                    await this.plansDataLoadingPromise;\n                }\n                return;\n            }\n            const runner = async () => {\n                const tasks = [\n                    this.fetchOrders(),\n                    this.fetchUSOrders(),\n                ];\n                const user = this.userInfo || {};\n                const usaOrder = user && user.usa_order ? user.usa_order : {};\n                if (usaOrder && usaOrder.id) {\n                    tasks.push(this.fetchFiles(usaOrder.id));\n                }\n                await Promise.allSettled(tasks);\n                this.plansDataLoaded = true;\n            };\n            this.plansDataLoadingPromise = useLoading\n                ? this.withGlobalLoading('Loading your plan details...', runner, 'Loading')\n                : runner();\n            try {\n                await this.plansDataLoadingPromise;\n            } finally {\n                this.plansDataLoadingPromise = null;\n            }\n        },\n        async loadClaimsDataIfNeeded(force = false, useLoading = true) {\n            if (this.claimsDataLoaded && !force) return;\n            if (this.claimsDataLoadingPromise && !force) {\n                if (useLoading) {\n                    this.beginGlobalLoading('Loading your claims history...', 'Loading');\n                    try {\n                        await this.claimsDataLoadingPromise;\n                    } finally {\n                        this.endGlobalLoading();\n                    }\n                } else {\n                    await this.claimsDataLoadingPromise;\n                }\n                return;\n            }\n            const runner = async () => {\n                await this.fetchClaimList();\n                this.claimsDataLoaded = true;\n            };\n            this.claimsDataLoadingPromise = useLoading\n                ? this.withGlobalLoading('Loading your claims history...', runner, 'Loading')\n                : runner();\n            try {\n                await this.claimsDataLoadingPromise;\n            } finally {\n                this.claimsDataLoadingPromise = null;\n            }\n        },\n        async fetchRewardSummary(page = 1) {\n            try {\n                const response = await this.apiGet(this.api.rewards, {\n                    params: { page, per_page: this.referralPageSize },\n                });\n                const data = response && response.data ? response.data : {};\n                const history = data.reward_history && Array.isArray(data.reward_history.data) ? data.reward_history.data : [];\n                this.referrals = history.map((item, index) => this.buildReferralHistoryItem(item, index));\n                this.referralCurrentPage = Number((data.reward_history && data.reward_history.current_page) || page || 1);\n                this.referralPageSize = Number((data.reward_history && data.reward_history.per_page) || this.referralPageSize || 10);\n                this.referralTotal = Number((data.reward_history && data.reward_history.total) || this.referrals.length || 0);\n                this.referralIssuedCount = Number(data.issued_num || 0);\n                this.referralProcessingCount = Number(data.processing_num || 0);\n            } catch (error) {\n                console.error('Fetch AU rewards failed:', error);\n            }\n        },\n        async fetchAusRewards() {\n            try {\n                await this.apiGet(this.api.ausRewards, {\n                    params: { page: 1, per_page: 10 },\n                });\n            } catch (error) {\n                console.error('Fetch AUS reward registration failed:', error);\n            }\n        },\n        async fetchUsaRewardCenter(page = 1) {\n            try {\n                const currentPage = Math.max(1, Number(page) || 1);\n                const limit = Math.max(1, Math.min(50, Number(this.referralPageSize || 10)));\n                const response = await this.apiGet(this.api.usaRewardCenter, {\n                    params: { limit, page: currentPage },\n                });\n                const data = this.getPayloadData(response) || {};\n                const summary = data.summary && typeof data.summary === 'object' ? data.summary : {};\n                const rewardStats = data.reward_stats && typeof data.reward_stats === 'object' ? data.reward_stats : {};\n                const history = data.history && typeof data.history === 'object' ? data.history : {};\n                const historyList = Array.isArray(history.data) ? history.data : [];\n                const historyCurrentPage = Math.max(1, Number(history.current_page || currentPage || 1));\n                const historyPerPage = Math.max(1, Number(history.per_page || history.limit || limit || 10));\n                const historyTotal = Math.max(0, Number(history.total || historyList.length || 0));\n                const tiers = Array.isArray(data.tiers) ? data.tiers : [];\n                const allowedCounts = [1, 2, 3, 5, 8, 12, 20, 50];\n\n                this.rewardCenterSummary = summary;\n                this.rewardCenterStats = rewardStats;\n                if (tiers.length) {\n                    const normalizedTiers = tiers\n                        .map(tier => this.normalizeRewardCenterTier(tier))\n                        .filter(tier => allowedCounts.includes(Number(tier.count)))\n                        .sort((a, b) => Number(a.count) - Number(b.count));\n                    if (normalizedTiers.length) {\n                        this.milestones = normalizedTiers;\n                    }\n                }\n                this.referrals = historyList.map((item, index) => this.buildReferralHistoryItem(item, index));\n                this.referralCurrentPage = historyCurrentPage;\n                this.referralPageSize = historyPerPage;\n                this.referralTotal = historyTotal;\n                this.referralIssuedCount = this.sumRewardStatsCount(rewardStats.history);\n                this.referralProcessingCount = this.sumRewardStatsCount(rewardStats.pending);\n            } catch (error) {\n                console.error('Fetch USA reward center failed:', error);\n                this.rewardCenterSummary = null;\n                this.rewardCenterStats = null;\n                this.referrals = [];\n                this.referralCurrentPage = 1;\n                this.referralTotal = 0;\n                this.referralIssuedCount = 0;\n                this.referralProcessingCount = 0;\n            }\n        },\n        async generateReferralCode() {\n            try {\n                const response = await this.apiPost(this.api.requestRewardCode, {});\n                this.notifySuccess((response.data && response.data.message) || 'Referral code requested');\n                await this.fetchDashboardUserInfo();\n            } catch (error) {\n                console.error('Generate referral code failed:', error);\n                this.notifyError('Referral code application failed. Please contact customer service.');\n            }\n        },\n        updateHeaderOffset() {\n            const root = document.getElementById('uc-app');\n            if (!root) return;\n\n            if (window.innerWidth > 760) {\n                root.style.setProperty('--uc-header-offset', '0px');\n                return;\n            }\n\n            const candidates = [\n                '#ast-mobile-header',\n                '#ast-desktop-header',\n                '.elementor-location-header',\n                '.site-header',\n                '.main-header-bar',\n            ];\n\n            let offset = 0;\n            for (const selector of candidates) {\n                const element = document.querySelector(selector);\n                if (!element) continue;\n                const rect = element.getBoundingClientRect();\n                const style = window.getComputedStyle(element);\n                if (style.display === 'none' || style.visibility === 'hidden') continue;\n                const isFloatingHeader = style.position === 'fixed'\n                    || style.position === 'sticky'\n                    || Math.abs(rect.top) <= 1;\n                if (!isFloatingHeader) continue;\n                offset = Math.max(offset, Math.max(0, Math.round(rect.bottom)));\n            }\n\n            root.style.setProperty('--uc-header-offset', offset + 'px');\n        },\n        setActiveTab(tab) {\n            if (tab === 'ugc' && !this.canShowUgcCenter) {\n                this.notifyError('UGC Center is available after purchasing insurance.');\n                return;\n            }\n            if (tab === 'waive' && !this.canShowWaiveCenter) {\n                this.notifyError(this.t('waive_center_after_purchase', 'Waive Center is available after your purchase is complete.'));\n                return;\n            }\n            if (tab === 'claims' && !this.canShowClaimsCenter) {\n                this.notifyError(this.t('claims_after_purchase', 'Claims are available after your purchase is complete.'));\n                return;\n            }\n            this.activeTab = tab;\n            this.closePlusBenefits();\n            this.closeStatusFlow();\n            if (tab === 'claims') {\n                this.loadClaimsDataIfNeeded();\n            } else if (tab === 'plans') {\n                this.loadPlansDataIfNeeded();\n            } else if (tab === 'waive') {\n                this.loadWaiverDataIfNeeded();\n            } else if (tab === 'referrals') {\n                this.loadReferralDataIfNeeded();\n            } else if (tab === 'ugc') {\n                this.loadUgcDataIfNeeded();\n            } else if (tab === 'help') {\n                this.loadTicketDataIfNeeded();\n            }\n            this.$nextTick(() => {\n                const app = document.getElementById('uc-app');\n                if (app) app.scrollIntoView({ block: 'start' });\n            });\n        },\n        openMobileMenu() {\n            this.updateHeaderOffset();\n            this.mobileMenuOpen = true;\n            document.body.classList.add('uc-drawer-open');\n        },\n        closeMobileMenu() {\n            this.mobileMenuOpen = false;\n            document.body.classList.remove('uc-drawer-open');\n            this.updateHeaderOffset();\n        },\n        toggleMobileMenu() {\n            if (this.mobileMenuOpen) {\n                this.closeMobileMenu();\n                return;\n            }\n            this.openMobileMenu();\n        },\n        goToPlanDocuments() {\n            this.setActiveTab('plans');\n            this.$nextTick(() => {\n                window.setTimeout(() => {\n                    const section = document.getElementById('uc-plan-documents-section');\n                    if (section && typeof section.scrollIntoView === 'function') {\n                        section.scrollIntoView({\n                            behavior: 'smooth',\n                            block: 'start',\n                        });\n                    }\n                }, 60);\n            });\n        },\n        toggleDetail(id) {\n            this.openDetails[id] = !this.openDetails[id];\n        },\n        isDetailOpen(id) {\n            return !!this.openDetails[id];\n        },\n        getOrderDetailKey(order, pageIndex) {\n            const item = order || {};\n            const token = item.id || item.policy || pageIndex;\n            return `order-${item.region || 'mix'}-${token}`;\n        },\n        getWaiveFaqDetailKey(article, index) {\n            const item = article || {};\n            const token = item.id || index;\n            return `waive-faq-${token}`;\n        },\n        clearOrderDetailStates() {\n            const next = {};\n            Object.keys(this.openDetails || {}).forEach((key) => {\n                if (!String(key).startsWith('order-')) {\n                    next[key] = this.openDetails[key];\n                }\n            });\n            this.openDetails = next;\n        },\n        changeOrderPage(page) {\n            const target = Math.min(this.orderPageCount, Math.max(1, Number(page) || 1));\n            if (target === this.orderCurrentPage) return;\n            this.orderPage = target;\n            this.clearOrderDetailStates();\n        },\n        resetOrderPagination() {\n            this.orderPage = 1;\n            this.clearOrderDetailStates();\n        },\n        getOrderPayStatusRaw(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            return Object.prototype.hasOwnProperty.call(item, 'payStatus') ? item.payStatus : raw.pay_status;\n        },\n        getOrderCreatedAtRaw(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            const coverage = raw.enrollmentCoverage || {};\n            const paymentInfo = raw.payment_info || raw.payment || item.paymentInfo || {};\n            return this.pickClaimValue(\n                item.createdAt,\n                raw.created_at,\n                raw.createdAt,\n                raw.create_time,\n                raw.created_time,\n                raw.order_date,\n                raw.purchase_date,\n                coverage.purchaseDate,\n                paymentInfo.created_at,\n                paymentInfo.createdAt\n            );\n        },\n        parseOrderDateTime(value) {\n            const text = String(value || '').trim();\n            if (!text) return 0;\n            const normalized = text\n                .replace(\/\\\/\/g, '-')\n                .replace(\/\\.\\d{3,6}Z$\/i, 'Z')\n                .replace(\/\\s+\/, 'T');\n            const ts = Date.parse(normalized);\n            if (!Number.isNaN(ts)) return ts;\n            const match = text.match(\/^(\\d{4})[-\/](\\d{1,2})[-\/](\\d{1,2})\/);\n            if (!match) return 0;\n            return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3])).getTime();\n        },\n        isDashboardPaymentStatusOrder(order) {\n            const createdAt = this.getOrderCreatedAtRaw(order);\n            const orderTs = this.parseOrderDateTime(createdAt);\n            const cutoffTs = this.parseOrderDateTime(this.dashboardPaymentCutoffDate);\n            if (!orderTs || !cutoffTs) return false;\n            return orderTs >= cutoffTs;\n        },\n        isUnpaidOrderStatus(value, region) {\n            const text = String(value === null || typeof value === 'undefined' ? '' : value).trim().toLowerCase();\n            const number = Number(value);\n            if (region === 'au') {\n                return number === -1 || ['unpaid', 'not_paid', 'pending_payment', 'awaiting_payment'].includes(text);\n            }\n            return number === 0 || ['unpaid', 'not_paid', 'pending_payment', 'awaiting_payment'].includes(text);\n        },\n        getAuOrderPayStatus(order) {\n            return Number(this.getOrderPayStatusRaw(order));\n        },\n        canShowAuPayNow(order) {\n            return order && order.region === 'au' && this.isUnpaidOrderStatus(this.getOrderPayStatusRaw(order), 'au');\n        },\n        getUsOrderPayStatus(order) {\n            return Number(this.getOrderPayStatusRaw(order));\n        },\n        canShowUsPayNow(order) {\n            return order && order.region === 'usa' && this.isUnpaidOrderStatus(this.getOrderPayStatusRaw(order), 'usa');\n        },\n        canShowOrderPayNow(order) {\n            return this.canShowAuPayNow(order) || this.canShowUsPayNow(order);\n        },\n        getBackPayLink(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            return String(item.backPay || raw.back_pay || '').trim();\n        },\n        getOshcFulfilLink(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            return String(item.fulfil || raw.fulfil || '').trim();\n        },\n        getOshcOrderEmail(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            const email = String(item.contactEmail || raw.email || '').trim();\n            return email === '-' ? '' : email;\n        },\n        getUsOrderEnrollmentId(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            return Number(raw.enrollment_id || item.enrollmentId || raw.id || item.id || 0) || 0;\n        },\n        getUsOrderRequestId(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            return String(item.requestId || raw.requestId || raw.request_id || raw.request_no || raw.requestNo || raw.req || raw.renew_request_id || raw.payment_request_id || '').trim();\n        },\n        getUsOrderWechatPayUrl(order) {\n            const item = order || {};\n            const raw = item.raw || {};\n            const paymentInfo = raw.payment_info || item.paymentInfo || {};\n            const paymentData = paymentInfo.payment_data || paymentInfo.paymentData || {};\n            return String(item.payUrl || paymentData.pay_url || paymentData.payUrl || paymentInfo.pay_url || paymentInfo.payUrl || raw.pay_url || raw.payUrl || '').trim();\n        },\n        getUsEnrollmentPaymentUrl(order) {\n            const requestId = this.getUsOrderRequestId(order);\n            if (!requestId) return '';\n            return `https:\/\/www.goglobalsafe.com\/us-enrollment?req=${encodeURIComponent(requestId)}`;\n        },\n        handleOrderPayNow(order) {\n            if (order && order.region === 'usa') {\n                this.handleUsOrderPayNow(order);\n                return;\n            }\n            this.handleAuOrderPayNow(order);\n        },\n        handleAuOrderPayNow(order) {\n            if (!this.canShowAuPayNow(order)) return;\n            const backPayLink = this.getBackPayLink(order);\n            if (backPayLink) {\n                window.location.href = backPayLink;\n                return;\n            }\n            this.selectedOshcPayOrder = order;\n            this.usPaymentStep = 'options';\n            this.openModal = 'oshcPayOptions';\n        },\n        handleUsOrderPayNow(order) {\n            if (!this.canShowUsPayNow(order)) return;\n            this.selectedOshcPayOrder = order;\n            this.usPaymentStep = 'options';\n            this.openModal = 'oshcPayOptions';\n        },\n        closeOshcPayModal() {\n            if (this.isOshcPaySubmitting) return;\n            this.openModal = '';\n            this.selectedOshcPayOrder = null;\n            this.usPaymentStep = 'options';\n        },\n        clearOshcEmailRedirectTimer() {\n            if (this.oshcEmailRedirectTimer) {\n                window.clearInterval(this.oshcEmailRedirectTimer);\n                this.oshcEmailRedirectTimer = null;\n            }\n        },\n        startOshcEmailRedirectCountdown() {\n            this.clearOshcEmailRedirectTimer();\n            this.oshcEmailRedirectSeconds = 5;\n            this.openModal = 'oshcEmailQueued';\n            this.oshcEmailRedirectTimer = window.setInterval(() => {\n                this.oshcEmailRedirectSeconds -= 1;\n                if (this.oshcEmailRedirectSeconds <= 0) {\n                    this.goToOshcOrderListNow();\n                }\n            }, 1000);\n        },\n        goToOshcOrderListNow() {\n            this.clearOshcEmailRedirectTimer();\n            this.openModal = '';\n            this.selectedOshcPayOrder = null;\n            this.usPaymentStep = 'options';\n            this.activeTab = 'plans';\n            this.fetchOrders().catch(() => {});\n        },\n        goToUsEnrollmentPayment(order) {\n            const url = this.getUsEnrollmentPaymentUrl(order);\n            if (!url) {\n                this.notifyError(this.t('us_payment_link_missing', 'Payment link is not available. Please continue on the enrollment page.'));\n                return;\n            }\n            window.location.href = url;\n        },\n        handleUsWechatPay() {\n            const order = this.selectedOshcPayOrder;\n            if (!order) return;\n            const payUrl = this.getUsOrderWechatPayUrl(order);\n            if (!payUrl) {\n                this.goToUsEnrollmentPayment(order);\n                return;\n            }\n            this.usPaymentStep = 'wechat';\n        },\n        async submitUsOrderCreditCardPayment() {\n            const order = this.selectedOshcPayOrder;\n            const enrollmentId = this.getUsOrderEnrollmentId(order);\n            if (!enrollmentId) {\n                this.notifyError('Missing order information. Please refresh and try again.');\n                return;\n            }\n            this.isOshcPaySubmitting = true;\n            this.beginGlobalLoading(this.t('preparing_payment_link', 'Preparing payment link...'), this.t('loading', 'Loading...'));\n            try {\n                const response = await this.apiGet(`${this.api.usPaymentLink}\/${encodeURIComponent(enrollmentId)}`);\n                const payload = response && response.data ? response.data : {};\n                const data = payload && payload.data && typeof payload.data === 'object' ? payload.data : payload;\n                const payUrl = String(data.pay_url || data.payUrl || payload.pay_url || payload.payUrl || '').trim();\n                if (!payUrl) throw new Error(this.t('payment_link_missing', 'Payment link is not available yet. Please try again later.'));\n                this.openModal = '';\n                this.selectedOshcPayOrder = null;\n                this.usPaymentStep = 'options';\n                this.openInNewTab(payUrl);\n            } catch (error) {\n                console.error('Fetch US payment link failed:', error);\n                this.notifyError(this.getApiErrorMessage(error, 'Payment request failed. Please try again later.'));\n            } finally {\n                this.isOshcPaySubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        async submitOshcOrderPayment(type) {\n            const order = this.selectedOshcPayOrder;\n            if (!order) return;\n            const raw = order.raw || {};\n            const payType = Number(type);\n            if (payType === 1 && this.getUnbrandedPlanName(raw.destination_name || order.plan || '') === 'Medibank') {\n                const fulfilLink = this.getOshcFulfilLink(order);\n                if (!fulfilLink) {\n                    this.notifyError(this.t('payment_link_missing', 'Payment link is not available yet. Please try again later.'));\n                    return;\n                }\n                this.openModal = '';\n                this.selectedOshcPayOrder = null;\n                this.openInNewTab(fulfilLink);\n                return;\n            }\n            this.isOshcPaySubmitting = true;\n            this.beginGlobalLoading(this.t('sending_payment_email', 'Sending payment email...'), this.t('loading', 'Loading...'));\n            try {\n                const response = await this.apiPost(this.api.oshcPayForm, {\n                    pay_type: payType,\n                    order_id: raw.id || order.id,\n                    email: this.getOshcOrderEmail(order),\n                });\n                const body = response && response.data ? response.data : {};\n                if (body.status === 200 || body.success) {\n                    if (payType === 1 && body.data) {\n                        this.openModal = '';\n                        this.selectedOshcPayOrder = null;\n                        window.location.href = String(body.data);\n                    } else {\n                        this.startOshcEmailRedirectCountdown();\n                    }\n                } else {\n                    this.notifyError(body.msg || body.message || 'Payment request failed. Please try again later.');\n                }\n            } catch (error) {\n                console.error('Submit OSHC payment failed:', error);\n                this.notifyError(this.getApiErrorMessage(error, 'Payment request failed. Please try again later.'));\n            } finally {\n                this.isOshcPaySubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        requestLogout() {\n            this.openModal = 'logoutConfirm';\n        },\n        async logout() {\n            if (this.authToken) {\n                try {\n                    await this.apiPost(this.api.logout, {});\n                } catch (error) {\n                    console.warn('Remote logout failed, clearing local session anyway', error);\n                }\n            }\n            localStorage.removeItem('student_token');\n            localStorage.removeItem('user_info');\n            this.authToken = '';\n            this.userInfo = {};\n            this.dashboardRegion = 'usa';\n            window.location.href = '\/student-login\/';\n        },\n        async confirmLogout() {\n            this.openModal = '';\n            await this.logout();\n        },\n        isHoverDevice() {\n            if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n            return window.matchMedia('(hover: hover) and (pointer: fine)').matches;\n        },\n        handlePlusBenefitsHoverEnter() {\n            if (!this.isHoverDevice()) return;\n            this.plusBenefitsOpen = true;\n        },\n        handlePlusBenefitsHoverLeave() {\n            if (!this.isHoverDevice()) return;\n            this.plusBenefitsOpen = false;\n        },\n        handlePlusBenefitsTriggerClick() {\n            if (this.isHoverDevice()) {\n                this.plusBenefitsOpen = true;\n                return;\n            }\n            this.plusBenefitsOpen = !this.plusBenefitsOpen;\n        },\n        closePlusBenefits() {\n            this.plusBenefitsOpen = false;\n        },\n        openStatusFlow() {\n            this.statusFlowOpen = true;\n        },\n        closeStatusFlow() {\n            this.statusFlowOpen = false;\n        },\n        toggleStatusFlow() {\n            this.statusFlowOpen = !this.statusFlowOpen;\n        },\n        handleDocumentClick(event) {\n            if (!this.plusBenefitsOpen && !this.statusFlowOpen && !this.activeMilestoneTipNode) return;\n            const triggerRefs = this.$refs.plusBenefitsTrigger;\n            const popoverRefs = this.$refs.plusBenefitsPopover;\n            const triggers = Array.isArray(triggerRefs) ? triggerRefs : (triggerRefs ? [triggerRefs] : []);\n            const popovers = Array.isArray(popoverRefs) ? popoverRefs : (popoverRefs ? [popoverRefs] : []);\n            const statusFlowRoot = this.$refs.statusFlowRoot;\n            const statusFlowPopover = this.$refs.statusFlowPopover;\n            const target = event && event.target ? event.target : null;\n            if (!target) {\n                this.plusBenefitsOpen = false;\n                this.statusFlowOpen = false;\n                this.hideMilestoneFloatingTip();\n                return;\n            }\n            if (this.activeMilestoneTipNode) {\n                const milestoneNode = target.closest && target.closest('.uc-milestone-node');\n                const milestoneTip = target.closest && target.closest('.uc-milestone-floating-tip');\n                if (!milestoneNode && !milestoneTip) {\n                    this.hideMilestoneFloatingTip();\n                }\n            }\n            if (this.plusBenefitsOpen) {\n                if (triggers.some(el => el && typeof el.contains === 'function' && el.contains(target))) return;\n                if (popovers.some(el => el && typeof el.contains === 'function' && el.contains(target))) return;\n                this.plusBenefitsOpen = false;\n            }\n            if (this.statusFlowOpen) {\n                if (statusFlowRoot && typeof statusFlowRoot.contains === 'function' && statusFlowRoot.contains(target)) return;\n                if (statusFlowPopover && typeof statusFlowPopover.contains === 'function' && statusFlowPopover.contains(target)) return;\n                this.statusFlowOpen = false;\n            }\n        },\n        async downloadFileCommon(url, params, fileName) {\n            this.beginGlobalLoading('Preparing your file download...', 'Downloading');\n            try {\n                const response = await this.apiGet(url, {\n                    params,\n                    responseType: 'blob',\n                });\n                const contentType = response.headers && response.headers['content-type'] ? response.headers['content-type'] : 'application\/octet-stream';\n                const blob = new Blob([response.data], { type: contentType });\n                const downloadUrl = window.URL.createObjectURL(blob);\n                const link = document.createElement('a');\n                link.href = downloadUrl;\n                link.setAttribute('download', fileName);\n                document.body.appendChild(link);\n                link.click();\n                document.body.removeChild(link);\n                window.URL.revokeObjectURL(downloadUrl);\n                this.notifySuccess('Download successful');\n            } catch (error) {\n                console.error('Download failed:', error);\n                let message = 'The file has not been generated yet. Please try again later.';\n                if (error.response && error.response.data instanceof Blob) {\n                    try {\n                        const text = await error.response.data.text();\n                        message = JSON.parse(text).message || message;\n                    } catch (parseError) {}\n                }\n                this.notifyError(message);\n            } finally {\n                this.endGlobalLoading();\n            }\n        },\n        getUsaSchoolNameForWaiver(order) {\n            const targetOrder = order || (this.userInfo && this.userInfo.usa_order) || null;\n            if (!targetOrder) return '';\n            const member = Array.isArray(targetOrder.members) ? targetOrder.members[0] : targetOrder;\n            const contacts = member && Array.isArray(member.contacts) ? member.contacts : [];\n            const schoolByNamedContact = this.pickNamedValue(contacts, 'School');\n            const schoolByIndex = contacts[2] && contacts[2].value ? String(contacts[2].value).trim() : '';\n            return schoolByNamedContact || schoolByIndex || '';\n        },\n        getWaiverMaterialProfile(order) {\n            const school = this.getUsaSchoolNameForWaiver(order);\n            const normalized = String(school || '').trim();\n            const ucSchools = [\n                'University Of California Los Angeles',\n                'University Of California Irvine',\n                'University of California Irvine (UCI)',\n                'University Of California Santa Barbara\uff08UCSB\uff09',\n                'University of California Santa Barbara\uff08UCSB\uff09',\n                'University of California San Diego UCSD',\n                'University Of California San Diego',\n                'University Of California Davis',\n            ];\n            if (normalized === 'Stanford University' || normalized === 'Stanford University J-visa') {\n                return {\n                    kind: 'certificate_image',\n                    title: this.t('material_id_image_title', 'ID Card Image'),\n                    desc: this.t('material_id_image_desc', 'Download your ID card image for waiver.'),\n                };\n            }\n            if (ucSchools.includes(normalized)) {\n                return {\n                    kind: 'certificate_image_with_summary',\n                    title: this.t('material_id_image_title', 'ID Card Image'),\n                    desc: this.t('material_id_image_desc', 'Download ID card image for waiver.'),\n                };\n            }\n            return {\n                kind: 'waiver_certificate',\n                title: this.t('material_certificate_title', 'Waiver Certificate'),\n                desc: this.t('material_certificate_desc', 'Download your waiver certificate for school submission.'),\n            };\n        },\n        getSummaryOfBenefitsUrl(order) {\n            const targetOrder = order || (this.userInfo && this.userInfo.usa_order) || null;\n            const candidates = [\n                targetOrder && targetOrder.product ? targetOrder.product.summary_of : '',\n                targetOrder ? targetOrder.summary_of : '',\n                this.userInfo && this.userInfo.product ? this.userInfo.product.summary_of : '',\n            ];\n            for (const item of candidates) {\n                const text = String(item || '').trim();\n                if (text) return text;\n            }\n            return '';\n        },\n        getPolicyTermsUrl(order) {\n            const targetOrder = order || (this.dashboardRegion === 'au'\n                ? (this.userInfo && this.userInfo.au_order)\n                : (this.userInfo && this.userInfo.usa_order)) || null;\n            const targetProduct = targetOrder && targetOrder.product && typeof targetOrder.product === 'object' ? targetOrder.product : {};\n            const userProduct = this.userInfo && this.userInfo.product && typeof this.userInfo.product === 'object' ? this.userInfo.product : {};\n            const candidates = [\n                targetProduct.policy_link,\n                targetProduct.policyLink,\n                targetProduct.policy_url,\n                targetProduct.policyUrl,\n                targetOrder && targetOrder.policy_link,\n                targetOrder && targetOrder.policyLink,\n                targetOrder && targetOrder.policy_url,\n                targetOrder && targetOrder.policyUrl,\n                userProduct.policy_link,\n                userProduct.policyLink,\n                userProduct.policy_url,\n                userProduct.policyUrl,\n            ];\n            for (const item of candidates) {\n                const text = String(item || '').trim();\n                if (text) return text;\n            }\n            return '';\n        },\n        getMaterialTitle(material) {\n            const item = material || {};\n            const id = String(item.id || '');\n            if (id === 'id_card') return this.t('material_id_card_title', item.title || 'Insurance ID Card');\n            if (id === 'policy') return this.t('material_policy_title', item.title || 'Policy & Terms');\n            if (id === 'summary_benefits') return this.t('material_summary_title', item.title || 'Summary of Benefits');\n            if (id !== 'waiver') return item.title || '';\n            return this.getWaiverMaterialProfile().title;\n        },\n        getMaterialDesc(material) {\n            const item = material || {};\n            const id = String(item.id || '');\n            if (id === 'id_card') return this.t('material_id_card_desc', item.desc || 'Download your digital ID card');\n            if (id === 'policy') return this.t('material_policy_desc', item.desc || 'View your full coverage details');\n            if (id === 'summary_benefits') return this.t('material_summary_desc', item.desc || 'School-specific waiver summary document.');\n            if (id !== 'waiver') return item.desc || '';\n            return this.getWaiverMaterialProfile().desc;\n        },\n        getMaterialUsage(material) {\n            const item = material || {};\n            const id = String(item.id || '');\n            if (id === 'id_card') return this.t('material_id_card_usage', 'Use for doctor visits, provider check-in, and school waiver uploads.');\n            if (id === 'policy') return this.t('material_policy_usage', 'Use to confirm benefits, exclusions, network rules, and coverage dates.');\n            if (id === 'summary_benefits') return this.t('material_summary_usage', 'Use when your school asks for a summary of benefits.');\n            if (id !== 'waiver') return '';\n            const profile = this.getWaiverMaterialProfile();\n            if (profile.kind === 'waiver_form') return this.t('material_waiver_form_usage', 'Upload this form to the school waiver portal.');\n            if (profile.kind === 'certificate_image' || profile.kind === 'certificate_image_with_summary') {\n                return this.t('material_id_image_usage', 'Upload this image where the school asks for insurance proof.');\n            }\n            return this.t('material_certificate_usage', 'Upload this certificate for school waiver submission.');\n        },\n        handleMaterialAction(material) {\n            if (!this.canUsePlanBenefits) {\n                this.notifyLockedUntilPurchase();\n                return;\n            }\n            const order = this.userInfo && this.userInfo.usa_order ? this.userInfo.usa_order : null;\n            const orderId = order && order.id ? order.id : '';\n            if (material.id === 'summary_benefits') {\n                const summaryUrl = this.getSummaryOfBenefitsUrl(order);\n                if (!summaryUrl) {\n                    this.notifyError('Summary of Benefits is not available yet.');\n                    return;\n                }\n                window.open(summaryUrl, '_blank');\n                return;\n            }\n            if (!orderId && material.id !== 'policy') {\n                this.notifyError('No USA enrollment found for this document');\n                return;\n            }\n            if (material.id === 'id_card') {\n                this.downloadFileCommon(this.api.downloadUsaCertificate, { enrollment_id: orderId }, `Certificate_of_Coverage_${orderId}.pdf`);\n                return;\n            }\n            if (material.id === 'waiver') {\n                const profile = this.getWaiverMaterialProfile(order);\n                if (profile.kind === 'waiver_form') {\n                    this.downloadFileCommon(this.api.downloadWaiverForm, { enrollment_id: orderId }, `Waiver_Form_${orderId}.pdf`);\n                    return;\n                }\n                if (profile.kind === 'certificate_image' || profile.kind === 'certificate_image_with_summary') {\n                    this.downloadFileCommon(this.api.downloadUsaIdCard, { enrollment_id: orderId }, `ID_Card_${orderId}.png`);\n                    return;\n                }\n                this.downloadFileCommon(this.api.downloadWaiverCertificate, { enrollment_id: orderId }, `Waiver_Certificate_${orderId}.pdf`);\n                return;\n            }\n            if (material.id === 'policy') {\n                const policyUrl = this.getPolicyTermsUrl(this.dashboardRegion === 'au' ? (this.userInfo && this.userInfo.au_order) : order);\n                if (policyUrl) {\n                    window.open(policyUrl, '_blank');\n                    return;\n                }\n                const auOrder = this.userInfo && this.userInfo.au_order ? this.userInfo.au_order : null;\n                if (auOrder && auOrder.id) {\n                    this.downloadFileCommon(this.api.downloadOshcPolicy, { enrollment_id: auOrder.id }, `Order_${auOrder.id}.pdf`);\n                    return;\n                }\n                this.notifyError('Policy & Terms is not available yet.');\n            }\n        },\n        handleDocumentDownload(doc) {\n            if (!this.canUsePlanBenefits) {\n                this.notifyLockedUntilPurchase();\n                return;\n            }\n            if (doc && doc.url) {\n                window.open(doc.url, '_blank');\n                return;\n            }\n            this.handleMaterialAction({ id: 'policy' });\n        },\n        downloadAllDocuments() {\n            this.materials.forEach(material => this.handleMaterialAction(material));\n        },\n        selectUgcPlatform(platformId) {\n            const normalizedId = Number(platformId || 0);\n            if (!normalizedId) return;\n            this.selectedPlatform = normalizedId;\n            this.ugcForm.alipayAccount = '';\n            this.ugcForm.alipayRealName = '';\n            this.ugcForm.shareLink = '';\n        },\n        openUgcPlatformByJumpUrl(platform) {\n            const item = platform && typeof platform === 'object' ? platform : {};\n            const url = String(item.jumpUrl || item.jump_url || '').trim();\n            if (!url) {\n                this.notifyError('Platform link is not available.');\n                return;\n            }\n            this.openInNewTab(url);\n        },\n        getTodayDateKey() {\n            const now = new Date();\n            const year = now.getFullYear();\n            const month = String(now.getMonth() + 1).padStart(2, '0');\n            const day = String(now.getDate()).padStart(2, '0');\n            return `${year}-${month}-${day}`;\n        },\n        loadUgcGeneratedTemplatesFromStorage() {\n            try {\n                const key = this.ugcGenerateStorageKey;\n                if (!key) {\n                    this.ugcGeneratedTemplates = [];\n                    return;\n                }\n                const text = localStorage.getItem(key);\n                if (!text) {\n                    this.ugcGeneratedTemplates = [];\n                    return;\n                }\n                const parsed = JSON.parse(text);\n                this.ugcGeneratedTemplates = Array.isArray(parsed) ? parsed : [];\n                this.cleanupUgcGeneratedTemplates();\n            } catch (error) {\n                console.warn('Load UGC generated templates failed:', error);\n                this.ugcGeneratedTemplates = [];\n            }\n        },\n        saveUgcGeneratedTemplatesToStorage() {\n            try {\n                const key = this.ugcGenerateStorageKey;\n                if (!key) return;\n                localStorage.setItem(key, JSON.stringify(this.ugcGeneratedTemplates || []));\n            } catch (error) {\n                console.warn('Save UGC generated templates failed:', error);\n            }\n        },\n        cleanupUgcGeneratedTemplates() {\n            const today = this.getTodayDateKey();\n            const source = Array.isArray(this.ugcGeneratedTemplates) ? this.ugcGeneratedTemplates : [];\n            this.ugcGeneratedTemplates = source\n                .filter((item) => String(item && item.dayKey ? item.dayKey : '') === today)\n                .slice(0, 30);\n            this.saveUgcGeneratedTemplatesToStorage();\n        },\n        async copyUgcTemplateContent(item) {\n            const data = item && typeof item === 'object' ? item : {};\n            const text = String(data.content || '').trim();\n            if (!text) {\n                this.notifyError(this.t('no_template_content', 'No template content to copy.'));\n                return;\n            }\n            try {\n                if (navigator.clipboard && window.isSecureContext) {\n                    await navigator.clipboard.writeText(text);\n                } else {\n                    const copied = this.copyTextLegacy(text);\n                    if (!copied) {\n                        throw new Error('Legacy clipboard copy failed');\n                    }\n                }\n                this.notifySuccess(this.t('template_copied', 'Template copied.'));\n            } catch (error) {\n                console.error('Copy UGC template failed:', error);\n                this.notifyError(this.t('copy_failed_manual', 'Copy failed. Please press and hold to copy manually.'));\n            }\n        },\n        appendUgcGeneratedTemplate(templatePayload) {\n            const template = templatePayload && typeof templatePayload === 'object' ? templatePayload : {};\n            const nowIso = new Date().toISOString();\n            const entry = {\n                localId: `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n                dayKey: this.getTodayDateKey(),\n                market: this.ugcMarket,\n                platformId: Number(this.selectedPlatform || 0),\n                templateId: Number(template.id || 0),\n                rewardType: String(template.reward_type || '').trim().toLowerCase(),\n                title: String(template.title || '').trim(),\n                content: String(template.content || '').trim(),\n                generatedAt: nowIso,\n            };\n            this.ugcGeneratedTemplates = [entry].concat(Array.isArray(this.ugcGeneratedTemplates) ? this.ugcGeneratedTemplates : []);\n            this.cleanupUgcGeneratedTemplates();\n        },\n        async generateUgcTemplate() {\n            if (!this.ugcSelectedPlatform) {\n                this.notifyError(this.t('please_select_platform', 'Please select a platform first.'));\n                return;\n            }\n            if (Number(this.ugcGenerateTodayRemainingCount || 0) <= 0) {\n                this.notifyError(this.t('generate_limit_tip', 'You can generate copy up to 3 times per day.'));\n                return;\n            }\n            this.ugcGenerating = true;\n            this.beginGlobalLoading(this.t('loading_generating_ugc', 'Generating your UGC copy...'), this.t('generating', 'Generating'));\n            try {\n                const response = await this.apiGet(this.api.ugcTemplateGenerate, {\n                    params: {\n                        platform_id: Number(this.ugcSelectedPlatform.id || 0),\n                        market: this.ugcMarket,\n                    },\n                });\n                const payload = response && response.data ? response.data : {};\n                const data = payload && payload.data && typeof payload.data === 'object' ? payload.data : {};\n                const template = data && data.template && typeof data.template === 'object' ? data.template : null;\n                if (!template || !template.id) {\n                    this.notifyError(String(payload.message || 'No template available.'));\n                    return;\n                }\n                this.appendUgcGeneratedTemplate(template);\n                this.notifySuccess('Copy generated. Click the item to select it for submission.');\n            } catch (error) {\n                console.error('Generate UGC template failed:', error);\n                this.notifyError(this.getApiErrorMessage(error, 'No template available.'));\n            } finally {\n                this.ugcGenerating = false;\n                this.endGlobalLoading();\n            }\n        },\n        triggerUgcFileSelect() {\n            const fileInput = document.getElementById('ugcScreenshotInput');\n            if (fileInput) {\n                fileInput.click();\n            }\n        },\n        handleUgcFileSelect(event) {\n            const files = event && event.target ? event.target.files : null;\n            if (!files || !files.length) return;\n            const file = files[0];\n            if (!file) return;\n            const fileName = String(file.name || '').toLowerCase();\n            const extensionValid = \/\\.(png|jpe?g|pdf)$\/i.test(fileName);\n            if (!extensionValid) {\n                this.notifyError('Only png, jpg, jpeg, and pdf files are allowed.');\n                this.ugcForm.screenshotFile = null;\n                event.target.value = '';\n                return;\n            }\n            const maxSize = 10 * 1024 * 1024;\n            if (Number(file.size || 0) > maxSize) {\n                this.notifyError('File size cannot exceed 10MB.');\n                this.ugcForm.screenshotFile = null;\n                event.target.value = '';\n                return;\n            }\n            this.ugcForm.screenshotFile = file;\n        },\n        resetUgcForm() {\n            this.ugcForm.agreeTerms = false;\n            this.ugcForm.alipayAccount = '';\n            this.ugcForm.alipayRealName = '';\n            this.ugcForm.shareLink = '';\n            this.ugcForm.screenshotFile = null;\n            const fileInput = document.getElementById('ugcScreenshotInput');\n            if (fileInput) {\n                fileInput.value = '';\n            }\n        },\n        mapUgcReviewStatus(status) {\n            const normalized = String(status || '').trim().toLowerCase();\n            if (normalized === 'approved') return { label: 'Approved', className: 'uc-status-green' };\n            if (normalized === 'rejected') return { label: 'Rejected', className: 'uc-status-red' };\n            if (normalized === 'pending') return { label: 'Pending Review', className: 'uc-status-blue' };\n            return { label: normalized ? normalized.toUpperCase() : 'Unknown', className: 'uc-status-gray' };\n        },\n        mapUgcRewardStatus(rewardType, cashStatus, starbucksStatus) {\n            const type = String(rewardType || '').trim().toLowerCase();\n            if (type === 'cash') {\n                const normalized = String(cashStatus || '').trim().toLowerCase();\n                if (normalized === 'paid') return 'Cash Issued';\n                if (normalized === 'processing') return 'Cash Processing';\n                if (normalized === 'failed') return 'Cash Issuance Failed';\n                return 'Cash Pending';\n            }\n            const normalized = String(starbucksStatus || '').trim().toLowerCase();\n            if (normalized === 'sent') return 'Gift Card Sent';\n            if (normalized === 'failed') return 'Gift Card Failed';\n            return 'Gift Card Pending';\n        },\n        async loadUgcDataIfNeeded(force = false, useLoading = true) {\n            if (this.ugcDataLoaded && !force) return;\n            if (this.ugcLoadingPromise && !force) {\n                if (useLoading) {\n                    this.beginGlobalLoading('Loading UGC center...', 'Loading');\n                    try {\n                        await this.ugcLoadingPromise;\n                    } finally {\n                        this.endGlobalLoading();\n                    }\n                } else {\n                    await this.ugcLoadingPromise;\n                }\n                return;\n            }\n            const runner = async () => {\n                this.loadUgcGeneratedTemplatesFromStorage();\n                await Promise.allSettled([\n                    this.fetchUgcConfig(),\n                    this.fetchUgcHistory(),\n                ]);\n                this.ugcDataLoaded = true;\n            };\n            this.ugcLoadingPromise = useLoading\n                ? this.withGlobalLoading('Loading UGC center...', runner, 'Loading')\n                : runner();\n            try {\n                await this.ugcLoadingPromise;\n            } finally {\n                this.ugcLoadingPromise = null;\n            }\n        },\n        async fetchUgcConfig() {\n            try {\n                const response = await this.apiGet(this.api.ugcConfig, {\n                    params: {\n                        market: this.ugcMarket,\n                    },\n                });\n                const payload = response && response.data ? response.data : {};\n                const data = payload && payload.data && typeof payload.data === 'object' ? payload.data : {};\n                this.ugcConfig = {\n                    market: String(data.market || this.ugcMarket).trim().toUpperCase(),\n                    platforms: Array.isArray(data.platforms) ? data.platforms : [],\n                };\n                if (!this.ugcPlatformsForDisplay.length) {\n                    this.selectedPlatform = '';\n                    return;\n                }\n                const selectedExists = this.ugcPlatformsForDisplay.some(item => Number(item.id) === Number(this.selectedPlatform || 0));\n                if (!selectedExists) {\n                    this.selectedPlatform = Number(this.ugcPlatformsForDisplay[0].id);\n                }\n            } catch (error) {\n                console.error('Fetch UGC config failed:', error);\n                this.ugcConfig = {\n                    market: this.ugcMarket,\n                    platforms: [],\n                };\n                this.notifyError(this.getApiErrorMessage(error, 'Failed to load UGC configuration.'));\n            }\n        },\n        async fetchUgcHistory() {\n            try {\n                const response = await this.apiGet(this.api.ugcHistory, {\n                    params: {\n                        market: this.ugcMarket,\n                    },\n                });\n                const payload = response && response.data ? response.data : {};\n                const data = payload && Array.isArray(payload.data) ? payload.data : [];\n                this.ugcHistory = data;\n            } catch (error) {\n                console.error('Fetch UGC history failed:', error);\n                this.ugcHistory = [];\n                this.notifyError(this.getApiErrorMessage(error, 'Failed to load UGC history.'));\n            }\n        },\n        async submitUgcSubmission() {\n            if (!this.ugcSelectedPlatform) {\n                this.notifyError('Please select a platform first.');\n                return;\n            }\n            const templateId = Number(this.ugcAutoTemplateIdForSubmit || 0);\n            if (!this.ugcForm.screenshotFile) {\n                this.notifyError('Please upload a screenshot file.');\n                return;\n            }\n            if (!this.normalizeBooleanLike(this.ugcForm.agreeTerms)) {\n                this.notifyError('Please agree to the terms before submitting.');\n                return;\n            }\n            if (this.ugcNeedAlipayFields) {\n                if (!String(this.ugcForm.alipayAccount || '').trim() || !String(this.ugcForm.alipayRealName || '').trim()) {\n                    this.notifyError('Alipay account and real name are required for cash reward.');\n                    return;\n                }\n            }\n            if (this.ugcNeedShareLink && !String(this.ugcForm.shareLink || '').trim()) {\n                this.notifyError(this.t('xiaohongshu_share_link_required', 'Please enter your Xiaohongshu share link.'));\n                return;\n            }\n\n            const formData = new FormData();\n            formData.append('market', this.ugcMarket);\n            formData.append('platform_id', String(this.ugcSelectedPlatform.id));\n            formData.append('copy_template_id', String(templateId || 0));\n            formData.append('screenshot', this.ugcForm.screenshotFile);\n            formData.append('agree_terms', '1');\n            if (this.ugcNeedShareLink) {\n                formData.append('share_link', String(this.ugcForm.shareLink || '').trim());\n            }\n            if (this.ugcNeedAlipayFields) {\n                formData.append('alipay_account', String(this.ugcForm.alipayAccount || '').trim());\n                formData.append('alipay_real_name', String(this.ugcForm.alipayRealName || '').trim());\n            }\n\n            this.ugcSubmitting = true;\n            this.beginGlobalLoading('Submitting your UGC screenshot...', 'Submitting');\n            try {\n                const response = await this.apiPost(this.api.ugcSubmit, formData, {\n                    headers: {\n                        'Content-Type': 'multipart\/form-data',\n                    },\n                });\n                const payload = response && response.data ? response.data : {};\n                if (payload && payload.success) {\n                    this.ugcSuccess = true;\n                    this.ugcSuccessMessage = String(payload.message || 'Submitted successfully');\n                    this.notifySuccess(this.ugcSuccessMessage);\n                    this.resetUgcForm();\n                    await this.fetchUgcHistory();\n                } else {\n                    const message = String(payload.message || 'UGC submit failed. Please try again.');\n                    this.notifyError(message);\n                }\n            } catch (error) {\n                console.error('Submit UGC failed:', error);\n                this.notifyError(this.getApiErrorMessage(error, 'UGC submit failed. Please try again.'));\n            } finally {\n                this.ugcSubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n        async copyReferralValue(value) {\n            const text = String(typeof value === 'undefined' ? this.dashboardReferralCode : value).trim();\n            if (!text) return;\n            try {\n                if (navigator.clipboard && window.isSecureContext) {\n                    await navigator.clipboard.writeText(text);\n                } else {\n                    const copied = this.copyTextLegacy(text);\n                    if (!copied) {\n                        throw new Error('Legacy clipboard copy failed');\n                    }\n                }\n                this.notifySuccess(\/^https?:\\\/\\\/\/i.test(text) ? 'Referral link copied' : 'Referral code copied');\n                await this.addShareCount(2);\n            } catch (error) {\n                console.error('Copy failed:', error);\n                this.notifyError('Copy failed. Please press and hold to copy manually.');\n            }\n        },\n        async addShareCount(type) {\n            try {\n                await this.apiPost(this.api.shareCount, { type });\n            } catch (error) {\n                console.warn('Share count failed:', error);\n            }\n        },\n        \n        \/\/ Claim related methods\n        openClaimInstructions() {\n            const url = String(this.claimInstructionsUrl || '').trim();\n            if (!url) {\n                this.notifyError('Claims instructions are not available right now.');\n                return;\n            }\n            window.open(url, '_blank', 'noopener');\n        },\n        openClaimTemplate() {\n            const url = String(this.claimTemplateUrl || '').trim();\n            if (!url) {\n                this.notifyError('Claim template is not available right now.');\n                return;\n            }\n            window.open(url, '_blank', 'noopener');\n        },\n        triggerFileSelect() {\n            const fileInput = document.getElementById('fileUploadInput');\n            if (fileInput) {\n                fileInput.click();\n            }\n        },\n        handleFileSelect(event) {\n            const files = event.target.files;\n            if (!files || files.length === 0) return;\n            \n            for (let i = 0; i < files.length; i++) {\n                const file = files[i];\n                const fileObj = {\n                    name: file.name,\n                    size: (file.size \/ 1024 \/ 1024).toFixed(2) + ' MB',\n                    status: 'loading',\n                    percent: 0,\n                };\n                this.uploadedFiles.push(fileObj);\n                this.uploadFile(file, this.uploadedFiles.length - 1);\n            }\n        },\n        handleDragOver(event) {\n            event.preventDefault();\n            event.stopPropagation();\n        },\n        handleDragLeave(event) {\n            event.preventDefault();\n            event.stopPropagation();\n        },\n        handleDrop(event) {\n            event.preventDefault();\n            event.stopPropagation();\n            const files = event.dataTransfer.files;\n            if (!files || files.length === 0) return;\n            \n            for (let i = 0; i < files.length; i++) {\n                const file = files[i];\n                const fileObj = {\n                    name: file.name,\n                    size: (file.size \/ 1024 \/ 1024).toFixed(2) + ' MB',\n                    status: 'loading',\n                    percent: 0,\n                };\n                this.uploadedFiles.push(fileObj);\n                this.uploadFile(file, this.uploadedFiles.length - 1);\n            }\n        },\n        async uploadFile(file, index) {\n            try {\n                const formData = new FormData();\n                formData.append('file', file);\n                formData.append('index', index);\n                formData.append('fileType', file.type);\n                formData.append('fileName', file.name);\n                \n                \/\/ Simulate upload progress\n                let progress = 0;\n                const progressInterval = setInterval(() => {\n                    progress += 10;\n                    if (progress <= 90) {\n                        this.uploadedFiles[index].percent = progress;\n                    }\n                }, 200);\n                \n                const response = await this.apiPost(this.api.claimUpload, formData, {\n                    headers: {\n                        'Content-Type': 'multipart\/form-data',\n                    },\n                    onUploadProgress: (progressEvent) => {\n                        if (progressEvent.lengthComputable) {\n                            const percentCompleted = Math.round((progressEvent.loaded * 100) \/ progressEvent.total);\n                            this.uploadedFiles[index].percent = percentCompleted;\n                        }\n                    },\n                });\n                \n                clearInterval(progressInterval);\n                \n                const payload = response && response.data ? response.data : {};\n                const uploadError = this.getUploadPayloadErrorMessage(payload);\n                if (uploadError) {\n                    throw new Error(uploadError);\n                }\n                if (payload && (payload.success || payload.filename || payload.status === 200)) {\n                    this.uploadedFiles[index].status = 'success';\n                    this.uploadedFiles[index].percent = 100;\n                    this.uploadedFiles[index].ggs = payload.filename || payload.file_name || payload.data?.filename || file.name;\n                } else {\n                    this.uploadedFiles[index].status = 'error';\n                    this.notifyError('File upload failed');\n                }\n            } catch (error) {\n                console.error('File upload failed:', error);\n                this.uploadedFiles[index].status = 'error';\n                this.notifyError(this.getApiErrorMessage(error, 'File upload failed'));\n            }\n        },\n        removeFile(index) {\n            this.uploadedFiles.splice(index, 1);\n        },\n        async submitClaimFiles() {\n            if (this.uploadedFiles.length === 0) {\n                this.notifyError('Please upload at least one file');\n                return;\n            }\n            this.beginGlobalLoading('Submitting your claim files...', 'Submitting');\n            try {\n                const user = this.userInfo || {};\n                const usaOrder = user.usa_order || {};\n                const files = this.uploadedFiles.filter(file => file.status === 'success' && file.ggs).map(file => file.ggs);\n                if (!usaOrder.member_id || !usaOrder.id) {\n                    this.notifyError('Member ID is required before submitting claim files');\n                    return;\n                }\n                if (!files.length) {\n                    this.notifyError('Please wait until files upload successfully');\n                    return;\n                }\n\n                const response = await this.apiPost(this.api.claimSubmit, {\n                    files,\n                    member_id: usaOrder.member_id,\n                    enrollment_id: usaOrder.id,\n                });\n                \n                if (response && response.data && (response.data.success || response.data.status === 200 || response.data.data?.status === 'Success')) {\n                    this.notifySuccess('Files submitted successfully!');\n                    this.uploadedFiles = [];\n                    await this.fetchClaimList();\n                } else {\n                    this.notifyError('Failed to submit files');\n                }\n            } catch (error) {\n                console.error('Submit claim failed:', error);\n                this.notifyError('Failed to submit files');\n            } finally {\n                this.endGlobalLoading();\n            }\n        },\n        async fetchClaimList() {\n            const memberId = this.resolveClaimMemberId();\n            if (!memberId) {\n                this.claim_list = [];\n                return;\n            }\n            try {\n                const response = await this.apiPost(this.api.claims, {\n                    member_id: memberId,\n                });\n                const payload = response && response.data ? response.data : {};\n                const responseClaims = payload?.data?.claims || payload?.data?.Claims || payload?.claims || payload?.Claims || [];\n                this.claim_list = Array.isArray(responseClaims) ? responseClaims.map(claim => this.normalizeClaimRecord(claim)) : [];\n            } catch (error) {\n                console.error('Fetch claim list failed:', error);\n            }\n        },\n        getClaimStatusLabel(status) {\n            const normalized = String(status || '').trim().toLowerCase();\n            if (normalized === 'processed') return this.t('status_processed', 'Processed');\n            if (normalized === 'complete' || normalized === 'completed') return this.t('status_completed', 'Completed');\n            if (normalized === 'approved') return this.t('status_approved', 'Approved');\n            if (normalized === 'denied') return this.t('status_denied', 'Denied');\n            if (normalized === 'processing') return this.t('processing', 'Processing');\n            if (normalized === 'pending') return this.t('pending', 'Pending');\n            if (normalized === 'in review' || normalized === 'in_review') return this.t('status_in_review', 'In Review');\n            if (normalized === 'submitted') return this.t('status_submitted', 'Submitted');\n            const statusMap = {\n                'Submitted': this.t('status_submitted', 'Submitted'),\n                'Pending': this.t('pending', 'Pending'),\n                'In Review': this.t('status_in_review', 'In Review'),\n                'Processing': this.t('processing', 'Processing'),\n                'Approved': this.t('status_approved', 'Approved'),\n                'Denied': this.t('status_denied', 'Denied'),\n                'Completed': this.t('status_completed', 'Completed'),\n            };\n            return statusMap[status] || status;\n        },\n        getClaimStatusClass(status) {\n            const normalized = String(status || '').trim().toLowerCase();\n            if (['processed', 'completed', 'complete', 'approved'].includes(normalized)) return 'uc-status-green';\n            if (normalized === 'denied') return 'uc-status-red';\n            if (normalized === 'processing') return 'uc-status-orange';\n            if (normalized === 'pending' || normalized === 'in review' || normalized === 'in_review' || normalized === 'submitted') return 'uc-status-blue';\n            const statusMap = {\n                'Submitted': 'uc-status-blue',\n                'Pending': 'uc-status-blue',\n                'In Review': 'uc-status-blue',\n                'Processing': 'uc-status-orange',\n                'Approved': 'uc-status-green',\n                'Denied': 'uc-status-red',\n                'Completed': 'uc-status-green',\n            };\n            return statusMap[status] || 'uc-status-gray';\n        },\n        isClaimProcessed(status) {\n            const normalized = String(status || '').trim().toLowerCase();\n            return normalized === 'completed' || normalized === 'complete';\n        },\n        canDownloadClaimEob(claim) {\n            const item = claim || {};\n            if (item.isLocalPending) return false;\n            const claimKey = String(item.claimKey || item.id || '').trim();\n            if (\/^local-\/i.test(claimKey)) return false;\n            if (this.normalizeBooleanLike(item.canDownloadEob)) return true;\n            return this.isClaimProcessed(item.claimStatus || item.statusRaw);\n        },\n        async downloadClaimEob(claim) {\n            const claimItem = claim || {};\n            if (!this.canDownloadClaimEob(claimItem)) {\n                this.notifyError('EOB is not available yet');\n                return;\n            }\n            const enrollmentId = this.userInfo && this.userInfo.usa_order ? this.userInfo.usa_order.id : '';\n            const claimKey = claimItem.id || claimItem.claimKey || '';\n            if (!enrollmentId || !claimKey) {\n                this.notifyError('Missing claim download parameters');\n                return;\n            }\n            const endpoint = claimItem.downloadEobApi || this.api.downloadEob;\n            const requestMethod = String(claimItem.downloadEobMethod || 'GET').toUpperCase();\n            const requestParams = claimItem.downloadEobParams && typeof claimItem.downloadEobParams === 'object'\n                ? claimItem.downloadEobParams\n                : {\n                    enrollment_id: enrollmentId,\n                    claim_id: claimKey,\n                };\n            this.beginGlobalLoading('Preparing EOB download...', 'Downloading');\n            try {\n                const response = requestMethod === 'POST'\n                    ? await this.apiPost(endpoint, requestParams, { responseType: 'blob' })\n                    : await this.apiGet(endpoint, { params: requestParams, responseType: 'blob' });\n                const blob = response.data instanceof Blob ? response.data : new Blob([response.data]);\n                const contentType = String(response && response.headers ? response.headers['content-type'] || '' : '').toLowerCase();\n                let isPdf = contentType.includes('application\/pdf');\n                if (!isPdf) {\n                    try {\n                        const head = await blob.slice(0, 5).text();\n                        isPdf = head === '%PDF-';\n                    } catch (error) {}\n                }\n\n                if (!isPdf) {\n                    let message = 'The EOB has not been generated yet. Download it later.';\n                    try {\n                        const text = await blob.text();\n                        const parsed = JSON.parse(text);\n                        message = (parsed && parsed.faults && parsed.faults[0]) || (parsed && parsed.message) || message;\n                    } catch (error) {}\n                    this.notifyError(message);\n                    return;\n                }\n\n                const downloadUrl = window.URL.createObjectURL(blob);\n                const link = document.createElement('a');\n                link.href = downloadUrl;\n                link.setAttribute('download', `WellAway_EOB_${claimKey}.pdf`);\n                document.body.appendChild(link);\n                link.click();\n                document.body.removeChild(link);\n                window.URL.revokeObjectURL(downloadUrl);\n                this.notifySuccess('EOB download successful');\n            } catch (error) {\n                console.error('Download EOB failed:', error);\n                let message = 'The EOB has not been generated yet. Download it later.';\n                if (error.response && error.response.data instanceof Blob) {\n                    try {\n                        const text = await error.response.data.text();\n                        const parsed = JSON.parse(text);\n                        message = (parsed && parsed.message) || message;\n                    } catch (parseError) {}\n                } else if (error.response && error.response.data && typeof error.response.data === 'object') {\n                    message = error.response.data.message || message;\n                }\n                this.notifyError(message);\n            } finally {\n                this.endGlobalLoading();\n            }\n        },\n        jumpClaim(claimKey) {\n            this.activeClaimId = claimKey;\n        },\n        async loadTicketDataIfNeeded(force = false, useLoading = true) {\n            if (this.ticketDataLoaded && !force) return;\n            if (this.ticketDataLoadingPromise && !force) {\n                if (useLoading) {\n                    this.beginGlobalLoading('Loading support center...', 'Loading');\n                    try {\n                        await this.ticketDataLoadingPromise;\n                    } finally {\n                        this.endGlobalLoading();\n                    }\n                } else {\n                    await this.ticketDataLoadingPromise;\n                }\n                return;\n            }\n            const runner = async () => {\n                await this.fetchTicketList();\n                this.ticketDataLoaded = true;\n            };\n            this.ticketDataLoadingPromise = useLoading\n                ? this.withGlobalLoading('Loading support center...', runner, 'Loading')\n                : runner();\n            try {\n                await this.ticketDataLoadingPromise;\n            } finally {\n                this.ticketDataLoadingPromise = null;\n            }\n        },\n        \n        \/\/ Ticket related methods\n        async fetchTicketList() {\n            try {\n                const response = await this.apiGet(this.api.tickets, {\n                    params: {\n                        page: this.tk_currentPage,\n                        per_page: this.tk_pageSize,\n                    },\n                });\n                const payload = this.getPayloadData(response) || {};\n                this.ticket_list = Array.isArray(payload.data) ? payload.data : [];\n                this.ticketCategories = Array.isArray(payload.category) ? payload.category : [];\n                this.tk_total = Number(payload.total || this.ticket_list.length);\n                if (this.ticket_list.some(ticket => Number(ticket && ticket.is_ticket || 0) === 1 || (ticket && ticket.is_ticket === true))) {\n                    this.userInfo = {\n                        ...(this.userInfo || {}),\n                        is_ticket: 1,\n                    };\n                } else if (this.userInfo && Number(this.userInfo.is_ticket || 0) === 1) {\n                    this.userInfo = {\n                        ...this.userInfo,\n                        is_ticket: 0,\n                    };\n                }\n            } catch (error) {\n                console.error('Fetch ticket list failed:', error);\n            }\n        },\n        async getTicketDetails(ticketId) {\n            try {\n                const response = await this.apiPost(this.api.ticketDetails, {\n                    ticket_id: ticketId,\n                });\n                \n                if (response && response.data && response.data.data) {\n                    this.selectTicketDetail = response.data.data;\n                    this.scrollTicketChatToBottom();\n                }\n            } catch (error) {\n                console.error('Fetch ticket detail failed:', error);\n            }\n        },\n        async openTicketDetail(ticket) {\n            const row = ticket && typeof ticket === 'object' ? ticket : {};\n            const ticketId = row.id || row.ticket_id || row.ticket_no || ticket;\n            this.selectTicketDetail = row && Object.keys(row).length ? { ...row } : null;\n            this.isTicketDetail = true;\n            this.openModal = 'ticketDetail';\n            await this.getTicketDetails(ticketId);\n            await this.fetchTicketList();\n            this.refreshTicketUnreadFromUserInfo().catch(() => {});\n        },\n        closeTicketDetail() {\n            this.openModal = '';\n            this.isTicketDetail = false;\n        },\n        async sendMessage(ticketId) {\n            if (!this.chatMessage || !this.chatMessage.trim()) {\n                this.notifyError('Please enter a message');\n                return;\n            }\n            \n            try {\n                const response = await this.apiPost(this.api.addChat, {\n                    ticket_id: ticketId,\n                    type: 1,\n                    content: this.chatMessage.trim(),\n                });\n                \n                if (response && response.data && (response.data.success || response.data.status === 200)) {\n                    this.chatMessage = '';\n                    await this.getTicketDetails(ticketId);\n                    this.notifySuccess('Sent success');\n                } else {\n                    this.notifyError('Failed to send message');\n                }\n            } catch (error) {\n                console.error('Send message failed:', error);\n                this.notifyError('Failed to send message');\n            }\n        },\n        triggerAddTicketFile() {\n            const fileInput = document.getElementById('addTicketFileUploadInput');\n            if (fileInput) {\n                fileInput.click();\n            }\n        },\n        triggerTicketFileSelect() {\n            const fileInput = document.getElementById('ticketFileUploadInput');\n            if (fileInput) {\n                fileInput.click();\n            }\n        },\n        handleTicketFileSelect(event) {\n            const files = event && event.target ? event.target.files : null;\n            if (!files || files.length === 0) return;\n            for (let i = 0; i < files.length; i += 1) {\n                const file = files[i];\n                if (!file) continue;\n                const isDuplicate = this.uploadedTicketFiles.some(existing => existing.name === file.name && Number(existing.rawSize || 0) === Number(file.size || 0));\n                if (isDuplicate) continue;\n                this.uploadedTicketFiles.push({\n                    name: file.name,\n                    size: `${(Number(file.size || 0) \/ 1024 \/ 1024).toFixed(2)} MB`,\n                    rawSize: Number(file.size || 0),\n                    type: file.type || '',\n                    file,\n                    status: 'ready',\n                    percent: 0,\n                    ggs: '',\n                });\n            }\n            if (event && event.target) {\n                event.target.value = '';\n            }\n            this.uploadTicketFilesForSubmit();\n        },\n        async uploadTicketFilesForSubmit() {\n            for (let i = 0; i < this.uploadedTicketFiles.length; i += 1) {\n                const fileItem = this.uploadedTicketFiles[i];\n                if (!fileItem || fileItem.status !== 'ready') continue;\n                this.uploadedTicketFiles[i].status = 'loading';\n                this.uploadedTicketFiles[i].percent = 0;\n                try {\n                    const formData = new FormData();\n                    formData.append('file', fileItem.file);\n                    formData.append('index', i);\n                    formData.append('fileType', fileItem.type || '');\n                    formData.append('fileName', fileItem.name || '');\n                    const response = await this.apiPost(this.api.claimUpload, formData, {\n                        headers: {\n                            'Content-Type': 'multipart\/form-data',\n                        },\n                        onUploadProgress: (progressEvent) => {\n                            if (!progressEvent || !progressEvent.total) return;\n                            const percent = Math.floor((progressEvent.loaded \/ progressEvent.total) * 100);\n                            if (this.uploadedTicketFiles[i]) {\n                                this.uploadedTicketFiles[i].percent = percent;\n                            }\n                        },\n                    });\n                    const payload = response && response.data ? response.data : {};\n                    const uploadError = this.getUploadPayloadErrorMessage(payload);\n                    if (uploadError) {\n                        throw new Error(uploadError);\n                    }\n                    const filename = payload.filename || payload.file_name || (payload.data && payload.data.filename) || '';\n                    if (!filename) {\n                        throw new Error('Upload response missing filename');\n                    }\n                    if (this.uploadedTicketFiles[i]) {\n                        this.uploadedTicketFiles[i].status = 'success';\n                        this.uploadedTicketFiles[i].percent = 100;\n                        this.uploadedTicketFiles[i].ggs = filename;\n                    }\n                } catch (error) {\n                    console.error('Ticket file upload failed:', error);\n                    if (this.uploadedTicketFiles[i]) {\n                        this.uploadedTicketFiles[i].status = 'fail';\n                    }\n                    this.notifyError(this.getApiErrorMessage(error, 'File upload failed'));\n                }\n            }\n        },\n        removeTicketFile(index) {\n            this.uploadedTicketFiles.splice(index, 1);\n        },\n        async handleAddTicketFile(event) {\n            const files = event.target.files;\n            if (!files || files.length === 0) return;\n            const ticketId = this.selectTicketDetail && this.selectTicketDetail.id;\n            if (!ticketId) {\n                this.notifyError('Ticket detail is not ready');\n                return;\n            }\n            for (let i = 0; i < files.length; i += 1) {\n                const file = files[i];\n                if (!file) continue;\n                try {\n                    const formData = new FormData();\n                    formData.append('file', file);\n                    formData.append('index', i);\n                    formData.append('fileType', file.type || '');\n                    formData.append('fileName', file.name || '');\n                    const response = await this.apiPost(this.api.claimUpload, formData, {\n                        headers: {\n                            'Content-Type': 'multipart\/form-data',\n                        },\n                    });\n                    const payload = response && response.data ? response.data : {};\n                    const uploadError = this.getUploadPayloadErrorMessage(payload);\n                    if (uploadError) {\n                        throw new Error(uploadError);\n                    }\n                    const filename = payload.filename || payload.file_name || (payload.data && payload.data.filename) || '';\n                    if (!filename) throw new Error('Upload response missing filename');\n                    await this.apiPost(this.api.updateTicket, {\n                        ticket_id: ticketId,\n                        file_name: filename,\n                        file_list: this.getTicketFileList(this.selectTicketDetail),\n                    });\n                } catch (error) {\n                    console.error('Upload ticket file failed:', error);\n                    this.notifyError(this.getApiErrorMessage(error, 'Failed to upload files'));\n                    if (event && event.target) event.target.value = '';\n                    return;\n                }\n            }\n            if (event && event.target) event.target.value = '';\n            this.notifySuccess('Files uploaded successfully!');\n            await this.getTicketDetails(ticketId);\n        },\n        async refreshTicketUnreadFromUserInfo() {\n            try {\n                const response = await this.apiGet(this.api.userInfo);\n                const user = this.getPayloadData(response) || {};\n                if (user && typeof user === 'object') {\n                    this.userInfo = {\n                        ...(this.userInfo || {}),\n                        is_ticket: user.is_ticket || 0,\n                    };\n                }\n            } catch (error) {\n                console.error('Refresh ticket unread status failed:', error);\n            }\n        },\n        async addTicket() {\n            if (!String(this.selectedParentId || '').trim()) {\n                this.notifyError('Please select category');\n                return;\n            }\n            if (!String(this.selectedSubId || '').trim()) {\n                this.notifyError('Please select subcategory');\n                return;\n            }\n            if (!this.ticketSubject.trim()) {\n                this.notifyError('Please enter ticket subject');\n                return;\n            }\n            if (!this.ticketDescription.trim()) {\n                this.notifyError('Please enter ticket description');\n                return;\n            }\n            if (!this.normalizeBooleanLike(this.ticketConfirm)) {\n                this.notifyError('Please confirm support follow-up agreement');\n                return;\n            }\n            const user = this.userInfo || {};\n            const isUsa = this.dashboardRegion !== 'au';\n            const usaOrder = user.usa_order || {};\n            const auOrder = user.au_order || {};\n            const files = this.uploadedTicketFiles\n                .filter(file => file && file.status === 'success' && file.ggs)\n                .map(file => file.ggs);\n            try {\n                const response = await this.apiPost(this.api.addTickets, {\n                    type: isUsa ? 1 : 2,\n                    file_list: files,\n                    student_id: user.id,\n                    member_id: isUsa ? (usaOrder.member_id || '') : '',\n                    school_name: isUsa && Array.isArray(usaOrder.members) && usaOrder.members[0]?.contacts?.[2]\n                        ? usaOrder.members[0].contacts[2].value\n                        : (usaOrder.school_name || ''),\n                    plan_name: isUsa ? (usaOrder.planName || usaOrder.plan_name || '') : (auOrder.destination_name || ''),\n                    content: this.ticketDescription.trim(),\n                    subject: this.ticketSubject.trim(),\n                    category_id: this.selectedSubId,\n                });\n                if (response && response.data && (response.data.success || response.data.status === 200)) {\n                    const payload = this.getPayloadData(response) || {};\n                    this.ticketId = payload.ticket_no || payload.id || '';\n                    this.ticketSuccess = true;\n                    this.notifySuccess('Submit success');\n                    this.ticketSubject = '';\n                    this.ticketDescription = '';\n                    this.selectedParentId = '';\n                    this.selectedSubId = '';\n                    this.ticketConfirm = false;\n                    this.uploadedTicketFiles = [];\n                    await this.fetchTicketList();\n                } else {\n                    this.notifyError('Error, please try again later');\n                }\n            } catch (error) {\n                console.error('Add ticket failed:', error);\n                this.notifyError('Network error, please try again later');\n            }\n        },\n        async TicketPageChange(page) {\n            this.tk_currentPage = page;\n            await this.fetchTicketList();\n        },\n        openChangePasswordModal() {\n            this.changePwdForm.oldPassword = '';\n            this.changePwdForm.newPassword = '';\n            this.changePwdForm.confirmPassword = '';\n            this.changePwdSubmitting = false;\n            this.openModal = 'changePassword';\n        },\n        openForgetPassword() {\n            this.openInNewTab('https:\/\/www.goglobalsafe.com\/forget-password\/');\n        },\n        async submitChangePassword() {\n            const oldPassword = String(this.changePwdForm.oldPassword || '').trim();\n            const newPassword = String(this.changePwdForm.newPassword || '').trim();\n            const confirmPassword = String(this.changePwdForm.confirmPassword || '').trim();\n            const chineseRegex = \/[\\u4e00-\\u9fa5]\/;\n\n            if (!oldPassword) {\n                this.notifyError('Please enter old password.');\n                return;\n            }\n            if (newPassword.length <= 6) {\n                this.notifyError('Password cannot be less than 6 characters.');\n                return;\n            }\n            if (chineseRegex.test(newPassword)) {\n                this.notifyError('Password cannot contain Chinese characters.');\n                return;\n            }\n            if (newPassword !== confirmPassword) {\n                this.notifyError('The password you entered is inconsistent.');\n                return;\n            }\n\n            const user = this.userInfo || {};\n            this.changePwdSubmitting = true;\n            this.beginGlobalLoading('Updating your password...', 'Submitting');\n            try {\n                const response = await this.apiPost(this.api.resetPasswordOld, {\n                    email: String(user.email || '').trim(),\n                    old_password: oldPassword,\n                    new_password: newPassword,\n                    new_password_confirmation: confirmPassword,\n                });\n                const payload = response && response.data ? response.data : {};\n                if (response && response.status === 200 && (payload.success || payload.status === 200 || payload.code === 200 || !payload.status)) {\n                    this.notifySuccess('Change success');\n                    this.openModal = '';\n                    window.setTimeout(() => {\n                        localStorage.removeItem('student_token');\n                        localStorage.removeItem('user_info');\n                        \/\/ window.location.href = '\/student-login\/';\n                    }, 900);\n                } else {\n                    this.notifyError(String(payload.message || 'Failed to change password.'));\n                }\n            } catch (error) {\n                console.error('Change password failed:', error);\n                this.notifyError(this.getApiErrorMessage(error, 'Failed to change password.'));\n            } finally {\n                this.changePwdSubmitting = false;\n                this.endGlobalLoading();\n            }\n        },\n    },\n    mounted() {\n        const pathName = String((window.location && window.location.pathname) || '').toLowerCase();\n        this.locale = pathName.includes('\/zh\/student-users\/') ? 'zh' : 'en';\n        this.initRenewTrackState();\n        this.updateHeaderOffset();\n        this.fetchDashboardUserInfo();\n        window.addEventListener('resize', this.updateHeaderOffset);\n        window.addEventListener('orientationchange', this.updateHeaderOffset);\n        document.addEventListener('click', this.handleDocumentClick);\n    },\n    beforeUnmount() {\n        this.clearRenewPopupRecheckTimer();\n        this.clearOshcEmailRedirectTimer();\n        this.clearGlobalLoadingTimers();\n        if (this.dashboardBackgroundPreloadTimer) {\n            window.clearTimeout(this.dashboardBackgroundPreloadTimer);\n            this.dashboardBackgroundPreloadTimer = null;\n        }\n        if (this.onboardingGuideTimer) {\n            window.clearTimeout(this.onboardingGuideTimer);\n            this.onboardingGuideTimer = null;\n        }\n        this.globalLoadingVisible = false;\n        this.globalLoadingCount = 0;\n        window.removeEventListener('resize', this.updateHeaderOffset);\n        window.removeEventListener('orientationchange', this.updateHeaderOffset);\n        document.removeEventListener('click', this.handleDocumentClick);\n    },\n}).mount('#uc-app');\n<\/script>\n<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"page-builder","ast-global-header-display":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","footnotes":""},"class_list":["post-31237","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v22.6 (Yoast SEO v26.4) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Account | GoGlobalsafe-\u7559\u5b66\u751f\u4fdd\u9669\u4e00\u7ad9\u5f0f\u89e3\u51b3\u65b9\u6848<\/title>\n<meta name=\"description\" content=\"User accounts allow these entities to log in, set preferences, and access resources based on their account permissions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.goglobalsafe.com\/zh\/student-users\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Account\" \/>\n<meta property=\"og:description\" content=\"User accounts allow these entities to log in, set preferences, and access resources based on their account permissions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.goglobalsafe.com\/zh\/student-users\/\" \/>\n<meta property=\"og:site_name\" content=\"GoGlobalsafe-\u7559\u5b66\u751f\u4fdd\u9669\u4e00\u7ad9\u5f0f\u89e3\u51b3\u65b9\u6848\" \/>\n<meta property=\"article:modified_time\" content=\"2026-05-27T05:40:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/04\/LOGO1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1000\" \/>\n\t<meta property=\"og:image:height\" content=\"1000\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.goglobalsafe.com\/student-users\/\",\"url\":\"https:\/\/www.goglobalsafe.com\/student-users\/\",\"name\":\"Account | GoGlobalsafe-\u7559\u5b66\u751f\u4fdd\u9669\u4e00\u7ad9\u5f0f\u89e3\u51b3\u65b9\u6848\",\"isPartOf\":{\"@id\":\"https:\/\/www.goglobalsafe.com\/#website\"},\"datePublished\":\"2024-07-03T07:06:32+00:00\",\"dateModified\":\"2026-05-27T05:40:25+00:00\",\"description\":\"User accounts allow these entities to log in, set preferences, and access resources based on their account permissions.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.goglobalsafe.com\/student-users\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.goglobalsafe.com\/student-users\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.goglobalsafe.com\/student-users\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.goglobalsafe.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Account\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.goglobalsafe.com\/#website\",\"url\":\"https:\/\/www.goglobalsafe.com\/\",\"name\":\"GoGlobalSafe Student Insurance\",\"description\":\"Your Health, Our Priority\",\"publisher\":{\"@id\":\"https:\/\/www.goglobalsafe.com\/#organization\"},\"alternateName\":\"GoGlobalSafe international student insurance\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.goglobalsafe.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.goglobalsafe.com\/#organization\",\"name\":\"Golobal student consulting limited\",\"alternateName\":\"GoGlobalSafe\",\"url\":\"https:\/\/www.goglobalsafe.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.goglobalsafe.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/04\/LOGO3.png\",\"contentUrl\":\"https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/04\/LOGO3.png\",\"width\":500,\"height\":140,\"caption\":\"Golobal student consulting limited\"},\"image\":{\"@id\":\"https:\/\/www.goglobalsafe.com\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"\u8d26\u6237 | GoGlobalsafe-\u5546\u52a1\u5546\u52a1\u4e00\u7ad9\u5f0f\u89e3\u51b3\u65b9\u6848","description":"User accounts allow these entities to log in, set preferences, and access resources based on their account permissions.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.goglobalsafe.com\/zh\/student-users\/","og_locale":"zh_CN","og_type":"article","og_title":"Account","og_description":"User accounts allow these entities to log in, set preferences, and access resources based on their account permissions.","og_url":"https:\/\/www.goglobalsafe.com\/zh\/student-users\/","og_site_name":"GoGlobalsafe-\u7559\u5b66\u751f\u4fdd\u9669\u4e00\u7ad9\u5f0f\u89e3\u51b3\u65b9\u6848","article_modified_time":"2026-05-27T05:40:25+00:00","og_image":[{"width":1000,"height":1000,"url":"https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/04\/LOGO1.png","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.goglobalsafe.com\/student-users\/","url":"https:\/\/www.goglobalsafe.com\/student-users\/","name":"\u8d26\u6237 | GoGlobalsafe-\u5546\u52a1\u5546\u52a1\u4e00\u7ad9\u5f0f\u89e3\u51b3\u65b9\u6848","isPartOf":{"@id":"https:\/\/www.goglobalsafe.com\/#website"},"datePublished":"2024-07-03T07:06:32+00:00","dateModified":"2026-05-27T05:40:25+00:00","description":"User accounts allow these entities to log in, set preferences, and access resources based on their account permissions.","breadcrumb":{"@id":"https:\/\/www.goglobalsafe.com\/student-users\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.goglobalsafe.com\/student-users\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.goglobalsafe.com\/student-users\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.goglobalsafe.com\/"},{"@type":"ListItem","position":2,"name":"Account"}]},{"@type":"WebSite","@id":"https:\/\/www.goglobalsafe.com\/#website","url":"https:\/\/www.goglobalsafe.com\/","name":"GoGlobalSafe \u5b66\u751f\u4fdd\u9669","description":"\u60a8\u7684\u5065\u5eb7\uff0c\u6211\u4eec\u7684\u9996\u8981\u4efb\u52a1","publisher":{"@id":"https:\/\/www.goglobalsafe.com\/#organization"},"alternateName":"GoGlobalSafe international student insurance","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.goglobalsafe.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"zh-Hans"},{"@type":"Organization","@id":"https:\/\/www.goglobalsafe.com\/#organization","name":"\u73af\u7403\u5b66\u751f\u54a8\u8be2\u6709\u9650\u516c\u53f8","alternateName":"GoGlobalSafe","url":"https:\/\/www.goglobalsafe.com\/","logo":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.goglobalsafe.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/04\/LOGO3.png","contentUrl":"https:\/\/www.goglobalsafe.com\/wp-content\/uploads\/2023\/04\/LOGO3.png","width":500,"height":140,"caption":"Golobal student consulting limited"},"image":{"@id":"https:\/\/www.goglobalsafe.com\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/pages\/31237","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/comments?post=31237"}],"version-history":[{"count":25,"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/pages\/31237\/revisions"}],"predecessor-version":[{"id":37926,"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/pages\/31237\/revisions\/37926"}],"wp:attachment":[{"href":"https:\/\/www.goglobalsafe.com\/zh\/wp-json\/wp\/v2\/media?parent=31237"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}