<?php
/**
 * Customer Account Template — platform-agnostic (WordPress + standalone).
 *
 * Auth section:
 *   WP         -> inline AJAX login/register tabs (wp_ajax_nopriv endpoints)
 *   Standalone -> redirect to /login (admin-ajax requires auth on standalone)
 *
 * Logged-in section:
 *   DB queries  -> DB:: (never global $wpdb)
 *   Auth checks -> Auth:: (never is_user_logged_in() / wp_get_current_user() raw)
 *   Password    -> per-platform (WP functions / bcrypt on standalone)
 *
 * Fixes: Bug G (missing shims), Bug H ($wpdb -> DB::), Bug I (user field mismatch),
 *        Bug J (inline WP registration bypassing UserService),
 *        Bug K (AJAX endpoints wired to login/register tabs).
 *
 * @since 3.22.26
 */

use Instinctor\Core\Auth;
use Instinctor\Core\DB;
use Instinctor\Core\Session;
use Instinctor\Core\StoreFeatures;
use Instinctor\Services\CheckoutConfig;

if (!defined('ABSPATH')) { exit; }

// == Environment & feature flags ==============================================

$isWP         = !defined('INSTINCTOR_ENV') || INSTINCTOR_ENV === 'wordpress';
$has_physical = StoreFeatures::hasPhysicalProducts();
$has_digital  = StoreFeatures::hasDigitalProducts();
$has_services = StoreFeatures::hasServices();

// == Standalone: redirect to /login if not authenticated =====================

if (!$isWP && (!Auth::check() || !empty($GLOBALS['impulse_preview_loggedout']))) {
    $base      = defined('INSTINCTOR_STANDALONE_URL') ? rtrim(INSTINCTOR_STANDALONE_URL, '/') : '';
    $reqUri    = sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'] ?? '/'));
    $returnUrl = $base . strtok($reqUri, '?');
    // Redirect to the site's login page ONLY when one actually exists -
    // the unconditional redirect 404'd on every site whose designer never
    // created a /login page (logged-out visitors tapping the header's
    // account icon hit it; looked device-specific because the owner's
    // desktop carries the admin session). Without a login page, render
    // the Login block inline right here so /account always works
    // out of the box. v2.1.1430.
    $_loginPage = class_exists('\Instinctor\Services\PageService')
        ? \Instinctor\Services\PageService::getBySlug('login')
        : null;
    if ($_loginPage && ($_loginPage['status'] ?? '') === 'published') {
        header('Location: ' . $base . '/login?redirect_to=' . urlencode($returnUrl), true, 302);
        exit;
    }
    if (function_exists('impulse_element_render_login')) {
        $_welcome = sanitize_text_field(wp_unslash($_GET['welcome'] ?? ''));
        echo '<div class="impulse-account-inline-login" style="min-height:60vh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:96px 20px 60px">';
        if ($_welcome === 'setpw' || $_welcome === 'active') {
            echo '<div style="background:#e8f5e9;border:1px solid #c8e6c9;color:#2e7d32;border-radius:8px;padding:14px 16px;margin-bottom:20px;max-width:420px;font-size:14px;line-height:1.5;text-align:center">'
                . '<strong>' . esc_html__('Payment received. Your membership is active.', 'instinctor') . '</strong><br>'
                . esc_html($_welcome === 'setpw'
                    ? __('Check your email to set your password, then log in below.', 'instinctor')
                    : __('Log in below to manage your membership.', 'instinctor'))
                . '</div>';
        }
        $_loginAllowed = function_exists('impulse_svg_allowed') ? impulse_svg_allowed() : ['div' => [], 'span' => [], 'a' => ['href' => true, 'target' => true, 'rel' => true], 'img' => ['src' => true, 'alt' => true, 'loading' => true]];
        $_loginFormAttr = ['id' => true, 'class' => true, 'style' => true, 'name' => true, 'value' => true, 'placeholder' => true, 'autocomplete' => true, 'tabindex' => true, 'required' => true, 'minlength' => true, 'aria-hidden' => true, 'checked' => true, 'action' => true, 'method' => true, 'data-redirect' => true, 'inputmode' => true, 'disabled' => true];
        foreach (['form', 'input', 'button', 'label'] as $_ft) { $_loginAllowed[$_ft] = $_loginFormAttr; }
        echo wp_kses(impulse_element_render_login(['id' => 0], ['redirect_to' => $returnUrl], 'frontend'), $_loginAllowed);
        echo '</div>';
        return;
    }
    // Renderer unavailable (should not happen) - fall back to home.
    header('Location: ' . $base . '/', true, 302);
    exit;
}

// == Standalone: handle inline logout via GET =================================

// Logout clears the plugin's OWN customer session (instinctor_auth) on
// WordPress and standalone alike (Option A, 2026-07-05). It never calls
// wp_logout, so a WP admin who is also browsing the store is not logged out
// of wp-admin — customers and the WP site's users are fully separate.
if (isset($_GET['logout'])) {
    if (wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_nonce'] ?? '')), 'instinctor_account_logout')) {
        setcookie('instinctor_auth', '', [
            'expires'  => time() - 3600,
            'path'     => '/',
            'secure'   => is_ssl(),
            'httponly' => true,
            'samesite' => 'Lax',
        ]);
    }
    // Reload the same page logged-out. On WP that's the current account page
    // (its slug is arbitrary); on standalone it's /account.
    if ($isWP) {
        $_lo = remove_query_arg(['logout', '_nonce']);
        wp_safe_redirect($_lo ?: home_url('/'));
    } else {
        $base = defined('INSTINCTOR_STANDALONE_URL') ? rtrim(INSTINCTOR_STANDALONE_URL, '/') : '';
        header('Location: ' . $base . '/account', true, 302);
    }
    exit;
}

// == CheckoutConfig ===========================================================

$config       = CheckoutConfig::get();
$allow_reg    = $config['create_account_option'] ?? true;
$showRegister = $allow_reg && ($isWP ? (bool) get_option('users_can_register') : true);

// == WP: AJAX auth panel if not logged in, then stop =========================

