// --- 依存関係のフォールバック (プレビュー環境でのクラッシュ回避用) ---
if (typeof window !== 'undefined') {
    if (!window.React) { window.React = { useState: () => [null, ()=>{}], useEffect: ()=>{}, useMemo: (f)=>f() }; }
    if (!window.Icons) {
        window.Icons = new Proxy({}, { get: () => function DummyIcon(props) { return window.React.createElement('span', {style:{display:'inline-block', width:'1em', height:'1em', backgroundColor:'#4b5563', borderRadius:'50%'}}, ''); } });
    }
    if (!window.FadeInSection) { window.FadeInSection = function Fade({children, className}) { return window.React.createElement('div', {className}, children); }; }
    if (!window.DateSelectors) { window.DateSelectors = function DS({dateValue, onChange, label, className}) { return window.React.createElement('div', {className}, window.React.createElement('input', {type:'date', value:dateValue, onChange: e=>onChange(e.target.value)})); }; }
    if (!window.getCourseDisplay) window.getCourseDisplay = c => c === '30min' ? '30分' : (c === '60min' ? '60分' : c);
    if (!window.getCourseShortDisplay) window.getCourseShortDisplay = c => c === '30min' ? '30分' : (c === '60min' ? '60分' : c);
    if (!window.fetchApi) window.fetchApi = async () => ({ success: true });
}

const { useState, useEffect, useMemo } = window.React;
const Icons = window.Icons;
const FadeInSection = window.FadeInSection;
const DateSelectors = window.DateSelectors;
const getCourseDisplay = window.getCourseDisplay;
const getCourseShortDisplay = window.getCourseShortDisplay;
const fetchApi = window.fetchApi;
const NO_IMAGE_SRC = window.NO_IMAGE_SRC || '';
const DUMMY_QR = window.DUMMY_QR || '';
// --------------------------------------------------------------------------

const InfoModal = ({ type, onClose }) => {
    const handleContactSubmit = async (e) => {
        e.preventDefault();
        const btn = e.target.querySelector('button[type="submit"]');
        btn.disabled = true;
        btn.innerText = '送信中...';
        
        try {
            const res = await fetchApi('send_contact', {
                method: 'POST',
                body: JSON.stringify({
                    name: e.target.sender_name.value,
                    email: e.target.sender_email.value,
                    message: e.target.sender_message.value,
                    type: 'company'
                })
            });
            if (res.success) {
                alert("お問い合わせを送信しました。担当者よりご連絡いたします。");
                onClose();
            } else {
                alert("送信に失敗しました。時間をおいて再度お試しください。");
            }
        } catch (err) {
            alert("通信エラーが発生しました。");
        } finally {
            btn.disabled = false;
            btn.innerText = '送信する';
        }
    };

    const renderContent = () => {
        switch(type) {
            case 'tokusho': return (
                <div className="space-y-6 text-gray-800">
                    <h3 className="text-2xl font-mincho font-bold text-indigo-900 border-b border-gray-200 pb-2">特定商取引法に基づく表記</h3>
                    <table className="w-full text-sm text-left">
                        <tbody className="divide-y divide-gray-200">
                            <tr><th className="py-3 font-bold w-1/3 text-indigo-900 border-b border-gray-100">販売業者</th><td className="py-3 border-b border-gray-100">株式会社 神龍</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">運営統括責任者</th><td className="py-3 border-b border-gray-100">山本 美貴子</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">所在地</th><td className="py-3 border-b border-gray-100">広島市（詳細住所はご請求に応じて遅滞なく開示いたします）</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">メールアドレス</th><td className="py-3 border-b border-gray-100 leading-relaxed">予約関連：support@amifortune.info<br/>会社/採用：admin@amifortune.info</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">販売価格</th><td className="py-3 border-b border-gray-100">各鑑定師のプロフィールページに表示された価格（税込）</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">商品代金以外の必要料金</th><td className="py-3 border-b border-gray-100">インターネット接続料金等（お客様ご負担）</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">お支払い方法</th><td className="py-3 border-b border-gray-100">クレジットカード・PayPay・コンビニによる事前決済、銀行振り込み</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">代金の支払時期</th><td className="py-3 border-b border-gray-100">【前払い】鑑定予約時間の60分前まで</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">サービスの提供時期</th><td className="py-3 border-b border-gray-100">ご予約いただいた日時</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">キャンセルについて</th><td className="py-3 border-b border-gray-100 leading-relaxed">鑑定開始の24時間前まではキャンセル料無料。それ以降および無断キャンセルの場合は、鑑定料金の100%を申し受けます。開始予定時刻から15分以上経過しても接続がない場合も無断キャンセル扱いとなります。</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">返金について</th><td className="py-3 border-b border-gray-100 leading-relaxed">鑑定サービスの性質上、提供済みのサービスに対する返金は原則承れません。ただし、当社側の事由によるキャンセル・サービス提供不能の場合は全額返金いたします。</td></tr>
                            <tr><th className="py-3 font-bold text-indigo-900">クーリングオフについて</th><td className="py-3 leading-relaxed">本サービスは通信販売に該当するため、特定商取引法上のクーリングオフ制度の適用対象外となります。ご不明な点はお気軽にお問い合わせください。</td></tr>
                        </tbody>
                    </table>

                    <div className="p-4 bg-red-50 border border-red-200 rounded-lg">
                        <h4 className="font-bold text-red-800 mb-3">&#9888; 禁止事項（お客様）</h4>
                        <ul className="text-sm text-red-700 space-y-1 list-disc pl-5">
                            <li>鑑定師への不当な金銭要求・詐欺行為</li>
                            <li>鑑定師に対する誹謗中傷・ハラスメント・脅迫・差別的言動</li>
                            <li>鑑定師へのプラットフォーム外での個人的連絡の強要・個人情報の収集</li>
                            <li>セッションの無断録音・録画・第三者への配布・SNS等への無断掲載</li>
                            <li>虚偽情報の提供、なりすまし、不正アクセス</li>
                            <li>営業目的・勧誘目的・反社会的勢力による利用</li>
                        </ul>
                    </div>

                    <div className="p-4 bg-orange-50 border border-orange-200 rounded-lg">
                        <h4 className="font-bold text-orange-800 mb-3">&#9888; 禁止事項（鑑定師）</h4>
                        <ul className="text-sm text-orange-700 space-y-1 list-disc pl-5">
                            <li>不安を煽る言動・断定的表現による不当勧誘（「必ず叶う」「このままでは不幸になる」等）— 消費者契約法第4条・特定商取引法違反</li>
                            <li>開運グッズ・お守り・高額商品の販売・推奨（プラットフォーム外取引含む）</li>
                            <li>お客様への個人的な金銭要求・贈与の受け取り</li>
                            <li>プラットフォーム外への誘導・個人的な連絡先の交換</li>
                            <li>お客様の個人情報の無断収集・目的外利用・第三者提供</li>
                            <li>宗教・投資・マルチ商法・ネットワークビジネスへの勧誘</li>
                            <li>お客様に対するハラスメント・差別的言動・プライバシーの侵害</li>
                        </ul>
                    </div>

                    <div className="p-4 bg-blue-50 border border-blue-200 rounded-lg">
                        <h4 className="font-bold text-blue-800 mb-3">&#10003; コンプライアンスへの取り組み</h4>
                        <ul className="text-sm text-blue-700 space-y-1 list-disc pl-5">
                            <li>特定商取引法・消費者契約法・個人情報保護法・景品表示法を遵守します</li>
                            <li>誇大広告・虚偽表示は一切行いません</li>
                            <li>鑑定師に対して定期的なコンプライアンス研修を実施します</li>
                            <li>不当勧誘・詐欺行為の報告があった場合、当該鑑定師の登録停止・法的措置を講じます</li>
                            <li>未成年者の方は、保護者の同意のうえでご利用ください</li>
                        </ul>
                    </div>

                    <div className="p-4 bg-green-50 border border-green-200 rounded-lg">
                        <h4 className="font-bold text-green-800 mb-2">&#128222; 苦情・相談窓口</h4>
                        <p className="text-sm text-green-700 leading-relaxed">
                            不当勧誘・詐欺行為・その他トラブルについては下記へご連絡ください。<br/>
                            <strong>support@amifortune.info</strong><br/>
                            また、消費生活に関するご相談は <strong>消費者ホットライン（局番なし 188）</strong> もご利用いただけます。
                        </p>
                    </div>
                </div>
            );
            case 'company': return (<div className="space-y-6 text-gray-800"><h3 className="text-2xl font-mincho font-bold text-indigo-900 border-b border-gray-200 pb-2">会社概要</h3><table className="w-full text-sm text-left"><tbody className="divide-y divide-gray-200"><tr><th className="py-3 font-bold w-1/3 text-indigo-900 border-b border-gray-100">会社名</th><td className="py-3 border-b border-gray-100">株式会社 神龍</td></tr><tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">代表取締役</th><td className="py-3 border-b border-gray-100">神龍 阿弥</td></tr><tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">所在地</th><td className="py-3 border-b border-gray-100">広島市</td></tr><tr><th className="py-3 font-bold text-indigo-900 border-b border-gray-100">事業内容</th><td className="py-3 border-b border-gray-100 leading-relaxed">占い鑑定業務、インターネット占いサイトの企画・制作・運営</td></tr><tr><th className="py-3 font-bold text-indigo-900">お問い合わせ</th><td className="py-3 leading-relaxed">admin@amifortune.info</td></tr></tbody></table></div>);
            case 'terms': return (<div className="space-y-4 text-sm text-gray-800 leading-relaxed"><h3 className="text-2xl font-mincho font-bold text-indigo-900 border-b border-gray-200 pb-2">利用規約</h3><p>この利用規約は，株式会社 神龍が提供するサービスの利用条件を定めるものです。</p><h4 className="font-bold text-indigo-800 mt-4">第1条（免責事項）</h4><p>本サービスが提供する鑑定結果の完全性、正確性、確実性等について、いかなる保証も行いません。鑑定結果をどのように利用するかは、ユーザー自身の判断と責任によるものとします。</p><h4 className="font-bold text-indigo-800 mt-4">第2条（禁止事項）</h4><p>法令または公序良俗に違反する行為、占い師に対する誹謗中傷やハラスメント行為を禁止します。</p></div>);
            case 'privacy': return (<div className="space-y-4 text-sm text-gray-800 leading-relaxed"><h3 className="text-2xl font-mincho font-bold text-indigo-900 border-b border-gray-200 pb-2">プライバシーポリシー</h3><p>株式会社 神龍は，本サービスにおける個人情報の取扱いについて，以下のとおり定めます。</p><h4 className="font-bold text-indigo-800 mt-4">第1条（個人情報の定義と収集）</h4><p>氏名，生年月日，連絡先など特定の個人を識別できる情報に加え、鑑定に必要な「出生時間」「出生地」「相談内容」なども個人情報として厳重に管理いたします。</p><h4 className="font-bold text-indigo-800 mt-4">第2条（第三者提供の制限）</h4><p>法令で認められる場合を除き，あらかじめユーザーの同意を得ることなく第三者に個人情報を提供することはありません。</p></div>);
            case 'cancel_policy': return (<div className="space-y-4 text-sm text-gray-800 leading-relaxed"><h3 className="text-2xl font-mincho font-bold text-indigo-900 border-b border-gray-200 pb-2">キャンセルポリシー</h3><h4 className="font-bold text-indigo-900 mt-4">1. キャンセルの期限と料金</h4><ul className="list-disc pl-5 space-y-2 bg-gray-50 p-4 rounded-lg"><li><strong>鑑定開始24時間前まで：</strong> 無料</li><li><strong>鑑定開始24時間以内・無断：</strong> 鑑定料金の100%</li></ul><h4 className="font-bold text-indigo-900 mt-6">2. 遅刻について</h4><p>開始予定時刻から15分以上経過しても接続がない場合は、無断キャンセル扱いとさせていただきます。</p></div>);
            case 'contact': return (
                <div className="space-y-4 text-sm text-gray-800 leading-relaxed">
                    <h3 className="text-2xl font-mincho font-bold text-indigo-900 border-b border-gray-200 pb-2">お問い合わせ</h3>
                    <p>会社に関するお問い合わせはこちらからお願いいたします。<br/>宛先: admin@amifortune.info</p>
                    <form className="space-y-5 mt-6" onSubmit={handleContactSubmit}>
                        <div><label className="block text-xs font-bold text-gray-700 mb-2">お名前</label><input required name="sender_name" className="w-full bg-gray-50 border border-gray-300 rounded-lg p-3 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-200 outline-none transition-all" /></div>
                        <div><label className="block text-xs font-bold text-gray-700 mb-2">メールアドレス</label><input required name="sender_email" type="email" className="w-full bg-gray-50 border border-gray-300 rounded-lg p-3 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-200 outline-none transition-all" /></div>
                        <div><label className="block text-xs font-bold text-gray-700 mb-2">内容</label><textarea required name="sender_message" className="w-full bg-gray-50 border border-gray-300 rounded-lg p-3 h-32 focus:border-indigo-500 focus:ring-1 focus:ring-indigo-200 outline-none transition-all resize-none"></textarea></div>
                        <button type="submit" className="w-full bg-indigo-600 text-white font-bold py-4 rounded-lg hover:bg-indigo-700 transition-colors shadow-md hover:shadow-lg disabled:opacity-50">送信する</button>
                    </form>
                </div>
            );
            default: return <div className="text-gray-800">コンテンツがありません。</div>;
        }
    };
    
    return ( 
        <div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
            <div className="absolute inset-0 bg-black/60 backdrop-blur-sm transition-opacity duration-300" onClick={onClose} />
            <div className="relative w-full max-w-2xl bg-white rounded-2xl shadow-2xl overflow-hidden flex flex-col max-h-[90vh] animate-slide-down border border-gray-100">
                <div className="p-5 border-b border-gray-200 flex justify-between items-center bg-gray-50/80 shrink-0">
                    <span className="text-xs font-bold tracking-widest text-indigo-400 uppercase">Information</span>
                    <button onClick={onClose} className="text-gray-400 hover:text-gray-800 text-2xl leading-none w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-200 transition-colors">&times;</button>
                </div>
                <div className="p-6 md:p-10 overflow-y-auto custom-scrollbar">{renderContent()}</div>
            </div>
        </div> 
    );
};

