<?php
/** Runtime profiles and optional module loading. */
if ( ! defined( 'ABSPATH' ) ) { exit; }

class YATOON_Feature_Modules {
    const PROFILE_OPTION = 'yatoon_runtime_profile';
    const PROFILE_VERSION_OPTION = 'yatoon_runtime_profile_version';
    // 4.6.2: records a profile this plugin chose for itself on a fresh install,
    // so it can be revisited once the licence state is known. Cleared the
    // moment an administrator makes their own choice.
    const PROFILE_AUTO_OPTION = 'yatoon_runtime_profile_auto';

    private static $profile = null;

    /**
     * Labelled module registry, in module_keys() order.
     *
     * 4.6.2: built by walking module_keys() rather than repeating the key list,
     * so the label-free runtime list and the labelled admin list can never
     * drift apart. A key present here but missing from module_keys() would
     * silently stop being profile-controlled; a key in module_keys() with no
     * entry here would render as a blank checkbox.
     */
    public static function registry() {
        $labels = array(
            'commerce'          => array( 'label' => __( 'Orders, invoices and refunds', 'yatoon-booking-system' ), 'description' => __( 'Orders, tax invoices, payment ledger and provider refunds.', 'yatoon-booking-system' ) ),
            'resources'         => array( 'label' => __( 'Shared resources', 'yatoon-booking-system' ), 'description' => __( 'Rooms, chairs, equipment and capacity checks.', 'yatoon-booking-system' ) ),
            'staff_locations'   => array( 'label' => __( 'Staff × Location rules', 'yatoon-booking-system' ), 'description' => __( 'Location assignments, services, hours and price overrides.', 'yatoon-booking-system' ) ),
            'group_appointments'=> array( 'label' => __( 'Group sessions', 'yatoon-booking-system' ), 'description' => __( 'Independent customers reserving capacity in Local mode.', 'yatoon-booking-system' ) ),
            'rest_api'          => array( 'label' => __( 'Business REST API', 'yatoon-booking-system' ), 'description' => __( 'Authenticated API for bookings and directory data.', 'yatoon-booking-system' ) ),
            'operations'        => array( 'label' => __( 'Operations and workflows', 'yatoon-booking-system' ), 'description' => __( 'Ledger, workflow jobs, operational dashboards and audit tools.', 'yatoon-booking-system' ) ),
            'insights'          => array( 'label' => __( 'Insights and performance', 'yatoon-booking-system' ), 'description' => __( 'Reporting events, performance measurements and salon operations.', 'yatoon-booking-system' ) ),
            'customer_portal'   => array( 'label' => __( 'Customer portal', 'yatoon-booking-system' ), 'description' => __( 'Customer self-service booking history and management.', 'yatoon-booking-system' ) ),
            'notifications'     => array( 'label' => __( 'Notifications', 'yatoon-booking-system' ), 'description' => __( 'Booking confirmation, reminder and review messages.', 'yatoon-booking-system' ) ),
            'ai'                => array( 'label' => __( 'AI assistant', 'yatoon-booking-system' ), 'description' => __( 'Optional AI-powered customer and admin assistance.', 'yatoon-booking-system' ) ),
            'pwa'               => array( 'label' => __( 'Merchant PWA push', 'yatoon-booking-system' ), 'description' => __( 'Optional merchant-admin push subscriptions. The installable customer app remains available in every profile.', 'yatoon-booking-system' ) ),
            'data_tools'        => array( 'label' => __( 'Import, export and backups', 'yatoon-booking-system' ), 'description' => __( 'Data portability, upgrade snapshots and recovery tools.', 'yatoon-booking-system' ) ),
        );
        $out = array();
        foreach ( self::module_keys() as $key ) {
            if ( isset( $labels[ $key ] ) ) {
                $out[ $key ] = $labels[ $key ];
            }
        }
        return $out;
    }

    /**
     * Module keys, without touching a single translation function.
     *
     * 4.6.2: registry() builds every label with __(), and bootstrap() and
     * enabled() both used to call profiles() -- which calls registry() -- while
     * this file is still being included, long before the `init` action. From
     * WordPress 6.7 that is exactly what _doing_it_wrong() reports as loading a
     * translation too early, and it also defeated the textdomain loader added in
     * the main plugin file this release (the first __() call freezes the domain
     * as untranslated for the rest of the request). The runtime paths now read
     * the label-free data below; only render() pays for labels.
     */
    public static function module_keys() {
        return array(
            'commerce', 'resources', 'staff_locations', 'group_appointments',
            'rest_api', 'operations', 'insights', 'customer_portal',
            'notifications', 'ai', 'pwa', 'data_tools',
        );
    }

