# MASTER PROMPT — Mobile-First Esports Tournament App (Single-File HTML + Firebase)

Copy everything below the line into your AI tool (Claude / ChatGPT / Gemini). Replace the `{{PLACEHOLDERS}}` first.

---

## 1. ROLE & GOAL

You are a senior front-end engineer who specialises in mobile-first web apps wrapped inside Android WebView and backed by Firebase. Build a **complete, production-quality, single-file `index.html`** for a **Free Fire style tournament & wallet app** called **`{{APP_NAME}}`** (original name: "Din Battle").

Users register, deposit money with bKash / Rocket / Nagad, join paid matches (Solo / Duo / Squad), see room ID and password, see results, win prizes, and withdraw winnings. Everything the admin controls (categories, matches, banners, notice, payment numbers, shop, notifications) is **live-synced from Firestore** with `onSnapshot`; nothing is hard-coded in the UI.

**Output rules**
- One file: `index.html` with inline `<style>` and one inline `<script type="module">`. No build tools, no frameworks, no extra files.
- Return the **full code in one code block**. No "rest remains the same", no TODOs, no placeholders in the logic.
- Mobile-only layout (360–430px wide). It must behave like a native app inside Android WebView (no text selection except in inputs, no tap highlight, safe-area aware).

---

## 2. TECH STACK (exact)

| Purpose | Library / CDN |
|---|---|
| Firebase (modular v10.12.0) | `https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js`, `firebase-firestore.js`, `firebase-auth.js` |
| Icons | Font Awesome 6.4.0 (`cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css`) |
| Fonts | Google Fonts: **Lato** (300/400/700/900) + **Hind Siliguri** (300–700). `font-family: 'Lato','Hind Siliguri',sans-serif` |
| Alerts | SweetAlert2 v11 (`cdn.jsdelivr.net/npm/sweetalert2@11`) + theme `@sweetalert2/theme-material-ui/material-ui.min.css` |
| Tab / menu icons | Icons8 PNGs: `https://img.icons8.com/?size=100&id=<ID>&format=png&color=000000` |

Icons8 IDs: Shop `x5pyLTwajYMT`, Play/Home `cdTzm4ndoVu4`, Matches `qbPAZjbNRPIS`, Result `MyHVj8kpSfdv`, Profile `xyyjPRvu3CUP`, Wallet `JeOIikeRv8rJ`, Edit Profile `O6yJLWcR6TNz`, Refer `mvX5rQmbiHy1`, Transactions `TF9VCgblG6vy`, Notification `ds3fC4MMLVI6`, Developer `Aiy01hWHN0hk`, Support FAB `yjJvTQzQoKEy`.

**Firebase config** — use this placeholder object (I will paste my own):
```js
const firebaseConfig = { apiKey:"{{API_KEY}}", authDomain:"{{PROJECT_ID}}.firebaseapp.com", projectId:"{{PROJECT_ID}}", storageBucket:"{{PROJECT_ID}}.firebasestorage.app", messagingSenderId:"{{SENDER_ID}}", appId:"{{APP_ID}}" };
```

**JS architecture:** because the script is `type="module"`, every function used from inline `onclick=""` must be exposed on `window` (e.g. `window.showTab = showTab`). Keep global state variables: `currentUser, depositBal, winningBal, activeCategories, rawMatches, currentActiveCategory, userJoinedMatches, currentJoinId, currentEntryFee, videoLinks, currentMatchFilter, supportLink, currentPayMethod, allParticipants`.

---

## 3. DESIGN SYSTEM