const ReviewModal = ({ booking, onClose, onSuccess }) => {
    const [form, setForm] = useState({ customer_name: booking.user_name || '', age_group: '', rating: 5, testimonial_text: '' });
    const [isSubmitting, setIsSubmitting] = useState(false);

    const handleSubmit = async (e) => {
        e.preventDefault(); setIsSubmitting(true);
        try {
            await window.fetchApi('submit_testimonial', { 
                method: 'POST', 
                body: JSON.stringify({ 
                    ...form, 
                    teller_name: `${booking.teller_name} 先生`,
                    fortune_teller_id: booking.fortune_teller_id 
                }) 
            });
            localStorage.setItem(`reviewed_${booking.id}`, 'true');
            alert('レビューを送信しました！\n（掲載には管理者の確認が必要です）');
            if(onSuccess) onSuccess();
            onClose();
        } catch (error) { alert('エラーが発生しました'); } finally { setIsSubmitting(false); }
    };

    const inputClass = "w-full bg-black/40 border border-white/20 rounded-xl p-3.5 text-white focus:border-dawnGold focus:bg-black/60 outline-none transition-all placeholder-gray-500 hover:border-white/40";

    return (
        <div className="fixed inset-0 z-[110] flex items-center justify-center p-4">
            <div className="absolute inset-0 bg-black/80 backdrop-blur-md transition-opacity duration-500" onClick={onClose} />
            <div className="relative w-full max-w-md glass-panel rounded-3xl shadow-2xl overflow-hidden flex flex-col animate-slide-down border border-white/20">
                <div className="p-5 border-b border-white/10 flex justify-between items-center bg-gradient-to-r from-black/80 to-black/40 shrink-0">
                    <h3 className="text-lg font-mincho text-white tracking-widest font-bold text-glow">レビューを投稿</h3>
                    <button onClick={onClose} className="text-gray-400 hover:text-white text-2xl p-2 rounded-full hover:bg-white/10 transition-colors w-8 h-8 flex items-center justify-center">&times;</button>
                </div>
                <div className="p-6 overflow-y-auto custom-scrollbar bg-gradient-to-b from-black/60 to-black/80">
                    <div className="mb-6 flex items-center gap-4 bg-white/5 p-4 rounded-xl border border-white/10">
                        <img src={booking.teller_image || window.NO_IMAGE_SRC} className="w-12 h-12 rounded-full object-cover border border-white/20" />
                        <div>
                            <p className="text-xs text-gray-400">担当鑑定師</p>
                            <p className="text-white font-bold font-mincho tracking-widest">{booking.teller_name} 先生</p>
                        </div>
                    </div>
                    <form onSubmit={handleSubmit} className="space-y-5">
                        <div>
                            <label className="block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow">お名前 (ニックネーム可) *</label>
                            <input required className={inputClass} value={form.customer_name} onChange={e=>setForm({...form, customer_name: e.target.value})} placeholder="ニックネーム" />
                        </div>
                        <div>
                            <label className="block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow">年代・性別 (任意)</label>
                            <input className={inputClass} value={form.age_group} onChange={e=>setForm({...form, age_group: e.target.value})} placeholder="例: 30代 女性" />
                        </div>
                        <div>
                            <label className="block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow">総合評価 *</label>
                            <div className="flex gap-2">
                                {[1, 2, 3, 4, 5].map(star => (
                                    <button type="button" key={star} onClick={() => setForm({...form, rating: star})} className={`transition-transform hover:scale-110 ${star <= form.rating ? 'text-yellow-400 text-glow-gold' : 'text-gray-600'}`}>
                                        <window.Icons.Star className="w-8 h-8" />
                                    </button>
                                ))}
                            </div>
                        </div>
                        <div>
                            <label className="block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow">感想 *</label>
                            <textarea required className={`${inputClass} h-32 resize-none`} value={form.testimonial_text} onChange={e=>setForm({...form, testimonial_text: e.target.value})} placeholder="鑑定の感想や先生へのメッセージをお聞かせください。"></textarea>
                        </div>
                        <div className="pt-4">
                            <button type="submit" disabled={isSubmitting || !form.customer_name || !form.testimonial_text} className="btn-dawn w-full py-4 text-sm font-bold tracking-[0.2em] shadow-lg rounded-full text-white disabled:opacity-50">
                                {isSubmitting ? '送信中...' : 'レビューを送信する'}
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    );
};

const WaitlistModal = ({ teller, onClose }) => {
    const [form, setForm] = useState({
        name: localStorage.getItem('user_name') || '',
        email: localStorage.getItem('user_email') || ''
    });
    const [isSubmitting, setIsSubmitting] = useState(false);

    const handleSubmit = async (e) => {
        e.preventDefault();
        setIsSubmitting(true);
        localStorage.setItem('user_name', form.name);
        localStorage.setItem('user_email', form.email);
        
        try {
            const res = await fetchApi('register_waitlist', {
                method: 'POST',
                body: JSON.stringify({
                    fortune_teller_id: teller.id,
                    user_name: form.name,
                    user_email: form.email
                })
            });
            if (res.success) {
                alert(`${teller.name} 先生のキャンセル待ちに登録しました。\n空きが出次第、メールにてお知らせいたします。`);
                onClose();
            } else {
                alert(res.message || '登録に失敗しました。');
            }
        } catch (error) {
            alert('エラーが発生しました。時間をおいてお試しください。');
        } finally {
            setIsSubmitting(false);
        }
    };

    const inputClass = "w-full bg-black/40 border border-white/20 rounded-xl p-3.5 text-white focus:border-dawnGold focus:bg-black/60 outline-none transition-all placeholder-gray-500 hover:border-white/40";

    return (
        <div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
            <div className="absolute inset-0 bg-black/80 backdrop-blur-md transition-opacity duration-500" onClick={onClose} />
            <div className="relative w-full max-w-md glass-panel rounded-3xl shadow-2xl overflow-hidden flex flex-col animate-slide-down border border-white/20">
                <div className="p-5 border-b border-white/10 flex justify-between items-center bg-gradient-to-r from-yellow-900/80 to-black/40 shrink-0">
                    <h3 className="text-lg font-mincho text-white tracking-widest font-bold text-glow">空き通知を受け取る</h3>
                    <button onClick={onClose} className="text-gray-400 hover:text-white text-2xl p-2 rounded-full hover:bg-white/10 transition-colors w-8 h-8 flex items-center justify-center">&times;</button>
                </div>
                <div className="p-6 overflow-y-auto custom-scrollbar bg-gradient-to-b from-black/60 to-black/80">
                    <div className="mb-6 flex items-center gap-4 bg-white/5 p-4 rounded-xl border border-white/10">
                        <img src={teller.image_url || NO_IMAGE_SRC} className="w-12 h-12 rounded-full object-cover border border-white/20" />
                        <div>
                            <p className="text-xs text-gray-400">対象の鑑定師</p>
                            <p className="text-white font-bold font-mincho tracking-widest">{teller.name} 先生</p>
                        </div>
                    </div>
                    
                    <p className="text-sm text-gray-300 leading-relaxed mb-6 bg-yellow-900/20 p-4 rounded-xl border border-yellow-700/50">
                        現在ご予約が満了しております。<br/>
                        ご登録いただくと、キャンセル等で空き枠が発生した際に、いち早くメールでお知らせいたします。
                    </p>

                    <form onSubmit={handleSubmit} className="space-y-5">
                        <div>
                            <label className="block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow">お名前 *</label>
                            <input required className={inputClass} value={form.name} onChange={e=>setForm({...form, name: e.target.value})} placeholder="山田 太郎" />
                        </div>
                        <div>
                            <label className="block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow">通知先メールアドレス *</label>
                            <input required type="email" className={inputClass} value={form.email} onChange={e=>setForm({...form, email: e.target.value})} placeholder="example@mail.com" />
                        </div>
                        <div className="pt-4">
                            <button type="submit" disabled={isSubmitting || !form.name || !form.email} className="btn-dawn w-full py-4 text-sm font-bold tracking-[0.2em] shadow-lg rounded-full text-white disabled:opacity-50">
                                {isSubmitting ? '登録中...' : '通知リストに登録する'}
                            </button>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    );
};