    /** Which modules each profile switches on. No translated strings here. */
    public static function profile_modules() {
        $base = array_fill_keys( self::module_keys(), false );
        $all  = array_fill_keys( self::module_keys(), true );
        return array(
            'square_single' => array_merge( $base, array( 'commerce'=>true, 'operations'=>true, 'customer_portal'=>true, 'notifications'=>true, 'data_tools'=>true ) ),
            'square_multi'  => array_merge( $base, array( 'commerce'=>true, 'resources'=>true, 'staff_locations'=>true, 'operations'=>true, 'insights'=>true, 'customer_portal'=>true, 'notifications'=>true, 'data_tools'=>true ) ),
            'local'         => array_merge( $base, array( 'customer_portal'=>true, 'notifications'=>true, 'data_tools'=>true ) ),
            'full'          => $all,
            'legacy'        => $all,
        );
    }

    public static function profiles() {
        $modules = self::profile_modules();
        $labels  = array(
            'square_single' => array(
                'label' => __( 'Square single-store lean', 'yatoon-booking-system' ),
                'description' => __( 'Square booking, payments, staff, customers, portals, notifications, operations and backups without unrelated modules.', 'yatoon-booking-system' ),
            ),
            'square_multi' => array(
                'label' => __( 'Square multi-store', 'yatoon-booking-system' ),
                'description' => __( 'Square lean mode plus location rules, shared resources and operational insights.', 'yatoon-booking-system' ),
            ),
            'local' => array(
                'label' => __( 'Local booking lean', 'yatoon-booking-system' ),
                'description' => __( 'Core local scheduling, staff, customers, portals, notifications and backups.', 'yatoon-booking-system' ),
            ),
            'full' => array(
                'label' => __( 'Complete feature set', 'yatoon-booking-system' ),
                'description' => __( 'Loads every optional module. Use when the business actively needs the complete platform.', 'yatoon-booking-system' ),
            ),
            'legacy' => array(
                'label' => __( 'Preserve upgraded site', 'yatoon-booking-system' ),
                'description' => __( 'Keeps the previous release behavior until an administrator deliberately selects a profile.', 'yatoon-booking-system' ),
            ),
        );
        $out = array();
        foreach ( $labels as $key => $label ) {
            $out[ $key ] = array_merge( $label, array( 'modules' => $modules[ $key ] ) );
        }
        return $out;
    }

    /** Persist a profile once, before migrations can make a fresh install look old. */
    public static function bootstrap() {
        $saved = sanitize_key( (string) get_option( self::PROFILE_OPTION, '' ) );
        if ( isset( self::profile_modules()[ $saved ] ) || 'custom' === $saved ) {
            self::$profile = $saved;
            return $saved;
        }
        $existing = false !== get_option( 'yatoon_schema_version', false )
            || false !== get_option( 'yatoon_versioned_schema_manifest', false );
        $profile = $existing ? 'legacy' : ( 'square' === sanitize_key( (string) get_option( 'yatoon_active_platform', 'local' ) ) ? 'square_single' : 'local' );
        if ( $existing ) {
            update_option( self::PROFILE_OPTION, 'legacy', false );
            update_option( self::PROFILE_VERSION_OPTION, YATOON_VERSION, false );
            self::$profile = 'legacy';
        } else {
            self::apply_profile( $profile, false );
            // 4.6.2: remember that *we* chose this, not an administrator.
            // bootstrap() runs while class-yatoon-feature-modules.php is being
            // included -- around line 70 of the main plugin file -- which is
            // before Freemius defines ybs_is_pro() (further down the same file)
            // and before class-yatoon-license.php is required. It therefore
            // cannot tell a paid install from a free one and has to pick the
            // lean profile for both. maybe_promote_auto_profile(), which runs
            // on plugins_loaded where the licence IS knowable, uses this marker
            // to finish the job exactly once.
            update_option( self::PROFILE_AUTO_OPTION, $profile, false );
        }
        return $profile;
    }