if ($isWP && (!Auth::check() || !empty($GLOBALS['impulse_preview_loggedout']))) {
    $frontendNonce = Session::token('instinctor_frontend');
    $lostPassUrl   = esc_url(\Instinctor\Core\UserService::lostPasswordUrl());
?>
<?php
$_authId = 'ia-auth-' . substr(md5(uniqid()), 0, 8);
// Inject scoped CSS into <head> — runs before theme styles complete, 
// and the #id specificity beats generic theme selectors
?>
<style id="<?php echo esc_attr($_authId); ?>-css">
#<?php echo esc_attr($_authId); ?>{max-width:400px;margin:40px auto;background:#fff;border:1px solid #e8e8ed;border-radius:6px;overflow:hidden;font-size:14px!important;line-height:1.5!important;color:#1d1d1f!important;box-sizing:border-box;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif!important}
#<?php echo esc_attr($_authId); ?> *{box-sizing:border-box}
#<?php echo esc_attr($_authId); ?> p{margin:0!important;padding:0!important;font-size:inherit!important;line-height:inherit!important}
#<?php echo esc_attr($_authId); ?> a{text-decoration:none!important}
/* Tabs */
#<?php echo esc_attr($_authId); ?> .ia-tabs{display:flex!important;margin:0!important;padding:0!important;border-bottom:1px solid #e8e8ed!important;list-style:none!important}
#<?php echo esc_attr($_authId); ?> .ia-tab{all:unset;flex:1!important;display:block!important;padding:13px!important;background:#f5f5f7!important;cursor:pointer!important;font-size:13px!important;font-weight:500!important;text-align:center!important;color:#1d1d1f!important;border-right:1px solid #e8e8ed!important;border-bottom:none!important;border-top:none!important;border-left:none!important;line-height:1.4!important}
#<?php echo esc_attr($_authId); ?> .ia-tab:last-child{border-right:none!important}
#<?php echo esc_attr($_authId); ?> .ia-tab.active{background:#fff!important;font-weight:600!important}
/* Panels */
#<?php echo esc_attr($_authId); ?> .ia-panel{display:none!important;padding:24px!important}
#<?php echo esc_attr($_authId); ?> .ia-panel.active{display:block!important}
#<?php echo esc_attr($_authId); ?> .ia-row{margin-bottom:14px!important}
#<?php echo esc_attr($_authId); ?> label{display:block!important;font-size:12px!important;font-weight:500!important;margin-bottom:5px!important;color:#1d1d1f!important;line-height:1.4!important}
#<?php echo esc_attr($_authId); ?> input[type=email],
#<?php echo esc_attr($_authId); ?> input[type=password],
#<?php echo esc_attr($_authId); ?> input[type=text]{display:block!important;width:100%!important;padding:9px 10px!important;border:1px solid #d2d2d7!important;border-radius:6px!important;font-size:13px!important;background:#fff!important;color:#1d1d1f!important;line-height:1.4!important;box-shadow:none!important;-webkit-appearance:none!important;appearance:none!important;margin:0!important}
#<?php echo esc_attr($_authId); ?> input[type=checkbox]{width:auto!important;height:auto!important;display:inline-block!important;margin:0!important}
#<?php echo esc_attr($_authId); ?> input:focus{outline:none!important;border-color:#1d1d1f!important;box-shadow:none!important}
/* Buttons */
#<?php echo esc_attr($_authId); ?> .ia-btn{all:unset;display:block!important;width:100%!important;padding:11px 20px!important;margin:0!important;background:var(--impulse-btn-bg,#1d1d1f)!important;color:var(--impulse-btn-color,#fff)!important;border:none!important;border-radius:6px!important;font-size:13px!important;font-weight:600!important;cursor:pointer!important;text-align:center!important;line-height:1.4!important;box-sizing:border-box!important}
#<?php echo esc_attr($_authId); ?> .ia-btn:hover{opacity:.85!important}
/* Error */
#<?php echo esc_attr($_authId); ?> .ia-error{background:#fee!important;color:#c00!important;padding:10px 12px!important;border-radius:6px!important;margin-bottom:14px!important;font-size:13px!important;display:none}
#<?php echo esc_attr($_authId); ?> .ia-error.show{display:block!important}
/* Forgot link */
#<?php echo esc_attr($_authId); ?> .ia-forgot{display:block!important;text-align:center!important;margin-top:14px!important;font-size:12px!important;color:#888!important;text-decoration:none!important;line-height:1.4!important}
#<?php echo esc_attr($_authId); ?> .ia-forgot:hover{color:#1d1d1f!important}
/* Row half */
#<?php echo esc_attr($_authId); ?> .ia-half{display:grid!important;grid-template-columns:1fr 1fr!important;gap:12px!important;margin-bottom:14px!important}
#<?php echo esc_attr($_authId); ?> .ia-hint{font-size:11px!important;color:#888!important;margin:3px 0 0!important}
#<?php echo esc_attr($_authId); ?> .ia-required{color:#c00!important}
#<?php echo esc_attr($_authId); ?> .ia-remember{display:flex!important;align-items:center!important;gap:8px!important}
#<?php echo esc_attr($_authId); ?> .ia-remember label{margin:0!important;font-size:12px!important;opacity:.7!important;cursor:pointer!important}
</style>
<div id="<?php echo esc_attr($_authId); ?>" class="instinctor-account-auth">
    <div class="ia-tabs instinctor-auth-tabs">
        <button type="button" class="ia-tab instinctor-auth-tab active" data-tab="login"><?php esc_html_e('Login', 'instinctor'); ?></button>
        <?php if ($showRegister): ?>
        <button type="button" class="ia-tab instinctor-auth-tab" data-tab="register"><?php esc_html_e('Register', 'instinctor'); ?></button>
        <?php endif; ?>
    </div>

    <div class="ia-panel instinctor-auth-panel active" id="instinctor-login-panel">
        <div class="ia-error instinctor-auth-error" id="instinctor-login-error"></div>
        <div class="ia-row">
            <label><?php esc_html_e('Email', 'instinctor'); ?> <span class="ia-required">*</span></label>
            <input type="email" id="instinctor-login-email" autocomplete="email" autofocus>
        </div>
        <div class="ia-row">
            <label><?php esc_html_e('Password', 'instinctor'); ?> <span class="ia-required">*</span></label>
            <input type="password" id="instinctor-login-password" autocomplete="current-password">
        </div>
        <div class="ia-row ia-remember">
            <input type="checkbox" id="instinctor-login-remember">
            <label for="instinctor-login-remember"><?php esc_html_e('Remember me', 'instinctor'); ?></label>
        </div>
        <button type="button" class="ia-btn instinctor-btn" id="instinctor-login-btn"><?php esc_html_e('Log in', 'instinctor'); ?></button>
        <div id="ia-forgot-wrap" style="margin-top:14px">
            <a href="#" class="ia-forgot" id="ia-forgot-toggle"><?php esc_html_e('Forgot password?', 'instinctor'); ?></a>
            <div id="ia-forgot-form" style="display:none;margin-top:10px">
                <div class="ia-row">
                    <label><?php esc_html_e('Email address', 'instinctor'); ?></label>
                    <input type="email" id="ia-forgot-email" autocomplete="email">
                </div>
                <div class="ia-error" id="ia-forgot-error"></div>
                <button type="button" class="ia-btn" id="ia-forgot-submit"><?php esc_html_e('Send reset link', 'instinctor'); ?></button>
                <p id="ia-forgot-sent" style="display:none;font-size:12px;color:#2e7d32;margin-top:8px"><?php esc_html_e('Check your email, a reset link is on its way.', 'instinctor'); ?></p>
            </div>
        </div>
    </div>

    <?php if ($showRegister): ?>
    <div class="ia-panel instinctor-auth-panel" id="instinctor-register-panel">
        <div class="ia-error instinctor-auth-error" id="instinctor-register-error"></div>
        <div class="ia-half">
            <div><label><?php esc_html_e('First Name', 'instinctor'); ?></label><input type="text" id="instinctor-reg-first" autocomplete="given-name"></div>
            <div><label><?php esc_html_e('Last Name', 'instinctor'); ?></label><input type="text" id="instinctor-reg-last" autocomplete="family-name"></div>
        </div>
        <div class="ia-row">
            <label><?php esc_html_e('Email', 'instinctor'); ?> <span class="ia-required">*</span></label>
            <input type="email" id="instinctor-reg-email" required autocomplete="email">
        </div>
        <div class="ia-row">
            <label><?php esc_html_e('Password', 'instinctor'); ?> <span class="ia-required">*</span></label>
            <input type="password" id="instinctor-reg-password" required minlength="8" autocomplete="new-password">
            <p class="instinctor-form-hint"><?php esc_html_e('Minimum 8 characters', 'instinctor'); ?></p>
        </div>
        <button type="button" class="instinctor-register-btn" id="instinctor-register-btn"><?php esc_html_e('Create Account', 'instinctor'); ?></button>
    </div>
    <?php endif; ?>
</div>
<?php
// Auth tab + login/register behavior — attached to the frontend bundle via
// wp_add_inline_script() so it ships through the enqueue system (WP.org rule).
\Instinctor\Core\Assets::enqueue('instinctor-frontend-js');
ob_start();
?>
(function () {
    document.querySelectorAll('.instinctor-auth-tab').forEach(function (tab) {
        tab.addEventListener('click', function () {
            document.querySelectorAll('.ia-tab').forEach(function (t) { t.classList.remove('active'); });
            document.querySelectorAll('.ia-panel').forEach(function (p) { p.classList.remove('active'); });
            this.classList.add('active');
            var panel = document.getElementById('instinctor-' + this.dataset.tab + '-panel');
            if (panel) panel.classList.add('active');
        });
    });

    var ajaxUrl = (typeof instinctorFrontend !== 'undefined') ? instinctorFrontend.ajaxUrl : '/wp-admin/admin-ajax.php';
    var nonce   = '<?php echo esc_js($frontendNonce); ?>';

    function showErr(id, msg) { var el = document.getElementById(id); if (el) { el.textContent = msg; el.style.display = 'block'; } }
    function hideErr(id)      { var el = document.getElementById(id); if (el) el.style.display = 'none'; }

    function postAjax(data, onOk, onErr) {
        var fd = new FormData();
        Object.keys(data).forEach(function (k) { fd.append(k, data[k]); });
        fetch(ajaxUrl, { method: 'POST', body: fd })
            .then(function (r) { return r.json(); })
            .then(function (res) {
                if (res.success) { onOk(res.data); }
                else { onErr((res.data && res.data.message) ? res.data.message : '<?php echo esc_js(__('An error occurred.', 'instinctor')); ?>'); }
            })
            .catch(function () { onErr('<?php echo esc_js(__('Network error. Please try again.', 'instinctor')); ?>'); });
    }

    var loginBtn = document.getElementById('instinctor-login-btn');
    if (loginBtn) {
        loginBtn.addEventListener('click', function () {
            hideErr('instinctor-login-error');
            var email    = document.getElementById('instinctor-login-email').value.trim();
            var password = document.getElementById('instinctor-login-password').value;
            var remember = document.getElementById('instinctor-login-remember').checked ? '1' : '';
            if (!email || !password) { showErr('instinctor-login-error', '<?php echo esc_js(__('Please fill in all fields.', 'instinctor')); ?>'); return; }
            loginBtn.disabled = true; loginBtn.textContent = '<?php echo esc_js(__('Logging in\u2026', 'instinctor')); ?>';
            postAjax({ action: 'instinctor_ajax_login', username: email, password: password, remember: remember, nonce: nonce },
                function (d) { window.location.href = d.redirect || window.location.href; },
                function (m) { showErr('instinctor-login-error', m); loginBtn.disabled = false; loginBtn.textContent = '<?php echo esc_js(__('Log in', 'instinctor')); ?>'; }
            );
        });
    }

    // Forgot password, inline expand
    var forgotToggle = document.getElementById('ia-forgot-toggle');
    var forgotForm   = document.getElementById('ia-forgot-form');
    var forgotSubmit = document.getElementById('ia-forgot-submit');
    var forgotSent   = document.getElementById('ia-forgot-sent');
    if (forgotToggle && forgotForm) {
        forgotToggle.addEventListener('click', function(e) {
            e.preventDefault();
            forgotForm.style.display = forgotForm.style.display === 'none' ? 'block' : 'none';
            if (forgotForm.style.display !== 'none') {
                var inp = document.getElementById('ia-forgot-email'); if (inp) inp.focus();
            }
        });
    }
    if (forgotSubmit) {
        forgotSubmit.addEventListener('click', function() {
            var emailEl = document.getElementById('ia-forgot-email');
            var errEl   = document.getElementById('ia-forgot-error');
            var email   = emailEl ? emailEl.value.trim() : '';
            if (!email) { if(errEl){errEl.textContent='<?php echo esc_js(__("Please enter your email.", "instinctor")); ?>';errEl.classList.add('show');} return; }
            if(errEl){errEl.textContent='';errEl.classList.remove('show');}
            forgotSubmit.disabled = true; forgotSubmit.textContent = '<?php echo esc_js(__("Sending…", "instinctor")); ?>';
            postAjax({ action: 'instinctor_forgot_password', email: email, nonce: nonce },
                function() {
                    if(forgotSent) forgotSent.style.display='block';
                    forgotSubmit.style.display='none';
                    if(emailEl) emailEl.parentElement.style.display='none';
                },
                function(m) {
                    if(errEl){errEl.textContent=m||'<?php echo esc_js(__("Failed. Please try again.", "instinctor")); ?>';errEl.classList.add('show');}
                    forgotSubmit.disabled=false; forgotSubmit.textContent='<?php echo esc_js(__("Send reset link", "instinctor")); ?>';
                }
            );
        });
    }

    var regBtn = document.getElementById('instinctor-register-btn');
    if (regBtn) {
        regBtn.addEventListener('click', function () {
            hideErr('instinctor-register-error');
            var email    = document.getElementById('instinctor-reg-email').value.trim();
            var password = document.getElementById('instinctor-reg-password').value;
            var first    = document.getElementById('instinctor-reg-first').value.trim();
            var last     = document.getElementById('instinctor-reg-last').value.trim();
            if (!email || !password) { showErr('instinctor-register-error', '<?php echo esc_js(__('Email and password are required.', 'instinctor')); ?>'); return; }
            regBtn.disabled = true; regBtn.textContent = '<?php echo esc_js(__('Creating account\u2026', 'instinctor')); ?>';
            postAjax({ action: 'instinctor_ajax_register', email: email, password: password, first_name: first, last_name: last, nonce: nonce },
                function (d) { window.location.href = d.redirect || window.location.href; },
                function (m) { showErr('instinctor-register-error', m); regBtn.disabled = false; regBtn.textContent = '<?php echo esc_js(__('Create Account', 'instinctor')); ?>'; }
            );
        });
    }
}());
<?php
$_accountInlineJs = ob_get_clean();
if (function_exists('wp_add_inline_script')) {
    wp_add_inline_script('instinctor-frontend-js', $_accountInlineJs);
} else {
    // Standalone fallback (unreachable in practice: wp_add_inline_script is shimmed).
    // $_accountInlineJs buffer uses json_encode/esc_js/intval only. wp_print_inline_script_tag
    // is a printing function (its output is escaped internally, not flagged by EscapeOutput).
    // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript -- inline script for the auth panel; ships via enqueue on every real environment.
    wp_print_inline_script_tag($_accountInlineJs);
}
    return;
}