const BookingModal = ({ teller, onClose }) => {
    const [step, setStep] = useState(1);
    const [form, setForm] = useState({ name: '', furigana: '', email: '', birth_date: '', gender: 'female', date: '', time: '', course: '30min', consultation_content: '' });
    const [existingBookings, setExistingBookings] = useState([]);
    const [myExistingBookings, setMyExistingBookings] = useState([]);
    const [isSubmitting, setIsSubmitting] = useState(false);
    
    const [couponCode, setCouponCode] = useState(() => {
        if (typeof window !== 'undefined') {
            const params = new URLSearchParams(window.location.search);
            const urlCoupon = params.get('coupon');
            if (urlCoupon) {
                sessionStorage.setItem('saved_coupon', urlCoupon);
                return urlCoupon;
            }
            return sessionStorage.getItem('saved_coupon') || '';
        }
        return '';
    });
    
    const [couponMessage, setCouponMessage] = useState('');
    const [discount, setDiscount] = useState(0);
    const [finalPrice, setFinalPrice] = useState(0);
    const [isValidatingCoupon, setIsValidatingCoupon] = useState(false);

    const availableMethods = useMemo(() => teller.available_methods ? teller.available_methods.split(',') : [], [teller]);
    
    const dateList = useMemo(() => { 
        const list = []; const today = new Date(); const weekDays = ['日', '月', '火', '水', '木', '金', '土']; 
        for (let i = 0; i < 14; i++) { 
            const d = new Date(today); d.setDate(today.getDate() + i); 
            list.push({ value: d.toISOString().split('T')[0], display: `${d.getMonth() + 1}/${d.getDate()}`, week: weekDays[d.getDay()] }); 
        } 
        return list; 
    }, []);
    
    const timeSlots = useMemo(() => { 
        const slots = []; 
        const [startH, startM] = (teller.work_start_time || '10:00').split(':').map(Number); 
        const [endH, endM] = (teller.work_end_time || '20:00').split(':').map(Number); 
        let current = startH * 60 + startM; const end = endH * 60 + endM; 
        while (current < end) { 
            slots.push(`${Math.floor(current/60).toString().padStart(2,'0')}:${(current%60).toString().padStart(2,'0')}`); 
            current += 30; 
        } 
        return slots; 
    }, [teller]);

    const endMinutes = useMemo(() => {
        const [endH, endM] = (teller.work_end_time || '20:00').split(':').map(Number);
        return endH * 60 + endM;
    }, [teller.work_end_time]);

    const getOccupiedSlots = (bookings, targetDateStr) => {
        const occupied = new Set();
        bookings.forEach(b => {
            if (b.status === 'cancelled') return;
            const bDateStr = b.booking_date || '';
            const [bDate, bTime] = bDateStr.split(' ');
            if (bDate === targetDateStr && bTime) {
                const timeStr = bTime.substring(0, 5); 
                occupied.add(timeStr);
                if (b.course && b.course.includes('60')) {
                    const [h, m] = timeStr.split(':').map(Number);
                    const nextM = m + 30;
                    const nextH = h + Math.floor(nextM / 60);
                    const finalM = nextM % 60;
                    const nextTimeStr = `${String(nextH).padStart(2, '0')}:${String(finalM).padStart(2, '0')}`;
                    occupied.add(nextTimeStr);
                }
            }
        });
        return occupied;
    };
    
    const occupiedByTeller = useMemo(() => getOccupiedSlots(existingBookings, form.date), [existingBookings, form.date]);
    const occupiedByMe = useMemo(() => getOccupiedSlots(myExistingBookings, form.date), [myExistingBookings, form.date]);
    
    const base30 = parseInt(teller.price_30min) || 5000;
    const base60 = parseInt(teller.price_60min) || 9000;

    useEffect(() => { 
        const basePrice = form.course === '30min' ? base30 : base60; 
        setFinalPrice(Math.max(0, basePrice - discount)); 
    }, [form.course, discount, base30, base60]);
    
    useEffect(() => { 
        fetchApi('bookings_public').then(data => { 
            if (Array.isArray(data)) setExistingBookings(data.filter(b => b.fortune_teller_id == teller.id)); 
        }); 
        setForm(prev => ({ 
            ...prev, 
            name: localStorage.getItem('user_name') || prev.name, 
            furigana: localStorage.getItem('user_furigana') || prev.furigana, 
            email: localStorage.getItem('user_email') || prev.email, 
            birth_date: localStorage.getItem('user_birth_date') || prev.birth_date, 
            gender: localStorage.getItem('user_gender') || prev.gender 
        })); 
    }, [teller.id]);
    
    useEffect(() => { 
        if (step === 2 && form.email) { 
            fetchApi('my_bookings', { method: 'POST', body: JSON.stringify({ email: form.email, birth_date: form.birth_date }) }).then(data => { 
                if (Array.isArray(data)) setMyExistingBookings(data.filter(b => b.status !== 'cancelled')); 
            }); 
        } 
    }, [step, form.email, form.birth_date]);

    const validateCoupon = async (codeToValidate = couponCode) => {
        if (!codeToValidate) return;
        setIsValidatingCoupon(true); setCouponMessage('');
        try {
            const data = await fetchApi('validate_coupon', { method: 'POST', body: JSON.stringify({ code: codeToValidate }) });
            if (data.valid) {
                const basePrice = form.course === '30min' ? base30 : base60;
                let discountVal = data.discount_type === 'percent' ? Math.floor(basePrice * (data.discount_value / 100)) : data.discount_value;
                setDiscount(discountVal); setCouponMessage(`適用中: ${data.description}`);
            } else { 
                setDiscount(0); setCouponMessage('無効なクーポンコードです'); 
            }
        } catch (e) { setCouponMessage('検証エラー'); } finally { setIsValidatingCoupon(false); }
    };

    useEffect(() => {
        if (step === 2 && couponCode) {
            validateCoupon(couponCode);
        }
    }, [step, form.course]);

    const submitBooking = async () => {
        setIsSubmitting(true);
        localStorage.setItem('user_name', form.name); localStorage.setItem('user_furigana', form.furigana); 
        localStorage.setItem('user_email', form.email); localStorage.setItem('user_birth_date', form.birth_date); 
        localStorage.setItem('user_gender', form.gender);
        
        const bookingData = { 
            ...form, user_name: form.name, user_email: form.email, fortune_teller_id: teller.id, 
            booking_date: `${form.date} ${form.time}:00`, payment_method: 'pending', consultation_method: '', 
            user_contact_info: '', coupon_code: discount > 0 ? couponCode : null, discount_amount: discount, final_price: finalPrice 
        };
        
        try {
            const res = await fetchApi('create_booking', { method: 'POST', body: JSON.stringify(bookingData) });
            if (res.success) { 
                setStep(4); 
                sessionStorage.removeItem('saved_coupon');
            } else { 
                alert(res.message || "予約エラーが発生しました"); 
            }
        } catch (e) { 
            alert("予約エラーが発生しました"); 
        } finally { 
            setIsSubmitting(false); 
        }
    };

    const inputClass = "w-full bg-black/40 border border-white/20 rounded-xl p-3.5 text-white focus:border-dawnGold focus:bg-black/60 outline-none transition-all placeholder-gray-600 hover:border-white/40 focus:ring-1 focus:ring-dawnGold/50";
    const labelClass = "block text-xs text-yellow-400 font-bold mb-2 tracking-widest uppercase text-shadow ml-1";

    return (
        <div className="fixed inset-0 z-[100] flex items-center justify-center p-0 md:p-4">
            <div className="absolute inset-0 bg-black/80 backdrop-blur-md transition-opacity duration-500" onClick={onClose} />
            <div className="relative w-full h-full md:h-auto md:max-h-[90vh] md:max-w-2xl glass-panel md:rounded-3xl shadow-2xl overflow-hidden flex flex-col animate-slide-down border border-white/20">
                <div className="p-5 border-b border-white/10 flex justify-between items-center bg-gradient-to-r from-black/80 to-black/40 shrink-0">
                    <div>
                        <span className="text-[10px] text-yellow-400 font-bold tracking-[0.3em] block mb-1 font-cinzel">予約手続き</span>
                        <h3 className="text-xl font-mincho text-white tracking-widest text-glow">{step === 4 ? '仮予約完了' : `${teller.name} 先生`}</h3>
                    </div>
                    <button onClick={onClose} className="text-gray-400 hover:text-white text-2xl p-2 rounded-full hover:bg-white/10 transition-colors w-10 h-10 flex items-center justify-center">&times;</button>
                </div>
                
                {step < 4 && (
                    <div className="bg-black/60 px-6 py-4 border-b border-white/5 shrink-0 flex justify-between items-center relative">
                        <div className="absolute top-1/2 left-10 right-10 h-0.5 bg-gray-800 -translate-y-1/2 z-0"></div>
                        <div className="absolute top-1/2 left-10 h-0.5 bg-dawnGold -translate-y-1/2 z-0 transition-all duration-500" style={{ width: `${((step - 1) / 2) * 100}%`, right: '2.5rem' }}></div>
                        
                        {[1, 2, 3].map(num => (
                            <div key={num} className="relative z-10 flex flex-col items-center gap-2">
                                <div className={`w-8 h-8 rounded-full flex items-center justify-center text-xs font-bold font-cinzel transition-colors duration-300 ${step >= num ? 'bg-gradient-to-br from-yellow-400 to-yellow-600 text-black shadow-[0_0_10px_rgba(250,204,21,0.5)]' : 'bg-gray-800 text-gray-500 border border-gray-700'}`}>
                                    {num}
                                </div>
                                <span className={`text-[10px] font-bold tracking-wider hidden sm:block ${step >= num ? 'text-yellow-400 text-shadow' : 'text-gray-600'}`}>
                                    {num === 1 ? 'お客様情報' : num === 2 ? '日時・コース' : '最終確認'}
                                </span>
                            </div>
                        ))}
                    </div>
                )}

                <div className="p-5 md:p-8 overflow-y-auto custom-scrollbar bg-gradient-to-b from-black/60 to-black/80 flex-1">
                    
                    {step === 1 && (
                        <FadeInSection delay={0}>
                            <div className="flex items-center gap-5 mb-8 p-5 bg-gradient-to-r from-white/5 to-transparent rounded-2xl border border-white/10 backdrop-blur-sm">
                                <img src={teller.image_url || NO_IMAGE_SRC} alt={teller.name} className="w-20 h-20 md:w-24 md:h-24 rounded-full object-cover border-2 border-dawnPink/50 shrink-0 shadow-[0_0_15px_rgba(251,113,133,0.3)]" />
                                <div>
                                    <span className="px-3 py-1 bg-gradient-to-r from-dawnPurple/50 to-purple-900/50 text-yellow-300 text-[10px] font-bold rounded-full border border-dawnPurple/50 mb-3 inline-block shadow-sm">{teller.role}</span>
                                    <div className="flex flex-wrap gap-2 mb-2">{availableMethods.map(m => ( <span key={m} className="px-2 py-1 bg-black/40 text-white text-[10px] rounded-md border border-white/20">{m}</span> ))}</div>
                                </div>
                            </div>
                            
                            <form onSubmit={(e) => { e.preventDefault(); setStep(2); }} className="space-y-8 pb-10 md:pb-0">
                                <div className="space-y-6 bg-white/5 p-5 md:p-6 rounded-2xl border border-white/10">
                                    <h4 className="text-sm text-white font-bold tracking-widest border-b border-white/10 pb-3 flex items-center gap-2"><Icons.User className="w-4 h-4 text-dawnPink"/> お客様情報 (必須)</h4>
                                    <div className="grid md:grid-cols-2 gap-5">
                                        <div><label className={labelClass}>お名前</label><input required className={inputClass} value={form.name} onChange={e=>setForm({...form,name:e.target.value})} placeholder="山田 太郎" /></div>
                                        <div><label className={labelClass}>生年月日</label><DateSelectors dateValue={form.birth_date} onChange={(d) => setForm({...form, birth_date: d})} className="w-full" /></div>
                                    </div>
                                    <div className="grid md:grid-cols-2 gap-5">
                                        <div><label className={labelClass}>メールアドレス</label><input required type="email" className={inputClass} value={form.email} onChange={e=>setForm({...form,email:e.target.value})} placeholder="example@mail.com" /></div>
                                        <div>
                                            <label className={labelClass}>性別</label>
                                            <div className="flex gap-4 pt-1">
                                                <label className={`flex-1 flex items-center justify-center gap-2 cursor-pointer text-sm font-bold p-3 rounded-xl border transition-all ${form.gender==='female' ? 'bg-pink-900/40 border-pink-500/50 text-pink-200' : 'bg-black/40 border-white/20 text-gray-400 hover:border-white/40'}`}>
                                                    <input type="radio" name="gender" value="female" checked={form.gender==='female'} onChange={e=>setForm({...form,gender:e.target.value})} className="sr-only"/>女性
                                                </label>
                                                <label className={`flex-1 flex items-center justify-center gap-2 cursor-pointer text-sm font-bold p-3 rounded-xl border transition-all ${form.gender==='male' ? 'bg-blue-900/40 border-blue-500/50 text-blue-200' : 'bg-black/40 border-white/20 text-gray-400 hover:border-white/40'}`}>
                                                    <input type="radio" name="gender" value="male" checked={form.gender==='male'} onChange={e=>setForm({...form,gender:e.target.value})} className="sr-only"/>男性
                                                </label>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <div className="space-y-6">
                                    <div className="grid md:grid-cols-2 gap-5">
                                        <div><label className={labelClass}>フリガナ <span className="text-[10px] text-gray-500 font-normal ml-1">任意</span></label><input className={inputClass} value={form.furigana} onChange={e=>setForm({...form,furigana:e.target.value})} placeholder="ヤマダ タロウ" /></div>
                                    </div>
                                    <div><label className={labelClass}>事前相談内容 <span className="text-[10px] text-gray-500 font-normal ml-1">任意</span></label><textarea className={inputClass + " h-28 resize-none"} value={form.consultation_content} onChange={e=>setForm({...form,consultation_content:e.target.value})} placeholder="占ってほしい内容を事前に伝えておくことで、スムーズに鑑定に入れます。"></textarea></div>
                                </div>
                                
                                <div className="pt-4">
                                    <button type="submit" disabled={!form.name || !form.birth_date || !form.email} className="btn-dawn w-full py-4 md:py-5 text-sm md:text-base font-bold tracking-[0.2em] shadow-lg rounded-full text-white disabled:opacity-50 transition-transform active:scale-95">日時・コースの選択へ進む</button>
                                </div>
                            </form>
                        </FadeInSection>
                    )}
                    
                    {step === 2 && (
                        <FadeInSection delay={0} className="space-y-8 pb-10 md:pb-0">
                            <div>
                                <label className={labelClass}>コースを選択 *</label>
                                <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
                                    <button type="button" onClick={() => setForm({...form, course: '30min', time: ''})} className={`p-5 md:p-6 border-2 rounded-2xl transition-all duration-300 flex flex-col items-center justify-center gap-2 group relative overflow-hidden ${form.course === '30min' ? 'border-yellow-400 bg-gradient-to-b from-yellow-400/20 to-black/40 text-white shadow-[0_0_25px_rgba(250,204,21,0.2)]' : 'bg-black/40 border-white/10 text-gray-400 hover:border-white/30 hover:bg-white/5'}`}>
                                        {form.course === '30min' && <div className="absolute inset-0 bg-yellow-400/5 animate-pulse"></div>}
                                        <span className="text-sm font-bold text-center relative z-10 tracking-widest">通常 30分<br/><span className={`text-[10px] font-normal ${form.course === '30min' ? 'text-yellow-200' : 'text-gray-500'}`}>(実質25分)</span></span>
                                        <span className="text-2xl md:text-3xl font-serif mt-2 relative z-10 text-glow-gold">¥{base30.toLocaleString()}</span>
                                    </button>
                                    <button type="button" onClick={() => setForm({...form, course: '60min', time: ''})} className={`p-5 md:p-6 border-2 rounded-2xl transition-all duration-300 flex flex-col items-center justify-center gap-2 group relative overflow-hidden ${form.course === '60min' ? 'border-dawnPink bg-gradient-to-b from-dawnPink/20 to-black/40 text-white shadow-[0_0_25px_rgba(251,113,133,0.3)]' : 'bg-black/40 border-white/10 text-gray-400 hover:border-white/30 hover:bg-white/5'}`}>
                                        {form.course === '60min' && <div className="absolute inset-0 bg-dawnPink/5 animate-pulse"></div>}
                                        {form.course === '60min' && <span className="absolute top-0 right-0 bg-dawnPink text-white text-[9px] font-bold px-3 py-1 rounded-bl-lg tracking-widest">RECOMMEND</span>}
                                        <span className="text-sm font-bold text-center flex items-center justify-center gap-1 relative z-10 tracking-widest"><Icons.Sparkles className={`w-4 h-4 ${form.course === '60min' ? 'text-dawnPink' : 'text-gray-500'}`}/> お得 60分<br/><span className={`text-[10px] font-normal ${form.course === '60min' ? 'text-pink-200' : 'text-gray-500'}`}>(実質55分)</span></span>
                                        <span className="text-2xl md:text-3xl font-serif mt-2 relative z-10 text-glow-gold">¥{base60.toLocaleString()}</span>
                                    </button>
                                </div>
                            </div>
                            
                            <div>
                                <label className={labelClass}>日付を選択 *</label>
                                <div className="flex gap-3 overflow-x-auto pb-4 pt-2 custom-scrollbar snap-x">
                                    {dateList.map(d => (
                                        <button key={d.value} type="button" onClick={() => setForm({...form, date: d.value, time: ''})} className={`snap-start flex-shrink-0 w-[4.5rem] h-[5.5rem] md:w-20 md:h-24 flex flex-col items-center justify-center border-2 rounded-2xl transition-all duration-300 ${form.date === d.value ? 'bg-gradient-to-br from-dawnPink to-dawnOrange text-white border-transparent shadow-[0_0_15px_rgba(251,113,133,0.5)] scale-110' : 'bg-black/40 text-gray-400 border-white/10 hover:border-white/30 hover:bg-white/5 hover:-translate-y-1'}`}>
                                            <span className="text-[10px] font-bold block mb-1 opacity-80">{d.week}</span><span className="text-xl md:text-2xl font-serif font-bold">{d.display.split('/')[1]}</span>
                                        </button>
                                    ))}
                                </div>
                            </div>

                            <div className="bg-black/40 p-5 md:p-6 rounded-2xl border border-white/10">
                                <label className={labelClass}>時間を選択 *</label>
                                <div className="grid grid-cols-3 md:grid-cols-4 gap-3 max-h-56 overflow-y-auto custom-scrollbar pr-2 mt-4">
                                    {form.date ? timeSlots.map(t => {
                                        const now = new Date(); const todayStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
                                        let isPastTime = false; 
                                        if (form.date === todayStr) { 
                                            const [h, m] = t.split(':').map(Number); 
                                            if (new Date(now.getFullYear(), now.getMonth(), now.getDate(), h, m) < now) isPastTime = true; 
                                        }

                                        const isOccupiedByMe = occupiedByMe.has(t);
                                        const isOccupiedByTeller = occupiedByTeller.has(t);
                                        
                                        const [h, m] = t.split(':').map(Number);
                                        const startMins = h * 60 + m;
                                        const duration = form.course === '60min' ? 60 : 30;
                                        const bookingEndMins = startMins + duration;
                                        const isOverTime = bookingEndMins > endMinutes;

                                        let isNextOccupied = false;
                                        if (form.course === '60min' && !isOverTime) {
                                            const nextM = m + 30;
                                            const nextH = h + Math.floor(nextM / 60);
                                            const finalM = nextM % 60;
                                            const nextTimeStr = `${String(nextH).padStart(2, '0')}:${String(finalM).padStart(2, '0')}`;
                                            
                                            if (occupiedByTeller.has(nextTimeStr) || occupiedByMe.has(nextTimeStr)) {
                                                isNextOccupied = true;
                                            }
                                        }

                                        const isDisabled = isPastTime || isOccupiedByMe || isOccupiedByTeller || isOverTime || isNextOccupied;
                                        
                                        return (
                                            <button key={t} type="button" onClick={() => setForm({...form, time: t})} disabled={isDisabled} className={`py-3 md:py-4 rounded-xl text-sm md:text-base border transition-all duration-300 font-bold flex flex-col items-center justify-center relative overflow-hidden ${form.time === t ? 'bg-gradient-to-r from-dawnPurple to-purple-700 border-transparent text-white shadow-[0_0_15px_rgba(129,140,248,0.5)] scale-105' : 'bg-black/60 text-gray-300 border-white/10 hover:border-yellow-400 hover:text-white disabled:bg-black/20 disabled:text-gray-600 disabled:border-transparent disabled:cursor-not-allowed'}`}>
                                                <span className="relative z-10 font-mono">{t}</span>
                                                {isOccupiedByMe && <span className="text-[9px] text-red-400 leading-none mt-1 font-normal relative z-10">ご予約済</span>}
                                                {(isOccupiedByTeller && !isOccupiedByMe) && <span className="text-[9px] text-gray-500 leading-none mt-1 font-normal relative z-10">満了</span>}
                                                {(!isOccupiedByTeller && !isOccupiedByMe && isOverTime) && <span className="text-[9px] text-purple-400 leading-none mt-1 font-normal relative z-10 scale-90">稼働時間外</span>}
                                                {(!isOccupiedByTeller && !isOccupiedByMe && !isOverTime && isNextOccupied) && <span className="text-[9px] text-orange-500 leading-none mt-1 font-normal relative z-10 scale-90">連続空きなし</span>}
                                            </button>
                                        );
                                    }) : <div className="col-span-full text-center text-sm text-gray-500 py-8 bg-black/20 rounded-xl border border-white/5 border-dashed">先に上の日付を選択してください</div>}
                                </div>
                            </div>
                            
                            <div className="bg-gradient-to-r from-yellow-900/10 to-transparent border border-yellow-600/20 p-5 rounded-2xl">
                                <label className="text-xs text-yellow-500 font-bold mb-3 flex items-center gap-2 tracking-widest"><Icons.Star className="w-4 h-4"/> クーポンコード</label>
                                <div className="flex gap-3">
                                    <input className="flex-1 bg-black/50 border border-white/20 rounded-xl p-3 text-white text-sm font-mono uppercase focus:border-yellow-400 outline-none transition-colors" value={couponCode} onChange={(e) => setCouponCode(e.target.value)} placeholder="お持ちの場合は入力" />
                                    <button type="button" onClick={() => validateCoupon(couponCode)} disabled={!couponCode || isValidatingCoupon} className="bg-white/10 hover:bg-yellow-600/20 border border-white/20 hover:border-yellow-500/50 hover:text-yellow-400 text-white text-sm font-bold px-6 rounded-xl transition-all disabled:opacity-50">適用</button>
                                </div>
                                {couponMessage && <p className={`text-xs mt-3 font-bold flex items-center gap-1 ${discount > 0 ? 'text-green-400' : 'text-red-400'}`}>{discount > 0 ? '✓ ' : '⚠ '}{couponMessage}</p>}
                            </div>
                            
                            <div className="flex gap-4 pt-6 border-t border-white/10">
                                <button onClick={() => setStep(1)} className="flex-1 py-4 text-sm font-bold text-gray-400 hover:text-white transition-colors uppercase border border-white/20 rounded-full hover:bg-white/5 active:scale-95">戻る</button>
                                <button onClick={() => setStep(3)} disabled={!form.date || !form.time} className="flex-[2] btn-dawn py-4 text-sm md:text-base font-bold tracking-[0.2em] shadow-lg rounded-full text-white active:scale-95">最終確認へ進む</button>
                            </div>
                        </FadeInSection>
                    )}
                    
                    {step === 3 && (
                        <FadeInSection delay={0} className="space-y-6 pb-10 md:pb-0">
                            <div className="bg-yellow-900/20 border border-yellow-500/30 p-4 rounded-xl text-yellow-200 text-sm text-center font-bold tracking-widest">
                                以下の内容で仮予約を確定しますか？
                            </div>
                            
                            <div className="bg-white/5 border border-white/10 rounded-2xl p-6 space-y-4">
                                <div className="flex justify-between items-center border-b border-white/10 pb-4">
                                    <span className="text-gray-400 text-xs font-bold tracking-widest">担当鑑定師</span>
                                    <span className="text-white font-bold font-mincho">{teller.name} 先生</span>
                                </div>
                                <div className="flex justify-between items-center border-b border-white/10 pb-4">
                                    <span className="text-gray-400 text-xs font-bold tracking-widest">予約日時</span>
                                    <span className="text-yellow-400 font-bold text-lg font-mono">{form.date.replace(/-/g, '/')} {form.time}</span>
                                </div>
                                <div className="flex justify-between items-center border-b border-white/10 pb-4">
                                    <span className="text-gray-400 text-xs font-bold tracking-widest">コース</span>
                                    <span className="text-white font-bold">{getCourseDisplay(form.course)}</span>
                                </div>
                                <div className="flex justify-between items-center border-b border-white/10 pb-4">
                                    <span className="text-gray-400 text-xs font-bold tracking-widest">お名前</span>
                                    <span className="text-white font-bold">{form.name} 様</span>
                                </div>
                                <div className="flex justify-between items-center pt-2">
                                    <span className="text-gray-400 text-sm font-bold tracking-widest">お支払い予定額</span>
                                    <div className="text-right">
                                        {discount > 0 && <span className="text-gray-500 line-through text-xs mr-2">¥{(form.course === '30min' ? base30 : base60).toLocaleString()}</span>}
                                        <span className="text-3xl font-bold text-yellow-400 text-glow-gold font-serif">¥{finalPrice.toLocaleString()}</span>
                                    </div>
                                </div>
                            </div>
                            
                            <div className="bg-black/40 p-4 rounded-xl text-xs text-gray-400 border border-gray-800 leading-relaxed">
                                ※予約確定後、マイページより対話方法を選択し、オンライン決済（クレジットカード・PayPay・コンビニ）を完了していただく必要があります。<br/>
                                ※決済完了をもって正式な予約確定となります。
                            </div>
                            
                            <div className="flex gap-4 pt-4">
                                <button onClick={() => setStep(2)} className="flex-1 py-4 text-sm font-bold text-gray-400 hover:text-white transition-colors uppercase border border-white/20 rounded-full hover:bg-white/5 active:scale-95">戻る</button>
                                <button onClick={submitBooking} disabled={isSubmitting} className="flex-[2] btn-dawn py-4 text-sm md:text-base font-bold tracking-[0.2em] shadow-[0_0_20px_rgba(234,179,8,0.4)] rounded-full text-white active:scale-95 flex justify-center items-center gap-2">
                                    {isSubmitting ? <><Icons.Refresh className="w-5 h-5 animate-spin"/> 処理中...</> : 'この内容で仮予約する'}
                                </button>
                            </div>
                        </FadeInSection>
                    )}

                    {step === 4 && (
                        <FadeInSection delay={0} className="text-center py-12">
                            <div className="w-24 h-24 bg-gradient-to-br from-green-400 to-green-600 text-white rounded-full flex items-center justify-center mx-auto mb-8 text-5xl shadow-[0_0_40px_rgba(74,222,128,0.4)] animate-[slideDown_0.5s_ease-out] border-4 border-black">✓</div>
                            <h3 className="text-3xl font-serif text-white mb-4 tracking-widest font-bold text-glow">仮予約を受付ました</h3>
                            <p className="text-gray-300 mb-10 text-sm leading-relaxed">確認メールをご登録のアドレスに送信いたしました。<br/>予約はまだ完了していません。</p>
                            
                            <div className="bg-gradient-to-r from-red-900/30 to-pink-900/30 border border-red-500/30 p-6 rounded-2xl mb-10 inline-block text-left shadow-inner relative overflow-hidden">
                                <div className="absolute top-0 right-0 w-16 h-16 bg-red-500/10 rounded-full blur-xl"></div>
                                <p className="text-gray-200 text-sm leading-relaxed relative z-10">
                                    続いて<span className="text-yellow-400 font-bold mx-1 border-b border-yellow-400/50 pb-0.5">「マイページ」</span>より当日の対話方法を選択し、<br/>
                                    お支払いを完了させてご予約を確定させてください。<br/>
                                    <span className="text-[10px] text-gray-400 mt-2 block">※鑑定開始の60分前までにお支払いがない場合、キャンセルとなる場合がございます。</span>
                                </p>
                            </div>
                            <div>
                                <button onClick={onClose} className="w-full md:w-auto px-16 py-4 rounded-full border border-white/30 text-white hover:bg-white/10 transition-all text-sm font-bold tracking-widest uppercase shadow-lg active:scale-95">閉じる</button>
                            </div>
                        </FadeInSection>
                    )}
                </div>
            </div>
        </div>
    );
};