    /**
     * Promote an automatically chosen lean profile on a licensed Pro site.
     *
     * The bug this fixes: a fresh Pro install landed on 'local', and 'local'
     * enables only customer_portal, notifications and data_tools. A merchant
     * who had just paid for Pro opened wp-admin and found no Reports, no
     * Orders & Invoices, no Shared resources, no Staff x Location rules, no
     * Group sessions, no Operations centre, no REST API and no AI assistant --
     * with nothing on screen to suggest those menus exist behind a switch.
     * The reasonable reading of that is "I bought it and it isn't there".
     *
     * Free sites are deliberately left alone: the lean profile is the right
     * default for a light site, and none of the promoted modules are available
     * to them anyway. The promotion is one-shot and only ever touches a profile
     * this plugin picked itself and that nobody has edited since -- once an
     * administrator applies a profile or saves custom modules, the marker no
     * longer matches and is dropped, so a deliberately lean Pro site is never
     * re-inflated on the next request.
     */
    private static function maybe_promote_auto_profile() {
        $auto = sanitize_key( (string) get_option( self::PROFILE_AUTO_OPTION, '' ) );
        if ( '' === $auto ) {
            return;
        }
        if ( self::current_profile() !== $auto ) {
            // An administrator has since made their own choice. Stand down.
            delete_option( self::PROFILE_AUTO_OPTION );
            return;
        }
        if ( ! function_exists( 'ybs_is_pro' ) ) {
            return; // Licence state still unknown; try again next request.
        }
        if ( ! ybs_is_pro() ) {
            // Keep the marker: a site that upgrades to Pro later should be
            // promoted then, not left permanently stripped down.
            return;
        }
        // The module require_once block at the top of the main plugin file has
        // already run by now, so the newly enabled modules load from the next
        // request onwards. That is one page view of lag on a brand new install,
        // against permanently missing menus before this existed.
        $target = ( 'square_single' === $auto ) ? 'square_multi' : 'full';
        // false: never let a profile switch silently disable a payment method
        // the merchant configured -- same argument bootstrap() makes.
        self::apply_profile( $target, false );
        delete_option( self::PROFILE_AUTO_OPTION );
    }

    public static function current_profile() {
        if ( null === self::$profile ) { self::bootstrap(); }
        return self::$profile;
    }

    /**
     * Files each optional module owns, relative to the plugin directory.
     *
     * 4.6.1: single source of truth for "which class comes from which switch".
     * Before this, the mapping only existed implicitly in a run of
     * `if ( enabled( 'x' ) ) require_once ...` lines in the bootstrap, and
     * every consumer had to remember to guard its own call site. They did not:
     * YATOON_Salon_Operations::init() was guarded by class_exists( 'YATOON_Insights' )
     * -- a class that always loads -- which fatally errored every fresh install
     * whose default profile leaves insights off.
     */
    public static function module_files() {
        return array(
            'insights'           => array( 'includes/class-yatoon-salon-operations.php', 'includes/class-yatoon-reporting.php', 'includes/class-yatoon-performance.php' ),
            'operations'         => array( 'includes/class-yatoon-operations.php', 'includes/class-yatoon-performance.php' ),
            'commerce'           => array( 'includes/class-yatoon-commerce.php' ),
            'resources'          => array( 'includes/class-yatoon-resources.php' ),
            'rest_api'           => array( 'includes/class-yatoon-rest-api.php' ),
            'staff_locations'    => array( 'includes/class-yatoon-staff-locations.php' ),
            'group_appointments' => array( 'includes/class-yatoon-group-appointments.php' ),
            'notifications'      => array( 'includes/class-yatoon-notifications.php' ),
            'data_tools'         => array( 'includes/class-yatoon-data-portability.php', 'includes/class-yatoon-backup-migration.php', 'includes/class-yatoon-saas-import.php' ),
            'ai'                 => array( 'includes/class-yatoon-ai.php' ),
            'customer_portal'    => array( 'includes/class-yatoon-customer-portal.php' ),
        );
    }