```css
:root{
  --primary:#3F51B5; --primary-light:#E8EAF6; --secondary:#ff9800;
  --success:#43A047; --danger:#D32F2F; --bg-color:#f5f6fa; --text-dark:#1d1b20;
  --wallet-gradient:linear-gradient(135deg,#2b1055,#7597de);
  --bkash-color:#E2136E; --rocket-color:#8C3494; --nagad-color:#F7941D;
  --bkash-dark:#b00e56; --rocket-dark:#6a2670; --nagad-dark:#c97612;
  --auth-bg-dark:#101010;
}
```
- Reset: `* {margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;user-select:none}`; `input,textarea,select{user-select:text}`.
- `body{background:var(--bg-color);padding-bottom:90px;overflow-x:hidden;min-height:100vh}`; `body.sub-page{padding-bottom:0}`.
- Cards: white, radius 8–15px, soft shadow `0 2px 5px rgba(0,0,0,.1)`. Category/shop cards: `#EEEEEE` background with **3px solid #546E7A** border, radius 10px, image height 110px.
- Buttons: pill (radius 30px) for primary actions, uppercase, weight 800.
- Other accents: yellow popup header `#FFD54F`, join button purple `#5E35B1`, withdraw green `#00c853`, add-money purple `#5a4bda`, timer footer green `#388E3C`, outline-blue `#1565C0`, result header blue `#3F51B5`, refer code `#FFCA28` with dashed black border.
- **Loading UX:** (a) global full-screen spinner overlay (rgba(0,0,0,.5), 50px white-top spinner, z-index 9999) shown ~500ms on every tab/sub-page navigation; (b) **shimmer skeleton** placeholders (`linear-gradient(90deg,#e8e8e8 25%,#f4f4f4 37%,#e8e8e8 63%)`, background-size 800px, 1.4s animation) for categories (4), match cards (2–3), history rows (4), notifications (3) until Firestore data arrives.

---

## 4. NAVIGATION MODEL

- Sections are `<section class="app-section">` (hidden by default, `.active` → `display:block`). Only one is active at a time.
- **Bottom tab bar** (fixed, 65px, white, 5 items, 20% width each): **Shop · Play · Matches · Result · Profile**. The active item has a `--primary-light` pill (60×32, radius 16) behind the icon and bold black label (10px). Tab bar is hidden (`.hidden`) on all sub-pages.
- `showTab(t)`: push history state → show loader → highlight tab → (for mymatches/result inject skeletons) → after 500ms switch section, remove `sub-page` class, show tab bar, load data, update FAB, hide loader.
- `navigateSub(t)` for: wallet, add-money, withdraw, history, notifications, refer, edit-profile, developer. Adds `body.sub-page`, hides tab bar, same 500ms loader pattern.
- Sub-pages have a sticky top **back-nav** bar (white, or black `.dark-mode` with white text) with an arrow icon and title.
- **Android hardware back button:** call `history.pushState` on every forward navigation; on `popstate`, click the active section's `.back-nav` if present; otherwise if not on Home, go to Home; on Home let the app exit naturally. Use an `isHandlingPopState` guard.
- **Support FAB** (50px round, bottom 80px / right 20px, `--primary-light` background, Telegram-style icon) is visible **only on the Play (home) tab** (not on sub-pages), with scale/translate show-hide animation and a tap pulse. Opens `supportLink` from settings; if empty show a Swal info "একটু অপেক্ষা করুন / সাপোর্ট লিংক লোড হচ্ছে, আবার চেষ্টা করুন।"; if popup blocked show warning "Popup Blocked / ব্রাউজার পপআপ ব্লক করেছে, ব্রাউজার সেটিংস চেক করুন।"

---

## 5. SCREENS (build every one, exactly)

### 5.1 Auth (full-screen, z-index 5000, shown when logged out)
Dark `#101010` top block (35vh) with large title + grey subtitle; white bottom card (min-height 65vh, top radius 30px) slides under it.
- **Login:** title "{{APP_NAME}}" / subtitle "Sign in to your account"; card title "Sign In"; inputs: Email Address, Password (with eye icon `fa-eye-slash` on the right); checked checkbox "I agree to the Terms and Conditions and Privacy Policy"; black pill button **Sign In**; right-aligned "Forget Password ?"; footer "Im a new user **Register Now**" (link colour `#0091EA`).
- **Register:** title "Let's Start" / "Create an account"; card title "Sign Up"; inputs: UserName, Email Address, Mobile Number (number), Password, Promo Code (Optional); checkbox; **Sign Up** button; footer "Already have an account **Sign in here**".
- `onAuthStateChanged` decides which view to show. Logged-in → hide auth, show `#main-content`, show tab bar, `showTab('home')`. Logged-out → clear joined matches, show auth in login mode.