// ===== PaymentFor 決済方法選択コンポーネント =====
const PaymentMethodSelector = ({ booking, amount, label, onPaymentComplete, onCancel, isExtension = false }) => {
    const [selectedMethod, setSelectedMethod] = useState('credit');
    const [isProcessing, setIsProcessing] = useState(false);
    const [cardForm, setCardForm] = useState({ number: '', exp_m: '', exp_y: '', csc: '', holder: '' });
    const [error, setError] = useState('');
    const [pfConfig, setPfConfig] = useState(null);

    useEffect(() => {
        fetchApi('pf_config').then(cfg => setPfConfig(cfg));
    }, []);

    const handleCreditPay = async () => {
        setIsProcessing(true);
        setError('');
        
        const doPayment = async (token) => {
            try {
                const apiAction = isExtension ? 'pf_extension_pay' : 'pf_credit_pay';
                const result = await fetchApi(apiAction, {
                    method: 'POST',
                    body: JSON.stringify({
                        booking_id: booking.id,
                        token: token,
                        pay_method: 'credit'
                    })
                });
                if (result.success) {
                    onPaymentComplete(result.message || 'クレジットカード決済が完了しました。');
                } else {
                    setError(result.message || '決済に失敗しました。');
                }
            } catch (e) {
                setError('通信エラーが発生しました。');
            } finally {
                setIsProcessing(false);
            }
        };

        // metapspaymentが利用可能ならトークン化、なければモックモード
        if (typeof window.metapspayment !== 'undefined') {
            window.metapspayment.setRequireCsc(true);
            window.metapspayment.setRequireName(true);
            window.metapspayment.createToken(
                { number: cardForm.number, csc: cardForm.csc, exp_m: cardForm.exp_m, exp_y: cardForm.exp_y, card_holder_name: cardForm.holder },
                function(status, response) {
                    if (response.error) {
                        setError('カード情報に誤りがあります: ' + response.error);
                        setIsProcessing(false);
                        return;
                    }
                    doPayment(response.id);
                }
            );
        } else {
            // モックモード: トークンなしで直接API呼び出し
            doPayment('MOCK_TOKEN_' + Date.now());
        }
    };

    const handleLinkPay = async (method) => {
        setIsProcessing(true);
        setError('');
        try {
            const apiAction = isExtension ? 'pf_extension_pay' : 'pf_create_payment';
            const result = await fetchApi(apiAction, {
                method: 'POST',
                body: JSON.stringify({ booking_id: booking.id, pay_method: method })
            });
            if (result.success) {
                if (result.payment_url) {
                    window.location.href = result.payment_url;
                } else if (result.mock_message) {
                    onPaymentComplete(result.mock_message);
                } else {
                    onPaymentComplete(method === 'paypay' ? 'PayPay決済が完了しました。' : 'コンビニ決済の手続きが完了しました。');
                }
            } else {
                setError(result.message || 'エラーが発生しました。');
            }
        } catch (e) {
            setError('通信エラーが発生しました。');
        } finally {
            setIsProcessing(false);
        }
    };

    const displayAmount = amount || booking.final_price || 0;
    const enableCredit = pfConfig ? pfConfig.enable_credit : true;
    const enablePaypay = pfConfig ? pfConfig.enable_paypay : true;
    const enableCvs = pfConfig ? pfConfig.enable_cvs : true;
    const isTestMode = pfConfig ? pfConfig.test_mode : true;

    const inputClass = "w-full bg-black/50 border border-white/20 rounded-lg px-4 py-3 text-white text-sm focus:border-yellow-400 focus:ring-1 focus:ring-yellow-400/30 outline-none transition-all placeholder-gray-500";

    return (
        <div className="space-y-4">
            {label && <p className="text-xs text-yellow-400 font-bold tracking-widest uppercase">{label}</p>}
            <div className="flex justify-between items-center">
                <span className="text-xs text-gray-400 font-bold">ご請求額</span>
                <span className="text-2xl font-bold text-yellow-400 text-glow-gold font-serif">¥{Number(displayAmount).toLocaleString()}</span>
            </div>

            {isTestMode && <div className="bg-blue-900/30 border border-blue-500/30 text-blue-300 text-[10px] px-3 py-2 rounded-lg text-center font-bold tracking-widest">テストモード</div>}

            <div className="grid grid-cols-3 gap-2">
                {enableCredit && <button onClick={() => setSelectedMethod('credit')} className={`py-3 rounded-xl text-xs font-bold border transition-all ${selectedMethod === 'credit' ? 'bg-yellow-400/20 border-yellow-400 text-yellow-400 shadow-[0_0_10px_rgba(250,204,21,0.2)]' : 'bg-black/30 border-white/10 text-gray-400 hover:border-white/30'}`}>カード</button>}
                {enablePaypay && <button onClick={() => setSelectedMethod('paypay')} className={`py-3 rounded-xl text-xs font-bold border transition-all ${selectedMethod === 'paypay' ? 'bg-red-400/20 border-red-400 text-red-300 shadow-[0_0_10px_rgba(248,113,113,0.2)]' : 'bg-black/30 border-white/10 text-gray-400 hover:border-white/30'}`}>PayPay</button>}
                {enableCvs && !isExtension && <button onClick={() => setSelectedMethod('cvs')} className={`py-3 rounded-xl text-xs font-bold border transition-all ${selectedMethod === 'cvs' ? 'bg-green-400/20 border-green-400 text-green-300 shadow-[0_0_10px_rgba(74,222,128,0.2)]' : 'bg-black/30 border-white/10 text-gray-400 hover:border-white/30'}`}>コンビニ</button>}
            </div>

            {error && <div className="text-red-400 text-xs bg-red-900/30 p-3 rounded-lg border border-red-500/30">{error}</div>}

            {selectedMethod === 'credit' && (
                <div className="space-y-3 bg-white/5 p-4 rounded-xl border border-white/10 animate-fade-in">
                    <input placeholder="カード番号" maxLength="16" inputMode="numeric" value={cardForm.number} onChange={e => setCardForm({...cardForm, number: e.target.value.replace(/\D/g, '')})} className={inputClass} />
                    <div className="grid grid-cols-3 gap-2">
                        <input placeholder="月(MM)" maxLength="2" inputMode="numeric" value={cardForm.exp_m} onChange={e => setCardForm({...cardForm, exp_m: e.target.value.replace(/\D/g, '')})} className={inputClass + " text-center"} />
                        <input placeholder="年(YY)" maxLength="2" inputMode="numeric" value={cardForm.exp_y} onChange={e => setCardForm({...cardForm, exp_y: e.target.value.replace(/\D/g, '')})} className={inputClass + " text-center"} />
                        <input placeholder="CVV" maxLength="4" type="password" inputMode="numeric" value={cardForm.csc} onChange={e => setCardForm({...cardForm, csc: e.target.value.replace(/\D/g, '')})} className={inputClass + " text-center"} />
                    </div>
                    <input placeholder="カード名義人 (TARO YAMADA)" value={cardForm.holder} onChange={e => setCardForm({...cardForm, holder: e.target.value.toUpperCase()})} className={inputClass} />
                    <button onClick={handleCreditPay} disabled={isProcessing || !cardForm.number || !cardForm.exp_m || !cardForm.exp_y || !cardForm.csc}
                        className="w-full btn-dawn text-white font-bold py-4 rounded-xl disabled:opacity-50 text-sm">
                        {isProcessing ? '決済処理中...' : `¥${Number(displayAmount).toLocaleString()} を支払う`}
                    </button>
                    <p className="text-[10px] text-gray-500 text-center">カード情報は暗号化されて安全に処理されます</p>
                </div>
            )}

            {selectedMethod === 'paypay' && (
                <div className="space-y-3 animate-fade-in">
                    <button onClick={() => handleLinkPay('paypay')} disabled={isProcessing}
                        className="w-full bg-[#ff0033] hover:bg-[#cc0029] text-white font-bold py-4 rounded-xl shadow-lg transition-all disabled:opacity-50 text-sm">
                        {isProcessing ? '処理中...' : `PayPayで ¥${Number(displayAmount).toLocaleString()} を支払う`}
                    </button>
                    <p className="text-[10px] text-gray-500 text-center">PayPayアプリまたはWebで決済</p>
                </div>
            )}

            {selectedMethod === 'cvs' && !isExtension && (
                <div className="space-y-3 animate-fade-in">
                    <button onClick={() => handleLinkPay('cvs')} disabled={isProcessing}
                        className="w-full bg-green-600 hover:bg-green-700 text-white font-bold py-4 rounded-xl shadow-lg transition-all disabled:opacity-50 text-sm">
                        {isProcessing ? '処理中...' : 'コンビニ払込番号を取得する'}
                    </button>
                    <p className="text-[10px] text-gray-500 text-center leading-relaxed">セブン-イレブン / ファミリーマート / ローソン / ミニストップ 等<br/>支払期限: {pfConfig?.cvs_kigen_days || 3}日以内</p>
                </div>
            )}

            {onCancel && <button onClick={onCancel} className="w-full text-sm text-gray-400 hover:text-white transition-colors py-2 underline">戻る</button>}
        </div>
    );
};
window.PaymentMethodSelector = PaymentMethodSelector;

