bigwhale5 / index.html
offerpk3's picture
Add 3 files
a800393 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Advanced Card Generator</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f8fafc;
}
.card-shadow {
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.card-gradient {
background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
}
.card-number {
letter-spacing: 2px;
}
.loading-spinner {
border-top-color: transparent;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.fade-in {
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
</head>
<body class="min-h-screen bg-gray-50">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="mb-8">
<h1 class="text-3xl font-bold text-gray-900 mb-2">Advanced Card Generator</h1>
<p class="text-gray-600">Generate valid test card numbers for development and testing purposes</p>
</header>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Left Column - Form -->
<div class="lg:col-span-2 space-y-6">
<!-- Card Type Selection -->
<div class="bg-white rounded-xl shadow-sm p-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4">Card Type</h2>
<div class="grid grid-cols-2 md:grid-cols-4 gap-3">
<button onclick="setCardType('visa')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors">
<img src="https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg" alt="Visa" class="h-8">
</button>
<button onclick="setCardType('mastercard')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors">
<img src="https://upload.wikimedia.org/wikipedia/commons/2/2a/Mastercard-logo.svg" alt="Mastercard" class="h-8">
</button>
<button onclick="setCardType('amex')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors">
<img src="https://upload.wikimedia.org/wikipedia/commons/3/30/American_Express_logo.svg" alt="American Express" class="h-8">
</button>
<button onclick="setCardType('discover')" class="card-type-btn flex items-center justify-center p-4 border rounded-lg hover:bg-gray-50 transition-colors">
<img src="https://upload.wikimedia.org/wikipedia/commons/5/5f/Discover_Card_logo.svg" alt="Discover" class="h-8">
</button>
</div>
</div>
<!-- Card Details Form -->
<div class="bg-white rounded-xl shadow-sm p-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4">Card Details</h2>
<div class="space-y-4">
<!-- BIN Input -->
<div>
<label for="bin" class="block text-sm font-medium text-gray-700 mb-1">BIN (Bank Identification Number)</label>
<div class="relative">
<input type="text" id="bin" maxlength="6" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="First 6 digits" oninput="formatBin(this)">
<div class="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none text-gray-400" id="bin-status">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
</div>
</div>
<p class="mt-1 text-xs text-gray-500">Enter the first 6 digits to generate cards with specific BIN</p>
</div>
<!-- Range Inputs -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label for="range-start" class="block text-sm font-medium text-gray-700 mb-1">Range Start</label>
<input type="text" id="range-start" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Optional">
</div>
<div>
<label for="range-end" class="block text-sm font-medium text-gray-700 mb-1">Range End</label>
<input type="text" id="range-end" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="Optional">
</div>
</div>
<!-- Expiry Date and CVV -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Expiry Date</label>
<div class="relative">
<input type="text" id="expiry-date" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder="MM/YYYY" readonly>
<div class="absolute inset-y-0 right-0 flex items-center pr-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clip-rule="evenodd" />
</svg>
</div>
</div>
</div>
<div>
<label for="cvv-length" class="block text-sm font-medium text-gray-700 mb-1">CVV Length</label>
<select id="cvv-length" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<option value="3">3 digits</option>
<option value="4">4 digits</option>
</select>
</div>
</div>
<!-- Batch Size -->
<div>
<label for="batch-size" class="block text-sm font-medium text-gray-700 mb-1">Number of Cards to Generate</label>
<select id="batch-size" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
<option value="1">1</option>
<option value="5" selected>5</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="50">50</option>
</select>
</div>
</div>
</div>
<!-- Generate Button -->
<div class="flex justify-end">
<button id="generate-btn" onclick="generateCards()" class="px-6 py-3 bg-indigo-600 text-white font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors flex items-center">
<span>Generate Cards</span>
<svg id="generate-spinner" class="hidden ml-2 h-5 w-5 text-white loading-spinner" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</button>
</div>
</div>
<!-- Right Column - Preview -->
<div class="space-y-6">
<!-- Card Preview -->
<div class="bg-white rounded-xl shadow-sm p-6">
<h2 class="text-lg font-semibold text-gray-800 mb-4">Card Preview</h2>
<div class="card-gradient rounded-xl p-6 text-white card-shadow">
<div class="flex justify-between items-start mb-8">
<div>
<p class="text-sm opacity-80">Card Type</p>
<p class="font-medium" id="preview-card-type">Visa</p>
</div>
<div id="preview-card-logo" class="h-8">
<img src="https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg" alt="Visa" class="h-full">
</div>
</div>
<div class="mb-6">
<p class="text-sm opacity-80 mb-1">Card Number</p>
<p class="text-xl font-semibold tracking-wider card-number" id="preview-card-number">•••• •••• •••• ••••</p>
</div>
<div class="flex justify-between">
<div>
<p class="text-sm opacity-80 mb-1">Expiry Date</p>
<p class="font-medium" id="preview-expiry">••/••</p>
</div>
<div>
<p class="text-sm opacity-80 mb-1">CVV</p>
<p class="font-medium" id="preview-cvv">•••</p>
</div>
</div>
</div>
</div>
<!-- BIN Information -->
<div id="bin-info" class="bg-white rounded-xl shadow-sm p-6 hidden">
<h2 class="text-lg font-semibold text-gray-800 mb-4">BIN Information</h2>
<div class="space-y-3">
<div class="flex justify-between">
<span class="text-gray-600">Brand:</span>
<span class="font-medium" id="bin-brand">Visa</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Type:</span>
<span class="font-medium" id="bin-type">Credit</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Bank:</span>
<span class="font-medium" id="bin-bank">Example Bank</span>
</div>
<div class="flex justify-between">
<span class="text-gray-600">Country:</span>
<span class="font-medium" id="bin-country">United States</span>
</div>
</div>
</div>
</div>
</div>
<!-- Generated Cards Section -->
<div id="generated-cards" class="mt-12 hidden">
<div class="flex justify-between items-center mb-6">
<h2 class="text-xl font-bold text-gray-900">Generated Cards</h2>
<div class="flex space-x-3">
<button id="copy-all-btn" onclick="copyAllCards()" class="px-4 py-2 bg-gray-100 text-gray-700 font-medium rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor">
<path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" />
<path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" />
</svg>
Copy All
</button>
<button id="download-btn" onclick="downloadCards()" class="px-4 py-2 bg-indigo-600 text-white font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M3 17a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm3.293-7.707a1 1 0 011.414 0L9 10.586V3a1 1 0 112 0v7.586l1.293-1.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
Download
</button>
</div>
</div>
<div id="cards-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<!-- Cards will be inserted here by JavaScript -->
</div>
</div>
</div>
<!-- Toast Notification -->
<div id="toast" class="fixed bottom-4 right-4 hidden">
<div class="bg-green-500 text-white px-4 py-2 rounded-md shadow-lg flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span id="toast-message">Copied to clipboard!</span>
</div>
</div>
<script>
// Global variables
let currentCardType = 'visa';
let generatedCards = [];
const cardTypes = {
visa: {
name: 'Visa',
logo: 'https://upload.wikimedia.org/wikipedia/commons/5/5e/Visa_Inc._logo.svg',
pattern: /^4/,
lengths: [13, 16],
cvvLength: 3
},
mastercard: {
name: 'Mastercard',
logo: 'https://upload.wikimedia.org/wikipedia/commons/2/2a/Mastercard-logo.svg',
pattern: /^5[1-5]/,
lengths: [16],
cvvLength: 3
},
amex: {
name: 'American Express',
logo: 'https://upload.wikimedia.org/wikipedia/commons/3/30/American_Express_logo.svg',
pattern: /^3[47]/,
lengths: [15],
cvvLength: 4
},
discover: {
name: 'Discover',
logo: 'https://upload.wikimedia.org/wikipedia/commons/5/5f/Discover_Card_logo.svg',
pattern: /^6(?:011|5)/,
lengths: [16],
cvvLength: 3
}
};
// Set card type
function setCardType(type) {
currentCardType = type;
document.querySelectorAll('.card-type-btn').forEach(btn => {
btn.classList.remove('border-indigo-500', 'bg-indigo-50');
});
event.currentTarget.classList.add('border-indigo-500', 'bg-indigo-50');
// Update preview
document.getElementById('preview-card-type').textContent = cardTypes[type].name;
document.getElementById('preview-card-logo').innerHTML = `<img src="${cardTypes[type].logo}" alt="${cardTypes[type].name}" class="h-full">`;
// Update CVV length
document.getElementById('cvv-length').value = cardTypes[type].cvvLength;
document.getElementById('preview-cvv').textContent = '•'.repeat(cardTypes[type].cvvLength);
}
// Format BIN input
function formatBin(input) {
let value = input.value.replace(/\D/g, '');
input.value = value;
if (value.length === 6) {
// Show checkmark
document.getElementById('bin-status').innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
`;
// Update preview with BIN
updatePreviewWithBin(value);
// Show BIN info
fetchBinInfo(value);
} else {
// Show neutral icon
document.getElementById('bin-status').innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
`;
// Hide BIN info if shown
document.getElementById('bin-info').classList.add('hidden');
}
}
// Update preview with BIN
function updatePreviewWithBin(bin) {
const previewNumber = document.getElementById('preview-card-number');
const cardLength = cardTypes[currentCardType].lengths[0]; // Use first length option
// Format: BIN + •••• + last 4 digits (if any)
let formatted = bin + '••••••••'.substring(0, cardLength - bin.length - 4);
if (formatted.length > 4) {
formatted = formatted.substring(0, 4) + ' ' + formatted.substring(4);
}
if (formatted.length > 9) {
formatted = formatted.substring(0, 9) + ' ' + formatted.substring(9);
}
if (formatted.length > 14) {
formatted = formatted.substring(0, 14) + ' ' + formatted.substring(14);
}
previewNumber.textContent = formatted;
}
// Fetch BIN information (mock)
function fetchBinInfo(bin) {
// In a real app, this would be an API call
setTimeout(() => {
document.getElementById('bin-brand').textContent = cardTypes[currentCardType].name;
document.getElementById('bin-type').textContent = 'Credit';
document.getElementById('bin-bank').textContent = 'Example Bank';
document.getElementById('bin-country').textContent = 'United States';
document.getElementById('bin-info').classList.remove('hidden');
}, 500);
}
// Generate cards
function generateCards() {
const bin = document.getElementById('bin').value;
const rangeStart = document.getElementById('range-start').value;
const rangeEnd = document.getElementById('range-end').value;
const batchSize = parseInt(document.getElementById('batch-size').value);
const cvvLength = parseInt(document.getElementById('cvv-length').value);
// Get expiry date (mock - in a real app you'd use a date picker)
const expiryDate = '12/25';
document.getElementById('preview-expiry').textContent = expiryDate;
// Show loading
const generateBtn = document.getElementById('generate-btn');
const generateSpinner = document.getElementById('generate-spinner');
generateBtn.disabled = true;
generateSpinner.classList.remove('hidden');
// Simulate generation delay
setTimeout(() => {
generatedCards = [];
const cardLength = cardTypes[currentCardType].lengths[0]; // Use first length option
for (let i = 0; i < batchSize; i++) {
let cardNumber;
if (bin.length === 6) {
// Generate with BIN
const remainingLength = cardLength - bin.length - 1; // -1 for check digit
let randomPart = '';
for (let j = 0; j < remainingLength; j++) {
randomPart += Math.floor(Math.random() * 10);
}
cardNumber = bin + randomPart;
// Calculate check digit using Luhn algorithm
let sum = 0;
let isSecond = false;
for (let k = cardNumber.length - 1; k >= 0; k--) {
let digit = parseInt(cardNumber.charAt(k));
if (isSecond) {
digit *= 2;
if (digit > 9) {
digit -= 9;
}
}
sum += digit;
isSecond = !isSecond;
}
const checkDigit = (10 - (sum % 10)) % 10;
cardNumber += checkDigit;
} else {
// Generate completely random valid card
cardNumber = generateRandomCardNumber(cardLength);
}
// Generate CVV
let cvv = '';
for (let j = 0; j < cvvLength; j++) {
cvv += Math.floor(Math.random() * 10);
}
generatedCards.push({
number: cardNumber,
expiry: expiryDate,
cvv: cvv,
type: currentCardType
});
}
// Display generated cards
displayGeneratedCards();
// Hide loading
generateBtn.disabled = false;
generateSpinner.classList.add('hidden');
}, 1000);
}
// Generate random card number with Luhn check
function generateRandomCardNumber(length) {
let cardNo = '';
for (let i = 0; i < length - 1; i++) {
cardNo += Math.floor(Math.random() * 10);
}
// Calculate check digit
let sum = 0;
let isSecond = false;
for (let i = cardNo.length - 1; i >= 0; i--) {
let digit = parseInt(cardNo.charAt(i));
if (isSecond) {
digit *= 2;
if (digit > 9) {
digit -= 9;
}
}
sum += digit;
isSecond = !isSecond;
}
const checkDigit = (10 - (sum % 10)) % 10;
return cardNo + checkDigit;
}
// Display generated cards
function displayGeneratedCards() {
const container = document.getElementById('cards-container');
container.innerHTML = '';
generatedCards.forEach((card, index) => {
const formattedNumber = formatCardNumber(card.number);
const cardElement = document.createElement('div');
cardElement.className = 'bg-white rounded-lg shadow-sm p-4 border border-gray-200 fade-in';
cardElement.innerHTML = `
<div class="flex justify-between items-start mb-3">
<div>
<p class="text-xs text-gray-500">Card #${index + 1}</p>
<p class="font-medium">${cardTypes[card.type].name}</p>
</div>
<img src="${cardTypes[card.type].logo}" alt="${cardTypes[card.type].name}" class="h-6">
</div>
<div class="mb-4">
<p class="text-sm text-gray-500 mb-1">Card Number</p>
<div class="flex items-center justify-between">
<p class="font-mono text-lg tracking-wider">${formattedNumber}</p>
<button onclick="copyToClipboard('${card.number}', 'Card number copied!')" class="text-gray-400 hover:text-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" />
<path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" />
</svg>
</button>
</div>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<p class="text-sm text-gray-500 mb-1">Expiry</p>
<p class="font-medium">${card.expiry}</p>
</div>
<div>
<p class="text-sm text-gray-500 mb-1">CVV</p>
<div class="flex items-center justify-between">
<p class="font-medium">${card.cvv}</p>
<button onclick="copyToClipboard('${card.cvv}', 'CVV copied!')" class="text-gray-400 hover:text-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z" />
<path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z" />
</svg>
</button>
</div>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-100">
<button onclick="generateQRCode(${index})" class="w-full py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 flex items-center justify-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v4m6 2h4m-10 4H8m6 4v-4m6-2h4M4 14h4m6-6h4M4 8h4m-4 4h16" />
</svg>
Generate QR Code
</button>
</div>
<div id="qr-container-${index}" class="mt-3 hidden flex justify-center"></div>
`;
container.appendChild(cardElement);
});
// Show generated cards section
document.getElementById('generated-cards').classList.remove('hidden');
}
// Format card number with spaces
function formatCardNumber(number) {
if (number.length === 15) { // Amex
return number.replace(/(\d{4})(\d{6})(\d{5})/, '$1 $2 $3');
} else { // Most cards
return number.replace(/(\d{4})(?=\d)/g, '$1 ');
}
}
// Copy to clipboard
function copyToClipboard(text, message) {
navigator.clipboard.writeText(text).then(() => {
showToast(message);
});
}
// Copy all cards
function copyAllCards() {
let allCardsText = generatedCards.map(card => {
return `${formatCardNumber(card.number)}\t${card.expiry}\t${card.cvv}`;
}).join('\n');
navigator.clipboard.writeText(allCardsText).then(() => {
showToast('All cards copied to clipboard!');
});
}
// Download cards as CSV
function downloadCards() {
let csvContent = "data:text/csv;charset=utf-8,";
csvContent += "Card Number,Expiry Date,CVV,Type\n";
generatedCards.forEach(card => {
csvContent += `${formatCardNumber(card.number)},${card.expiry},${card.cvv},${cardTypes[card.type].name}\n`;
});
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "generated_cards.csv");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showToast('Cards downloaded as CSV!');
}
// Generate QR code for a card
function generateQRCode(index) {
const card = generatedCards[index];
const qrContainer = document.getElementById(`qr-container-${index}`);
if (qrContainer.classList.contains('hidden')) {
qrContainer.innerHTML = '';
qrContainer.classList.remove('hidden');
QRCode.toCanvas(qrContainer, `${card.number}|${card.expiry}|${card.cvv}`, {
width: 150,
margin: 1,
color: {
dark: '#000000',
light: '#ffffff'
}
}, function (error) {
if (error) console.error(error);
});
} else {
qrContainer.classList.add('hidden');
}
}
// Show toast notification
function showToast(message) {
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toast-message');
toastMessage.textContent = message;
toast.classList.remove('hidden');
setTimeout(() => {
toast.classList.add('hidden');
}, 3000);
}
// Initialize
document.addEventListener('DOMContentLoaded', () => {
// Set default card type
setCardType('visa');
// Set default expiry date (next month)
const now = new Date();
const nextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
const formattedDate = `${String(nextMonth.getMonth() + 1).padStart(2, '0')}/${nextMonth.getFullYear().toString().slice(-2)}`;
document.getElementById('expiry-date').value = formattedDate;
document.getElementById('preview-expiry').textContent = formattedDate;
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=offerpk3/bigwhale5" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>