### 5.2 Home (Play tab)
1. **Banner slider** (16:9, `padding-bottom:56.25%`), images from `settings.banners`, auto-advance every 3s using `translateX(-N*100%)` with 0.5s transition; dots below (active dot = orange `--secondary` pill 20px wide). Banner with a `link` opens it in a new tab.
2. **Marquee notice**: orange (`#ff9800`) weight 800 text scrolling right-to-left (15s linear infinite); text from `settings.notice`, default "Welcome to {{APP_NAME}}! Join matches and win big prizes."
3. Title **FREE FIRE** (centered, uppercase, weight 900, 18px).
4. **Category grid** (2 columns, 15px gap) from `categories` collection: image, uppercase name, and "`N matches found`" (count of matches in that category whose status ≠ Finished, live-updated). Tap → `openCategory(id)`.

### 5.3 Category matches screen
Back-nav "Back to Home". Three tabs (flex, underline style, active = primary colour + 3px bottom border): **Upcoming · On-Going · Result** (filter by `status` = Upcoming / Ongoing / Finished within the current category). Empty state: "No {status} Matches Found". Result tab cards open the result details page.

### 5.4 Match card component (shared by every list)
- Header: 90×55 thumbnail (category image) + title row `"{title} | Mobile | Regular"` + date/time string.
- 3×2 stats grid (label 10px grey uppercase, value bold): **WIN PRIZE** `{total_prize} TK`, **ENTRY TYPE** `{type}`, **ENTRY FEE** `{entry} TK`, **PER KILL** `{per_kill} TK`, **MAP** `{map}`, **VERSION** `MOBILE`.
- Join row: green gradient progress bar (`joined/total`, default total 48), caption "Only N spots are left" + "joined/total", and a button: outlined primary **Join**, grey disabled **JOINED** (if the user is already in that match), or **RESULT** for finished matches.
- Two outlined `#1565C0` buttons side by side: **🔑 Room Details ⌄** and **🏆 Prize Details ⌄** (Prize button hidden on finished matches).
- Footer bar (green, hidden on finished): clock icon + live countdown `Starts In: 3h:12m:45s`, or `Match Started` after the time passes. One global `setInterval(1000)` updates every `.match-countdown[data-time=<ms timestamp>]`.
- Tapping the card opens Match Details (or Result Details if finished). Inner buttons use `event.stopPropagation()`.

### 5.5 Match Details page
Info card (title, "Starts In: {time}", countdown bar) and a participants table: header "Participants" + `count/total`; rows `# | Player (IGN) | Kills | Win`; empty text "No participants joined yet."

### 5.6 Result Details page (dark back-nav "Results")
Card with title `"{title} | Mobile |"`, "Organized On {time}", a stats row (WIN PRIZE / PER KILL / ENTRY FEE with ৳). Blue banner **WINNER WINNER CHICKEN DINNER** + black table head (`# | Player Name | Kills | Winning`) listing players with `win > 0` sorted by win desc (fallback "No winners declared yet"); second blue banner **FULL RESULT** listing all participants (fallback "No participants").

### 5.7 Join Match page (full page)
Back-nav "Match Joining". Card: match title, date, row "Win Prize: X TK" and "Entry Fee: Y TK", dashed-orange warning "*অবশ্যই এখানে আপনার গেমের এর নামটি দিয়ে জয়েন করবেন।", a type badge (Solo/Duo/Squad), and dynamically generated inputs — **1 for Solo, 2 for Duo, 4 for Squad** — placeholder `Player N Name (Game ID)`. Fixed bottom full-width purple pill button **Join Now!**.

