PageSourceSearch

https://fortune-cookie.tokyo/register

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