<!-- Favicon -->
<link rel="icon" type="image/jpeg" href="https://i.imgur.com/mXfCGsO.jpeg">
<link rel="shortcut icon" href="https://i.imgur.com/mXfCGsO.jpeg">
<link rel="apple-touch-icon" href="https://i.imgur.com/mXfCGsO.jpeg">
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-light: #34d399;
--discord: #5865f2;
--discord-dark: #4752c4;
--bg-dark: #0f172a;
--bg-darker: #020617;
--bg-light: #1e293b;
--text-primary: #f8fafc;
--text-secondary: #cbd5e1;
--text-muted: #64748b;
--border: #334155;
--shadow: rgba(0, 0, 0, 0.5);
--gradient: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
}
body {
font-family: 'Inter', sans-serif;
background: var(--bg-darker);
color: var(--text-primary);
min-height: 100vh;
overflow-x: hidden;
}
/* Background Animation */
.bg-animation {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%);
}
.bg-animation::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(circle at 20% 80%, rgba(16, 185, 129, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 20%, rgba(88, 101, 242, 0.1) 0%, transparent 50%);
animation: bgMove 20s ease-in-out infinite alternate;
}
@keyframes bgMove {
0% { transform: translate(0, 0) rotate(0deg); }
100% { transform: translate(-20px, -20px) rotate(1deg); }
}
.floating-elements {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
}
.floating-shape {
position: absolute;
border-radius: 50%;
background: linear-gradient(45deg, var(--primary), var(--discord));
opacity: 0.1;
animation: float 6s ease-in-out infinite;
}
.floating-shape:nth-child(1) {
width: 80px;
height: 80px;
top: 20%;
left: 10%;
animation-delay: 0s;
}
.floating-shape:nth-child(2) {
width: 60px;
height: 60px;
top: 60%;
right: 20%;
animation-delay: 2s;
}
.floating-shape:nth-child(3) {
width: 100px;
height: 100px;
bottom: 20%;
left: 80%;
animation-delay: 4s;
}
@keyframes float {
0%, 100% { transform: translateY(0px) rotate(0deg); }
50% { transform: translateY(-20px) rotate(180deg); }
}
/* Main Container */
.container {
min-height: calc(100vh - 70px);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
margin-bottom: 70px;
}
/* Login Card */
.login-card {
background: rgba(30, 41, 59, 0.8);
backdrop-filter: blur(20px);
border: 1px solid var(--border);
border-radius: 24px;
padding: 3rem;
width: 100%;
max-width: 480px;
box-shadow: 0 25px 50px var(--shadow);
position: relative;
overflow: hidden;
}
.login-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, var(--primary), transparent);
}
/* Header */
.header {
text-align: center;
margin-bottom: 2.5rem;
}
/* Logo Container */
.server-logo-container {
position: relative;
width: 80px;
height: 80px;
margin: 0 auto 1.5rem;
border-radius: 20px;
border: 3px solid var(--primary);
overflow: hidden;
box-shadow: 0 10px 25px rgba(16, 185, 129, 0.3);
transition: all 0.3s ease;
}
.server-logo-container:hover {
transform: scale(1.05);
box-shadow: 0 15px 35px rgba(16, 185, 129, 0.4);
}
.server-logo {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
transition: all 0.3s ease;
}
/* Fallback quando a imagem não carrega */
.server-logo-fallback {
width: 100%;
height: 100%;
background: linear-gradient(135deg, var(--primary), var(--primary-light));
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: 700;
color: white;
border-radius: 17px;
}
.server-name {
font-family: 'Poppins', sans-serif;
font-size: 2rem;
font-weight: 700;
margin-bottom: 0.5rem;
background: linear-gradient(135deg, var(--primary), var(--primary-light));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.server-tagline {
color: var(--text-secondary);
font-size: 1rem;
font-weight: 400;
}
/* Welcome Section */
.welcome {
text-align: center;
margin-bottom: 2rem;
}
.welcome-title {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: var(--text-primary);
}
.welcome-text {
color: var(--text-secondary);
font-size: 0.95rem;
line-height: 1.6;
}
/* Features Grid */
.features {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
margin: 2rem 0;
}
.feature {
background: rgba(51, 65, 85, 0.5);
border: 1px solid var(--border);
border-radius: 16px;
padding: 1.5rem;
text-align: center;
transition: all 0.3s ease;
cursor: pointer;
}
.feature:hover {
transform: translateY(-2px);
background: rgba(51, 65, 85, 0.7);
border-color: var(--primary);
box-shadow: 0 10px 25px rgba(16, 185, 129, 0.1);
}
.feature-icon {
font-size: 2rem;
margin-bottom: 1rem;
display: block;
}
.feature-title {
font-size: 1rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: var(--text-primary);
}
.feature-desc {
font-size: 0.875rem;
color: var(--text-secondary);
line-height: 1.5;
}
/* Login Button */
.login-section {
margin: 2.5rem 0;
}
.discord-btn {
width: 100%;
background: var(--discord);
color: white;
border: none;
border-radius: 12px;
padding: 1rem 1.5rem;
font-size: 1rem;
font-weight: 600;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
transition: all 0.3s ease;
cursor: pointer;
}
.discord-btn:hover {
background: var(--discord-dark);
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(88, 101, 242, 0.3);
}
.discord-btn:active {
transform: translateY(0);
}
/* Security Info */
.security-info {
background: rgba(16, 185, 129, 0.1);
border: 1px solid rgba(16, 185, 129, 0.2);
border-radius: 12px;
padding: 1rem;
margin: 1.5rem 0;
}
.security-item {
display: flex;
align-items: center;
gap: 0.75rem;
font-size: 0.875rem;
color: var(--text-secondary);
margin-bottom: 0.5rem;
}
.security-item:last-child {
margin-bottom: 0;
}
.security-icon {
color: var(--primary);
font-size: 1rem;
}
/* Stats Footer */
.stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin-top: 2rem;
padding-top: 2rem;
border-top: 1px solid var(--border);
}
.stat {
text-align: center;
}
.stat-number {
font-size: 1.5rem;
font-weight: 700;
color: var(--primary);
display: block;
transition: all 0.3s ease;
}
.stat-label {
font-size: 0.875rem;
color: var(--text-muted);
margin-top: 0.25rem;
}
/* Credits - RODAPÉ FIXO */
.credits {
position: fixed;
bottom: 0;
left: 0;
right: 0;
width: 100%;
background: rgba(15, 23, 42, 0.9);
backdrop-filter: blur(10px);
border-top: 1px solid var(--border);
padding: 1rem 2rem;
text-align: center;
font-size: 0.875rem;
color: var(--text-muted);
z-index: 1000;
box-shadow: 0 -5px 15px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
animation: slideUp 0.5s ease-out;
}
.credits:hover {
background: rgba(15, 23, 42, 0.95);
border-top-color: var(--primary);
}
.credits a {
color: var(--primary);
text-decoration: none;
transition: all 0.3s ease;
font-weight: 500;
position: relative;
}
.credits a:hover {
color: var(--primary-light);
transform: translateY(-1px);
}
.credits a::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: var(--primary-light);
transition: width 0.3s ease;
}
.credits a:hover::after {
width: 100%;
}
.credits i {
margin-right: 0.25rem;
transition: transform 0.3s ease;
}
.credits a:hover i {
transform: scale(1.1);
}
/* Status Indicator */
.status-indicator {
position: absolute;
top: 1rem;
right: 1rem;
background: rgba(16, 185, 129, 0.2);
border: 1px solid var(--primary);
border-radius: 8px;
padding: 0.5rem 1rem;
font-size: 0.75rem;
color: var(--primary);
font-weight: 600;
}
/* Loading Animation */
.loading {
display: inline-block;
width: 12px;
height: 12px;
border: 2px solid var(--border);
border-top: 2px solid var(--primary);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Pulse animation for stats */
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.7; }
100% { opacity: 1; }
}
/* Animação de entrada do rodapé */
@keyframes slideUp {
from {
transform: translateY(100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
/* Responsive */
@media (max-width: 640px) {
.container {
padding: 1rem;
min-height: calc(100vh - 60px);
margin-bottom: 60px;
}
.login-card {
padding: 2rem;
}
.server-name {
font-size: 1.75rem;
}
.features {
gap: 0.75rem;
}
.feature {
padding: 1rem;
}
.stats {
gap: 0.75rem;
}
.credits {
padding: 0.75rem 1rem;
font-size: 0.8rem;
}
}
</style>
<!-- Main Container -->
<div class="container">
<div class="login-card">
<!-- Status Indicator -->
<div class="status-indicator">
🟢 Online
</div>
<!-- Header -->
<div class="header">
<div class="server-logo-container">
<img src="https://i.imgur.com/mXfCGsO.jpeg"
alt="Liberdade RP"
class="server-logo"
id="serverLogo"
onload="console.log('✅ Logo carregado com sucesso')"
onerror="handleLogoError(this)">
</div>
<h1 class="server-name">Liberdade RP</h1>
<p class="server-tagline">Dashboard de Gerenciamento</p>
</div>
<!-- Welcome -->
<div class="welcome">
<h2 class="welcome-title">Bem-vindo de volta!</h2>
<p class="welcome-text">Acesse o dashboard com sua conta Discord para gerenciar o servidor</p>
</div>
<!-- Features -->
<div class="features">
<div class="feature">
<span class="feature-icon">🎮</span>
<h3 class="feature-title">Sistema de Whitelist</h3>
<p class="feature-desc">Gerencie candidaturas automaticamente</p>
</div>
<div class="feature">
<span class="feature-icon">📊</span>
<h3 class="feature-title">Analytics em Tempo Real</h3>
<p class="feature-desc">Monitore atividades do servidor</p>
</div>
<div class="feature">
<span class="feature-icon">🛡️</span>
<h3 class="feature-title">Painel de Moderação</h3>
<p class="feature-desc">Ferramentas completas de gestão</p>
</div>
</div>
<!-- Login Button -->
<div class="login-section">
<a href="/auth/discord" class="discord-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
<path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.010c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418Z"/>
</svg>
Entrar com Discord
</a>
</div>
<!-- Security Info -->
<div class="security-info">
<div class="security-item">
<i class="fas fa-shield-alt security-icon"></i>
<span>Login seguro via OAuth2</span>
</div>
<div class="security-item">
<i class="fas fa-users security-icon"></i>
<span>Apenas membros do servidor</span>
</div>
<div class="security-item">
<i class="fas fa-lock security-icon"></i>
<span>Dados protegidos e criptografados</span>
</div>
</div>
<!-- Stats -->
<div class="stats" id="serverStats">
<div class="stat">
<span class="stat-number loading-stat">---</span>
<div class="stat-label">Membros</div>
</div>
<div class="stat">
<span class="stat-number loading-stat">---</span>
<div class="stat-label">Online</div>
</div>
<div class="stat">
<span class="stat-number loading-stat">---</span>
<div class="stat-label">Boosts</div>
</div>
</div>
</div>
</div>
<!-- Credits - RODAPÉ FIXO -->
<div class="credits">
Criado por <a href="https://www.instagram.com/0.g_.1/" target="_blank"><i class="fab fa-instagram"></i> @guss</a>
para <a href="https://instagram.com/liberdaderp" target="_blank"><i class="fab fa-instagram"></i> @liberdaderp</a>
</div>
<!-- JavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Carregar estatísticas reais do servidor Discord
async function loadServerStats() {
try {
console.log('🔄 Carregando dados reais do servidor...');
// Mostrar indicador de carregamento
const statNumbers = document.querySelectorAll('.stat-number');
statNumbers.forEach(stat => {
stat.innerHTML = '<span class="loading"></span>';
});
const response = await fetch('/test-stats');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log('📊 Dados recebidos:', data);
if (data.server) {
// Atualizar dados reais do servidor com animação
const memberCount = data.server.memberCount || 0;
const onlineCount = data.server.onlineCount || 0;
const boostCount = data.server.boosts ? data.server.boosts.count : 0;
setTimeout(() => {
animateNumber(statNumbers[0], memberCount);
animateNumber(statNumbers[1], onlineCount);
animateNumber(statNumbers[2], boostCount);
}, 500);
console.log('✅ Dados reais exibidos:', {
membros: memberCount,
online: onlineCount,
boosts: boostCount
});
// Adicionar classe de sucesso
statNumbers.forEach(stat => {
stat.classList.add('pulse');
setTimeout(() => stat.classList.remove('pulse'), 2000);
});
} else {
throw new Error('Dados do servidor não encontrados na resposta');
}
} catch (error) {
console.error('❌ Erro ao carregar estatísticas:', error);
// Em caso de erro, exibir valores de erro
const statNumbers = document.querySelectorAll('.stat-number');
statNumbers.forEach(stat => {
stat.textContent = '---';
stat.style.color = '#ef4444';
});
}
}
// Função para animar números
function animateNumber(element, targetNumber) {
const duration = 1000; // 1 segundo
const steps = 60;
const increment = targetNumber / steps;
let current = 0;
const timer = setInterval(() => {
current += increment;
if (current >= targetNumber) {
current = targetNumber;
clearInterval(timer);
}
element.textContent = Math.floor(current);
}, duration / steps);
}
// Carregar dados imediatamente e depois a cada 30 segundos
loadServerStats();
setInterval(loadServerStats, 30000);
// Adicionar efeitos de hover e interatividade
const features = document.querySelectorAll('.feature');
features.forEach(feature => {
feature.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-4px) scale(1.02)';
});
feature.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0) scale(1)';
});
});
// Efeito no logo
const logo = document.querySelector('.server-logo');
logo.addEventListener('click', function() {
this.style.transform = 'scale(1.1) rotate(5deg)';
setTimeout(() => {
this.style.transform = 'scale(1) rotate(0deg)';
}, 200);
});
// Log de inicialização
console.log('🚀 Sistema redesenhado inicializado para Liberdade RP');
console.log('📍 Rodapé fixo ativado');
});
// Função para lidar com erro no carregamento do logo
function handleLogoError(img) {
console.log('❌ Erro ao carregar logo, usando fallback');
// Criar elemento de fallback
const fallback = document.createElement('div');
fallback.className = 'server-logo-fallback';
fallback.innerHTML = 'LRP';
// Substituir a imagem pelo fallback
img.parentNode.replaceChild(fallback, img);
}
// Função melhorada para carregamento do logo
function initLogo() {
const logo = document.getElementById('serverLogo');
if (!logo) return;
// Lista de URLs alternativos
const logoUrls = [
'https://i.imgur.com/mXfCGsO.jpeg',
'https://imgur.com/mXfCGsO.jpeg',
'https://cdn.discordapp.com/embed/avatars/0.png'
];
let currentUrlIndex = 0;
function tryNextUrl() {
if (currentUrlIndex < logoUrls.length) {
logo.src = logoUrls[currentUrlIndex];
console.log(`🔄 Tentando carregar logo: ${logoUrls[currentUrlIndex]}`);
currentUrlIndex++;
} else {
// Se todas as URLs falharam, criar fallback
createFallbackLogo();
}
}
function createFallbackLogo() {
console.log('📝 Criando logo de fallback');
const container = logo.parentElement;
const fallback = document.createElement('div');
fallback.className = 'server-logo-fallback';
fallback.innerHTML = 'LRP';
fallback.style.cssText = `
width: 100%;
height: 100%;
background: linear-gradient(135deg, #10b981, #34d399);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: 700;
color: white;
border-radius: 17px;
`;
container.replaceChild(fallback, logo);
}
// Event listeners
logo.addEventListener('load', function() {
console.log('✅ Logo carregado com sucesso!');
});
logo.addEventListener('error', function() {
console.log('❌ Erro ao carregar logo');
tryNextUrl();
});
// Verificar se a imagem já carregou (cache)
if (logo.complete && logo.naturalHeight !== 0) {
console.log('✅ Logo já estava carregado (cache)');
} else {
// Forçar reload da imagem
logo.src = logo.src + '?t=' + Date.now();
}
}
// Inicializar logo quando a página carregar
initLogo();
</script>