### 5.8 Modals
- **Prize modal:** yellow header "TOTAL WINPRIZE" + match title, floating round white ✕ button on top edge. If `prize_desc` exists, show it (newlines → `<br>`). Otherwise show: 👑 Winner 40% of total (floor), 🥈 2nd 20%, 🥉 3rd 10%, 🏅 4th 20 Taka, 🏅 5th 10 Taka, 🔥 Per Kill: Based on Match, 🏆 Total Prize Pool.
- **Room modal:** yellow header "ROOM DETAILS / Match Room Information"; large Room ID and Password, each with a COPY button.
  - Not joined → small modal: icon, "ম্যাচে জয়েন করুন", "আপনি এই ম্যাচে জয়েন করেননি", orange button "ঠিক আছে".
  - Joined but `room_id` empty (or length < 2) → Swal info "অপেক্ষা করুন" / "ম্যাচ শুরু হওয়ার ১০ মিনিট আগে দেওয়া হবে" / "ঠিক আছে".
- **Startup popup:** if `settings.show_popup && popup_text`, after 1.5s show a rounded modal: "আসসালামু আলাইকুম 😍", the text (newlines → `<br>`), orange pill button "Okay".

### 5.9 Shop tab
White page, title "SHOP", 2-column grid from `shop_items` (skip `active === false`, sort by `order`): image, bold name, green price, blue "কিনুন" button when `link` exists (opens link). Press animation `scale(.98)`. Empty state: round icon with a bag SVG, "শপে এখনো কোনো প্রোডাক্ট নেই", "শীঘ্রই নতুন প্রোডাক্ট যুক্ত করা হবে, একটু পরে আবার চেক করুন".

### 5.10 My Matches tab ("Matches")
Heading "My Matches"; lists every match the current user joined (all statuses) using the match card with a disabled **JOINED** button. Empty: "No joined matches"; logged out: "Login to see matches".

### 5.11 Result tab
Heading "Match Results"; all matches with `status === 'Finished'`; empty "No results yet".

### 5.12 Profile tab
Gradient header (`--primary` → `#42a5f5`, bottom radius 20px): 80px avatar, name, email, and two figures **Deposit ৳** / **Winnings ৳**. Menu list (icon + label + chevron): **My Wallet, Edit Profile, Refer & Earn, All Transactions, Notification** (red count badge, hidden when 0), **Developer**, and red **Logout** (Swal confirm "Logout? / Are you sure you want to logout?"). Footer "App Version 1.0.0".

### 5.13 Wallet
Black back-nav "My Wallet". Gradient card (`--wallet-gradient`, radius 15): card icon in gold, "{{APP_NAME}} **WALLET**" (WALLET in gold), "Available Balance" (yellow label), big `৳ deposit+winning`, "GAMING" bottom-right. White stats card with two columns: **DEPOSITED** (blue wallet icon) and **WINNING** (trophy icon). Two buttons: purple **Add Money**, green **Withdraw**. "Quick Actions" → card "Transaction History / View all your transactions". "Learn and Support" → three cards opening video links from settings: "How to add money? / কিভাবে টাকা অ্যাড করবেন", "How to join a match? / কিভাবে ম্যাচে জয়েন করবেন", "How to get Room ID? / কিভাবে রুম আইডি পাবেন".

### 5.14 Add Money
Three selectable cards (bKash, Rocket, Nagad logos with a check badge on the active one). Below, a coloured box per method (bkash `#E2136E`, rocket `#8C3494`, nagad `#F7941D`) containing: title "ট্রানজেকশন আইডি দিন", an input in the darker shade, and Bangla steps:
1. "*247# ডায়াল করে আপনার BKASH মোবাইল মেনুতে যান অথবা BKASH অ্যাপে যান ।" (Rocket `*322#`, Nagad `*167#`)
2. Highlighted yellow: "Send Money/Make Payment - এ ক্লিক করুন ।" (Rocket/Nagad: "Send Money - এ ক্লিক করুন ।")
3. "প্রাপক নম্বর হিসেবে নিচের এই নম্বরটি লিখুন" → number row (from settings) + "(Send Money)" + **Copy** button
4. "নিশ্চিত করতে এখন আপনার BKASH মোবাইল মেনু পিন লিখুন।"
5. "এখন উপরের বক্সে আপনার Transaction ID এবং Amount দিন আর নিচের VERIFY বাটনে ক্লিক করুন।"

A big **VERIFY** button whose colour changes with the selected method.