    /**
     * Load a module's classes on demand.
     *
     * Use this instead of assuming a class is present because some *other*
     * class is. Safe to call repeatedly and safe to call for a module that is
     * switched off -- an administrator can flip a switch mid-request, and an
     * admin screen that is registered unconditionally still has to render
     * without fataling.
     *
     * @param string $module Module key from registry().
     * @return bool True when the module's files are now loaded.
     */
    public static function ensure_loaded( $module ) {
        $module = sanitize_key( $module );
        $map    = self::module_files();
        if ( ! isset( $map[ $module ] ) ) {
            return false;
        }
        $loaded = true;
        foreach ( $map[ $module ] as $relative ) {
            $path = YATOON_PLUGIN_DIR . $relative;
            if ( file_exists( $path ) ) {
                require_once $path;
            } else {
                $loaded = false;
            }
        }
        return $loaded;
    }

    public static function enabled( $module ) {
        $module = sanitize_key( $module );
        if ( ! in_array( $module, self::module_keys(), true ) ) { return false; }
        if ( 'pwa' === $module && '1' !== get_option( 'yatoon_pwa_enabled', '0' ) ) { return false; }
        $explicit = get_option( 'yatoon_module_' . $module, null );
        if ( null !== $explicit ) { return '0' !== (string) $explicit; }
        $profile = self::current_profile();
        if ( 'custom' === $profile || 'legacy' === $profile ) { return true; }
        // 4.6.2: profile_modules(), not profiles() -- this runs at include time
        // on every request and must not build translated labels. See module_keys().
        $profiles = self::profile_modules();
        return ! empty( $profiles[ $profile ][ $module ] );
    }

    public static function apply_profile( $profile, $disable_alternate_payments = true ) {
        $profile = sanitize_key( $profile );
        $profiles = self::profile_modules();
        if ( ! isset( $profiles[ $profile ] ) ) { return false; }
        foreach ( $profiles[ $profile ] as $module => $enabled ) {
            update_option( 'yatoon_module_' . $module, $enabled ? '1' : '0', false );
        }
        if ( $disable_alternate_payments && in_array( $profile, array( 'square_single', 'square_multi' ), true ) ) {
            update_option( 'yatoon_woocommerce_enabled', '0', false );
            update_option( 'yatoon_deposit_enabled', '0', false );
            update_option( 'yatoon_dynamic_pricing_enabled', '0', false );
            update_option( 'yatoon_pwa_enabled', '0', false );
        }
        update_option( self::PROFILE_OPTION, $profile, false );
        update_option( self::PROFILE_VERSION_OPTION, YATOON_VERSION, false );
        // 4.6.2: any explicit apply is a decision, so the auto marker goes.
        // Without this, an administrator who deliberately selects the SAME
        // profile the plugin had already auto-picked would still be promoted
        // out of it on the next request -- the marker would still match.
        // bootstrap() re-writes the marker after calling this, which is the
        // one case where it is meant to survive.
        delete_option( self::PROFILE_AUTO_OPTION );
        self::$profile = $profile;
        return true;
    }

    public static function init() {
        self::bootstrap();
        self::maybe_promote_auto_profile();
        add_action( 'admin_menu', array( __CLASS__, 'add_menu' ), 99 );
        add_action( 'admin_post_yatoon_save_feature_modules', array( __CLASS__, 'save' ) );
        add_action( 'admin_post_yatoon_apply_runtime_profile', array( __CLASS__, 'apply_profile_request' ) );
        add_action( 'admin_post_yatoon_dismiss_module_hint', array( __CLASS__, 'dismiss_hint' ) );
        if ( is_admin() ) {
            add_action( 'admin_notices', array( __CLASS__, 'render_disabled_modules_hint' ) );
        }
    }

    /** Module keys that are switched off right now, in registry order. */
    public static function disabled_modules() {
        $off = array();
        foreach ( self::module_keys() as $key ) {
            // The merchant PWA has its own explicit opt-in switch and is off by
            // design on a site that never asked for it; nagging about it would
            // be noise, not discovery.
            if ( 'pwa' === $key ) { continue; }
            if ( ! self::enabled( $key ) ) { $off[] = $key; }
        }
        return $off;
    }

    public static function add_menu() {
        // 4.6.2: the menu entry carries the same count bubble WordPress core
        // uses for pending items whenever modules are switched off. Before
        // this, a disabled module simply had no menu entry anywhere and the
        // only way to find the switch was to already know it existed and type
        // it into the admin search box.
        $off   = count( self::disabled_modules() );
        $title = __( 'Feature Modules', 'yatoon-booking-system' );
        $menu  = $off > 0
            ? $title . ' <span class="awaiting-mod"><span class="pending-count">' . absint( $off ) . '</span></span>'
            : $title;
        add_submenu_page( 'yatoon-booking-system', $title, $menu, 'yatoon_manage_settings', 'yatoon-feature-modules', array( __CLASS__, 'render' ) );
    }