const CheckReservationModal = ({ onClose, onRebook }) => {
    const [email, setEmail] = useState(localStorage.getItem('user_email') || '');
    const [birthDate, setBirthDate] = useState(localStorage.getItem('user_birth_date') || '');
    const [myBookings, setMyBookings] = useState(null);
    const [loading, setLoading] = useState(false);
    const [payingBooking, setPayingBooking] = useState(null);
    const [payingExtensionBooking, setPayingExtensionBooking] = useState(null); 
    const [paymentBooking, setPaymentBooking] = useState(null); // PF決済方法選択用
    const [selectedMethod, setSelectedMethod] = useState(''); 
    const [contactInfo, setContactInfo] = useState(''); 
    const [isPaymentProcessing, setIsPaymentProcessing] = useState(false);
    const [activeTab, setActiveTab] = useState('upcoming');
    const [activeSessionBooking, setActiveSessionBooking] = useState(null);
    const [showExtensionQR, setShowExtensionQR] = useState(false);
    const [reviewingBooking, setReviewingBooking] = useState(null);

    const fetchMyBookings = async () => {
        if (!email || !birthDate) return;
        setLoading(true); localStorage.setItem('user_email', email); localStorage.setItem('user_birth_date', birthDate);
        try {
            const data = await fetchApi('my_bookings', { method: 'POST', body: JSON.stringify({ email, birth_date: birthDate }) });
            setMyBookings(Array.isArray(data) ? data : []);
        } catch(e) { setMyBookings([]); } finally { setLoading(false); }
    };

    useEffect(() => {
        if (!myBookings) { setActiveSessionBooking(null); return; }
        const checkActive = () => {
            const now = new Date(); let active = null;
            for (const b of myBookings) {
                if (b.status === 'confirmed' || b.status === 'paid') {
                    const dateStr = b.booking_date || '';
                    const start = new Date(dateStr.replace(/-/g, '/')); 
                    const duration = (b.course && b.course.includes('60')) ? 60 : 30; 
                    const end = new Date(start.getTime() + duration * 60000);
                    const displayStart = new Date(start.getTime() - 10 * 60000);
                    if (now >= displayStart && now <= end) { active = { ...b, isBeforeStart: now < start }; break; }
                }
            }
            setActiveSessionBooking(active);
        };
        checkActive(); const timer = setInterval(checkActive, 10000); return () => clearInterval(timer);
    }, [myBookings]);

    const handleConfirmBooking = async () => {
        setIsPaymentProcessing(true);
        try { 
            await fetchApi('booking_status', { method: 'POST', body: JSON.stringify({ id: payingBooking.id, status: 'confirmed', consultation_method: selectedMethod, user_contact_info: contactInfo }) }); 
            alert('対話方法を選択し、予約が確定しました。\nマイページの「お支払い」ボタンから決済を完了してください。'); setPayingBooking(null); fetchMyBookings(); 
        } catch(e) { alert('エラーが発生しました'); } finally { setIsPaymentProcessing(false); }
    };

    const handleNotifyPaymentComplete = async (bookingId) => {
        setIsPaymentProcessing(true);
        try { 
            await fetchApi('booking_status', { method: 'POST', body: JSON.stringify({ id: bookingId, status: 'paid' }) }); 
            alert('お支払い完了の通知を送信しました！\n確認が取れ次第、鑑定にお進みいただけます。'); fetchMyBookings(); 
        } catch(e) { alert('エラーが発生しました'); } finally { setIsPaymentProcessing(false); }
    };

    const handleCancel = async (bookingId) => {
        if (!confirm('本当に予約をキャンセルしますか？\n※キャンセルすると元に戻せません。')) return;
        try { 
            await fetchApi('booking_status', { method: 'POST', body: JSON.stringify({ id: bookingId, status: 'cancelled' }) }); 
            alert('予約をキャンセルしました。'); fetchMyBookings(); 
        } catch(e) { alert('エラーが発生しました'); }
    };

    const { upcoming, past } = useMemo(() => {
        if (!myBookings) return { upcoming: [], past: [] };
        const now = new Date(); const u = [], p = [];
        myBookings.forEach(b => {
            if (b.status === 'cancelled') { p.push(b); return; }
            const dateStr = b.booking_date || '';
            const start = new Date(dateStr.replace(/-/g, '/')); 
            const end = new Date(start.getTime() + ((b.course && b.course.includes('60')) ? 60 : 30) * 60000);
            if (b.status === 'completed' || end < now) p.push(b); else u.push(b);
        });
        u.sort((a, b) => new Date((a.booking_date || '').replace(/-/g, '/')) - new Date((b.booking_date || '').replace(/-/g, '/'))); 
        p.sort((a, b) => new Date((b.booking_date || '').replace(/-/g, '/')) - new Date((a.booking_date || '').replace(/-/g, '/')));
        return { upcoming: u, past: p };
    }, [myBookings]);

    const getStatusBadge = (status) => {
        switch(status) {
            case 'confirmed': return <span className="px-3 py-1 text-[10px] font-bold rounded-full border bg-pink-900/50 text-pink-400 border-pink-700 shadow-sm animate-pulse">支払い待ち</span>;
            case 'paid': return <span className="px-3 py-1 text-[10px] font-bold rounded-full border bg-green-900/50 text-green-400 border-green-700 shadow-sm">確定済 (支払完了)</span>;
            case 'pending': return <span className="px-3 py-1 text-[10px] font-bold rounded-full border bg-yellow-900/50 text-yellow-400 border-yellow-700 shadow-sm">仮予約</span>;
            case 'completed': return <span className="px-3 py-1 text-[10px] font-bold rounded-full border bg-blue-900/50 text-blue-400 border-blue-700 shadow-sm">完了</span>;
            case 'cancelled': return <span className="px-3 py-1 text-[10px] font-bold rounded-full border bg-gray-700/50 text-gray-400 border-gray-600 shadow-sm">キャンセル</span>;
            default: return <span className="px-3 py-1 text-[10px] font-bold rounded-full border bg-gray-800 text-gray-400">{status}</span>;
        }
    };

    const inputClass = "w-full bg-black/40 border border-white/20 rounded-xl p-3.5 text-white focus:border-dawnGold focus:bg-black/60 outline-none transition-all placeholder-gray-500 hover:border-white/40";
    const currentList = activeTab === 'upcoming' ? upcoming : past;

    return (
        <div className="fixed inset-0 z-[100] flex items-center justify-center p-0 md:p-4">
            <div className="absolute inset-0 bg-black/90 backdrop-blur-md transition-opacity duration-500" onClick={onClose} />
            <div className="relative w-full h-full md:h-auto md:max-h-[90vh] md:max-w-xl glass-panel md:rounded-3xl shadow-2xl overflow-hidden flex flex-col animate-slide-down border border-white/20 text-white">
                <div className="p-5 border-b border-white/10 flex justify-between items-center bg-gradient-to-r from-black/80 to-black/40 shrink-0">
                    <div className="text-center w-full relative">
                        <span className="text-[10px] text-yellow-400 font-bold tracking-[0.3em] uppercase block mb-1 font-cinzel">マイページ</span>
                        <h3 className="text-xl font-serif tracking-widest font-bold text-glow">{payingExtensionBooking ? '延長料金のお支払い' : paymentBooking ? 'お支払い' : payingBooking ? '対話方法の選択' : '予約確認・履歴'}</h3>
                        <button onClick={onClose} className="absolute right-0 top-1/2 -translate-y-1/2 text-gray-400 hover:text-white text-2xl w-10 h-10 flex items-center justify-center rounded-full hover:bg-white/10 transition-colors">&times;</button>
                    </div>
                </div>

                {payingExtensionBooking ? (
                    <div className="p-6 md:p-8 space-y-6 animate-fade-in overflow-y-auto custom-scrollbar flex-1 bg-gradient-to-b from-black/60 to-black/80">
                        <div className="bg-white/5 p-6 rounded-2xl border border-white/10 backdrop-blur-sm">
                            <p className="text-xs text-gray-400 mb-2 font-bold tracking-widest">追加オプション</p>
                            <p className="text-white font-bold text-lg mb-4">10分延長</p>
                            <p className="text-sm text-red-400 font-bold bg-red-900/20 py-2 px-4 rounded-xl border border-red-500/30 text-center">※鑑定士からの延長許可が下りました</p>
                        </div>
                        <PaymentMethodSelector
                            booking={payingExtensionBooking}
                            amount={payingExtensionBooking.price_extend10min || payingExtensionBooking.extension_fee || 1500}
                            label="延長料金のお支払い"
                            isExtension={true}
                            onPaymentComplete={(msg) => { alert(msg); setPayingExtensionBooking(null); fetchMyBookings(); }}
                            onCancel={() => setPayingExtensionBooking(null)}
                        />
                    </div>
                ) : paymentBooking ? (
                    <div className="p-6 md:p-8 space-y-6 animate-fade-in overflow-y-auto custom-scrollbar flex-1 bg-gradient-to-b from-black/60 to-black/80">
                        <div className="bg-white/5 p-5 rounded-2xl border border-white/10">
                            <div className="flex gap-4 items-center mb-3">
                                <img src={paymentBooking.teller_image || NO_IMAGE_SRC} className="w-12 h-12 rounded-full object-cover border-2 border-white/20" />
                                <div>
                                    <p className="text-white font-bold text-sm">{paymentBooking.teller_name} 先生</p>
                                    <p className="text-yellow-400 text-xs font-bold">{(paymentBooking.booking_date || '').split(' ')[0]} {(paymentBooking.booking_date || '').split(' ')[1]?.substring(0,5)}</p>
                                </div>
                            </div>
                        </div>
                        <PaymentMethodSelector
                            booking={paymentBooking}
                            label="お支払い方法を選択"
                            onPaymentComplete={(msg) => { alert(msg); setPaymentBooking(null); fetchMyBookings(); }}
                            onCancel={() => setPaymentBooking(null)}
                        />
                    </div>
                ) : payingBooking ? (
                    <div className="p-6 md:p-8 space-y-8 animate-fade-in overflow-y-auto custom-scrollbar flex-1 bg-gradient-to-b from-black/60 to-black/80">
                        <div className="bg-yellow-900/20 p-5 rounded-2xl border border-yellow-700/50 text-sm text-yellow-200 leading-relaxed shadow-inner">
                            当日の対話方法を選択してください。確定後、ご指定のメールアドレスに接続先情報をお送りします。
                        </div>
                        <div className="bg-black/30 p-6 rounded-2xl border border-white/5">
                            <p className="text-sm font-bold text-yellow-400 mb-4 uppercase tracking-widest text-shadow flex items-center gap-2"><Icons.MessageCircle className="w-4 h-4"/> 対話方法を選択 *</p>
                            <div className="grid grid-cols-2 gap-3 mb-6">{(payingBooking.available_methods || '電話,Zoom').split(',').map(m => (<button key={m} onClick={() => setSelectedMethod(m)} className={`p-3.5 border-2 rounded-xl text-sm font-bold transition-all duration-300 ${selectedMethod === m ? 'border-yellow-400 bg-yellow-400/20 text-white shadow-[0_0_15px_rgba(250,204,21,0.3)] scale-105' : 'border-white/20 bg-black/40 text-gray-400 hover:text-gray-200 hover:bg-white/5 hover:border-white/40'}`}>{m}</button>))}</div>
                            {selectedMethod && (<div className="animate-slide-down"><label className="block text-sm font-bold text-yellow-400 mb-2 uppercase tracking-widest text-shadow">{selectedMethod === '電話' ? '電話番号' : 'ID / 連絡先'} *</label><input required className={inputClass} value={contactInfo} onChange={e => setContactInfo(e.target.value)} placeholder={`${selectedMethod}の連絡先を入力してください`} /></div>)}
                        </div>
                        <div className="pt-6 border-t border-white/10 text-center pb-10 md:pb-0">
                            <button onClick={handleConfirmBooking} disabled={isPaymentProcessing || !selectedMethod || !contactInfo} className="w-full btn-dawn py-4 font-bold tracking-[0.2em] shadow-lg rounded-full disabled:opacity-50 text-white text-sm md:text-base hover:scale-[1.02] active:scale-95 transition-all">{isPaymentProcessing ? '処理中...' : '対話方法を決定して予約を確定する'}</button>
                            <button onClick={() => setPayingBooking(null)} className="mt-6 text-sm text-gray-400 hover:text-white transition-colors underline">戻る</button>
                        </div>
                    </div>
                ) : !myBookings ? (
                    <div className="p-6 md:p-10 space-y-8 bg-gradient-to-b from-black/60 to-black/80 flex-1 flex flex-col justify-center">
                        <FadeInSection delay={0}><div><label className="block text-sm font-bold text-yellow-400 mb-3 uppercase tracking-widest">メールアドレス</label><input type="email" value={email} onChange={e => setEmail(e.target.value)} className={inputClass} placeholder="example@mail.com" /></div></FadeInSection>
                        <FadeInSection delay={100}><div><DateSelectors dateValue={birthDate} onChange={setBirthDate} label="生年月日" className="w-full" /></div></FadeInSection>
                        <FadeInSection delay={200} className="pt-4"><button onClick={fetchMyBookings} disabled={loading || !email || !birthDate} className="w-full btn-dawn py-4 font-bold tracking-[0.2em] rounded-full shadow-lg">{loading ? '検索中...' : '予約履歴を表示'}</button></FadeInSection>
                    </div>
                ) : (
                    <div className="flex flex-col flex-1 bg-gradient-to-b from-black/60 to-black/80 overflow-hidden animate-fade-in">
                        <div className="flex border-b border-white/10 shrink-0 bg-black/40">
                            <button onClick={() => setActiveTab('upcoming')} className={`flex-1 py-4 text-sm font-bold tracking-widest transition-all duration-300 ${activeTab === 'upcoming' ? 'text-yellow-400 border-b-2 border-yellow-400 bg-white/5' : 'text-gray-500 hover:text-gray-300 hover:bg-white/5'}`}>これからの予約 ({upcoming.length})</button>
                            <button onClick={() => setActiveTab('past')} className={`flex-1 py-4 text-sm font-bold tracking-widest transition-all duration-300 ${activeTab === 'past' ? 'text-yellow-400 border-b-2 border-yellow-400 bg-white/5' : 'text-gray-500 hover:text-gray-300 hover:bg-white/5'}`}>過去の履歴 ({past.length})</button>
                        </div>

                        {activeSessionBooking && activeTab === 'upcoming' && (
                            <div className="m-5 mb-2 bg-gradient-to-r from-purple-900/80 to-indigo-900/80 p-5 rounded-2xl border border-dawnPurple/50 shadow-[0_0_25px_rgba(129,140,248,0.3)] animate-slide-down shrink-0 relative overflow-hidden">
                                <div className="absolute top-0 right-0 w-32 h-32 bg-dawnPurple/10 rounded-full blur-2xl -translate-y-1/2 translate-x-1/3"></div>
                                <div className="flex items-center gap-4 mb-4 relative z-10">
                                    <div className="relative"><img src={activeSessionBooking.teller_image} className="w-14 h-14 rounded-full object-cover border-2 border-dawnGold shadow-lg" /><div className="absolute -bottom-1 -right-1 w-4 h-4 bg-green-500 rounded-full border-2 border-black animate-pulse shadow-[0_0_10px_rgba(34,197,94,0.8)]"></div></div>
                                    <div className="flex-1"><div className="text-xs text-green-400 font-bold tracking-widest mb-1 drop-shadow-md">{activeSessionBooking.isBeforeStart ? '🟢 まもなく鑑定開始 (入室可能)' : '🟢 現在鑑定中'}</div><div className="text-base font-bold font-mincho">{activeSessionBooking.teller_name} 先生</div></div>
                                </div>
                                <div className="bg-black/50 rounded-xl p-4 relative z-10 border border-white/5">
                                    {!showExtensionQR ? (
                                        <button onClick={() => setShowExtensionQR(true)} className="w-full bg-gradient-to-r from-dawnPink to-dawnOrange hover:brightness-110 transition-all text-white text-sm font-bold py-3 rounded-lg shadow-lg flex items-center justify-center gap-2"><Icons.Plus className="w-4 h-4"/> 延長10分 (¥{Number(activeSessionBooking.price_extend10min || 1500).toLocaleString()}) を追加</button>
                                    ) : (
                                        <div className="animate-slide-down">
                                            <PaymentMethodSelector
                                                booking={activeSessionBooking}
                                                amount={activeSessionBooking.price_extend10min || 1500}
                                                isExtension={true}
                                                onPaymentComplete={(msg) => { alert(msg); setShowExtensionQR(false); fetchMyBookings(); }}
                                                onCancel={() => setShowExtensionQR(false)}
                                            />
                                        </div>
                                    )}
                                </div>
                            </div>
                        )}

                        <div className="p-5 md:p-8 overflow-y-auto custom-scrollbar flex-1 pb-24 md:pb-8">
                            {currentList.length === 0 ? (
                                <div className="flex flex-col items-center justify-center h-48 text-gray-500"><Icons.Calendar className="w-12 h-12 mb-4 opacity-50"/><p className="text-sm font-bold tracking-widest">{activeTab === 'upcoming' ? 'これからの予約はありません' : '過去の履歴はありません'}</p></div>
                            ) : (
                                <div className="space-y-5">
                                    {currentList.map((b, index) => {
                                        const isReviewed = localStorage.getItem(`reviewed_${b.id}`);
                                        
                                        return (
                                            <FadeInSection key={b.id} delay={index * 100} className={`bg-white/5 p-5 border border-white/10 rounded-2xl relative overflow-hidden backdrop-blur-sm shadow-lg hover:bg-white/10 transition-colors duration-300 ${activeSessionBooking?.id === b.id ? 'opacity-50' : ''}`}>
                                                {b.status === 'confirmed' && <div className="absolute top-0 right-0 w-20 h-20 bg-gradient-to-bl from-pink-500/20 to-transparent pointer-events-none rounded-tr-2xl"></div>}
                                                {b.status === 'paid' && <div className="absolute top-0 right-0 w-20 h-20 bg-gradient-to-bl from-green-500/20 to-transparent pointer-events-none rounded-tr-2xl"></div>}
                                                <div className="flex gap-5 items-start mb-4 relative z-10">
                                                    <img src={b.teller_image || NO_IMAGE_SRC} alt={b.teller_name} className="w-14 h-14 rounded-full object-cover border-2 border-white/20 shrink-0 shadow-md" />
                                                    <div className="flex-1 min-w-0">
                                                        <div className="flex justify-between items-start mb-2">
                                                            <div>
                                                                <p className="text-yellow-400 font-bold text-sm font-mincho tracking-wider">{(b.booking_date || '').split(' ')[0]}</p>
                                                                <p className="text-white text-sm font-bold tracking-widest mt-0.5">{(b.booking_date || '').split(' ')[1]?.substring(0,5)} 〜</p>
                                                            </div>
                                                            {getStatusBadge(b.status)}
                                                        </div>
                                                        <p className="text-sm text-gray-300 font-bold truncate flex items-center gap-1"><Icons.User className="w-3 h-3 text-gray-500"/> {b.teller_name} 先生</p>
                                                    </div>
                                                </div>
                                                <div className="bg-black/40 rounded-xl p-3 mb-4 flex justify-between items-center text-sm border border-white/5 relative z-10"><span className="text-gray-300 font-medium">{getCourseDisplay(b.course)}</span><span className="text-white font-bold font-serif">¥{b.final_price ? Number(b.final_price).toLocaleString() : '-'}</span></div>
                                                
                                                {b.status === 'confirmed' && activeTab === 'upcoming' && (
                                                    <div className="mt-4 relative z-10">
                                                        <button onClick={() => setPaymentBooking(b)} className="w-full btn-dawn text-white font-bold py-3 rounded-xl shadow-lg text-sm tracking-widest flex items-center justify-center gap-2">
                                                            お支払いへ進む
                                                        </button>
                                                    </div>
                                                )}

                                                {b.status === 'completed' && activeTab === 'past' && !isReviewed && (
                                                    <button onClick={() => setReviewingBooking(b)} className="w-full mb-4 bg-gradient-to-r from-yellow-500/10 to-orange-500/10 border border-yellow-500/50 hover:bg-yellow-500/20 text-yellow-400 py-3 rounded-xl text-xs font-bold flex items-center justify-center gap-2 transition-colors">
                                                        <Icons.Star className="w-4 h-4"/> レビューを投稿する
                                                    </button>
                                                )}
                                                {b.status === 'completed' && activeTab === 'past' && isReviewed && (
                                                    <div className="w-full mb-4 bg-black/40 border border-gray-600/50 text-gray-500 py-3 rounded-xl text-xs font-bold flex items-center justify-center gap-2">
                                                        <Icons.Star className="w-4 h-4"/> レビュー送信済
                                                    </div>
                                                )}
                                                
                                                <div className="flex gap-3 mt-4 relative z-10">
                                                    {b.status === 'pending' && activeTab === 'upcoming' && <button onClick={() => setPayingBooking(b)} className="flex-1 bg-gradient-to-r from-yellow-500 to-orange-500 hover:brightness-110 text-white py-3 rounded-xl text-xs font-bold tracking-widest shadow-lg transition-all hover:-translate-y-0.5">対話方法を選択</button>}
                                                    {(b.status === 'pending' || b.status === 'confirmed') && activeTab === 'upcoming' && <button onClick={() => handleCancel(b.id)} className="px-5 py-3 rounded-xl border border-red-500/50 hover:bg-red-500/10 text-red-400 text-xs font-bold transition-colors">キャンセル</button>}
                                                    {(activeTab === 'past' || b.status === 'cancelled') && <button onClick={() => onRebook(b.fortune_teller_id)} className="flex-1 border border-dawnPurple/50 hover:bg-dawnPurple/10 text-purple-300 py-3 rounded-xl text-xs font-bold flex items-center justify-center gap-2 transition-colors"><Icons.Refresh className="w-4 h-4"/> もう一度予約</button>}
                                                </div>
                                            </FadeInSection>
                                        )
                                    })}
                                </div>
                            )}
                        </div>
                        <div className="p-4 border-t border-white/10 shrink-0 bg-black/40"><button onClick={() => setMyBookings(null)} className="w-full text-gray-500 text-sm hover:text-white transition-colors py-2 font-bold tracking-widest">検索に戻る</button></div>
                    </div>
                )}
            </div>
            
            {reviewingBooking && (
                <ReviewModal 
                    booking={reviewingBooking} 
                    onClose={() => setReviewingBooking(null)} 
                    onSuccess={fetchMyBookings}
                />
            )}
        </div>
    );
};