### 5.15 Withdraw
Black back-nav "Withdraw Money". Balance card "Available Balance — BDT {winning}". Method grid (bKash / Nagad / Rocket, active = primary border + light-blue fill). "Withdrawal Details": mobile number, amount, notice "MINIMUM WITHDRAW 100 TK", green **Withdraw Money** button.

### 5.16 Transactions
Cards (newest first, realtime) with 5px left border (green if type contains "Deposit", else red): uppercase title, date, "Won Amount : N", right side tag `#` + first 4 chars of txID (or `#TRX`) and status text. Empty "No Transactions".

### 5.17 Notifications
Simple list (newest first) of `title` bold + `body` grey. Skeleton while loading.

### 5.18 Edit Profile (black back-nav "My Profile")
Avatar ring + name + email, card "Basic Details" (username, email **disabled**, phone) and card "Password Change" (current, new, confirm). One button **Change Password** saves everything.

### 5.19 Refer & Earn
Dark header with round light-blue avatar, "REFER MORE TO EARN MORE!", description: "আপনি যখন কাউকে আপনার রেফার কোড দিয়ে রেফার করবেন তখন উক্ত ইউজার যদি প্রথমবার ১০০ টাকা বা তার বেশি ডিপোজিট করে তাহলে আপনি ১০ টাকা পাবেন". Body: "YOUR PROMO CODE", yellow dashed code box (tap = copy), a 3-step inline SVG illustration (person → coin → locked wallet) in purple `#673AB7`/`#EDE7F6`, and a **REFER NOW** button (copies the code).

### 5.20 Developer / About page
White page with a configurable promo block (title, one description, 3–4 check-mark bullets, price line, contact link). Use `{{DEV_TEXT}}` and `{{DEV_CONTACT_LINK}}` placeholders.

---

## 6. FIRESTORE DATA MODEL

| Path | Fields |
|---|---|
| `categories/{id}` | `name`, `img` |
| `matches/{id}` | `title, categoryId, status ('Upcoming'|'Ongoing'|'Finished'), time (display string), timestamp (ms), type ('Solo'|'Duo'|'Squad'), entry, total_prize, per_kill, map, total (default 48), joined, room_id, room_pass, prize_desc` |
| `match_participants/{auto}` | `matchKey` (= match doc id), `ign`, `joinedBy` (uid), `kills`, `win` |
| `users/{uid}` | `username, email, phone, deposit, winning, referCode, referredBy, referBonusGiven` |
| `users/{uid}/transactions/{auto}` | `type, amount, method, number, status, date, createdAt, txID` |
| `notifications/{auto}` | `title, body` |
| `shop_items/{id}` | `name, img, price, link, order, active` |
| `settings/app_settings` | `notice, bkash_number, nagad_number, rocket_number, how_to_add_money_link, how_to_get_room_id_link, how_to_play_link, support_link, show_popup, popup_text, banners {key:{img,link}}` |
| `XNXANIKPAY/{auto}` | `txid, amount` (incoming payment SMS records written by the payment-forwarding service) |
| `autoPay/{trxId}` | `amount, usedBy, time` (marks a TrxID as already used) |

**Realtime listeners (`onSnapshot`) started once on load:** categories, shop_items, matches, match_participants (group by `matchKey`), settings/app_settings, and (after login) `users/{uid}`. History and notifications attach their own listener when opened.

---

## 7. BUSINESS LOGIC

**Register:** validate required fields → `createUserWithEmailAndPassword` → `updateProfile({displayName})` → own `referCode = 'DB' + uid.slice(0,6).toUpperCase()` → if promo code entered, query `users where referCode == promo` (ignore self) to get `referredBy` → `setDoc(users/uid, {username,email,phone,deposit:0,winning:0,referCode,referredBy,referBonusGiven:false})`. If promo was invalid show a Swal info "নোট / প্রোমো কোডটি সঠিক নয়, তবে আপনার অ্যাকাউন্ট তৈরি হয়ে গেছে।" (2.5s, no button). Old users without `referCode` get one back-filled on first load.