    /**
     * Name the switched-off modules on Yatoon's own admin screens.
     *
     * The count bubble above says *that* something is off; this says *what*,
     * with a direct link to each card. Dismissal is stored per user against a
     * hash of the disabled set, so dismissing it does not hide a different set
     * of modules being switched off later.
     */
    public static function render_disabled_modules_hint() {
        if ( ! function_exists( 'yatoon_is_plugin_admin_request' ) || ! yatoon_is_plugin_admin_request() ) {
            return;
        }
        if ( ! current_user_can( 'yatoon_manage_settings' ) && ! current_user_can( 'manage_options' ) ) {
            return;
        }
        $page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only screen routing, no state change.
        if ( 'yatoon-feature-modules' === $page ) {
            return;
        }
        $off = self::disabled_modules();
        if ( empty( $off ) ) {
            return;
        }
        $signature = md5( implode( ',', $off ) );
        if ( (string) get_user_meta( get_current_user_id(), 'yatoon_module_hint_dismissed', true ) === $signature ) {
            return;
        }

        $registry = self::registry();
        $links    = array();
        foreach ( $off as $key ) {
            if ( ! isset( $registry[ $key ] ) ) { continue; }
            $links[] = '<a href="' . esc_url( admin_url( 'admin.php?page=yatoon-feature-modules#yatoon-module-' . $key ) ) . '">' . esc_html( $registry[ $key ]['label'] ) . '</a>';
        }
        if ( empty( $links ) ) {
            return;
        }

        echo '<div class="notice notice-info"><p><strong>' . esc_html__( 'Some Yatoon features are switched off.', 'yatoon-booking-system' ) . '</strong> ';
        echo esc_html__( 'These modules are installed but not loaded, so their menus are hidden. Switch one on to use it:', 'yatoon-booking-system' ) . ' ';
        echo wp_kses( implode( ', ', $links ), array( 'a' => array( 'href' => array() ) ) );
        echo '</p><p>';
        echo '<a class="button button-small" href="' . esc_url( admin_url( 'admin.php?page=yatoon-feature-modules' ) ) . '">' . esc_html__( 'Open Feature Modules', 'yatoon-booking-system' ) . '</a> ';
        echo '<a class="button button-small" href="' . esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=yatoon_dismiss_module_hint&signature=' . $signature ), 'yatoon_dismiss_module_hint' ) ) . '">' . esc_html__( 'Dismiss', 'yatoon-booking-system' ) . '</a>';
        echo '</p></div>';
    }