// =============================================================================
// AUTHENTICATED — only reached when user is logged in
// =============================================================================

$userId   = Auth::userId();
$authUser = Auth::user();

$custTable   = DB::prefix() . 'instinctor_customers';
$ordTable    = DB::prefix() . 'instinctor_orders';
$itemsTable  = DB::prefix() . 'instinctor_order_items';
$dlPermTable = DB::prefix() . 'instinctor_download_permissions';
$dlFileTable = DB::prefix() . 'instinctor_downloads';
$bookTable   = DB::prefix() . 'instinctor_bookings';
$prodTable   = DB::prefix() . 'instinctor_products';
$usersTable  = DB::prefix() . 'instinctor_users';

$message = '';

// -- Address save -------------------------------------------------------------
if (
    (sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'] ?? ''))) === 'POST' &&
    isset($_POST['instinctor_account_nonce']) &&
    wp_verify_nonce(sanitize_text_field(wp_unslash((string)($_POST['instinctor_account_nonce'] ?? ''))), 'instinctor_save_account')
) {
    $existing = DB::get_row(DB::prepare("SELECT * FROM `{$custTable}` WHERE user_id = %d LIMIT 1", $userId));
    if ($existing) {
        $nb = array_map('sanitize_text_field', [
            'first_name' => sanitize_text_field(wp_unslash($_POST['billing_first_name'] ?? '')),
            'last_name'  => sanitize_text_field(wp_unslash($_POST['billing_last_name'] ?? '')),
            'address_1'  => sanitize_text_field(wp_unslash($_POST['billing_address_1'] ?? '')),
            'city'       => sanitize_text_field(wp_unslash($_POST['billing_city'] ?? '')),
            'state'      => sanitize_text_field(wp_unslash($_POST['billing_state'] ?? '')),
            'postcode'   => sanitize_text_field(wp_unslash($_POST['billing_postcode'] ?? '')),
            'country'    => sanitize_text_field(wp_unslash($_POST['billing_country'] ?? '')),
            'email'      => $existing->email,
            'phone'      => $existing->phone ?? '',
        ]);
        DB::update($custTable, [
            'first_name'      => $nb['first_name'],
            'last_name'       => $nb['last_name'],
            'billing_address' => wp_json_encode($nb),
        ], ['id' => $existing->id]);
    }
    $message = __('Address saved.', 'instinctor');
}

// -- Details save -------------------------------------------------------------
if (
    (sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'] ?? ''))) === 'POST' &&
    isset($_POST['instinctor_details_nonce']) &&
    wp_verify_nonce(sanitize_text_field(wp_unslash((string)($_POST['instinctor_details_nonce'] ?? ''))), 'instinctor_save_details')
) {
    $nf = sanitize_text_field(wp_unslash($_POST['details_first_name'] ?? ''));
    $nl = sanitize_text_field(wp_unslash($_POST['details_last_name']  ?? ''));
    $np = sanitize_text_field(wp_unslash($_POST['details_phone']       ?? ''));

    $existing = DB::get_row(DB::prepare("SELECT * FROM `{$custTable}` WHERE user_id = %d LIMIT 1", $userId));
    if ($existing) {
        $bil = !empty($existing->billing_address) ? (array) json_decode($existing->billing_address, true) : [];
        $bil['first_name'] = $nf;
        $bil['last_name']  = $nl;
        $bil['phone']      = $np;
        DB::update($custTable, [
            'first_name'      => $nf,
            'last_name'       => $nl,
            'phone'           => $np,
            'billing_address' => wp_json_encode($bil),
        ], ['id' => $existing->id]);
    }
    // Keep the plugin's own account display name in sync in instinctor_users,
    // on WordPress and standalone alike — no wp_update_user (Option A,
    // 2026-07-05, WP.org compliance). Customers are Instinctor accounts, not
    // WP users; the WP site's users are never touched.
    if ($userId > 0) {
        $dn = trim($nf . ' ' . $nl);
        if ($dn !== '') {
            DB::update($usersTable, ['display_name' => $dn], ['id' => $userId]);
        }
        $authUser = \Instinctor\Core\Auth::user();
    }
    $message = __('Details saved.', 'instinctor');
}

// -- Password change ----------------------------------------------------------
if (
    (sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'] ?? ''))) === 'POST' &&
    isset($_POST['instinctor_password_nonce']) &&
    wp_verify_nonce(sanitize_text_field(wp_unslash((string)($_POST['instinctor_password_nonce'] ?? ''))), 'instinctor_change_password')
) {
    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- password must not be altered by sanitization; it is verified.
    $cur = wp_unslash($_POST['current_password'] ?? '');
    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- password must not be altered by sanitization; it is hashed.
    $new = wp_unslash($_POST['new_password']      ?? '');
    // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- password confirmation must not be altered by sanitization.
    $con = wp_unslash($_POST['confirm_password']  ?? '');

    if (strlen($new) < 8) {
        $message = __('New password must be at least 8 characters.', 'instinctor');
    } elseif ($new !== $con) {
        $message = __('Passwords do not match.', 'instinctor');
    } else {
        // Customer passwords live in instinctor_users on WordPress + standalone
        // alike now (Option A, 2026-07-05) — no wp_set_password / wp_set_auth_cookie.
        $row = DB::get_row(DB::prepare("SELECT password_hash FROM `{$usersTable}` WHERE id = %d LIMIT 1", $userId));
        if (!$row) {
            $message = __('Account not found.', 'instinctor');
        } elseif (!password_verify($cur, $row->password_hash)) {
            $message = __('Current password is incorrect.', 'instinctor');
        } else {
            DB::update($usersTable, ['password_hash' => password_hash($new, PASSWORD_BCRYPT, ['cost' => 12]), 'hash_type' => 'bcrypt'], ['id' => $userId]);
            $message = __('Password updated.', 'instinctor');
        }
    }
}

// -- Customer row (fetch or auto-create) -------------------------------------
$customer = DB::get_row(DB::prepare("SELECT * FROM `{$custTable}` WHERE user_id = %d LIMIT 1", $userId));
if (!$customer) {
    $email = $authUser->email ?? ''; // Option A: resolved account is an instinctor_users row on WP + standalone
    $dn    = $authUser->display_name ?? '';
    $pts   = explode(' ', trim($dn), 2);
    DB::insert($custTable, ['user_id' => $userId, 'email' => $email, 'first_name' => $pts[0] ?? '', 'last_name' => $pts[1] ?? '']);
    $customer = DB::get_row(DB::prepare("SELECT * FROM `{$custTable}` WHERE id = %d LIMIT 1", (int) DB::insert_id()));
}

$custEmail   = $customer->email      ?? ($authUser->email ?? '');
$custFirst   = $customer->first_name ?? '';
$custLast    = $customer->last_name  ?? '';
$custPhone   = $customer->phone      ?? '';
$displayName = trim($custFirst . ' ' . $custLast) ?: ($authUser->display_name ?? $custEmail);
$billing     = !empty($customer->billing_address) ? (array) json_decode($customer->billing_address, true) : [];
$customerId  = (int) ($customer->id ?? 0);

// -- Data queries ------------------------------------------------------------
$orders = DB::get_results(DB::prepare(
    "SELECT * FROM `{$ordTable}` WHERE customer_id = %d ORDER BY created_at DESC", $customerId
)) ?: [];

$downloads = $has_digital ? (DB::get_results(DB::prepare(
    "SELECT dp.*, d.name, d.file_url, d.download_limit, o.order_number
     FROM `{$dlPermTable}` dp
     JOIN `{$dlFileTable}` d ON dp.download_id = d.id
     JOIN `{$ordTable}` o    ON dp.order_id    = o.id
     WHERE dp.customer_id = %d ORDER BY dp.access_granted DESC", $customerId
)) ?: []) : [];

$bookings = $has_services ? (DB::get_results(DB::prepare(
    "SELECT b.*, p.name AS service_name
     FROM `{$bookTable}` b
     LEFT JOIN `{$prodTable}` p ON b.product_id = p.id
     WHERE b.customer_id = %d AND b.status IN ('pending','confirmed')
     ORDER BY b.start_time ASC", $customerId
)) ?: []) : [];
$upcomingBookings = $has_services ? array_filter((array) $bookings, function ($b) { return strtotime($b->start_time) > time(); }) : [];

// -- Memberships (recurring subscriptions) -----------------------------------
$memberships = DB::get_results(DB::prepare(
    "SELECT s.*, p.name AS product_name
       FROM `" . DB::prefix() . "instinctor_subscriptions` s
       LEFT JOIN `" . DB::prefix() . "instinctor_products` p ON p.id = s.product_id
      WHERE s.customer_id = %d AND s.status IN ('active','trialing','past_due')
      ORDER BY s.created_at DESC", $customerId
)) ?: [];
$hasMemberships = !empty($memberships);
$subCancelNonce = Session::token('instinctor_frontend');

// -- URLs --------------------------------------------------------------------
$isPreviewContext = defined('INSTINCTOR_PREVIEW_CONTEXT') && INSTINCTOR_PREVIEW_CONTEXT;
$accountUrl = \Instinctor\Services\PageService::resolveUrl('account');
// If resolveUrl returns home (no dedicated account page configured), use the current
// page URL so tabs stay on the page that actually contains the account block.
$_homeUrl = rtrim(home_url('/'), '/') . '/';
if (rtrim($accountUrl, '/') . '/' === $_homeUrl) {
    if (function_exists('get_permalink') && !empty($GLOBALS['post']->ID)) {
        $accountUrl = get_permalink($GLOBALS['post']->ID) ?: $accountUrl;
    } elseif (isset($_SERVER['REQUEST_URI'])) {
        $accountUrl = strtok(home_url(esc_url_raw(wp_unslash($_SERVER['REQUEST_URI'] ?? ''))), '?');
    }
}
// In preview, prevent tabs from navigating away from the iframe
$navLinkAttr = $isPreviewContext ? ' onclick="return false"' : '';

$logoutUrl = ($isWP && function_exists('wp_logout_url'))
    ? wp_logout_url(home_url('/'))
    : add_query_arg(['logout' => '1', '_nonce' => Session::token('instinctor_account_logout')], $accountUrl);

$activeTab    = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'dashboard';
$impulseSet   = $GLOBALS['impulse_account_settings'] ?? null;
$accountTitle = ($impulseSet ? ($impulseSet['title'] ?? '') : '') ?: __('My Account', 'instinctor');
$dateFormat   = get_option('date_format') ?: 'M j, Y';

$_acSet      = $GLOBALS['impulse_account_settings'] ?? [];
$_acText     = esc_attr($_acSet['text_color']       ?? '');
$_acNavColor = esc_attr($_acSet['nav_active_color'] ?? '');
$_acBtnBg    = esc_attr($_acSet['btn_bg']           ?? '');
$_acBtnColor = esc_attr($_acSet['btn_color']        ?? '');
$_acRadius   = isset($_acSet['border_radius']) ? intval($_acSet['border_radius']) : null;
$_acVars = '';
if ($_acText)     $_acVars .= '--impulse-text-color:'        . $_acText     . ';';
if ($_acNavColor) $_acVars .= '--impulse-nav-active-color:'  . $_acNavColor . ';';
if ($_acBtnBg)    $_acVars .= '--impulse-btn-bg:'            . $_acBtnBg    . ';';
if ($_acBtnColor) $_acVars .= '--impulse-btn-color:'         . $_acBtnColor . ';';
if ($_acRadius !== null) $_acVars .= '--impulse-border-radius:' . $_acRadius . 'px;';
?>
<div class="instinctor-account"<?php if ($_acVars) echo ' style="' . esc_attr($_acVars) . '"'; ?>>
    <div class="instinctor-account-title"><?php echo esc_html($accountTitle); ?></div>
    <?php $_welcome = sanitize_text_field(wp_unslash($_GET['welcome'] ?? '')); if ($_welcome === 'setpw' || $_welcome === 'active'): ?>
    <div style="background:#e8f5e9;border:1px solid #c8e6c9;color:#2e7d32;border-radius:8px;padding:14px 16px;margin-bottom:16px;font-size:14px">
        <strong><?php esc_html_e('Welcome! Your membership is active.','instinctor'); ?></strong>
        <?php if ($_welcome === 'setpw'): ?> <?php esc_html_e('Check your email to set your password so you can log in next time.','instinctor'); ?><?php endif; ?>
    </div>
    <?php endif; ?>
    <?php if ($message): ?><div class="instinctor-notice"><?php echo esc_html($message); ?></div><?php endif; ?>

    <div class="instinctor-account-grid">
        <nav class="instinctor-account-nav">
            <a href="<?php echo esc_url(add_query_arg('tab','dashboard',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='dashboard'?'active':''; ?>"><?php esc_html_e('Dashboard','instinctor'); ?></a>
            <a href="<?php echo esc_url(add_query_arg('tab','orders',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='orders'?'active':''; ?>"><?php echo esc_html(StoreFeatures::orderNoun()); ?></a>
            <?php if ($hasMemberships): ?>
            <a href="<?php echo esc_url(add_query_arg('tab','membership',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='membership'?'active':''; ?>"><?php esc_html_e('Membership','instinctor'); ?></a>
            <?php endif; ?>
            <?php if ($has_services && !empty($upcomingBookings)): ?>
            <a href="<?php echo esc_url(add_query_arg('tab','bookings',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='bookings'?'active':''; ?>"><?php esc_html_e('Appointments','instinctor'); ?> <span><?php echo count($upcomingBookings); ?></span></a>
            <?php endif; ?>
            <?php if ($has_digital): ?>
            <a href="<?php echo esc_url(add_query_arg('tab','downloads',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='downloads'?'active':''; ?>"><?php esc_html_e('Downloads','instinctor'); ?></a>
            <?php endif; ?>
            <?php if ($has_physical): ?>
            <a href="<?php echo esc_url(add_query_arg('tab','address',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='address'?'active':''; ?>"><?php esc_html_e('Address','instinctor'); ?></a>
            <?php endif; ?>
            <a href="<?php echo esc_url(add_query_arg('tab','details',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="<?php echo $activeTab==='details'?'active':''; ?>"><?php esc_html_e('Profile','instinctor'); ?></a>
            <?php if (!Auth::can('administrator')): ?>
            <a href="<?php echo esc_url($logoutUrl); ?>"<?php echo wp_kses_data($navLinkAttr); ?> class="instinctor-nav-logout"><?php esc_html_e('Logout','instinctor'); ?></a>
            <?php endif; ?>
        </nav>

        <div class="instinctor-account-content">

<?php if ($activeTab === 'dashboard'): ?>
            <p><?php
                /* translators: %s: customer display name */
                if ($has_physical && $has_digital) printf(esc_html__('Hello %s! View your orders, downloads, and manage your details.','instinctor'),'<strong>'.esc_html($displayName).'</strong>');
                /* translators: %s: customer display name */
                elseif ($has_digital)  printf(esc_html__('Hello %s! View your orders and downloads below.','instinctor'),'<strong>'.esc_html($displayName).'</strong>');
                /* translators: %s: customer display name */
                elseif ($has_services) printf(esc_html__('Hello %s! View your orders and upcoming appointments.','instinctor'),'<strong>'.esc_html($displayName).'</strong>');
                /* translators: %s: customer display name */
                else                   printf(esc_html__('Hello %1$s! View your %2$s and manage your account.','instinctor'),'<strong>'.esc_html($displayName).'</strong>', esc_html(strtolower(StoreFeatures::orderNoun())));
            ?></p>
            <?php if ($hasMemberships): foreach ($memberships as $_m):
                $_mPeriod = ['monthly'=>'month','weekly'=>'week','yearly'=>'year'][$_m->period] ?? $_m->period;
                $_mNext = $_m->current_period_end ? gmdate($dateFormat, strtotime($_m->current_period_end)) : '';
                $_mCanceling = !empty($_m->cancel_at_period_end);
            ?>
            <div style="border:1px solid #e8e8ed;border-radius:8px;padding:16px 18px;margin-bottom:16px;background:#fafafa">
                <div style="font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:#888;margin-bottom:4px"><?php esc_html_e('Active membership','instinctor'); ?></div>
                <div style="font-weight:600;font-size:16px"><?php echo esc_html($_m->product_name ?: __('Membership','instinctor')); ?></div>
                <div style="color:#555;font-size:13px;margin-top:4px">$<?php echo esc_html(number_format((float)$_m->price,2)); ?> / <?php echo esc_html($_mPeriod); ?>
                    <?php if ($_mNext): ?>&middot; <?php
                    /* translators: %s is the next billing date. */
                    echo $_mCanceling ? sprintf(esc_html__('Cancels %s','instinctor'), esc_html($_mNext)) : sprintf(esc_html__('Renews %s','instinctor'), esc_html($_mNext)); ?><?php endif; ?></div>
                <a href="<?php echo esc_url(add_query_arg('tab','membership',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?> style="display:inline-block;margin-top:10px;font-size:13px;font-weight:600;color:#1d2327"><?php esc_html_e('Manage membership','instinctor'); ?> &rarr;</a>
            </div>
            <?php endforeach; endif; ?>
            <div class="instinctor-stats-row">
                <div class="instinctor-stat-box"><span class="num"><?php echo count($orders); ?></span><span class="label"><?php echo esc_html(StoreFeatures::orderNoun()); ?></span></div>
                <div class="instinctor-stat-box"><span class="num">$<?php echo esc_html(number_format((float)($customer->total_spent??0),2)); ?></span><span class="label"><?php echo esc_html(StoreFeatures::spentLabel()); ?></span></div>
                <?php if ($has_digital): ?><div class="instinctor-stat-box"><span class="num"><?php echo count($downloads); ?></span><span class="label"><?php esc_html_e('Downloads','instinctor'); ?></span></div><?php endif; ?>
            </div>

<?php elseif ($activeTab === 'orders'):
    $viewOrder = isset($_GET['view']) ? intval($_GET['view']) : 0;
    if ($viewOrder):
        $acOrder = DB::get_row(DB::prepare("SELECT * FROM `{$ordTable}` WHERE id = %d AND customer_id = %d LIMIT 1", $viewOrder, $customerId));
        if ($acOrder):
            $items = DB::get_results(DB::prepare("SELECT * FROM `{$itemsTable}` WHERE order_id = %d", $acOrder->id)) ?: []; ?>
            <p><a href="<?php echo esc_url(add_query_arg('tab','orders',$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?>>&larr; <?php esc_html_e('Back','instinctor'); ?></a></p>
            <div class="instinctor-section-title"><?php /* translators: %s: order number */ printf(esc_html__('Order #%s','instinctor'),esc_html($acOrder->order_number)); ?></div>
            <p><?php echo esc_html(date_i18n($dateFormat,strtotime($acOrder->created_at))); ?>
               &bull; <span class="instinctor-status instinctor-status-<?php echo esc_attr($acOrder->status); ?>"><?php echo esc_html(ucfirst($acOrder->status)); ?></span></p>
            <table class="instinctor-table">
                <thead><tr><th><?php esc_html_e('Product','instinctor'); ?></th><th><?php esc_html_e('Qty','instinctor'); ?></th><th><?php esc_html_e('Total','instinctor'); ?></th></tr></thead>
                <tbody>
                <?php foreach ($items as $item):
                    $meta=$item->meta??'{}'; $acM=json_decode($meta,true); $hasB=!empty($acM['booking_date'])&&!empty($acM['booking_time']); ?>
                <tr>
                    <td><?php echo esc_html($item->name); ?><?php if($hasB):?><div class="instinctor-item-meta"><?php esc_html_e('Appointment:','instinctor'); ?> <?php echo esc_html(date_i18n($dateFormat,strtotime($acM['booking_date']))); ?> <?php esc_html_e('at','instinctor'); ?> <?php echo esc_html($acM['booking_time']); ?></div><?php endif; ?></td>
                    <td><?php echo intval($item->quantity); ?></td>
                    <td>$<?php echo esc_html(number_format((float)$item->total,2)); ?></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
                <tfoot>
                    <tr><td colspan="2"><?php esc_html_e('Subtotal','instinctor'); ?></td><td>$<?php echo esc_html(number_format((float)$acOrder->subtotal,2)); ?></td></tr>
                    <?php if((float)$acOrder->shipping_total>0):?><tr><td colspan="2"><?php esc_html_e('Shipping','instinctor'); ?></td><td>$<?php echo esc_html(number_format((float)$acOrder->shipping_total,2)); ?></td></tr><?php endif; ?>
                    <?php if((float)$acOrder->tax_total>0):?><tr><td colspan="2"><?php esc_html_e('Tax','instinctor'); ?></td><td>$<?php echo esc_html(number_format((float)$acOrder->tax_total,2)); ?></td></tr><?php endif; ?>
                    <tr class="total"><td colspan="2"><?php esc_html_e('Total','instinctor'); ?></td><td>$<?php echo esc_html(number_format((float)$acOrder->total,2)); ?></td></tr>
                </tfoot>
            </table>
            <?php
            // Tracking info
            $trackTable = DB::prefix() . 'instinctor_order_tracking';
            $trackRow = DB::get_row(DB::prepare(
                "SELECT carrier, tracking_number, tracking_url FROM `{$trackTable}` WHERE order_id = %d ORDER BY created_at DESC LIMIT 1",
                $acOrder->id
            ));
            if ($trackRow && $trackRow->tracking_number):
            ?>
            <div class="instinctor-tracking-info" style="margin-top:20px;padding:16px;border:1px solid #e0e0e0;border-radius:6px;background:#f9f9f9">
                <div style="font-size:12px;font-weight:600;color:#888;text-transform:uppercase;letter-spacing:.04em;margin-bottom:10px"><?php esc_html_e('Shipment Tracking', 'instinctor'); ?></div>
                <?php if ($trackRow->carrier): ?>
                <div style="font-size:13px;color:#555;margin-bottom:4px"><?php esc_html_e('Carrier:', 'instinctor'); ?> <strong><?php echo esc_html($trackRow->carrier); ?></strong></div>
                <?php endif; ?>
                <div style="font-size:13px;color:#555">
                    <?php esc_html_e('Tracking #:', 'instinctor'); ?>
                    <?php if ($trackRow->tracking_url): ?>
                    <a href="<?php echo esc_url($trackRow->tracking_url); ?>" target="_blank" rel="noopener" style="color:#1d2327;font-weight:600"><?php echo esc_html($trackRow->tracking_number); ?></a>
                    <?php else: ?>
                    <strong><?php echo esc_html($trackRow->tracking_number); ?></strong>
                    <?php endif; ?>
                </div>
            </div>
            <?php endif; ?>
        <?php endif; // order exists
    else: // order list ?>
            <div class="instinctor-section-title"><?php echo esc_html(StoreFeatures::orderNoun()); ?></div>
            <?php if(empty($orders)):?><p><?php
            /* translators: %s is the lowercase order noun, e.g. "orders". */
            printf(esc_html__('No %s yet.','instinctor'), esc_html(strtolower(StoreFeatures::orderNoun()))); ?></p><?php else: ?>
            <table class="instinctor-table">
                <thead><tr><th><?php echo esc_html(StoreFeatures::orderNoun(false)); ?></th><th><?php esc_html_e('Date','instinctor'); ?></th><th><?php esc_html_e('Status','instinctor'); ?></th><th><?php esc_html_e('Total','instinctor'); ?></th><th></th></tr></thead>
                <tbody>
                <?php foreach($orders as $o): ?>
                <tr>
                    <td>#<?php echo esc_html($o->order_number); ?></td>
                    <td><?php echo esc_html(date_i18n($dateFormat,strtotime($o->created_at))); ?></td>
                    <td><span class="instinctor-status instinctor-status-<?php echo esc_attr($o->status); ?>"><?php echo esc_html(ucfirst($o->status)); ?></span></td>
                    <td>$<?php echo esc_html(number_format((float)$o->total,2)); ?></td>
                    <td><a href="<?php echo esc_url(add_query_arg(['tab'=>'orders','view'=>$o->id],$accountUrl)); ?>"<?php echo wp_kses_data($navLinkAttr); ?>><?php esc_html_e('View','instinctor'); ?></a></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
            <?php endif; endif; ?>

<?php elseif ($activeTab==='downloads' && $has_digital): ?>
            <div class="instinctor-section-title"><?php esc_html_e('Downloads','instinctor'); ?></div>
            <?php if(empty($downloads)):?><p><?php esc_html_e('No downloads available.','instinctor'); ?></p><?php else: ?>
            <table class="instinctor-table">
                <thead><tr><th><?php esc_html_e('File','instinctor'); ?></th><th><?php echo esc_html(StoreFeatures::orderNoun(false)); ?></th><th><?php esc_html_e('Remaining','instinctor'); ?></th><th></th></tr></thead>
                <tbody>
                <?php foreach($downloads as $dl): $remaining=$dl->download_limit?($dl->download_limit-$dl->download_count):'&#8734;'; ?>
                <tr>
                    <td><?php echo esc_html($dl->name); ?></td>
                    <td>#<?php echo esc_html($dl->order_number); ?></td>
                    <td><?php echo esc_html((string)$remaining); ?></td>
                    <td><a href="<?php echo esc_url(add_query_arg(['instinctor_download'=>$dl->id,'_wpnonce'=>wp_create_nonce('download_'.$dl->id)],home_url())); ?>" class="instinctor-btn-sm"><?php esc_html_e('Download','instinctor'); ?></a></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
            <?php endif; ?>

<?php elseif ($activeTab==='bookings' && $has_services): ?>
            <div class="instinctor-section-title"><?php esc_html_e('Upcoming Appointments','instinctor'); ?></div>
            <?php if(empty($upcomingBookings)):?><p><?php esc_html_e('No upcoming appointments.','instinctor'); ?></p>
            <?php else: foreach($upcomingBookings as $booking): $ts=strtotime($booking->start_time); ?>
            <div class="instinctor-booking-card" style="border-left-color:<?php echo $booking->status==='confirmed'?'#2e7d32':'#f0ad4e'; ?>">
                <div class="instinctor-booking-row">
                    <div>
                        <strong class="instinctor-booking-name"><?php echo esc_html($booking->service_name?:__('Service','instinctor')); ?></strong>
                        <div class="instinctor-booking-time"><?php echo esc_html(date_i18n('l, F j, Y',$ts)); ?> &mdash; <?php echo esc_html(date_i18n('g:i A',$ts)); ?></div>
                        <?php if(!empty($booking->customer_note)):?><div class="instinctor-booking-note"><?php echo esc_html($booking->customer_note); ?></div><?php endif; ?>
                    </div>
                    <span class="instinctor-status instinctor-status-<?php echo esc_attr($booking->status); ?>"><?php echo esc_html(ucfirst($booking->status)); ?></span>
                </div>
            </div>
            <?php endforeach; endif; ?>

<?php elseif ($activeTab==='address' && $has_physical): ?>
            <div class="instinctor-section-title"><?php esc_html_e('Address','instinctor'); ?></div>
            <form method="post" class="instinctor-address-form">
                <?php wp_nonce_field('instinctor_save_account','instinctor_account_nonce'); ?>
                <div class="instinctor-row-half">
                    <div><label><?php esc_html_e('First Name','instinctor'); ?></label><input type="text" name="billing_first_name" value="<?php echo esc_attr($billing['first_name']??$custFirst); ?>"></div>
                    <div><label><?php esc_html_e('Last Name','instinctor'); ?></label><input type="text" name="billing_last_name" value="<?php echo esc_attr($billing['last_name']??$custLast); ?>"></div>
                </div>
                <div><label><?php esc_html_e('Address','instinctor'); ?></label><input type="text" name="billing_address_1" value="<?php echo esc_attr($billing['address_1']??''); ?>"></div>
                <div class="instinctor-row-half">
                    <div><label><?php esc_html_e('City','instinctor'); ?></label><input type="text" name="billing_city" value="<?php echo esc_attr($billing['city']??''); ?>"></div>
                    <div><label><?php esc_html_e('State / Region','instinctor'); ?></label><input type="text" name="billing_state" value="<?php echo esc_attr($billing['state']??''); ?>"></div>
                </div>
                <div class="instinctor-row-half">
                    <div><label><?php esc_html_e('Postcode','instinctor'); ?></label><input type="text" name="billing_postcode" value="<?php echo esc_attr($billing['postcode']??''); ?>"></div>
                    <div><label><?php esc_html_e('Country','instinctor'); ?></label><input type="text" name="billing_country" value="<?php echo esc_attr($billing['country']??''); ?>"></div>
                </div>
                <button type="submit" class="instinctor-btn"><?php esc_html_e('Save Address','instinctor'); ?></button>
            </form>

<?php elseif ($activeTab==='membership' && $hasMemberships): ?>
    <h3 style="margin:0 0 14px;font-size:16px"><?php esc_html_e('My Membership','instinctor'); ?></h3>
    <?php
    $_anLogin   = (string) \Instinctor\Core\Config::get('instinctor_authorizenet_api_login_id', '');
    $_anPubKey  = (string) \Instinctor\Core\Config::get('instinctor_authorizenet_public_client_key', '');
    $_anSandbox = (bool) \Instinctor\Core\Config::get('instinctor_authorizenet_sandbox', true);
    $_canUpdateCard = $_anLogin !== '' && $_anPubKey !== '';
    if ($_canUpdateCard) {
        // Authorize.Net Accept.js (card tokenization) — registered + enqueued, not
        // printed as a raw <script> tag, per WP.org guidelines. External payment
        // library, documented in the readme External Services section. Mirrors the
        // proven checkout.php pattern: emit immediately because the card-update JS
        // below needs the Accept.js global, and standalone does not call wp_footer().
        $_anJsUrl = $_anSandbox
            ? 'https://jstest.authorize.net/v1/Accept.js'
            : 'https://js.authorize.net/v1/Accept.js';
        // No ?ver on Accept.js — a query string fails Authorize.net's CDN-origin
        // check and breaks card tokenization. Pass null, not INSTINCTOR_VERSION.
        wp_register_script('instinctor-authorizenet-accept', $_anJsUrl, array(), null, false); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion -- external Authorize.net Accept.js SDK; a ?ver query string fails its CDN-origin check and breaks card tokenization (see note above), so the version is intentionally null.
        wp_enqueue_script('instinctor-authorizenet-accept');
        if (defined('INSTINCTOR_ENV') && INSTINCTOR_ENV === 'standalone') {
            if (function_exists('_instinctor_emit_script')) {
                _instinctor_emit_script('instinctor-authorizenet-accept', false);
                _instinctor_emit_script('instinctor-authorizenet-accept', true);
            }
        } elseif (function_exists('wp_print_scripts')) {
            wp_print_scripts(array('instinctor-authorizenet-accept'));
        }
    }
    ?>
    <?php foreach ($memberships as $sub):
        $amount    = number_format((float) $sub->price, 2);
        $periodLbl = ['monthly'=>'month','weekly'=>'week','yearly'=>'year'][$sub->period] ?? $sub->period;
        $nextBill  = $sub->current_period_end ? gmdate($dateFormat, strtotime($sub->current_period_end)) : '';
        $isCanceling = !empty($sub->cancel_at_period_end);
        $isAN = ($sub->payment_method ?? '') === 'authorizenet';
        $canUpd = $_canUpdateCard && $isAN;
        $cardOnFile = $isAN ? \Instinctor\Services\SubscriptionService::instance()->getCardOnFile((int) $sub->id) : null;
        $payHistory = $isAN ? \Instinctor\Services\SubscriptionService::instance()->getPaymentHistory((int) $sub->id) : [];
    ?>
    <div style="border:1px solid #e8e8ed;border-radius:8px;padding:18px;margin-bottom:14px">
        <div style="display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:10px">
            <div>
                <div style="font-weight:600;font-size:15px"><?php echo esc_html($sub->product_name ?: __('Membership','instinctor')); ?></div>
                <div style="color:#555;font-size:13px;margin-top:4px">$<?php echo esc_html($amount); ?> / <?php echo esc_html($periodLbl); ?></div>
                <?php if ($cardOnFile): ?>
                <div style="color:#555;font-size:13px;margin-top:6px"><?php
                    // translators: %1$s is the card brand, %2$s is the last 4 digits, %3$s is the expiry date.
                    if (!empty($cardOnFile['expiry'])) printf(esc_html__('Card on file: %1$s ending %2$s, exp %3$s','instinctor'), esc_html($cardOnFile['brand']), esc_html($cardOnFile['last4']), esc_html($cardOnFile['expiry']));
                    // translators: %1$s is the card brand, %2$s is the last 4 digits.
                    else printf(esc_html__('Card on file: %1$s ending %2$s','instinctor'), esc_html($cardOnFile['brand']), esc_html($cardOnFile['last4']));
                ?></div>
                <?php endif; ?>
                <?php if ($isCanceling): ?>
                    <div style="color:#c62828;font-size:13px;margin-top:6px"><?php
                    /* translators: %s is the cancellation date. */
                    printf(esc_html__('Cancels on %s','instinctor'), esc_html($nextBill)); ?></div>
                <?php else: ?>
                    <div style="color:#555;font-size:13px;margin-top:6px"><?php
                    /* translators: %s is the next renewal date. */
                    printf(esc_html__('Renews: %s','instinctor'), esc_html($nextBill)); ?></div>
                <?php endif; ?>
            </div>
            <div style="display:flex;gap:8px;flex-wrap:wrap">
                <?php if ($canUpd): ?>
                <button type="button" class="instinctor-updcard-toggle" data-sub-id="<?php echo (int) $sub->id; ?>" style="background:#fff;color:#1d2327;border:1px solid #1d2327;border-radius:6px;padding:9px 16px;font-size:13px;font-weight:600;cursor:pointer"><?php esc_html_e('Update card','instinctor'); ?></button>
                <?php endif; ?>
                <?php if (!$isCanceling): ?>
                <button type="button" class="instinctor-cancel-sub" data-sub-id="<?php echo (int) $sub->id; ?>" style="background:#fff;color:#c62828;border:1px solid #c62828;border-radius:6px;padding:9px 16px;font-size:13px;font-weight:600;cursor:pointer"><?php esc_html_e('Cancel membership','instinctor'); ?></button>
                <?php endif; ?>
            </div>
        </div>
        <?php if ($canUpd): ?>
        <div class="instinctor-updcard-form" data-sub-id="<?php echo (int) $sub->id; ?>" style="display:none;margin-top:14px;border-top:1px solid #eee;padding-top:14px">
            <div style="display:grid;grid-template-columns:1fr 90px 80px 90px;gap:8px;max-width:520px">
                <input type="text" class="uc-num" inputmode="numeric" autocomplete="cc-number" placeholder="<?php esc_attr_e('Card number','instinctor'); ?>" style="height:38px;border:1px solid #ccc;border-radius:6px;padding:0 10px;font-size:14px">
                <input type="text" class="uc-exp" inputmode="numeric" autocomplete="cc-exp" placeholder="MM/YY" style="height:38px;border:1px solid #ccc;border-radius:6px;padding:0 10px;font-size:14px">
                <input type="text" class="uc-cvv" inputmode="numeric" autocomplete="cc-csc" placeholder="CVV" style="height:38px;border:1px solid #ccc;border-radius:6px;padding:0 10px;font-size:14px">
                <input type="text" class="uc-zip" inputmode="numeric" autocomplete="postal-code" placeholder="ZIP" style="height:38px;border:1px solid #ccc;border-radius:6px;padding:0 10px;font-size:14px">
            </div>
            <button type="button" class="instinctor-save-card" data-sub-id="<?php echo (int) $sub->id; ?>" style="margin-top:10px;background:#1d2327;color:#fff;border:none;border-radius:6px;padding:10px 18px;font-size:13px;font-weight:600;cursor:pointer"><?php esc_html_e('Save new card','instinctor'); ?></button>
            <div class="uc-msg" style="display:none;margin-top:8px;font-size:13px"></div>
        </div>
        <?php endif; ?>
        <?php if (!empty($payHistory)): ?>
        <div style="margin-top:16px;border-top:1px solid #eee;padding-top:14px">
            <div style="font-size:12px;text-transform:uppercase;letter-spacing:.04em;color:#888;margin-bottom:8px"><?php esc_html_e('Payment history','instinctor'); ?></div>
            <table style="width:100%;border-collapse:collapse;font-size:13px">
                <?php foreach ($payHistory as $_t):
                    $_tDate = $_t['date'] ? gmdate($dateFormat, strtotime($_t['date'])) : '';
                ?>
                <tr style="border-bottom:1px solid #f1f1f1">
                    <td style="padding:7px 0;color:#555"><?php echo esc_html($_tDate); ?></td>
                    <td style="padding:7px 0;color:#888"><?php echo esc_html($_t['status']); ?></td>
                    <td style="padding:7px 0;text-align:right;font-weight:600">$<?php echo esc_html(number_format($_t['amount'], 2)); ?></td>
                </tr>
                <?php endforeach; ?>
            </table>
        </div>
        <?php endif; ?>
    </div>
    <?php endforeach; ?>
    <div class="instinctor-cancel-msg" style="display:none;margin-top:10px;font-size:14px"></div>
    <?php ob_start(); ?>
    (function(){
        var nonce = '<?php echo esc_js($subCancelNonce); ?>';
        var ajaxUrl = (typeof instinctorFrontend !== 'undefined') ? instinctorFrontend.ajaxUrl : '/wp-admin/admin-ajax.php';
        var CANCEL_TXT = '<?php echo esc_js(__('Cancel membership','instinctor')); ?>';
        document.querySelectorAll('.instinctor-cancel-sub').forEach(function(btn){
            btn.addEventListener('click', function(){
                if (!window.confirm('<?php echo esc_js(__('Cancel this membership? You keep access until the end of the current billing period, and no further payments will be taken.','instinctor')); ?>')) return;
                var id = btn.getAttribute('data-sub-id');
                btn.disabled = true; btn.textContent = '<?php echo esc_js(__('Cancelling...','instinctor')); ?>';
                var fd = new FormData();
                fd.append('action','instinctor_cancel_subscription'); fd.append('subscription_id', id); fd.append('nonce', nonce);
                fetch(ajaxUrl, {method:'POST', body:fd, credentials:'same-origin'})
                    .then(function(r){return r.json();})
                    .then(function(res){
                        var msg = document.querySelector('.instinctor-cancel-msg');
                        if (res && res.success) { window.location.search = '?tab=membership&cancelled=1'; }
                        else { msg.style.display='block'; msg.style.color='#c62828'; msg.textContent=(res&&res.data&&res.data.message)||'Could not cancel. Please try again.'; btn.disabled=false; btn.textContent=CANCEL_TXT; }
                    }).catch(function(){ btn.disabled=false; btn.textContent=CANCEL_TXT; });
            });
        });
        <?php if ($_canUpdateCard): ?>
        var AN_KEY='<?php echo esc_js($_anPubKey); ?>', AN_LOGIN='<?php echo esc_js($_anLogin); ?>';
        document.querySelectorAll('.instinctor-updcard-toggle').forEach(function(t){
            t.addEventListener('click', function(){
                var f=document.querySelector('.instinctor-updcard-form[data-sub-id="'+t.getAttribute('data-sub-id')+'"]');
                if (f) f.style.display=(f.style.display==='none'||!f.style.display)?'block':'none';
            });
        });
        document.querySelectorAll('.instinctor-save-card').forEach(function(btn){
            btn.addEventListener('click', function(){
                var id=btn.getAttribute('data-sub-id');
                var form=document.querySelector('.instinctor-updcard-form[data-sub-id="'+id+'"]');
                var msg=form.querySelector('.uc-msg');
                var num=form.querySelector('.uc-num').value.replace(/\s+/g,'');
                var ex=form.querySelector('.uc-exp').value.split('/');
                var cvv=form.querySelector('.uc-cvv').value.trim();
                var zip=form.querySelector('.uc-zip').value.trim();
                var mo=(ex[0]||'').trim(), yr=(ex[1]||'').trim(); if(yr.length===2)yr='20'+yr;
                if(!num||!mo||!yr||!cvv){msg.style.display='block';msg.style.color='#c62828';msg.textContent='Please fill in all card fields.';return;}
                if(typeof Accept==='undefined'){msg.style.display='block';msg.style.color='#c62828';msg.textContent='Payment library not loaded. Refresh and try again.';return;}
                btn.disabled=true; btn.textContent='<?php echo esc_js(__('Saving...','instinctor')); ?>';
                Accept.dispatchData({authData:{clientKey:AN_KEY,apiLoginID:AN_LOGIN},cardData:{cardNumber:num,month:mo,year:yr,cardCode:cvv}}, function(resp){
                    if(resp.messages.resultCode!=='Ok'){msg.style.display='block';msg.style.color='#c62828';msg.textContent=(resp.messages.message[0]&&resp.messages.message[0].text)||'Card check failed.';btn.disabled=false;btn.textContent='<?php echo esc_js(__('Save new card','instinctor')); ?>';return;}
                    var fd=new FormData();
                    fd.append('action','instinctor_update_card'); fd.append('subscription_id',id); fd.append('descriptor',resp.opaqueData.dataDescriptor); fd.append('opaque_value',resp.opaqueData.dataValue); fd.append('zip',zip); fd.append('nonce',nonce);
                    fetch(ajaxUrl,{method:'POST',body:fd,credentials:'same-origin'})
                        .then(function(r){return r.json();})
                        .then(function(res){
                            if(res&&res.success){window.location.search='?tab=membership&card=updated';}
                            else{msg.style.display='block';msg.style.color='#c62828';msg.textContent=(res&&res.data&&res.data.message)||'Could not update card.';btn.disabled=false;btn.textContent='<?php echo esc_js(__('Save new card','instinctor')); ?>';}
                        }).catch(function(){btn.disabled=false;btn.textContent='<?php echo esc_js(__('Save new card','instinctor')); ?>';});
                });
            });
        });
        <?php endif; ?>
    })();
    <?php $_inst_ljs = ob_get_clean(); wp_add_inline_script('instinctor-frontend-js', $_inst_ljs, 'after'); ?>
<?php elseif ($activeTab==='details'): ?>
            <div class="instinctor-section-title"><?php esc_html_e('Personal Details','instinctor'); ?></div>
            <form method="post" class="instinctor-address-form">
                <?php wp_nonce_field('instinctor_save_details','instinctor_details_nonce'); ?>
                <div class="instinctor-row-half">
                    <div><label><?php esc_html_e('First Name','instinctor'); ?></label><input type="text" name="details_first_name" value="<?php echo esc_attr($custFirst); ?>"></div>
                    <div><label><?php esc_html_e('Last Name','instinctor'); ?></label><input type="text" name="details_last_name" value="<?php echo esc_attr($custLast); ?>"></div>
                </div>
                <div class="instinctor-row-half">
                    <div>
                        <label><?php esc_html_e('Email','instinctor'); ?></label>
                        <input type="email" value="<?php echo esc_attr($custEmail); ?>" disabled>
                        <p class="instinctor-form-hint"><?php esc_html_e('Contact support to change your email.','instinctor'); ?></p>
                    </div>
                    <div><label><?php esc_html_e('Phone','instinctor'); ?></label><input type="tel" name="details_phone" value="<?php echo esc_attr($custPhone); ?>"></div>
                </div>
                <button type="submit" class="instinctor-btn"><?php esc_html_e('Save Details','instinctor'); ?></button>
            </form>

            <details class="instinctor-pw-disclosure" style="margin-top:28px;border-top:1px solid #eee;padding-top:18px">
                <summary style="cursor:pointer;font-weight:600;font-size:14px;color:#1d2327"><?php esc_html_e('Change password','instinctor'); ?></summary>
            <form method="post" class="instinctor-address-form" style="margin-top:14px">
                <?php wp_nonce_field('instinctor_change_password','instinctor_password_nonce'); ?>
                <div class="instinctor-row-half">
                    <div><label><?php esc_html_e('Current Password','instinctor'); ?></label><input type="password" name="current_password" required autocomplete="current-password"></div>
                    <div><label><?php esc_html_e('New Password','instinctor'); ?></label><input type="password" name="new_password" required minlength="8" autocomplete="new-password"></div>
                </div>
                <div class="instinctor-row-half">
                    <div></div>
                    <div><label><?php esc_html_e('Confirm Password','instinctor'); ?></label><input type="password" name="confirm_password" required autocomplete="new-password"></div>
                </div>
                <button type="submit" class="instinctor-btn"><?php esc_html_e('Update Password','instinctor'); ?></button>
            </form>
            </details>

<?php endif; ?>

        </div><!-- .instinctor-account-content -->
    </div><!-- .instinctor-account-grid -->
</div><!-- .instinctor-account -->

<?php ob_start(); ?>
.instinctor-account{width:100%;max-width:960px;margin:0 auto;padding:20px;font-size:14px;line-height:1.5;color:var(--impulse-text-color,inherit);box-sizing:border-box}
.instinctor-account-title{font-size:22px;font-weight:600;margin:0 0 24px}
.instinctor-section-title{font-size:15px;font-weight:600;margin:0 0 16px}
.instinctor-account-grid{display:grid;grid-template-columns:170px 1fr;gap:32px}
.instinctor-account-nav{display:flex;flex-direction:column;gap:2px}
.instinctor-account-nav a{display:flex;justify-content:space-between;align-items:center;padding:9px 12px;border-radius:var(--impulse-border-radius,6px);text-decoration:none;color:inherit;font-size:13px}
.instinctor-account-nav a:hover{background:#f5f5f7}
.instinctor-account-nav a.active{background:none;color:inherit;font-weight:600}
.instinctor-account-nav a span{opacity:.5;font-size:11px}
.instinctor-nav-logout{margin-top:8px;opacity:.5}
.instinctor-nav-logout:hover{opacity:1!important}
.instinctor-account-content{background:#fff;border:1px solid #e8e8ed;border-radius:var(--impulse-border-radius,4px);padding:24px;min-height:180px}
.instinctor-stats-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));gap:12px;margin:20px 0 0}
.instinctor-stat-box{background:#f5f5f7;padding:16px;border-radius:var(--ia-radius,8px);text-align:center}
.instinctor-stat-box .num{display:block;font-size:20px;font-weight:600}
.instinctor-stat-box .label{font-size:11px;color:#86868b;margin-top:2px}
.instinctor-table{width:100%;border-collapse:collapse;font-size:13px}
.instinctor-table th{text-align:left;padding:8px 6px;border-bottom:1px solid #e8e8ed;color:#86868b;font-weight:500;font-size:12px}
.instinctor-table td{padding:10px 6px;border-bottom:1px solid #f0f0f0;vertical-align:middle}
.instinctor-table a{color:#0066cc;text-decoration:none}
.instinctor-table tfoot td{font-weight:500;color:#555;border-bottom:none}
.instinctor-table .total td{font-weight:600;font-size:14px;color:#1d1d1f;border-top:1px solid #e8e8ed}
.instinctor-item-meta{font-size:11px;color:#888;margin-top:3px}
.instinctor-status{display:inline-block;padding:2px 8px;border-radius:20px;font-size:11px;font-weight:500}
.instinctor-status-pending{background:#fff3e0;color:#e65100}
.instinctor-status-processing{background:#e3f2fd;color:#1565c0}
.instinctor-status-completed{background:#e8f5e9;color:#2e7d32}
.instinctor-status-cancelled,.instinctor-status-refunded{background:#ffebee;color:#c62828}
.instinctor-address-form>div{margin-bottom:12px}
.instinctor-address-form label{display:block;font-size:12px;font-weight:500;margin-bottom:4px;color:inherit}
.instinctor-address-form input{width:100%;padding:9px 10px;border:1px solid #d2d2d7;border-radius:var(--impulse-border-radius,6px);font-size:13px;box-sizing:border-box}
.instinctor-address-form input:focus{outline:none;border-color:#1d1d1f}
.instinctor-address-form input:disabled{background:#f5f5f7;color:#888;cursor:not-allowed}
.instinctor-row-half{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.instinctor-btn{background:var(--impulse-btn-bg,#1d1d1f);color:var(--impulse-btn-color,#fff);border:none;padding:10px 20px;border-radius:var(--impulse-border-radius,6px);font-size:13px;font-weight:500;cursor:pointer;margin-top:4px}
.instinctor-btn:hover{opacity:.85}
.instinctor-btn-sm{background:#1d1d1f;color:#fff;padding:5px 10px;border-radius:4px;font-size:12px;text-decoration:none}
.instinctor-notice{background:#e8f5e9;color:#2e7d32;padding:10px 14px;border-radius:6px;margin-bottom:18px;font-size:13px}
.instinctor-booking-card{background:#f9f9f9;border-radius:8px;padding:14px 16px;margin-bottom:10px;border-left:3px solid #ccc}
.instinctor-booking-row{display:flex;justify-content:space-between;align-items:flex-start;gap:12px}
.instinctor-booking-name{font-size:14px;font-weight:600}
.instinctor-booking-time{font-size:12px;color:#666;margin-top:4px}
.instinctor-booking-note{font-size:12px;color:#888;margin-top:6px;font-style:italic}
.instinctor-form-hint{font-size:11px;color:#888;margin:3px 0 0}
/* Auth panel (unauthenticated), all rules scoped to defeat theme overrides */
.instinctor-account-auth{max-width:400px;margin:40px auto;background:#fff;border:1px solid #e8e8ed;border-radius:var(--impulse-border-radius,4px);overflow:hidden;font-size:14px;line-height:1.5;color:#1d1d1f;box-sizing:border-box}
.instinctor-account-auth *{box-sizing:border-box}
.instinctor-account-auth p{margin:0;padding:0;font-size:inherit;line-height:inherit}
.instinctor-account-auth a{text-decoration:none}
/* Tabs */
.instinctor-auth-tabs{display:flex;border-bottom:1px solid #e8e8ed;margin:0;padding:0}
.instinctor-auth-tab{all:unset;flex:1;display:block;padding:13px;background:#f5f5f7;cursor:pointer;font-size:13px;font-weight:500;text-align:center;color:#1d1d1f;border:none;border-right:1px solid #e8e8ed}
.instinctor-auth-tab:last-child{border-right:none}
.instinctor-auth-tab.active{background:#fff;font-weight:600}
/* Panels */
.instinctor-auth-panel{display:none;padding:24px}
.instinctor-auth-panel.active{display:block}
.instinctor-auth-panel .instinctor-form-row{margin-bottom:14px}
.instinctor-auth-panel label{display:block;font-size:12px;font-weight:500;margin-bottom:5px;color:#1d1d1f;line-height:1.4}
.instinctor-auth-panel input[type=email],
.instinctor-auth-panel input[type=password],
.instinctor-auth-panel input[type=text]{display:block;width:100%;padding:9px 10px;border:1px solid #d2d2d7;border-radius:var(--impulse-border-radius,6px);font-size:13px;background:#fff;color:#1d1d1f;line-height:1.4;box-shadow:none;-webkit-appearance:none;appearance:none}
.instinctor-auth-panel input:focus{outline:none;border-color:#1d1d1f;box-shadow:none}
/* Buttons, override theme with !important on appearance-critical props */
.instinctor-auth-panel .instinctor-btn,
.instinctor-register-btn{display:block;width:100%;padding:11px 20px;margin:0;background:var(--impulse-btn-bg,#1d1d1f)!important;color:var(--impulse-btn-color,#fff)!important;border:none!important;border-radius:var(--impulse-border-radius,6px);font-size:13px;font-weight:600;cursor:pointer;text-align:center;line-height:1.4;box-shadow:none;-webkit-appearance:none;appearance:none;text-decoration:none}
.instinctor-auth-panel .instinctor-btn:hover,
.instinctor-register-btn:hover{opacity:.85}
/* Error */
.instinctor-auth-error{background:#fee;color:#c00;padding:10px 12px;border-radius:6px;margin-bottom:14px;font-size:13px}
/* Lost password link */
.instinctor-auth-panel>p{margin-top:14px;text-align:center}
.instinctor-auth-link{font-size:12px;color:#888!important;text-decoration:none!important;line-height:1.4}
.instinctor-auth-link:hover{color:#1d1d1f!important}
/* Misc */
.instinctor-auth-panel .instinctor-form-hint{font-size:11px;color:#888;margin:3px 0 0}
.instinctor-auth-panel .required{color:#c00}
.instinctor-auth-panel .instinctor-row-half{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:14px}
@media(max-width:768px){
    .instinctor-account-grid{grid-template-columns:1fr}
    .instinctor-account-nav{flex-direction:column;gap:0;border-bottom:none}
    .instinctor-account-nav a{padding:10px 8px;font-size:13px;border-radius:0;border-bottom:1px solid #f0f0f0}
    .instinctor-account-nav a:last-child{border-bottom:none}
    .instinctor-stats-row,.instinctor-row-half{grid-template-columns:1fr}
    .instinctor-row-half{grid-template-columns:1fr}
}
<?php $_inst_lcss = ob_get_clean(); wp_add_inline_style("instinctor-page-inline", $_inst_lcss); ?>
