PageSourceSearch

https://fortune-cookie.tokyo/login

html fortune-cookie.tokyo collected 2026-10-07 17:57:46 UTC 77,279 bytes, 2,098 lines download raw bytes

1<!doctype html>
2
3<html lang="ja">
4
5<head>
6  
7  
8  
8<script src="https://fortune-cookie.tokyo/assets/js/fortune-cookie-namespace.js?v=1.0.610"></script>
8
9
10  
11  <style>
12    :root {
13      --bottom-right-slot-right: 16px;
14      --bottom-right-slot-bottom: calc(max(80px + env(safe-area-inset-bottom, 0px), var(--bottom-right-slot-bar-footer-nav, 0px), var(--bottom-right-slot-bar-coin-convert, 0px)) + 12px);
15    }
16  </style>
17  
17<script>
18    // 右下の表示枠: claim した部品のうち優先順位の最も高いものだけを出す
19    window.BottomRightSlot = window.BottomRightSlot || (function () {
20      var PRIORITY = JSON.parse('[\u0022offer\u0022,\u0022pwa_mascot\u0022,\u0022pc_qr_panel\u0022]');
21      var claimed = {};
22      var listeners = [];
23
24      function current() {
25        for (var i = 0; i < PRIORITY.length; i++) {
26          if (claimed[PRIORITY[i]]) return PRIORITY[i];
27        }
28        return null;
29      }
30
31      function notify() {
32        var selected = current();
33        for (var i = 0; i < listeners.length; i++) {
34          try { listeners[i](selected); } catch (_e) {}
35        }
36      }
37
38      return {
39        current: current,
40        claim: function (key) {
41          if (claimed[key]) return;
42          claimed[key] = true;
43          notify();
44        },
45        release: function (key) {
46          if (!claimed[key]) return;
47          delete claimed[key];
48          notify();
49        },
50        subscribe: function (fn) {
51          listeners.push(fn);
52          fn(current());
53        },
54        // 要素を、部品 key が選ばれている間だけ出す(claim は呼び出し側が行う)
55        bind: function (el, key) {
56          this.subscribe(function (selected) { el.hidden = selected !== key; });
57        }
58      };
59    })();
60  </script>
60
61  
62  
63  
63<script src="https://fortune-cookie.tokyo/assets/js/pusher-channels.js?v=1.0.610"></script>
63
64
65    <!-- AB テスト variant 情報(GTM 有無に関わらず dataLayer に push する) -->
66  
66<script>
67    window.dataLayer = window.dataLayer || [];
68    window.dataLayer.push({
69      'ab_experiments': JSON.parse('{\u0022exp_review_prompt_timing_v1\u0022:\u0022day3_coin5000\u0022,\u0022exp_entry_price_2607\u0022:\u0022variant_a\u0022,\u0022exp_review_prompt_timing_v2\u0022:\u0022day2_login\u0022}')
70    });
71  </script>
71
72  
73    <!-- Meta Advanced Matching用ユーザーデータ -->
74  
74<script>
75    window.dataLayer = window.dataLayer || [];
76      </script>
76
77  <!-- Google Tag Manager -->
78  
78<script>
vendor: 343 bytes, lines 78-82
78(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
79    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
80    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
81    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
82    })(window,document,'script','dataLayer','
82GTM-W6FMFXKX
vendor: 3 bytes, line 82
82');
82</script>
82
83  <!-- End Google Tag Manager -->
84  
85    
85<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-3033473782328094"
86     crossorigin="anonymous"></script>
vendor: 72 bytes, lines 86-89
86
87  
88  
89  <script async src="https://www.googletagmanager.com/gtag/js?id=
89AW-16587701139
vendor: 16 bytes, lines 89-90
89"></script>
90    
90<script>
91      // dataLayer と gtag は GTM と共存するため、既存があれば流用する(上書きしない)。
92      // Google 公式が示す gtag/js + GTM 併用パターン。
93      window.dataLayer = window.dataLayer || [];
94      window.gtag = window.gtag || function(){ window.dataLayer.push(arguments); };
95      gtag('js', new Date());
96              gtag('config', 'AW-16587701139');
97              gtag('config', 'AW-17961283546');
98              gtag('config', 'AW-18319167511');
99          </script>
99
100    
101    
102        
102<script async src="https://s.yimg.jp/images/listing/tool/cv/ytag.js"></script>
102
103    
103<script>
104      window.yjDataLayer = window.yjDataLayer || [];
105      window.ytag = window.ytag || function(){ window.yjDataLayer.push(arguments); };
106            ytag({
107        "type": "yjad_retargeting",
108        "config": {
109          "yahoo_retargeting_id": 'FFLGSVUI8R',
110          "yahoo_retargeting_label": "",
111          "yahoo_retargeting_page_type": "",
112          "yahoo_retargeting_items": [{ item_id: '', category_id: '', price: '', quantity: '' }]
113        }
114      });
115                  ytag({
116        "type": "yss_retargeting",
117        "config": {
118          "yahoo_ss_retargeting_id": '1001384193',
119          "yahoo_sstag_custom_params": {}
120        }
121      });
122            ytag({
123        "type": "yss_retargeting",
124        "config": {
125          "yahoo_ss_retargeting_id": '1001398501',
126          "yahoo_sstag_custom_params": {}
127        }
128      });
129          </script>
129
130    
131    
132        
132<script>
133      window.FortuneCookie = window.FortuneCookie || {};
134      window.FortuneCookie.adsRemarketing = window.FortuneCookie.adsRemarketing || {};
135      window.FortuneCookie.adsRemarketing.config = {
136        googleConversionIds: JSON.parse('[\u0022AW-16587701139\u0022,\u0022AW-17961283546\u0022,\u0022AW-18319167511\u0022]'),
137        yahooDisplayId: 'FFLGSVUI8R',
138        yahooSearchIds: JSON.parse('[\u00221001384193\u0022,\u00221001398501\u0022]'),
139        purchaseLabel: 'fortunecookie_purchase'
140      };
141    </script>
141
142    
142<script src="https://fortune-cookie.tokyo/assets/js/ads-remarketing-tags.js?v=1.0.610"></script>
142
143    
144  <!-- Required meta tags -->
145<meta charset="utf-8">
146<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
147<meta name="csrf-token" content="LdTtfdwLRURamsmgnFiSP4hkj9k2mbfiBjpreNSz">
148
149<meta name="description" content="ポケカ30thオリパなら『フォーチュンクッキー』!アド確ガチャ業界最多&全品送料無料で安心安全。人気トレカの争奪戦を毎日開催中!友達招待でポケカパックがもらえる。" />
150
151
152
153<!-- Favicon -->
154<link rel="icon" type="image/svg+xml" href="https://fortune-cookie.tokyo/assets/icons/svg/logo.svg">
155
156
157<link rel="manifest" href="https://fortune-cookie.tokyo/manifest.json">
158<meta name="apple-mobile-web-app-capable" content="yes">
159<meta name="apple-mobile-web-app-status-bar-style" content="default">
160<meta name="apple-mobile-web-app-title" content="フォーチュンクッキー">
161
162<meta name="theme-color" content="#030b26">
163<link rel="apple-touch-icon" href="https://fortune-cookie.tokyo/assets/images/apple-touch-icon.png?v=1.0.610">
164<link rel="stylesheet" href="https://fortune-cookie.tokyo/assets/css/pwa-install.css?v=1.0.610">
165
166  
167  <!-- Bootstrap CSS -->
168  <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/normalize.css?v=1.0.610" rel="stylesheet">
169  <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/bootstrap-grid.min.css?v=1.0.610" rel="stylesheet">
170
171  <link rel="stylesheet" href="https://fortune-cookie.tokyo/assets/library/scroll-hint/scroll-hint.css?v=1.0.610">
172  
172<script src="https://fortune-cookie.tokyo/assets/library/scroll-hint/scroll-hint.min.js?v=1.0.610"></script>
172
173
174  <title>ログイン</title>
175    <style>
176			/* ログインページ専用コンテナー */
177			.login-container {
178				min-height: 100vh;
179				padding: 54px 8px 32px;
180			}
181
182			/* ログインページタイトル */
183			.login-title {
184				text-align: center;
185				margin-bottom: 24px;
186				font-size: 20px;
187				font-weight: 700;
188			}
189		</style>
190    <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/foundation.css?v=1.0.610" rel="stylesheet">
191  <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/utility.css?v=1.0.610" rel="stylesheet">
192  <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/layout.css?v=1.0.610" rel="stylesheet">
193  <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/project.css?v=1.0.610" rel="stylesheet">
194  <link href="https://fortune-cookie.tokyo/assets/ECommerce/css/component.css?v=1.0.610" rel="stylesheet">
195  <link href="https://fortune-cookie.tokyo/assets/css/gummy-button.css?v=1.0.610" rel="stylesheet">
196  <link href="https://fortune-cookie.tokyo/assets/css/animation-efficiency.css?v=1.0.610" rel="stylesheet">
197  
198  
198<script src="https://fortune-cookie.tokyo/assets/js/offscreen-animation-pause.js?v=1.0.610" defer></script>
198
199    <link href="https://fortune-cookie.tokyo/assets/Lottery/css/project.css?v=1.0.610" rel="stylesheet" />
200    <link href="https://fortune-cookie.tokyo/assets/css/anniv-half.css?v=1.0.610" rel="stylesheet">
201  <link href="https://fortune-cookie.tokyo/assets/css/dark-mode.css?v=1.0.610" rel="stylesheet">
202  <link href="https://fortune-cookie.tokyo/assets/css/cutin-overlay.css?v=1.0.610" rel="stylesheet">
203  <link href="https://fortune-cookie.tokyo/assets/css/waitlist-entry-complete-popup.css?v=1.0.610" rel="stylesheet">
204  
205  
205<script src="https://fortune-cookie.tokyo/assets/js/countdown-sync-clock.js?v=1.0.610"></script>
205
206  
207    
207<script>
208    window.AUTO_DARK_BATTLE = {
209        lotteryId: 2032,
210        startMs:   1791468000000,
211        endMs:     1791468600000
212    };
213  </script>
213
214    
214<script src="https://fortune-cookie.tokyo/assets/js/dark-mode-auto-trigger.js?v=1.0.610"></script>
214
215  
215<script>
216    const root_url = "https://fortune-cookie.tokyo/";
217    const home_url = "https://fortune-cookie.tokyo/";
218    const admin_url = "https://fortune-cookie.tokyo/admin/";
219    const csrf_token = "LdTtfdwLRURamsmgnFiSP4hkj9k2mbfiBjpreNSz";
220    const languages = ["ja","en",];
221    const cookieLoadingImages = [
222      "https://fortune-cookie.tokyo/assets/images/cookieKun1.png",
223      "https://fortune-cookie.tokyo/assets/images/cookieKun2.png",
224      "https://fortune-cookie.tokyo/assets/images/cookieKun3.png"
225    ];
226    // ログインユーザーID (BigQuery/GA4連携用)
227    window.userId = null;
228  </script>
228
229  
229<script type="application/ld+json">
230    {
231      "@context": "https://schema.org",
232      "@type": "WebSite",
233      "name": "フォーチュンクッキー",
234      "url": "https://fortune-cookie.tokyo/"
235    }
236  </script>
236
237
238  <style>
239    
240:root {
241  --main-color: #FF0000;/* メインカラー */
242  --sub1-color: #FAA;/* サブンカラー */
243  --accent1-color: #08F;/* アクセントカラー */
244  --accent2-color: #f91880;/* アクセントカラー */
245  --base-color: ;/* ベース */
246  --bg-color: #FFF;/* 背景 */
247  --bd-color: #FF0000;/* ボーダーカラー */
248  --font-color: #000;/* フォントカラー */
249  --anchor-color: #000;
250  --hover-color:#FF0000;
251  --hover-bg-color:#FFF;
252  --hover-bd-color:#FF0000;
253  --swiper-theme-color: #FF0000;
254  --bg-sub1-color:#f5f5f5;
255  --sub2-color: #267cd1;
256  --caution-color: #dc3545;
257
258  --bd-width:1px;
259  --radius:5px;
260}        
261
262/*====================================================
263**color
264====================================================*/
265/* variableカラーの変更*/
266.vc-m{
267 --main-color:#FF0000!important;
268 --bd-color:#FF0000!important;
269}
270.vc-s1{
271 --main-color:#FAA!important;
272 --bd-color:#FAA!important;
273}
274
275.vc-a1{
276 --main-color:#08F!important;
277 --bd-color:#08F!important;  
278}
279.vc-a2{
280 --main-color:var(--accent2-color)!important;
281 --bd-color:var(--accent2-color)!important;  
282}
283 .vc-white{
284 --main-color:#fff!important;
285 --bd-color:#fff!important;
286}
287.vc-fc-white{
288 --font-color:#fff!important;
289}
290.vc-black{
291 --main-color:#000!important;
292 --bd-color:#000!important;
293}
294.vc-fc-black{
295 --font-color:#000!important;
296}
297.bg-root{
298 background: var(--bg-color);
299}
300.bg-sub1{
301 background: var(--bg-color);
302}
303        body{font-family: "游ゴシック体", YuGothic, "游ゴシック", "Yu Gothic", sans-serif;}
304html{font-size: 90%;}
305
306  </style>
307        
308  
309  
310    <style>
311    @view-transition {
312      navigation: auto;
313    }
314
315    ::view-transition-group(root),
316    ::view-transition-old(root),
317    ::view-transition-new(root) {
318      animation: none;
319    }
320
321    @media (prefers-reduced-motion: reduce) {
322      ::view-transition-group(*),
323      ::view-transition-old(*),
324      ::view-transition-new(*) {
325        animation: none !important;
326      }
327    }
328  </style>
329    
330    
331  </head>
332
333<body class="anniv-half ">
334    <!-- Google Tag Manager (noscript) -->
vendor: 70 bytes, lines 334-335
334
335  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
335GTM-W6FMFXKX
vendor: 87 bytes, lines 335-337
335"
336  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
337  
337<!-- End Google Tag Manager (noscript) -->
338    
339  <div class="dm-viewport-ring dm-viewport-ring--base" aria-hidden="true"><span class="dm-viewport-ring__spin"></span></div>
340
341      
342      
343    <div id="loading">
344    <div class="loading-content">
345      <img id="loading-image" src="" alt="Loading..." />
346      <div class="loading-text">ガチャ開封中<span class="loading-dots"><span>.</span><span>.</span><span>.</span></span></div>
347    </div>
348  </div>
349      <div id="wrapper" class="wrapper">
350
351    
352              <header class="simple-header">
353    <div class="simple-header-container">
354        
355        <div class="bubble-layer" aria-hidden="true">
356            
357            <span class="bubble bubble--burst" style="left:12%; --size: 38px; animation-delay: -3.2s"></span>
358            <span class="bubble bubble--burst" style="left:38%; --size: 42px; animation-delay: -0.9s"></span>
359            <span class="bubble bubble--burst" style="left:60%; --size: 30px; animation-delay: -4.6s"></span>
360            <span class="bubble bubble--burst" style="left:82%; --size: 34px; animation-delay: -5.4s"></span>
361            
362            <span class="bubble" style="left: 6%; --size: 20px; animation-delay: -1.6s"></span>
363            <span class="bubble" style="left:18%; --size: 14px; animation-delay: -2.7s"></span>
364            <span class="bubble" style="left:26%; --size: 16px; animation-delay: -4.1s"></span>
365            <span class="bubble" style="left:32%; --size: 18px; animation-delay: -0.6s"></span>
366            <span class="bubble" style="left:48%; --size: 22px; animation-delay: -3.3s"></span>
367            <span class="bubble" style="left:56%; --size: 15px; animation-delay: -2.4s"></span>
368            <span class="bubble" style="left:68%; --size: 18px; animation-delay: -0.3s"></span>
369            <span class="bubble" style="left:76%; --size: 20px; animation-delay: -5.0s"></span>
370            <span class="bubble" style="left:90%; --size: 14px; animation-delay: -3.7s"></span>
371            
372            <span class="bubble bubble--sm" style="left: 2%; --size: 5px; animation-delay: -0.2s"></span>
373            <span class="bubble bubble--sm" style="left: 8%; --size: 4px; animation-delay: -1.8s"></span>
374            <span class="bubble bubble--sm" style="left:11%; --size: 7px; animation-delay: -2.6s"></span>
375            <span class="bubble bubble--sm" style="left:15%; --size: 5px; animation-delay: -0.7s"></span>
376            <span class="bubble bubble--sm" style="left:20%; --size: 4px; animation-delay: -2.9s"></span>
377            <span class="bubble bubble--sm" style="left:24%; --size: 6px; animation-delay: -1.4s"></span>
378            <span class="bubble bubble--sm" style="left:29%; --size: 5px; animation-delay: -0.9s"></span>
379            <span class="bubble bubble--sm" style="left:34%; --size: 7px; animation-delay: -2.2s"></span>
380            <span class="bubble bubble--sm" style="left:37%; --size: 4px; animation-delay: -0.5s"></span>
381            <span class="bubble bubble--sm" style="left:41%; --size: 8px; animation-delay: -3.0s"></span>
382            <span class="bubble bubble--sm" style="left:45%; --size: 5px; animation-delay: -1.7s"></span>
383            <span class="bubble bubble--sm" style="left:50%; --size: 4px; animation-delay: -0.3s"></span>
384            <span class="bubble bubble--sm" style="left:53%; --size: 6px; animation-delay: -2.5s"></span>
385            <span class="bubble bubble--sm" style="left:58%; --size: 5px; animation-delay: -1.1s"></span>
386            <span class="bubble bubble--sm" style="left:63%; --size: 7px; animation-delay: -2.8s"></span>
387            <span class="bubble bubble--sm" style="left:66%; --size: 4px; animation-delay: -0.6s"></span>
388            <span class="bubble bubble--sm" style="left:71%; --size: 5px; animation-delay: -2.0s"></span>
389            <span class="bubble bubble--sm" style="left:74%; --size: 6px; animation-delay: -0.8s"></span>
390            <span class="bubble bubble--sm" style="left:78%; --size: 4px; animation-delay: -2.4s"></span>
391            <span class="bubble bubble--sm" style="left:81%; --size: 7px; animation-delay: -1.3s"></span>
392            <span class="bubble bubble--sm" style="left:85%; --size: 5px; animation-delay: -2.7s"></span>
393            <span class="bubble bubble--sm" style="left:88%; --size: 4px; animation-delay: -0.4s"></span>
394            <span class="bubble bubble--sm" style="left:92%; --size: 6px; animation-delay: -1.9s"></span>
395            <span class="bubble bubble--sm" style="left:95%; --size: 5px; animation-delay: -2.3s"></span>
396            <span class="bubble bubble--sm" style="left:97%; --size: 4px; animation-delay: -1.5s"></span>
397            <span class="bubble bubble--sm" style="left:99%; --size: 6px; animation-delay: -3.1s"></span>
398        </div>
399        
400        <div class="logo-section">
401            <a href="https://fortune-cookie.tokyo" class="logo-link" aria-label="フォーチュンクッキー ポケモンカード30th アニバーサリーフェス トップへ">
402                <span class="metal">
403                    <img src="https://fortune-cookie.tokyo/assets/images/pokemon30th_anniversary_fes_logo.png" alt="フォーチュンクッキー ポケモンカード30th アニバーサリーフェス" class="logo-svg">
404                    <span class="metal-sheen" aria-hidden="true"></span>
405                </span>
406            </a>
407        </div>
408
409        
410                                                <!-- 未ログイン時:新規登録・ログインボタン -->
411                <div class="auth-buttons">
412                    <a href="https://fortune-cookie.tokyo/register"
413                       class="gummy-btn gummy-btn-yellow"
414                       onclick="window.FortuneCookie.gtm.fireEvent('register_navigate_button_click', {})">
415                        新規登録
416                    </a>
417                    <a href="https://fortune-cookie.tokyo/login" class="gummy-btn gummy-btn-aqua">ログイン</a>
418                </div>
419                        </div>
420</header>
421
422<style>
423/* simple-header 表示時は wrapper 上余白を 60px にする(layout.css の default 80px を上書き)
424   上部バナー領域 (auction-hook-banner / battle-countdown-banner の top:50px + 高さ) の直下から content が始まるように調整 */
425#wrapper { margin-top: 60px; }
426
427/* iOS Safari / Android で viewport-fit=cover 時の上部セーフエリアを LP gradient の左端色で埋める。
428   meta theme-color だけでは反映されない環境向けの実体オーバーレイ。
429   高さは env(safe-area-inset-top)。非対応端末では 0px で無効化される。 */
430body::before {
431    content: "";
432    position: fixed;
433    top: 0;
434    left: 0;
435    right: 0;
436    height: env(safe-area-inset-top, 0px);
437    background: #ffe45f;
438    z-index: 1001;
439    pointer-events: none;
440}
441
442.simple-header {
443    position: fixed;
444    bottom: 6px;
445    left: 0;
446    right: 0;
447    /* overflow は visible(吹き出しがヘッダー外にはみ出せるようにする) */
448    overflow: visible;
449    /* LP と同じ chaos gradient: 光 → 中央 → 闇 (yellow→green→cyan→blue→purple→black)。
450       resources/views/components/event-lp/world.blade.php の
451       .event-lp-world--chaos .event-lp-world__split と同一 stops */
452    background: linear-gradient(104deg,
453        #ffe45f 0%,   /* L1 yellow */
454        #c6f25a 10%,  /* L2 yellow-green */
455        #5fe8c4 20%,  /* L3 cyan-green */
456        #46c0f2 30%,  /* L4 cyan */
457        #bfeeff 40%,  /* L5 light blue */
458        #c8daff 47%,  /* C1 */
459        #c4b8f0 51%,  /* C2 */
460        #cf7bff 58%,  /* D1 light purple */
461        #8a35ee 68%,  /* D2 purple */
462        #4a17b8 78%,  /* D3 deep purple */
463        #240a72 89%,  /* D4 */
464        #0d0433 100%  /* D5 black-purple */
465    );
466    border-top: none;
467    box-shadow: none;
468    z-index: 1000;
469    height: 50px;
470    /* layout.css の generic `header { padding: var(--xs) }` を打ち消して content の垂直中央を維持 */
471    padding: 0;
472}
473
474.simple-header-container {
475    max-width: 768px;
476    margin: 0 auto;
477    height: 100%;
478    display: flex;
479    align-items: center;
480    justify-content: space-between;
481    padding: 0 10px 0 0;
482    position: relative;
483    z-index: 2;
484}
485
486/* ---- 泡 (bubble) レイヤー ----
487   シャンパンの泡が下から上に立ち上がるイメージ。
488   各 span を bottom 起点で配置し、上方向へ translateY + fade in/out で流す */
489.bubble-layer {
490    position: absolute;
491    inset: 0;
492    pointer-events: none;
493    z-index: 3;
494    overflow: hidden;
495}
496.bubble {
497    position: absolute;
498    bottom: -6px;
499    width: var(--size, 8px);
500    height: var(--size, 8px);
501    border-radius: 50%;
502    background: radial-gradient(
503        circle at 32% 30%,
504        rgba(255, 255, 255, 0.95) 0%,
505        rgba(255, 252, 235, 0.55) 45%,
506        rgba(255, 250, 225, 0.20) 75%,
507        rgba(255, 250, 225, 0.05) 100%
508    );
509    box-shadow:
510        inset 0 0 0 1px rgba(255, 255, 255, 0.55),
511        0 0 3px rgba(255, 250, 220, 0.55);
512    opacity: 0;
513    animation: bubbleRise 5.5s linear infinite;
514}
515
516@keyframes bubbleRise {
517    0%   { transform: translateY(0)    scale(0.7); opacity: 0; }
518    12%  {                                          opacity: 0.85; }
519    85%  {                                          opacity: 0.85; }
520    100% { transform: translateY(-64px) scale(1.0); opacity: 0; }
521}
522
523/* 小玉: 炭酸の細かい泡感。速めに上へ抜けさせ、密度で「シュワッ」を演出 */
524.bubble--sm {
525    animation: bubbleRiseSm 3.2s linear infinite;
526    box-shadow:
527        inset 0 0 0 1px rgba(255, 255, 255, 0.7),
528        0 0 2px rgba(255, 250, 220, 0.6);
529}
530@keyframes bubbleRiseSm {
531    0%   { transform: translateY(0)    scale(0.5); opacity: 0; }
532    18%  {                                          opacity: 0.95; }
533    100% { transform: translateY(-58px) scale(1.0); opacity: 0; }
534}
535
536/* 大玉 (burst): 上端で弾けるように scale 拡大 + blur */
537.bubble--burst {
538    animation: bubbleRiseBurst 6.5s linear infinite;
539}
540@keyframes bubbleRiseBurst {
541    0%   { transform: translateY(0)    scale(0.5); opacity: 0; }
542    10%  {                                          opacity: 0.75; }
543    72%  { transform: translateY(-40px) scale(1.0); opacity: 0.85; }
544    88%  { transform: translateY(-52px) scale(1.15); opacity: 0.55; filter: blur(1px); }
545    100% { transform: translateY(-60px) scale(1.6);  opacity: 0;   filter: blur(3px); }
546}
547
548
549/* ロゴセクション: ポケモンカード30th アニバーサリーフェス画像を配置 */
550.logo-section {
551    flex-shrink: 0;
552    /* .simple-header-container の align-items: center に打ち消されないよう、
553       ロゴだけ top 揃えにして padding-top で 4px の隙間を明示的に確保 */
554    align-self: flex-start;
555    padding-top: 4px;
556    margin-left: 8px;
557    position: relative;
558    z-index: 4;
559}
560
561.logo-link {
562    text-decoration: none;
563    display: block;
564    position: relative;
565    transition: transform 0.2s ease;
566}
567
568.logo-link:hover {
569    transform: scale(1.06);
570}
571
572.logo-svg {
573    /* pokemon30th ロゴは透過余白をトリミング済み (744x512 / as
573pect 1.45:1)。
574       旧・お月見ロゴ (1.5:1) と同アスペクトなので 44px で header (50px) 内に収まる */
575    height: 44px;
576    width: auto;
577    object-fit: contain;
578    display: block;
579    /* LP gradient 背景 (左=明色 / 右=闇) の両端で読ませるため、実体影 + 淡いハイライト */
580    filter:
581        drop-shadow(0 2px 3px rgba(0, 0, 0, 0.55))
582        drop-shadow(0 0 6px rgba(255, 255, 255, 0.35));
583}
584
585/* ---- ロゴの sheen (光沢) アニメ: .metal-sheen を mask-image でロゴ形にクリップし screen blend で光を走らせる ----
586   光は .metal-sheen::before (幅 260%) を transform: translateX で動かす (合成のみで再描画しない)。
587   旧実装 (background-size: 260% の background-position を 180% → -80%) と同じ位置:
588   画像左端 = -1.6W × p → translateX = -1.6 × p / 2.6 (要素幅 2.6W 基準) */
589.metal {
590    position: relative;
591    display: inline-block;
592    isolation: isolate;
593    line-height: 0;
594}
595
596.metal-sheen {
597    position: absolute;
598    inset: 0;
599    pointer-events: none;
600    overflow: hidden;
601
602    /* ロゴの alpha に沿って光を乗せる (透明部分は光らない) */
603    -webkit-mask-image: url('https://fortune-cookie.tokyo/assets/images/pokemon30th_anniversary_fes_logo.png');
604            mask-image: url('https://fortune-cookie.tokyo/assets/images/pokemon30th_anniversary_fes_logo.png');
605    -webkit-mask-size: 100% 100%;
606            mask-size: 100% 100%;
607    -webkit-mask-repeat: no-repeat;
608            mask-repeat: no-repeat;
609
610    mix-blend-mode: screen;
611}
612
613.metal-sheen::before {
614    content: "";
615    position: absolute;
616    top: 0;
617    left: 0;
618    width: 260%;
619    height: 100%;
620    background: linear-gradient(110deg,
621        transparent calc(30% - 11%),
622        rgba(255, 255, 255, 0.23) 30%,
623        transparent calc(30% + 11%),
624        transparent calc(50% - 4% - 11%),
625        rgba(255, 255, 255, 0.32) calc(50% - 4%),
626        rgba(255, 255, 255, 0.90) 50%,
627        rgba(255, 255, 255, 0.32) calc(50% + 4%),
628        transparent calc(50% + 4% + 11%)
629    );
630    background-size: 100% 100%;
631    background-repeat: no-repeat;
632    animation: mh-logo-sheen 7.2s cubic-bezier(.45, .05, .35, 1) infinite;
633}
634
635@keyframes mh-logo-sheen {
636    0%        { transform: translateX(-110.7692%); }
637    60%, 100% { transform: translateX(49.2308%); }
638}
639
640.coin-icon {
641    font-size: 1.4rem;
642}
643
644.coin-svg {
645    width: 20px;
646    height: 20px;
647}
648
649/* 未使用クーポンバッジ(夜空背景でも視認できる暖黄) */
650.coupon-badge {
651    position: absolute;
652    top: -10px;
653    right: -10px;
654    background-color: #FACC15; /* Tailwind yellow-400 */
655    color: #1F2937;
656    font-size: 11px;
657    font-weight: bold;
658    min-width: 20px;
659    height: 20px;
660    border-radius: 10px;
661    display: flex;
662    align-items: center;
663    justify-content: center;
664    padding: 0 4px;
665    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.35);
666    z-index: 10;
667}
668
669.plus-svg {
670    width: 24px;
671    height: 24px;
672    object-fit: contain;
673}
674
675/* 未読バッジ(件数バッジ。ドットバッジ .is-general は既存仕様のまま変更しない) */
676.notice-badge {
677    position: absolute;
678    top: -5px;
679    right: -5px;
680    background-color: #f87878;
681    color: white;
682    font-size: 8px;
683    font-weight: bold;
684    min-width: 13px;
685    height: 13px;
686    border-radius: 6.5px;
687    display: flex;
688    align-items: center;
689    justify-content: center;
690    padding: 0 2px;
691    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
692    z-index: 10;
693}
694
695.notice-badge.is-general {
696    background-color: #0EA5E9;
697    /* 全員宛は数字なしのため、小さい丸にして注意度を抑える(個別宛の赤バッジと差別化) */
698    min-width: 10px;
699    width: 10px;
700    height: 10px;
701    border-radius: 50%;
702    padding: 0;
703    top: -4px;
704    right: -4px;
705}
706
707.notice-icon-svg {
708    width: 18px;
709    height: 15px;
710    display: block;
711}
712
713/* ヘッダー右側のアクション群コンテナ(bingo icon + capsule を横並び) */
714.header-actions {
715    display: flex;
716    align-items: center;
717    gap: 4px;
718    margin-left: auto;
719    position: relative;
720    z-index: 4;
721}
722
723/* ヘッダーカプセル(アバター+名前 / 残高+チャージ / 通知の3タップターゲットを1つのカプセルに集約・v3で帯内固定に変更) */
724.header-capsule {
725    height: 32px;
726    display: flex;
727    align-items: center;
728    padding: 0 8px 0 3px;
729    background: #fff;
730    border-radius: 16px;
731    z-index: 4;
732    /* 夜空背景で浮かせて見せる控えめな影 */
733    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
734}
735
736.header-capsule-target {
737    position: relative;
738    display: flex;
739    align-items: center;
740    height: 100%;
741    text-decoration: none;
742    transition: background-color 0.1s ease-out;
743}
744
745/* 縦方向のみ透明に拡張し、実効タップ領域 44px 以上を確保する(可視背景はここでは描かない。
746   横方向は隣接ターゲットと重ならないよう自身の幅のまま — spec「タップ領域の寸法」) */
747.header-capsule-target::before {
748    content: "";
749    position: absolute;
750    top: -6px;
751    bottom: -6px;
752    left: 0;
753    right: 0;
754}
755
756.header-capsule-target:active {
757    /* 押下フィードバックはタップした領域単位。カプセル全体には広げない・scale は使わない */
758    background: #e6ecff;
759}
760
761.header-capsule-divider {
762    width: 1px;
763    height: 18px;
764    margin: 0 7px;
765    background: #d9d9d9;
766    flex-shrink: 0;
767}
768
769.header-capsule-avatar {
770    width: 26px;
771    height: 26px;
772    border-radius: 50%;
773    flex-shrink: 0;
774    object-fit: cover;
775}
776
777.header-capsule-avatar--fallback {
778    display: flex;
779    align-items: center;
780    justify-content: center;
781    background: radial-gradient(circle at 35% 30%, #ffe066, #fc0 60%, #e6a800);
782}
783
784.header-capsule-name {
785    margin-left: 4px;
786    font-family: 'Noto Sans JP', sans-serif;
787    font-weight: 700;
788    font-size: 11px;
789    color: #6f6969;
790    /* ニックネームは最大10文字(member.profile.update-nickname の max:10)。11em = 全角10文字分 */
791    max-width: 11em;
792    overflow: hidden;
793    text-overflow: ellipsis;
794    white-space: nowrap;
795}
796
797.header-capsule-coin-amount {
798    font-weight: bold;
799    font-size: 13px;
800    color: #6f6969;
801    min-width: 16px;
802    text-align: right;
803}
804
805.header-capsule-coin-add {
806    /* 既存 .coin-add-btn を踏襲(背景は透明のまま) — plus.svg 自体が赤丸+白プラスを内包した自己完結アイコンのため、
807       ここに背景色を追加すると二重の丸になる(既存挙動を変えない、spec「既存 L41-51」) */
808    position: relative;
809    width: 20px;
810    height: 20px;
811    margin-left: 4px;
812    border-radius: 50%;
813    display: flex;
814    align-items: center;
815    justify-content: center;
816    flex-shrink: 0;
817}
818
819.header-capsule-notice-icon {
820    position: relative;
821    width: 18px;
822    height: 15px;
823    margin-right: 2px;
824}
825
826/* 認証ボタン(未ログイン時) */
827.auth-buttons {
828    display: flex;
829    gap: 8px;
830    align-items: center;
831    position: relative;
832    z-index: 4;
833}
834
835.auth-buttons .gummy-btn {
836    width: 80px;
837    height: 32px;
838    font-size: 0.85rem;
839    font-weight: bold;
840    text-decoration: none;
841    display: flex;
842    align-items: center;
843    justify-content: center;
844    border-radius: 16px;
845    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.6);
846}
847
848@media (max-width: 480px) {
849    .auth-buttons {
850        gap: 6px;
851    }
852
853    .auth-buttons .gummy-btn {
854        width: 70px;
855        height: 30px;
856        font-size: 0.8rem;
857    }
858}
859
860@media (prefers-reduced-motion: reduce) {
861    .bubble, .bubble--sm, .bubble--burst { animation: none; opacity: 0; }
862    .metal-sheen::before { animation: none; transform: translateX(-23.3846%); }
863}
864
865/* 新規限定ガチャ詳細 × 未ログイン時の新規登録 CTA 強調 */
866/* 吹き出しは auth-buttons の中、新規登録ボタンの兄弟として配置し、
867   ボタンの左側に position: absolute で重ねる(ボタンに常に追従するため) */
868.auth-buttons--promote {
869    /* .auth-buttons 既存定義で position: relative; z-index: 4 設定済み */
870}
871
872.register-cta-balloon {
873    /* 新規登録ボタンの左隣にオーバーレイ。flex 配置に影響しないよう position: absolute */
874    position: absolute;
875    right: calc(100% - 0px); /* auth-buttons--promote の左端から左方向に */
876    top: 50%;
877    /* gap 用に少し右にずらして余白を作る(margin で吹き出し⇔ボタン間隔を確保) */
878    margin-right: 8px;
879    /* 上下中央寄せ + アニメ初期位置 */
880    transform: translateY(-50%);
881    display: inline-flex;
882    flex-direction: column;
883    align-items: flex-end;
884    background: #FFFFFF;
885    color: #EF4444;
886    font-size: 11px;
887    font-weight: bold;
888    line-height: 1.3;
889    padding: 6px 10px;
890    border-radius: 8px;
891    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
892    white-space: nowrap;
893    pointer-events: none;
894    animation: registerCtaBalloonFloat 2s ease-in-out infinite;
895    z-index: 5; /* auth-buttons (z-index:4) 内で前面 */
896}
897.register-cta-balloon::after {
898    /* 右向き三角の尻尾(新規登録ボタン方向を指す) */
899    content: "";
900    position: absolute;
901    right: -6px;
902    top: 50%;
903    transform: translateY(-50%);
904    border: 6px solid transparent;
905    border-left-color: #FFFFFF;
906    border-right: 0;
907}
908.register-cta-balloon__line {
909    display: block;
910}
911
912@keyframes registerCtaBalloonFloat {
913    0%, 100% { transform: translateY(-50%); }
914    50%      { transform: translateY(calc(-50% - 4px)); }
915}
916
917@media (max-width: 360px) {
918    /* 320px 等の超小型画面でロゴと重なる可能性があるため、フォントãƒ
918»ãƒ‘ディングを縮小 */
919    .register-cta-balloon {
920        font-size: 10px;
921        padding: 4px 7px;
922    }
923}
924
925@media (prefers-reduced-motion: reduce) {
926    .register-cta-balloon { animation: none; }
927}
928</style>
929<script>
930// ロゴクリックで TOP へ行くときは常に先頭表示にする(スクロール位置の復元をスキップ)。
931// 「明示的に TOP へ行く操作=先頭から見たい」「ブラウザバック=続きから見たい」の切り分け。
932// キー名は top-page.js / top.blade.php の navigate() と共有(変更時は3箇所同時に修正すること)。
933// 修飾キー付きクリック(新規タブ/ウィンドウで開く)は現タブのフラグを汚さないよう除外する。
934// 中クリックは click ではなく auxclick になるためこのハンドラには元々到達しない
935// (e.button チェックは古いブラウザ向けの保険)。
936document.addEventListener('click', function (e) {
937    var link = e.target.closest('a.logo-link');
938    if (!link || e.defaultPrevented) return;
939    if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
940    try {
941        sessionStorage.setItem('top_skip_restore', '1');
942        sessionStorage.removeItem('top_scroll_y');
943    } catch (err) {}
944});
945</script>
945
946    
947      
948      
949      
950            
951      
952                
953      
954      
955      
956      
957      
957<script>
958        window.SE_CONFIG = JSON.parse('{\u0022files\u0022:{\u0022auction-bid-oneclock\u0022:\u0022https:\\\/\\\/fortune-cookie.tokyo\\\/uploads\\\/owner\\\/%E3%80%90%E3%82%AA%E3%83%BC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%80%91%E5%85%A5%E6%9C%AD_202607292054.mp3?v=1.0.610\u0022,\u0022auction-bid-double-push\u0022:\u0022https:\\\/\\\/fortune-cookie.tokyo\\\/uploads\\\/owner\\\/%E3%80%90%E3%82%AA%E3%83%BC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%80%91%E5%80%8D%E3%83%97%E3%83%83%E3%82%B7%E3%83%A5_202607292056.mp3?v=1.0.610\u0022,\u0022cutin\u0022:\u0022https:\\\/\\\/fortune-cookie.tokyo\\\/uploads\\\/owner\\\/%E3%80%90%E3%82%AA%E3%83%BC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%80%91%E5%88%9D%E5%85%A5%E6%9C%AD_202607292053_1.mp3?v=1.0.610\u0022,\u0022auction-card-select\u0022:\u0022https:\\\/\\\/fortune-cookie.tokyo\\\/uploads\\\/owner\\\/%E3%80%90%E3%82%AA%E3%83%BC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%80%91%E3%82%AB%E3%83%BC%E3%83%89%E9%81%B8%E6%8A%9E_202607292053.mp3?v=1.0.610\u0022},\u0022volume\u0022:1}');
959      </script>
959
960      
960<script src="https://fortune-cookie.tokyo/assets/js/se-effects.js?v=1.0.610"></script>
960
961      
961<script src="https://fortune-cookie.tokyo/assets/js/cutin-overlay.js?v=1.0.610"></script>
961
962
963      <!-- LOGIN CONTAINER -->
964	<div class="login-container">
965		<!-- ロゴ -->
966		<div style="text-align: center; margin-bottom: 24px;">
967			<img src="https://fortune-cookie.tokyo/assets/images/logo_font.png" alt="Logo" style="max-width: 280px; height: auto;">
968		</div>
969
970		
971		
972		<div class="login-title">ログイン</div>
973
974		<!-- アカウント選択ボタン(ログイン用) -->
975		<!-- アカウント選択ボタン -->
976<div class="account-select-buttons-wrap">
977	<!-- X(Twitter)ボタン -->
978		<a href="https://fortune-cookie.tokyo/auth/twitter?mode=login"
979	   class="account-select-btn x-btn"
980	   	   >
981		<img src="https://fortune-cookie.tokyo/assets/icons/svg/x_logo.svg" alt="X">
982		<span>Xで続ける</span>
983			</a>
984	
985	<!-- LINEボタン -->
986		<a href="https://fortune-cookie.tokyo/auth/line?mode=login"
987	   class="account-select-btn line-btn"
988	   	   >
989		<img src="https://fortune-cookie.tokyo/assets/icons/svg/line_logo.svg" alt="LINE">
990		<span>LINEで続ける</span>
991			</a>
992	
993	<!-- Googleボタン -->
994		<a href="https://fortune-cookie.tokyo/auth/google?mode=login"
995	   class="account-select-btn google-btn"
996	   	   >
997		<img src="https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/google.svg" alt="Google">
998		<span>Googleで続ける</span>
999			</a>
1000	
1001	<!-- メールボタン -->
1002		<a href="https://fortune-cookie.tokyo/login_email"
1003	   class="account-select-btn email-btn"
1004	   >
1005		<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1006			<path d="M20 4H4C2.9 4 2.01 4.9 2.01 6L2 18C2 19.1 2.9 20 4 20H20C21.1 20 22 19.1 22 18V6C22 4.9 21.1 4 20 4ZM20 8L12 13L4 8V6L12 11L20 6V8Z" fill="#333"/>
1007		</svg>
1008		<span>メールで続ける</span>
1009			</a>
1010	</div>
1011
1012<style>
1013	/* アカウント選択ボタンラッパー */
1014	.account-select-buttons-wrap {
1015		max-width: 400px;
1016		margin: 0 auto;
1017		padding: 0 16px;
1018	}
1019
1020	/* アカウント選択ボタンスタイル */
1021	.account-select-btn {
1022		width: 100%;
1023		height: 46px;
1024		border-radius: 23px;
1025		display: flex;
1026		align-items: center;
1027		justify-content: center;
1028		text-decoration: none;
1029		font-size: 16px;
1030		font-weight: 600;
1031		margin-bottom: 16px;
1032		transition: transform 0.2s, box-shadow 0.2s;
1033		border: none;
1034		cursor: pointer;
1035		gap: 12px;
1036		position: relative;
1037		padding: 0 16px;
1038	}
1039
1040	.account-select-btn:hover {
1041		transform: translateY(-2px);
1042		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1043	}
1044
1045	.account-select-btn img {
1046		width: 24px;
1047		height: 24px;
1048	}
1049
1050	.account-select-btn.x-btn {
1051		background-color: #000;
1052		color: #fff;
1053	}
1054
1055	.account-select-btn.line-btn {
1056		background-color: #06C755;
1057		color: #fff;
1058	}
1059
1060	.account-select-btn.google-btn {
1061		background-color: #fff;
1062		color: #333;
1063		border: 2px solid #ddd;
1064	}
1065
1066	.account-select-btn.email-btn {
1067		background-color: #e0e0e0;
1068		color: #333;
1069	}
1070
1071	/* 最終使用バッジ */
1072	.last-used-badge {
1073		position: absolute;
1074		right: 12px;
1075		font-size: 11px;
1076		font-weight: 500;
1077		padding: 2px 8px;
1078		border-radius: 10px;
1079		line-height: 1;
1080		white-space: nowrap;
1081	}
1082
1083	/* 暗い背景のボタン用(X) */
1084	.last-used-badge--light {
1085		background-color: rgba(255, 255, 255, 0.25);
1086		color: rgba(255, 255, 255, 0.9);
1087	}
1088
1089	/* 明るい背景のボタン用(Google・メール) */
1090	.last-used-badge--dark {
1091		background-color: rgba(0, 0, 0, 0.1);
1092		color: rgba(0, 0, 0, 0.6);
1093	}
1094</style>
1095	</div>
1096
1097          <footer style="background-color: #FFED93; height: 300px; display: flex;">
1098  <div style="margin: 0 auto;">
1099    <!-- タイトル -->
1100    <div class="mb-4">
1101      <h3 style="font-size: 18px; font-weight: bold; margin: 20px 0; color: #4A5568;">フォーチュンクッキーについて</h3>
1102    </div>
1103    
1104    <!-- ボタンエリア -->
1105    <div class="mb-4">
1106      <a href="https://fortune-cookie.tokyo/page/terms" style="color: #4A5568; text-decoration: none; display: block; margin-bottom: 6px; font-size: 12px;" onmouseover="this.style.color='#2D3748'; this.style.textDecoration='underline';" onmouseout="this.style.color='#4A5568'; this.style.textDecoration='none';">利用規約</a>
1107      <a href="https://fortune-cookie.tokyo/page/privacy" style="color: #4A5568; text-decoration: none; display: block; margin-bottom: 6px; font-size: 12px;" onmouseover="this.style.color='#2D3748'; this.style.textDecoration='underline';" onmouseout="this.style.color='#4A5568'; this.style.textDecoration='none';">プライバシーポリシー</a>
1108      <a href="https://fortune-cookie.tokyo/page/tradelaw" style="color: #4A5568; text-decoration: none; display: block; margin-bottom: 6px; font-size: 12px;" onmouseover="this.style.color='#2D3748'; this.style.textDecoration='underline';" onmouseout="this.style.color='#4A5568'; this.style.textDecoration='none';">特定商法取引に基づく規約</a>
1109    </div>
1110    
1111    <!-- ロゴエリア -->
1112    <div style="display: flex; align-items: center; color: #4A5568;">
1113      <img src="https://fortune-cookie.tokyo/assets/images/full_logo.png" alt="ロゴ" style="height: 40px; width: auto;">
1114    </div>
1115  </div>
1116</footer>    
1117      </div>
1118    <div id="gray-layer"></div>
1119  <div id="to_top"><a href="#" class="to-btn"><i class="fas fa-chevron-up"></i><br><span class="text">TOP</span></a></div>
1120  
1121    
1122  <!-- END WRAPPER -->
1123  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.1/css/all.css">
1124  <link rel="preconnect" href="https://fonts.googleapis.com">
1125  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
1126  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;500;700&display=swap" rel="stylesheet">
1127
1128  <!-- Option 1: Bootstrap Bundle with Popper -->
1129  
1129<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
1129
1130  
1130<script src="https://fortune-cookie.tokyo/assets/ECommerce/js/common.js?v=1.0.610"></script>
1130
1131  
1131<script src="https://fortune-cookie.tokyo/assets/ECommerce/js/main.js?v=1.0.610"></script>
1131
1132  
1132<script src="https://fortune-cookie.tokyo/assets/ECommerce/js/functions.js?v=1.0.610"></script>
1132
1133    
1133<script src="https://fortune-cookie.tokyo/assets/Lottery/js/main.js?v=1.0.610"></script>
1133
1134  
1134<script src="https://fortune-cookie.tokyo/assets/Lottery/js/functions.js?v=1.0.610"></script>
1134
1135    
1135<script src="https://fortune-cookie.tokyo/assets/js/click.js?v=1.0.610"></script>
1135
1136  
1136<script src="https://fortune-cookie.tokyo/assets/js/utilities.js?v=1.0.610"></script>
1136
1137  
1137<script src="https://fortune-cookie.tokyo/assets/js/common.js?v=1.0.610"></script>
1137
1138  
1138<script src="https://fortune-cookie.tokyo/assets/js/validation.js?v=1.0.610"></script>
1138
1139  
1139<script src="https://fortune-cookie.tokyo/assets/js/ajax.js?v=1.0.610"></script>
1139
1140  
1140<script src="https://fortune-cookie.tokyo/assets/js/autokana.js?v=1.0.610"></script>
1140
1141  
1141<script src="https://fortune-cookie.tokyo/assets/js/zip-search.js?v=1.0.610"></script>
1141
1142  
1142<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/fetch-jsonp.min.js"></script>
1142
1143
1144  
1145  
1146  
1147  
1148  
1149      
1150  
1151  
1152  
1153          
1154    
1155          
1156  
1157  
1158  
1159  
1160  
1161  
1162  
1163      
1164    
1165  
1166
1167    <!-- タップ時の星エフェクト(軽量版) -->
1168  <style>
1169    .tap-star {
1170      position: fixed;
1171      pointer-events: none;
1172      z-index: 99999;
1173      animation: starBurst 0.8s ease-out forwards;
1174    }
1175
1176    .tap-star svg {
1177      width: 100%;
1178      height: 100%;
1179    }
1180
1181    @keyframes starBurst {
1182      0% {
1183        transform: translate(-50%, -50%) scale(0.5);
1184        opacity: 0;
1185      }
1186      30% {
1187        opacity: 1;
1188      }
1189      100% {
1190        transform: translate(-50%, -50%) translate(var(--burst-x), var(--burst-y)) scale(0.8);
1191        opacity: 0;
1192      }
1193    }
1194  </style>
1195
1196  
1196<script>
1197    // タップエフェクト(軽量版)
1198    (function() {
1199      // 黄色の星SVG
1200      const starSVG = `<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
1201        <path d="M 50,15 L 61,45 L 92,45 L 68,63 L 78,93 L 50,73 L 22,93 L 32,63 L 8,45 L 39,45 Z"
1202              fill="#FFE082"/>
1203      </svg>`;
1204
1205      // スクロール中フラグ
1206      let isScrolling = false;
1207      let scrollTimeout;
1208      let lastClickTime = 0;
1209
1210      // スクロール検出(passive: trueでパフォーマンス向上)
1211      window.addEventListener('scroll', function() {
1212        isScrolling = true;
1213        clearTimeout(scrollTimeout);
1214        scrollTimeout = setTimeout(function() {
1215          isScrolling = false;
1216        }, 100);
1217      }, { passive: true });
1218
1219      document.addEventListener('click', function(e) {
1220        const now = Date.now();
1221
1222        // スクロール中、または連続クリック(100ms以内)は無視
1223        if (isScrolling || now - lastClickTime < 100) return;
1224
1225        lastClickTime = now;
1226
1227        // 星を7個生成
1228        const starCount = 7;
1229
1230        for (let i = 0; i < starCount; i++) {
1231          const star = document.createElement('div');
1232          star.className = 'tap-star';
1233          star.innerHTML = starSVG;
1234
1235          // ランダムなサイズ(20px〜40px)
1236          const size = 20 + Math.random() * 20;
1237          star.style.width = size + 'px';
1238          star.style.height = size + 'px';
1239
1240          // クリック位置を設定
1241          star.style.left = e.clientX + 'px';
1242          star.style.top = e.clientY + 'px';
1243
1244          // ランダムな角度に飛び散る
1245          const angle = (Math.PI * 2 * i) / starCount + (Math.random() - 0.5) * 0.5;
1246          const distance = 50 + Math.random() * 30;
1247          const burstX = Math.cos(angle) * distance;
1248          const burstY = Math.sin(angle) * distance;
1249
1250          star.style.setProperty('--burst-x', burstX + 'px');
1251          star.style.setProperty('--burst-y', burstY + 'px');
1252
1253          document.body.appendChild(star);
1254
1255          // アニメーション終了後に削除
1256          setTimeout(() => star.remove(), 850);
1257        }
1258      });
1259    })();
1260  </script>
1260
1261  
1262    
1263  
1264  <!-- 汎用的なメッセージポップアップコンポーネント -->
1265<div id="messagePopup" class="message-popup" style="display: none;">
1266    <div class="message-popup-overlay" onclick="closeMessagePopup()"></div>
1267    <div class="message-popup-content">
1268        <h3 id="messagePopupTitle" class="message-popup-title"></h3>
1269        <p id="messagePopupBody" class="message-popup-body"></p>
1270        <div class="message-popup-footer" id="messagePopupFooter">
1271            <!-- アクションボタン(条件付きで表示) -->
1272            <a class="gummy-btn gummy-btn-yellow" id="messagePopupActionBtn" style="display: none; width: 100%; margin-bottom: 8px;">
1273                <span id="messagePopupActionBtnText"></span>
1274                <span class="shine-right"></span>
1275            </a>
1276            <!-- 閉じるボタン -->
1277            <button type="button" class="btn-yellow-frame" id="messagePopupCloseBtn" onclick="closeMessagePopup()">
1278                閉じる
1279            </button>
1280        </div>
1281    </div>
1282</div>
1283
1284<style>
1285.message-popup {
1286    position: fixed;
1287    top: 0;
1288    left: 0;
1289    width: 100%;
1290    height: 100%;
1291    /* 他のオーバーレイ(ガチャ通知 popup 等、z-index 9999999)の上に表示する */
1292    z-index: 10000001;
1293}
1294
1295.message-popup-overlay {
1296    position: absolute;
1297    top: 0;
1298    left: 0;
1299    width: 100%;
1300    height: 100%;
1301    background-color: rgba(0, 0, 0, 0.5);
1302}
1303
1304.message-popup-content {
1305    position: absolute;
1306    top: 50%;
1307    left: 50%;
1308    transform: translate(-50%, -50%);
1309    display: flex;
1310    width: 343px;
1311    padding: 24px 16px;
1312    flex-direction: column;
1313    align-items: center;
1314    gap: 16px;
1315    border-radius: 8px;
1316    border: 2px solid #D9D9D9;
1317    background: #FFF;
1318    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1319    animation: none;
1320    transition: none;
1321}
1322
1323.message-popup-title {
1324    margin: 0;
1325    font-size: 20px;
1326    font-weight: 700;
1327    color: #333;
1328    text-align: center;
1329    white-space: nowrap;
1330    overflow: hidden;
1331    text-overflow: ellipsis;
1332    max-width: 100%;
1333}
1334
1335.message-popup-body {
1336    margin: 0;
1337    font-size: 16px;
1338    font-weight: 400;
1339    line-height: 1.6;
1340    color: #333;
1341    text-align: center;
1342    white-space: pre-line; /* 改行文字を正しく表示 */
1343}
1344
1345.message-popup-footer {
1346    display: flex;
1347    flex-direction: column;
1348    align-items: center;
1349    width: 100%;
1350    margin-top: 8px;
1351}
1352
1353.message-popup-footer .btn-yellow-frame {
1354    width: 300px;
1355    height: 32px;
1356    padding: 8px 16px;
1357}
1358
1359.message-popup-footer .gummy-btn {
1360    min-height: 32px;
1361    padding: 8px 16px;
1362}
1363</style>
1364
1365<script>
1366// 関数が未定義の場合のみ定義(重複定義を防ぐ)
1367if (typeof showMessagePopup === 'undefined') {
1368    // 閉じるボタンのコールバックを保持する変数
1369    let messagePopupCloseCallback = null;
1370
1371    /**
1372     * メッセージポップアップを表示する
1373     * @param {string} title - ポップアップのタイトル
1374     * @param {string} body - ポップアップの本文(\nで改行)
1375     * @param {string|function} actionButton - アクションボタン(URLまたは関数、省略可)
1376     * @param {string} buttonMessage - アクションボタンのテキスト(省略可)
1377     * @param {function} closeCallback - 閉じるボタンのコールバック(省略可)
1378     * @param {string} closeBtnText - 閉じるボタンのテキスト(省略可、デフォルト: '閉じる')
1379     * @param {string} actionBtnColor - アクションボタンの色クラス(省略可、デフォルト: 'gummy-btn-yellow')
1380     */
1381    window.showMessagePopup = function(title, body, actionButton, buttonMessage, closeCallback, closeBtnText, actionBtnColor) {
1382        // 閉じるボタンのコールバックを保存
1383        messagePopupCloseCallback = closeCallback || null;
1384        // タイトルを設定(XSS対策: textContentを使用)
1385        const titleEl = document.getElementById('messagePopupTitle');
1386        titleEl.style.fontSize = '20px'; // リセット
1387        titleEl.textContent = title;
1388        // タイトルが溢れる場合はフォントサイズを自動縮小
1389        requestAnimationFrame(function() {
1390            let fontSize = 20;
1391            while (titleEl.scrollWidth > titleEl.clientWidth && fontSize > 12) {
1392                fontSize--;
1393                titleEl.style.fontSize = fontSize + 'px';
1394            }
1395        });
1396
1397        // 本文を設定(XSS対策: textContentを使用、改行はCSSで処理)
1398        const bodyElement = document.getElementById('messagePopupBody');
1399        // body が {html: '...'} オブジェクトの場合のみ innerHTML 経由で HTML を許可。
1400        // 呼び出し側で HTML エスケープ済みであることが前提 (Blade {{ }} や e() で escape してから
1401        // <strong>...</strong> 等の限定タグのみを含める運用)。
1402        if (body && typeof body === 'object' && typeof body.html === 'string') {
1403            bodyElement.innerHTML = body.html;
1404        } else {
1405            bodyElement.textContent = body;
1406        }
1407
1408        // 閉じるボタンのテキストを設定
1409        document.getElementById('messagePopupCloseBtn').textContent = closeBtnText || '閉じる';
1410
1411        // アクションボタンの表示制御
1412        const actionBtn = document.getElementById('messagePopupActionBtn');
1413        if (actionButton && buttonMessage) {
1414            // ボタンテキストを設定
1415            document.getElementById('messagePopupActionBtnText').textContent = buttonMessage;
1416
1417            // ボタンの色クラスを設定
1418            actionBtn.className = 'gummy-btn ' + (actionBtnColor || 'gummy-btn-yellow');
1419            actionBtn.style.width = '100%';
1420            actionBtn.style.marginBottom = '8px';
1421
1422            // ボタンを表示
1423            actionBtn.style.display = 'flex';
1424
1425            // アクションが文字列(URL)の場合はhrefを設定(url-auto-appendが自動でパラメータ付与)
1426            if (typeof actionButton === 'string') {
1427                actionBtn.href = actionButton;
1428                actionBtn.removeAttribute('data-action-fn');
1429            }
1430            // アクションが関数の場合はclickイベントで実行
1431            else if (typeof actionButton === 'function') {
1432                actionBtn.removeAttribute('href');
1433                actionBtn.setAttribute('data-action-fn', 'true');
1434
1435                // 既存のイベントリスナーを削除(重複防止)
1436                const newActionBtn = actionBtn.cloneNode(true);
1437                actionBtn.parentNode.replaceChild(newActionBtn, actionBtn);
1438
1439                document.getElementById('messagePopupActionBtn').addEventListener('click', function() {
1440                    actionButton();
1441                    closeMessagePopup();
1442                });
1443            }
1444        } else {
1445            // アクションボタンを非表示
1446            actionBtn.style.display = 'none';
1447        }
1448
1449        // ポップアップを表示
1450        document.getElementById('messagePopup').style.display = 'block';
1451    };
1452
1453    /**
1454     * メッセージポップアップを閉じる
1455     */
1456    window.closeMessagePopup = function() {
1457        document.getElementById('messagePopup').style.display = 'none';
1458
1459        // 閉じるボタンのコールバックが設定されている場合は実行
1460        if (messagePopupCloseCallback && typeof messagePopupCloseCallback === 'function') {
1461            messagePopupCloseCallback();
1462            messagePopupCloseCallback = null; // 実行後にクリア
1463        }
1464    };
1465}
1466</script>
1466
1467          
1468  
1469  
1470  
1471  
1472  
1473  <div id="waitlistEntryCompletePopup" class="wec-popup" style="display: none;">
1474    <div class="wec-overlay" onclick="closeWaitlistEntryCompletePopup()"></div>
1475    <div class="wec-content">
1476        <h3 class="wec-title">エントリー完了</h3>
1477        
1478        <div id="wecThumbnailWrap" class="rainbow-border-wrapper wec-thumbnail-wrap" style="display:none;">
1479            <img id="wecThumbnail" class="wec-thumbnail" src="" alt="">
1480        </div>
1481        
1482        <div id="wecEntryBlock" class="wec-entry-block" style="display:none;">
1483            <div class="wec-entry-block__no">エントリー<span class="wec-entry-block__no-label">No.</span><span id="wecEntryBlockNo" class="wec-entry-block__no-value"></span></div>
1484            <div class="wec-entry-block__self">
1485                <img id="wecEntryBlockIcon" class="wec-entry-block__icon" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="">
1486                <span id="wecEntryBlockName" class="wec-entry-block__name"></span>
1487            </div>
1488        </div>
1489        
1490        <div id="wecRecentEntrants" class="waitlist-users-section waitlist-users-below wec-recent-entrants" style="display:none;">
1491            <span class="waitlist-entry-label">エントリー済み:</span>
1492            <div class="waitlist-users-icons" id="wecRecentEntrantsIcons"></div>
1493        </div>
1494        <strong id="wecEventDate" class="wec-event-date" style="display:none;"></strong>
1495        <div class="wec-footer">
1496            <a href="#"
1497               id="wecCalendarBtn"
1498               class="gummy-btn gummy-btn-yellow gummy-btn-rainbow-ring wec-calendar-btn"
1499               style="display: none;">
1500                <span>📅 カレンダーに登録する</span>
1501                <span class="gummy-btn-rainbow-ring-shell"></span>
1502                <span class="shine-right"></span>
1503            </a>
1504            <a href="javascript:void(0)" class="wec-close-link" onclick="closeWaitlistEntryCompletePopup()">閉じる</a>
1505        </div>
1506    </div>
1507</div>
1508
1509
1510
1511<script>
1512if (typeof window.showWaitlistEntryCompletePopup === 'undefined') {
1513    /**
1514     * エントリー完了ポップアップを表示する
1515     * @param {object} [options]
1516     * @param {string} [options.calendarUrl]    - .ics エンドポイント URL(iOS / PC 用)
1517     * @param {string} [options.gcalUrl]        - Google Calendar URL(Android 用)
1518     * @param {string} [options.shareFileName]  - ダウンロード時のファイル名
1519     * @param {string} [options.playType]       - 'battle' / 'raid' / null
1520     * @param {number|string} [options.lotteryId]  - GA4 計測用
1521     * @param {string} [options.startDate]      - ISO8601 開催日時文字列
1522     * @param {string} [options.lotteryImage]   - サムネイル画像 URL
1523     * @param {number} [options.entryNumber]    - 自分は何番目のエントリーか(1-based)
1524     * @param {number} [options.otherEntrantsCount]  - 自分を除いた全体件数
1525     * @param {Array<{icon_url: string}>} [options.recentEntrants] - 直近エントリー者アイコン列
1526     * @param {string} [options.selfName]       - 大きな赤ブロックに表示する自分の名前
1527     * @param {string} [options.selfIconUrl]    - 大きな赤ブロックに表示する自分のアイコン URL
1528     */
1529    function wecFormatEventDate(isoString) {
1530        var DAYS_JA = ['日', '月', '火', '水', '木', '金', '土'];
1531        var d = new Date(isoString);
1532        if (isNaN(d.getTime())) return '';
1533        var month = d.getMonth() + 1;
1534        var day = d.getDate();
1535        var dayOfWeek = DAYS_JA[d.getDay()];
1536        var hours = d.getHours();
1537        var minutes = ('0' + d.getMinutes()).slice(-2);
1538        return month + '月' + day + '日(' + dayOfWeek + ') ' + hours + ':' + minutes + '〜';
1539    }
1540
1541    window.showWaitlistEntryCompletePopup = function(options) {
1542        options = options || {};
1543        var popup = document.getElementById('waitlistEntryCompletePopup');
1544        if (!popup) return;
1545
1546        // サムネイル + 虹枠ラッパー
1547        var thumbEl = document.getElementById('wecThumbnail');
1548        var thumbWrapEl = document.getElementById('wecThumbnailWrap');
1549        if (thumbEl && thumbWrapEl) {
1550            if (options.lotteryImage) {
1551                thumbEl.src = options.lotteryImage;
1552                thumbWrapEl.style.display = 'block';
1553            } else {
1554                thumbWrapEl.style.display = 'none';
1555            }
1556        }
1557
1558        // 大きな赤ブロック(エントリー No. + 自分のアイコン + 名前)
1559        var entryBlockEl = document.getElementById('wecEntryBlock');
1560        var entryBlockNoEl = document.getElementById('wecEntryBlockNo');
1561        var entryBlockIconEl = document.getElementById('wecEntryBlockIcon');
1562        var entryBlockNameEl = document.getElementById('wecEntryBlockName');
1563        if (entryBlockEl && entryBlockNoEl && entryBlockIconEl && entryBlockNameEl) {
1564            if (typeof options.entryNumber === 'number' && options.entryNumber > 0) {
1565                entryBlockNoEl.textContent = String(options.entryNumber);
1566                if (options.selfIconUrl) {
1567                    entryBlockIconEl.src = String(options.selfIconUrl);
1568                }
1569                entryBlockNameEl.textContent = options.selfName ? String(options.selfName) : '';
1570                entryBlockEl.style.display = 'block';
1571            } else {
1572                entryBlockEl.style.display = 'none';
1573            }
1574        }
1575
1576        // 直近エントリー者: gacha-card の .waitlist-users-section 構造をそのまま再現
1577        // (アイコンは負マージン -8px で少し重ねる、超過分は "...")
1578        var recentEntrantsEl = document.getElementById('wecRecentEntrants');
1579        var recentEntrantsIconsEl = document.getElementById('wecRecentEntrantsIcons');
1580        if (recentEntrantsEl && recentEntrantsIconsEl) {
1581            var otherCount = typeof options.otherEntrantsCount === 'number' ? options.otherEntrantsCount : 0;
1582            var entrants = Array.isArray(options.recentEntrants) ? options.recentEntrants : [];
1583            var MAX_ICONS = 5;
1584            if (otherCount > 0) {
1585                while (recentEntrantsIconsEl.firstChild) {
1586                    recentEntrantsIconsEl.removeChild(recentEntrantsIconsEl.firstChild);
1587                }
1588                var displayed = 0;
1589                for (var i = 0; i < entrants.length && displayed < MAX_ICONS; i++) {
1590                    var url = entrants[i] && entrants[i].icon_url ? String(entrants[i].icon_url) : '';
1591                    if (!url) continue;
1592                    var iconWrap = document.createElement('div');
1593                    iconWrap.className = 'waitlist-user-icon';
1594                    iconWrap.style.marginLeft = displayed > 0 ? '-8px' : '0';
1595                    iconWrap.style.zIndex = String(10 - displayed);
1596                    var img = document.createElement('img');
1597                    img.src = url;
1598                    img.alt = '';
1599                    img.loading = 'lazy';
1600                    iconWrap.appendChild(img);
1601                    recentEntrantsIconsEl.appendChild(iconWrap);
1602                    displayed++;
1603                }
1604                // 表示上限超え or ellipsis flag
1605                if (otherCount > displayed) {
1606                    var ellipsis = document.createElement('div');
1607                    ellipsis.className = 'waitlist-user-ellipsis';
1608                    ellipsis.style.marginLeft = '4px';
1609                    var span = document.createElement('span');
1610                    span.textContent = '...';
1611                    ellipsis.appendChild(span);
1612                    recentEntrantsIconsEl.appendChild(ellipsis);
1613                }
1614                recentEntrantsEl.style.display = 'flex';
1615            } else {
1616                recentEntrantsEl.style.display = 'none';
1617            }
1618        }
1619
1620        // 開催日時
1621        var eventDateEl = document.getElementById('wecEventDate');
1622        if (eventDateEl) {
1623            if (options.startDate) {
1624                var label = wecFormatEventDate(options.startDate);
1625                if (label) {
1626                    eventDateEl.textContent = label;
1627                    eventDateEl.style.display = 'block';
1628                } else {
1629                    eventDateEl.style.display = 'none';
1630                }
1631            } else {
1632                eventDateEl.style.display = 'none';
1633            }
1634        }
1635
1636        // カレンダーボタン
1637        var calendarBtn = document.getElementById('wecCalendarBtn');
1638        if (options.calendarUrl) {
1639            var ua = navigator.userAgent || '';
1640            var isIOS = (/iPad|iPhone|iPod/.test(ua) && !window.MSStream)
1641                || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
1642            var isAndroid = /Android/i.test(ua);
1643
1644            if (isIOS) {
1645                calendarBtn.setAttribute('href', options.calendarUrl);
1646                calendarBtn.removeAttribute('target');
1647                calendarBtn.removeAttribute('rel');
1648            } else if (isAndroid && options.gcalUrl) {
1649                calendarBtn.setAttribute('href', options.gcalUrl);
1650                calendarBtn.removeAttribute('target');
1651                calendarBtn.removeAttribute('rel');
1652            } else if (options.gcalUrl) {
1653                calendarBtn.setAttribute('href', options.gcalUrl);
1654                calendarBtn.setAttribute('target', '_blank');
1655                calendarBtn.setAttribute('rel', 'noopener noreferrer');
1656            } else {
1657                calendarBtn.setAttribute('href', options.calendarUrl);
1658                calendarBtn.setAttribute('download', options.shareFileName || 'fortune-cookie-event.ics');
1659                calendarBtn.removeAttribute('target');
1660                calendarBtn.removeAttribute('rel');
1661            }
1662
1663            calendarBtn.setAttribute('data-calendar-url', options.calendarUrl);
1664            if (options.gcalUrl) {
1665                calendarBtn.setAttribute('data-gcal-url', options.gcalUrl);
1666            } else {
1667                calendarBtn.removeAttribute('data-gcal-url');
1668            }
1669            calendarBtn.setAttribute('data-play-type', options.playType || '');
1670            calendarBtn.setAttribute('data-lottery-id', String(options.lotteryId || ''));
1671            calendarBtn.setAttribute('data-source', options.source || 'entry_complete_popup');
1672
1673            calendarBtn.style.display = 'flex';
1674
1675            calendarBtn.onclick = function() {
1676                var lid = calendarBtn.getAttribute('data-lottery-id') || '';
1677                var ptype = calendarBtn.getAttribute('data-play-type') || '';
1678                var src = calendarBtn.getAttribute('data-source') || 'entry_complete_popup';
1679                if (typeof window.FortuneCookie !== 'undefined' && window.FortuneCookie.gtm) {
1680                    window.FortuneCookie.gtm.fireEvent('calendar_add_button_click', {
1681                        lottery_id: lid,
1682                        play_type: ptype,
1683                        source: src,
1684                    });
1685                }
1686                closeWaitlistEntryCompletePopup();
1687            };
1688        } else {
1689            calendarBtn.style.display = 'none';
1690            calendarBtn.onclick = null;
1691        }
1692
1693        popup.style.display = 'block';
1694        // シェイクアニメ: 表示直後にクラスを付与 → animationend で外す
1695        popup.classList.remove('is-shaking');
1696        void popup.offsetWidth;
1697        popup.classList.add('is-shaking');
1698        var content = popup.querySelector('.wec-content');
1699        if (content) {
1700            var onShakeEnd = function () {
1701                popup.classList.remove('is-shaking');
1702                content.removeEventListener('animationend', onShakeEnd);
1703            };
1704            content.addEventListener('animationend', onShakeEnd, { once: true });
1705        }
1706    };
1707
1708    window.closeWaitlistEntryCompletePopup = function() {
1709        var popup = document.getElementById('waitlistEntryCompletePopup');
1710        if (popup) {
1711            popup.style.display = 'none';
1712            popup.classList.remove('is-shaking');
1713        }
1714    };
1715}
1716</script>
1716
1717
1718  
1719  <div id="cutin-overlay" aria-hidden="true">
1720    <div class="cutin-flash"></div>
1721    <canvas class="cutin-bolt" aria-hidden="true"></canvas>
1722    <div class="cutin-band">
1723        <div class="cutin-rain">
1724            <div class="cutin-streak" style="--top: 6%;  --dur: 0.55s; --delay: 0.00s;"></div>
1725            <div class="cutin-streak" style="--top: 15%; --dur: 0.70s; --delay: 0.08s;"></div>
1726            <div class="cutin-streak" style="--top: 24%; --dur: 0.60s; --delay: 0.16s;"></div>
1727            <div class="cutin-streak" style="--top: 33%; --dur: 0.80s; --delay: 0.05s;"></div>
1728            <div class="cutin-streak" style="--top: 42%; --dur: 0.65s; --delay: 0.20s;"></div>
1729            <div class="cutin-streak" style="--top: 51%; --dur: 0.55s; --delay: 0.30s;"></div>
1730            <div class="cutin-streak" style="--top: 60%; --dur: 0.75s; --delay: 0.10s;"></div>
1731            <div class="cutin-streak" style="--top: 69%; --dur: 0.70s; --delay: 0.25s;"></div>
1732            <div class="cutin-streak" style="--top: 78%; --dur: 0.60s; --delay: 0.35s;"></div>
1733            <div class="cutin-streak" style="--top: 84%; --dur: 0.80s; --delay: 0.02s;"></div>
1734            <div class="cutin-streak" style="--top: 90%; --dur: 0.55s; --delay: 0.18s;"></div>
1735            <div class="cutin-streak" style="--top: 96%; --dur: 0.65s; --delay: 0.28s;"></div>
1736        </div>
1737        <div class="cutin-frame-top"></div>
1738        <div class="cutin-frame-bottom"></div>
1739        <div class="cutin-icon-wrap">
1740            <div class="cutin-icon">
1741                
1742                <img class="cutin-icon-img" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="">
1743            </div>
1744            <span class="cutin-you-badge" hidden>You</span>
1745        </div>
1746        <div class="cutin-name-wrap">
1747            <div class="cutin-headline"></div>
1748            <div class="cutin-name"></div>
1749        </div>
1750    </div>
1751</div>
1752
1753  
1754  <div class="ucp-overlay" id="unlockCelebrationPopup" role="dialog" aria-modal="true" aria-label="ガチャ解放のお知らせ">
1755    <canvas id="unlockCelebrationConfettiCanvas" class="ucp-confetti-canvas"></canvas>
1756    <div class="ucp-modal">
1757        <p class="ucp-heading">新しいガチャを解放しました!</p>
1758
1759        <img class="ucp-thumb" id="unlockCelebrationThumb" src="" alt="">
1760
1761        <p class="ucp-lottery-name" id="unlockCelebrationName"></p>
1762
1763        <div class="ucp-actions">
1764            <a class="gummy-btn gummy-btn-yellow gummy-btn-lg ucp-cta" id="unlockCelebrationCta" href="#">ガチャを見に行く</a>
1765            <button type="button" class="ucp-close" onclick="closeUnlockCelebrationPopup()">閉じる</button>
1766        </div>
1767    </div>
1768</div>
1769
1770<style>
1771.ucp-overlay {
1772    display: none; /* 既定は非表示。表示は .active クラスで行う(インライン style は使わない) */
1773    position: fixed;
1774    inset: 0;
1775    z-index: 100000;
1776    background: rgba(60, 48, 52, 0.55);
1777    align-items: center;
1778    justify-content: center;
1779}
1780.ucp-overlay.active { display: flex; }
1781
1782.ucp-confetti-canvas {
1783    position: fixed;
1784    inset: 0;
1785    pointer-events: none;
1786    z-index: 200001;
1787    display: none;
1788}
1789
1790.ucp-modal {
1791    position: relative;
1792    width: 343px;
1793    max-width: calc(100% - 32px);
1794    background: #fff;
1795    border-radius: 16px;
1796    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.32);
1797    color: #6f6969;
1798    max-height: 90vh;
1799    overflow-y: auto;
1800    padding: 24px 20px 16px;
1801    box-sizing: border-box;
1802    text-align: center;
1803}
1804
1805.ucp-heading {
1806    font-size: 17px;
1807    font-weight: 900;
1808    line-height: 1.5;
1809    color: #4a4444;
1810    margin: 0 0 16px;
1811}
1812
1813.ucp-thumb {
1814    display: block;
1815    width: 100%;
1816    max-width: 100%;
1817    height: auto;
1818    border-radius: 12px;
1819    margin: 0 auto 14px;
1820}
1821
1822.ucp-lottery-name {
1823    font-size: 15px;
1824    font-weight: 700;
1825    color: #4a4444;
1826    margin: 0 0 18px;
1827}
1828
1829.ucp-actions {
1830    display: flex;
1831    flex-direction: column;
1832    align-items: center;
1833    gap: 8px;
1834    margin-top: 8px;
1835}
1836
1837.ucp-cta {
1838    width: 100%;
1839    min-height: 52px;
1840}
1841
1842/* タップ領域は最低 44x44px を確保する */
1843.ucp-close {
1844    background: none;
1845    border: none;
1846    cursor: pointer;
1847    font-size: 13px;
1848    color: #666;
1849    font-weight: 700;
1850    min-height: 44px;
1851    padding: 12px 24px;
1852    box-sizing: border-box;
1853}
1854</style>
1855
1856<script>
1857(function () {
1858    var overlay = null;
1859    var confettiAnim = null;
1860    var reduceMotion = typeof window.matchMedia === 'function'
1861        && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
1862
1863    window.showUnlockCelebrationPopup = function (item) {
1864        overlay = document.getElementById('unlockCelebrationPopup');
1865        if (!overlay || !item) {
1866            window.showNextUnlockCelebration();
1867            return;
1868        }
1869
1870        var thumb = document.getElementById('unlockCelebrationThumb');
1871        var nameEl = document.getElementById('unlockCelebrationName');
1872        var cta = document.getElementById('unlockCelebrationCta');
1873
1874        if (thumb) {
1875            thumb.src = item.image_url || '';
1876            thumb.alt = item.name || '';
1877        }
1878        if (nameEl) {
1879            // XSS対策: textContent を使用
1880            nameEl.textContent = item.name || '';
1881        }
1882        if (cta) {
1883            cta.href = item.lottery_url || '#';
1884        }
1885
1886        overlay.classList.add('active');
1887
1888        if (!reduceMotion && typeof ConfettiCannon !== 'undefined') {
1889            var canvas = document.getElementById('unlockCelebrationConfettiCanvas');
1890            if (canvas) {
1891                confettiAnim = ConfettiCannon.start(canvas);
1892            }
1893        }
1894    };
1895
1896    window.closeUnlockCelebrationPopup = function () {
1897        if (overlay) {
1898            overlay.classList.remove('active');
1899        }
1900        if (confettiAnim) {
1901            confettiAnim.stop();
1902            confettiAnim = null;
1903        }
1904        window.showNextUnlockCelebration();
1905    };
1906
1907    // window.__unlockCelebrationQueue(base.blade.php が seed する配列)から先頭1件を取り出して表示する。
1908    // キューが空なら何もしない(常に呼び出し安全)。閉じるボタン押下時にも呼ばれ、
1909    // 1ページロード内で全件を順番に見せきる(複数同時解放時のキュー表示)。
1910    window.showNextUnlockCelebration = function () {
1911        if (!Array.isArray(window.__unlockCelebrationQueue) || window.__unlockCelebrationQueue.length === 0) {
1912            return;
1913        }
1914        var next = window.__unlockCelebrationQueue.shift();
1915        window.showUnlockCelebrationPopup(next);
1916    };
1917})();
1918</script>
1918
1919  
1920  
1921  <!-- ローディングポップアップコンポーネント -->
1922<div id="loadingPopup" class="loading-popup" style="display: none;">
1923    <div class="loading-popup-overlay"></div>
1924    <div class="loading-popup-content">
1925        <div class="loading-spinner"></div>
1926        <div id="loadingProgress" class="loading-progress" style="display: none;">
1927            <p id="loadingProgressText" class="loading-progress-text">処理中...</p>
1928        </div>
1929    </div>
1930</div>
1931
1932<style>
1933.loading-popup {
1934    position: fixed;
1935    top: 0;
1936    left: 0;
1937    width: 100%;
1938    height: 100%;
1939    z-index: 10000;
1940}
1941
1942.loading-popup-overlay {
1943    position: absolute;
1944    top: 0;
1945    left: 0;
1946    width: 100%;
1947    height: 100%;
1948    background-color: rgba(0, 0, 0, 0.5);
1949}
1950
1951.loading-popup-content {
1952    position: absolute;
1953    top: 50%;
1954    left: 50%;
1955    transform: translate(-50%, -50%);
1956}
1957
1958.loading-spinner {
1959    width: 60px;
1960    height: 60px;
1961    border: 6px solid rgba(59, 130, 246, 0.2);
1962    border-top-color: #3b82f6;
1963    border-radius: 50%;
1964    animation: spin 1s linear infinite;
1965}
1966
1967@keyframes spin {
1968    0% {
1969        transform: rotate(0deg);
1970    }
1971    100% {
1972        transform: rotate(360deg);
1973    }
1974}
1975
1976.loading-progress {
1977    margin-top: 20px;
1978    text-align: center;
1979}
1980
1981.loading-progress-text {
1982    color: white;
1983    font-size: 16px;
1984    font-weight: bold;
1985    margin: 0;
1986}
1987</style>
1988
1989<script>
1990/**
1991 * ローディングポップアップを表示する
1992 * @param {string} progressText - 進行状況のテキスト(オプション)
1993 */
1994function showLoadingPopup(progressText = null) {
1995    const popup = document.getElementById('loadingPopup');
1996    const progress = document.getElementById('loadingProgress');
1997    const progressTextElement = document.getElementById('loadingProgressText');
1998
1999    if (popup) {
2000        popup.style.display = 'block';
2001    }
2002
2003    if (progressText && progress && progressTextElement) {
2004        progress.style.display = 'block';
2005        progressTextElement.textContent = progressText;
2006    } else if (progress) {
2007        progress.style.display = 'none';
2008    }
2009}
2010
2011/**
2012 * ローディングポップアップを閉じる
2013 */
2014function hideLoadingPopup() {
2015    const popup = document.getElementById('loadingPopup');
2016    const progress = document.getElementById('loadingProgress');
2017
2018    if (popup) {
2019        popup.style.display = 'none';
2020    }
2021
2022    if (progress) {
2023        progress.style.display = 'none';
2024    }
2025}
2026
2027/**
2028 * ローディング進行状況を更新する
2029 * @param {string} text - 進行状況のテキスト
2030 */
2031function updateLoadingProgress(text) {
2032    const progress = document.getElementById('loadingProgress');
2033    const progressTextElement = document.getElementById('loadingProgressText');
2034
2035    if (progress && progressTextElement) {
2036        progress.style.display = 'block';
2037        progressTextElement.textContent = text;
2038    }
2039}
2040</script>
2040
2041
2042  
2043  
2044  
2045  
2045<script>
2046    window.FortuneCookie.urlAppendCookieKeys = {"utm_source":"fc_utm_source","utm_medium":"fc_utm_medium","utm_campaign":"fc_utm_campaign","utm_term":"fc_utm_term","utm_content":"fc_utm_content","utm_id":"fc_utm_id","twclid":"fc_twclid","fbclid":"fc_fbclid","ttclid":"fc_ttclid","yclid":"fc_yclid","gclid":"fc_gclid","cxsid":"fc_cxsid","ma_campaign_id":"fc_ma_campaign_id"};
2047    window.FortuneCookie.sessionParams = {
2048      code: null    };
2049  </script>
2049
2050
2051  
2051<script src="https://fortune-cookie.tokyo/assets/js/url-auto-append.js?v=1.0.610"></script>
2051
2052
2053  
2054  
2055    
2055<script src="https://fortune-cookie.tokyo/assets/js/anniv-half.js?v=1.0.610" defer></script>
2055
2056  
2057      
2058    
2058<script>
2059      window.PWA_INSTALLATIONS_URL = 'https:\/\/fortune-cookie.tokyo\/api\/pwa-installations';
2060      window.CSRF_TOKEN_URL = 'https:\/\/fortune-cookie.tokyo\/api\/csrf-token';
2061      window.PWA_IS_USER_LOGGED_IN = false;
2062      if ('serviceWorker' in navigator) {
2063        window.addEventListener('load', function () {
2064          // updateViaCache: 'none' で SW スクリプト自体のブラウザキャッシュを無効化し、
2065          // ページロード時に毎回 SW の更新チェックを走らせる
2066          navigator.serviceWorker.register(
2067            'https:\/\/fortune-cookie.tokyo\/sw.js',
2068            { updateViaCache: 'none' }
2069          )
2070            .then(function (registration) {
2071              // ページ可視化時にも更新チェックを実行(タブ復帰時の取りこぼし対策)
2072              registration.update();
2073            })
2074            .catch(function (err) { console.warn('[PWA] SW registration failed:', err); });
2075        });
2076      }
2077    </script>
2077
2078    
2078<script src="https://fortune-cookie.tokyo/assets/js/pwa-install.js?v=1.0.610" defer></script>
2078
2079
2080  
2081  
2082      
2083  
2084  
2085  
2086  
2086<script>
2087    document.addEventListener('contextmenu', function (e) {
2088      if (e.target && e.target.tagName === 'IMG') {
2089        e.preventDefault();
2090      }
2091    });
2092  </script>
2092
2093
2094    
2095  <div class="dm-viewport-ring dm-viewport-ring--particle" aria-hidden="true"><span class="dm-viewport-ring__blur"><span class="dm-viewport-ring__spin"></span></span></div>
2096</body>
2097
2098</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.