**Joined detection:** a match is "joined" if any participant doc of that match has `joinedBy === currentUser.uid`. Recompute whenever participants or auth change and re-render the visible list.

**Join match:** block if already joined → require every name field → `total = entryFee × players` → block "Insufficient Balance" if `deposit + winning < total` → deduct from **deposit first, then winning** → add one `match_participants` doc per player → increment `matches.joined` by player count → log transaction `{type:'Match Join', amount:total, method:'Wallet', status:'Success'}` → success Swal "Joined! / You have successfully joined the match." → return to list. Do the balance, participants, joined count and transaction writes in **one `writeBatch`/transaction** so a failure never charges without joining.

**Auto deposit verify:** require TrxID → reject if `autoPay/{trxId}` exists ("This TrxID has already been used!") → find a record in `XNXANIKPAY` whose `txid` matches case-insensitively → on match: add amount to `deposit`, write `autoPay/{trxId}`, log `{type:'Deposit (Auto)', status:'Success', method, txID}`, Swal "Successful! / Successfully added N TK!" and go to wallet; no match → "Invalid TrxID.".

**Referral bonus:** on a user's first deposit ≥ 100 TK, if they have `referredBy` and `referBonusGiven` is false → `increment(10)` on the referrer's `deposit`, set `referBonusGiven:true`, log `{type:'Referral Bonus', amount:10, method:'Referral'}` for the referrer. Failure here must never block the deposit.

**Withdraw:** validate number + amount, min 100, ≤ winning balance → create a transaction `{type:'Withdraw', amount, number, method, status:'Pending'}` → confirm and return to wallet. The admin panel approves and deducts.

**Profile update:** username change → `updateProfile` + update `users` doc; password change requires current password (reauthenticate with `EmailAuthProvider.credential`), matching new/confirm, then `updatePassword`. Show Swal success/error.

**Copy:** `navigator.clipboard.writeText` with a hidden-textarea `execCommand('copy')` fallback; Swal "Copied!" (1.5s, no button).

---

## 8. QUALITY & SECURITY REQUIREMENTS (important)

1. **Escape all user/admin supplied strings** (IGN, titles, notices, popup text, notification text) before inserting into `innerHTML`. Never trust Firestore data as HTML.
2. Do not hard-code real secrets, phone numbers, or links; only the `{{PLACEHOLDERS}}` above.
3. Use only `async/await` + try/catch around every Firestore write, always hide the loader in `finally`.
4. Unsubscribe the per-user listener on logout and avoid stacking duplicate `onSnapshot` listeners when History/Notifications are opened repeatedly.
5. Use `viewport-fit=cover` and `env(safe-area-inset-bottom)` for the tab bar, auth card and fixed join button.
6. After the code, output a **recommended `firestore.rules`** file that (a) lets users read/write only their own `users/{uid}` doc without letting them edit `deposit`/`winning` directly, (b) makes `categories, matches, settings, shop_items, notifications` read-only for users, (c) allows creating own `match_participants` only, and (d) says clearly which operations (balance changes, deposit verification, referral bonus, join payment) should be moved to **Cloud Functions** for a truly secure production app.
7. Keep Bangla strings exactly as written in this prompt (UTF-8).

---

## 9. ACCEPTANCE CHECKLIST (verify before answering)

- [ ] Works as one `index.html`; all `onclick` handlers exist on `window`
- [ ] 5-tab bottom bar + all sub-pages reachable and the Android back button steps back correctly
- [ ] Skeleton shimmer + global loader appear exactly where described
- [ ] Banner slider, marquee, category counts and shop update live from Firestore
- [ ] Match card shows all 6 stats, progress bar, join/joined/result states, live countdown
- [ ] Solo/Duo/Squad join creates 1/2/4 inputs and charges deposit first, then winning
- [ ] Room details gating (not joined / room not set / revealed) works
- [ ] bKash/Rocket/Nagad deposit flow, Withdraw (min 100), referral (+10 on first deposit ≥ 100) work
- [ ] Transactions, notifications, edit profile, refer, developer pages all present
- [ ] XSS-safe rendering, atomic join write, `firestore.rules` delivered

Now generate the complete `index.html`.