    public static function dismiss_hint() {
        self::authorize();
        check_admin_referer( 'yatoon_dismiss_module_hint' );
        $signature = isset( $_GET['signature'] ) ? sanitize_key( wp_unslash( $_GET['signature'] ) ) : '';
        update_user_meta( get_current_user_id(), 'yatoon_module_hint_dismissed', $signature );
        wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'admin.php?page=yatoon-booking-system' ) );
        exit;
    }

    private static function authorize() {
        if ( ! current_user_can( 'yatoon_manage_settings' ) && ! current_user_can( 'manage_options' ) ) {
            wp_die( esc_html__( 'You do not have permission to change modules.', 'yatoon-booking-system' ) );
        }
    }

    public static function apply_profile_request() {
        self::authorize();
        check_admin_referer( 'yatoon_apply_runtime_profile' );
        $profile = sanitize_key( (string) wp_unslash( $_POST['profile'] ?? '' ) );
        if ( ! self::apply_profile( $profile, true ) ) {
            wp_die( esc_html__( 'Invalid runtime profile.', 'yatoon-booking-system' ) );
        }
        wp_safe_redirect( add_query_arg( array( 'page'=>'yatoon-feature-modules', 'profile_updated'=>1 ), admin_url( 'admin.php' ) ) );
        exit;
    }

    public static function save() {
        self::authorize();
        check_admin_referer( 'yatoon_save_feature_modules' );
        $selected = array_map( 'sanitize_key', (array) wp_unslash( $_POST['modules'] ?? array() ) );
        foreach ( self::module_keys() as $key ) {
            update_option( 'yatoon_module_' . $key, in_array( $key, $selected, true ) ? '1' : '0', false );
        }
        update_option( self::PROFILE_OPTION, 'custom', false );
        update_option( self::PROFILE_VERSION_OPTION, YATOON_VERSION, false );
        delete_option( self::PROFILE_AUTO_OPTION );
        self::$profile = 'custom';
        wp_safe_redirect( add_query_arg( array( 'page'=>'yatoon-feature-modules', 'updated'=>1 ), admin_url( 'admin.php' ) ) );
        exit;
    }

    public static function render() {
        self::authorize();
        $current = self::current_profile();
        $profiles = self::profiles();
        ?>
        <div class="wrap yfm-wrap">
            <h1><?php esc_html_e( 'Runtime Profile & Feature Modules', 'yatoon-booking-system' ); ?></h1>
            <p><?php esc_html_e( 'Choose a tested profile or customize individual modules. Disabled modules keep their data and skip their runtime hooks.', 'yatoon-booking-system' ); ?></p>
            <?php if ( ! empty( $_GET['updated'] ) || ! empty( $_GET['profile_updated'] ) ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
                <div class="notice notice-success is-dismissible"><p><?php esc_html_e( 'Runtime configuration saved.', 'yatoon-booking-system' ); ?></p></div>
            <?php endif; ?>
            <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="yfm-profile-form">
                <?php wp_nonce_field( 'yatoon_apply_runtime_profile' ); ?>
                <input type="hidden" name="action" value="yatoon_apply_runtime_profile">
                <div class="yfm-profile-grid">
                    <?php foreach ( array( 'square_single', 'square_multi', 'local', 'full' ) as $key ) : $profile = $profiles[ $key ]; ?>
                        <label class="yfm-profile-card"><input type="radio" name="profile" value="<?php echo esc_attr( $key ); ?>" <?php checked( $current, $key ); ?>><span><strong><?php echo esc_html( $profile['label'] ); ?></strong><small><?php echo esc_html( $profile['description'] ); ?></small></span></label>
                    <?php endforeach; ?>
                </div>
                <?php if ( 'legacy' === $current ) : ?><p class="description"><?php esc_html_e( 'This upgraded site is preserving all previous module behavior. Select a profile only when you are ready.', 'yatoon-booking-system' ); ?></p><?php endif; ?>
                <p><button class="button button-primary"><?php esc_html_e( 'Apply runtime profile', 'yatoon-booking-system' ); ?></button></p>
            </form>
            <hr>
            <h2><?php esc_html_e( 'Custom modules', 'yatoon-booking-system' ); ?></h2>
            <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
                <?php wp_nonce_field( 'yatoon_save_feature_modules' ); ?><input type="hidden" name="action" value="yatoon_save_feature_modules">
                <div class="yfm-grid"><?php foreach ( self::registry() as $key => $module ) : ?><label class="yfm-card" id="yatoon-module-<?php echo esc_attr( $key ); ?>"><input type="checkbox" name="modules[]" value="<?php echo esc_attr( $key ); ?>" <?php checked( self::enabled( $key ) ); ?>><span><strong><?php echo esc_html( $module['label'] ); ?></strong><small><?php echo esc_html( $module['description'] ); ?></small></span></label><?php endforeach; ?></div>
                <p><button class="button"><?php esc_html_e( 'Save custom modules', 'yatoon-booking-system' ); ?></button></p>
            </form>
            <style>.yfm-wrap{max-width:1100px}.yfm-profile-grid,.yfm-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.yfm-profile-card,.yfm-card{display:flex;gap:12px;background:#fff;border:1px solid #dcdcde;border-radius:8px;padding:16px;scroll-margin-top:90px}.yfm-profile-card:has(input:checked){border-color:#2271b1;box-shadow:0 0 0 1px #2271b1}.yfm-card:target{border-color:#3858e9;box-shadow:0 0 0 2px rgba(56,88,233,.22)}.yfm-profile-card input,.yfm-card input{margin-top:3px}.yfm-profile-card strong,.yfm-profile-card small,.yfm-card strong,.yfm-card small{display:block}.yfm-profile-card small,.yfm-card small{margin-top:5px;color:#646970}.yfm-profile-form{margin:20px 0 28px}@media(max-width:700px){.yfm-profile-grid,.yfm-grid{grid-template-columns:1fr}}</style>
        </div>
        <?php
    }
}