const TellerProfileModal = ({ teller, onClose, openBooking, openWaitlist }) => {
    const [reviews, setReviews] = useState([]);
    const [loadingReviews, setLoadingReviews] = useState(true);

    useEffect(() => {
        const fetchReviews = async () => {
            try {
                const revData = await window.fetchApi('testimonials_public', { urlParams: `teller_id=${teller.id}` });
                setReviews(revData || []);
            } catch (e) {
                console.error(e);
            } finally {
                setLoadingReviews(false);
            }
        };
        fetchReviews();
    }, [teller.id]);

    const isAvailable = parseInt(teller.is_available) === 1;

    return (
        <div className="fixed inset-0 z-[90] flex items-center justify-center p-0 md:p-4">
            <div className="absolute inset-0 bg-black/80 backdrop-blur-md transition-opacity duration-500" onClick={onClose} />
            <div className="relative w-full h-full md:h-auto md:max-h-[90vh] md:max-w-4xl glass-panel md:rounded-3xl shadow-2xl overflow-hidden flex flex-col animate-slide-down border border-white/20 border-t-4" style={{ borderTopColor: teller.color === 'red' ? '#ef4444' : teller.color === 'blue' ? '#3b82f6' : teller.color === 'green' ? '#22c55e' : teller.color === 'gray' ? '#6b7280' : '#a855f7' }}>
                
                {/* ヘッダー */}
                <div className="p-4 md:p-5 border-b border-white/10 flex justify-between items-center bg-gradient-to-r from-black/80 to-black/40 shrink-0">
                    <span className="text-xs font-bold tracking-widest text-gray-400 uppercase font-cinzel">Profile</span>
                    <button onClick={onClose} className="text-gray-400 hover:text-white text-2xl leading-none w-10 h-10 flex items-center justify-center rounded-full hover:bg-white/10 transition-colors bg-black/50 md:bg-transparent">&times;</button>
                </div>

                <div className="p-6 md:p-10 overflow-y-auto custom-scrollbar flex-1 bg-gradient-to-b from-black/60 to-black/90 text-white">
                    <div className="flex flex-col md:flex-row gap-8 lg:gap-12 items-center md:items-start relative z-10 mb-12">
                        {/* プロフ画像 */}
                        <div className="shrink-0 relative">
                            <div className="w-40 h-40 md:w-56 md:h-56 rounded-full overflow-hidden border-4 border-white/10 shadow-2xl">
                                <img src={teller.image_url || NO_IMAGE_SRC} alt={teller.name} className="w-full h-full object-cover" />
                            </div>
                            <div className="absolute -bottom-3 left-1/2 -translate-x-1/2">
                                <span className={`px-4 py-1.5 rounded-full text-[10px] font-bold tracking-widest uppercase border backdrop-blur-md shadow-lg whitespace-nowrap ${isAvailable ? 'bg-green-500/30 border-green-400 text-green-100 shadow-[0_0_15px_rgba(34,197,94,0.4)]' : 'bg-red-500/30 border-red-400 text-red-100 shadow-[0_0_15px_rgba(239,68,68,0.4)]'}`}>
                                    {isAvailable ? '予約可' : '満了'}
                                </span>
                            </div>
                        </div>

                        {/* プロフ詳細 */}
                        <div className="flex-1 w-full text-center md:text-left">
                            <span className="px-4 py-1.5 bg-white/10 text-yellow-400 text-xs font-bold rounded-full mb-4 inline-block border border-white/20">{teller.role}</span>
                            <h1 className="text-3xl md:text-5xl font-serif font-bold text-white mb-2 text-glow">{teller.name}</h1>
                            
                            {/* 星評価 */}
                            <div className="flex items-center justify-center md:justify-start gap-2 text-yellow-400 mb-6 w-max mx-auto md:mx-0 py-1">
                                <Icons.Star className="w-5 h-5 fill-current drop-shadow-[0_0_8px_rgba(250,204,21,0.5)]" />
                                <span className="font-bold text-xl leading-none text-glow-gold">{Number(teller.avg_rating || 0).toFixed(1)}</span>
                                <span className="text-gray-400 text-sm ml-1">({teller.review_count || 0}件の評価)</span>
                            </div>

                            <p className="text-sm md:text-base text-gray-300 leading-relaxed mb-10 whitespace-pre-wrap">{teller.description}</p>

                            <div className="flex flex-col sm:flex-row gap-4 justify-center md:justify-start">
                                <button 
                                    onClick={() => { onClose(); isAvailable ? openBooking(teller) : openWaitlist(teller); }} 
                                    className={`py-4 px-8 rounded-full text-sm font-bold tracking-[0.2em] transition-all duration-300 shadow-lg ${isAvailable ? 'bg-gradient-to-r from-dawnPink to-dawnOrange text-white hover:scale-105' : 'bg-white/10 text-yellow-400 border border-yellow-400/50 hover:bg-yellow-400/20'}`}
                                >
                                    {isAvailable ? '日時を選んで予約する' : '空き通知を受け取る'}
                                </button>
                            </div>
                        </div>
                    </div>

                    {/* お客様の声 (レビュー) セクション */}
                    <div className="mt-8 border-t border-white/10 pt-10">
                        <h3 className="text-2xl font-serif font-bold text-white mb-8 text-center md:text-left flex items-center justify-center md:justify-start gap-3">
                            <Icons.Quote className="w-6 h-6 text-yellow-400 opacity-80" /> この先生への口コミ・評価
                        </h3>
                        
                        {loadingReviews ? (
                            <div className="py-10 flex justify-center"><Icons.Refresh className="w-8 h-8 animate-spin text-gray-500"/></div>
                        ) : reviews.length === 0 ? (
                            <p className="text-gray-500 text-center py-10 bg-white/5 rounded-2xl border border-white/5">まだ口コミは投稿されていません。</p>
                        ) : (
                            <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
                                {reviews.map(r => (
                                    <div key={r.id} className="bg-white/5 p-6 rounded-2xl relative group hover:bg-white/10 transition-colors border border-white/5">
                                        <Icons.Quote className="absolute top-4 right-4 w-8 h-8 text-white/5 group-hover:text-white/10 transition-colors" />
                                        <div className="flex text-yellow-400 mb-3 drop-shadow-sm">
                                            {[...Array(r.rating || 5)].map((_, i) => <Icons.Star key={i} className="w-4 h-4 fill-current" />)}
                                        </div>
                                        <p className="text-sm text-gray-300 leading-relaxed mb-6 min-h-[3rem]">「{r.testimonial_text}」</p>
                                        <div className="text-xs text-gray-500 flex justify-between items-center border-t border-white/10 pt-4">
                                            <span className="font-bold text-gray-400">{r.customer_name} 様 <span className="font-normal text-[10px] ml-1">{r.age_group}</span></span>
                                            <span className="font-mono bg-black/40 px-2 py-1 rounded">{r.created_at ? r.created_at.split(' ')[0].replace(/-/g, '/') : ''}</span>
                                        </div>
                                    </div>
                                ))}
                            </div>
                        )}
                    </div>
                </div>
            </div>
        </div>
    );
};

// --- ファイルの一番下に追加 ---
window.InfoModal = InfoModal;
window.ReviewModal = ReviewModal;
window.WaitlistModal = WaitlistModal;
window.BookingModal = BookingModal;
window.CheckReservationModal = CheckReservationModal;
window.TellerProfileModal = TellerProfileModal;