CONFIGURAÇÃO 1

This commit is contained in:
Flatlogic Bot 2026-02-18 01:17:28 +00:00
parent b61b163577
commit 9f27edfd4b
18 changed files with 959 additions and 146 deletions

Binary file not shown.

42
core/forms.py Normal file
View File

@ -0,0 +1,42 @@
from django import forms
class LotterySimulatorForm(forms.Form):
lottery_type = forms.ChoiceField(
label="Loteria",
choices=[],
widget=forms.Select(
attrs={
"class": "form-select form-select-lg",
}
),
)
draws_to_consider = forms.IntegerField(
label="Ultimos sorteios",
min_value=3,
max_value=20,
initial=10,
widget=forms.NumberInput(
attrs={
"class": "form-control",
"inputmode": "numeric",
}
),
)
games_to_generate = forms.IntegerField(
label="Jogos sugeridos",
min_value=1,
max_value=12,
initial=4,
widget=forms.NumberInput(
attrs={
"class": "form-control",
"inputmode": "numeric",
}
),
)
def __init__(self, *args, **kwargs):
lottery_choices = kwargs.pop("lottery_choices", [])
super().__init__(*args, **kwargs)
self.fields["lottery_type"].choices = lottery_choices

View File

@ -1,8 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}Knowledge Base{% endblock %}</title>
{% if project_description %}
<meta name="description" content="{{ project_description }}">
@ -14,12 +15,26 @@
<meta property="twitter:image" content="{{ project_image_url }}">
{% endif %}
{% load static %}
<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=Space+Grotesk:wght@400;500;600;700&family=Work+Sans:wght@400;500;600&display=swap"
rel="stylesheet">
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
{% block head %}{% endblock %}
</head>
<body>
<body class="app-body">
{% block content %}{% endblock %}
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
crossorigin="anonymous"></script>
</body>
</html>

View File

@ -1,145 +1,257 @@
{% extends "base.html" %}
{% load static %}
{% block title %}{{ project_name }}{% endblock %}
{% block head %}
<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@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
inset: 0;
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><path d='M-10 10L110 10M10 -10L10 110' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% {
background-position: 0% 0%;
}
100% {
background-position: 100% 100%;
}
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2.5rem 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
}
h1 {
font-size: clamp(2.2rem, 3vw + 1.2rem, 3.2rem);
font-weight: 700;
margin: 0 0 1.2rem;
letter-spacing: -0.02em;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
opacity: 0.92;
}
.loader {
margin: 1.5rem auto;
width: 56px;
height: 56px;
border: 4px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.runtime code {
background: rgba(0, 0, 0, 0.25);
padding: 0.15rem 0.45rem;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}
footer {
position: absolute;
bottom: 1rem;
width: 100%;
text-align: center;
font-size: 0.85rem;
opacity: 0.75;
}
</style>
{% endblock %}
{% block title %}{{ project_name }} · Analise Loterias BR{% endblock %}
{% block content %}
<main>
<div class="card">
<h1>Analyzing your requirements and generating your app…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
<div class="hero-shell">
<header class="site-header">
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container">
<a class="navbar-brand brand" href="#top">{{ project_name }}</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain"
aria-controls="navbarMain" aria-expanded="false" aria-label="Alternar navegacao">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarMain">
<ul class="navbar-nav ms-auto align-items-lg-center gap-lg-3">
<li class="nav-item"><a class="nav-link" href="#simulador">Simulador</a></li>
<li class="nav-item"><a class="nav-link" href="#jogos">Jogos</a></li>
<li class="nav-item"><a class="nav-link" href="#como-funciona">Como funciona</a></li>
<li class="nav-item"><a class="nav-link" href="/admin/">Admin</a></li>
<li class="nav-item">
<a class="btn btn-brand" href="#simulador">Gerar jogos</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main id="top" class="site-main">
<section class="hero-section">
<div class="container">
<div class="row align-items-center g-5">
<div class="col-lg-6">
<div class="eyebrow">Inteligencia matematica aplicada</div>
<h1 class="hero-title">Geracoes inteligentes de numeros para todas as loterias do Brasil.</h1>
<p class="hero-lead">
Use historico recente, frequencias e probabilidades reais para montar seus jogos. Configure cada
loteria e acompanhe os indicadores mais relevantes antes do proximo sorteio.
</p>
<div class="hero-actions">
<a class="btn btn-brand btn-lg" href="#simulador">Simular agora</a>
<a class="btn btn-ghost btn-lg" href="#jogos">Ver configuracoes</a>
</div>
<div class="hero-stats">
<div class="stat-card">
<span class="stat-value">5 loterias</span>
<span class="stat-label">Mega-Sena, Quina, Dupla Sena, Lotomania, Lotofacil</span>
</div>
<div class="stat-card">
<span class="stat-value">Analise recencia</span>
<span class="stat-label">Ultimos sorteios para ajustar pesos e tendencias</span>
</div>
<div class="stat-card">
<span class="stat-value">Probabilidade real</span>
<span class="stat-label">Calculo matematico de combinacoes e odds</span>
</div>
</div>
</div>
<div class="col-lg-6">
<div id="simulador" class="card-glass">
<div class="card-glass-header">
<h2 class="card-title">Simulador de jogos</h2>
<p class="card-subtitle">Escolha a loteria, ajuste o recorte e gere combinacoes sugeridas.</p>
</div>
<form method="post" class="generator-form">
{% csrf_token %}
<div class="mb-3">
<label class="form-label" for="{{ form.lottery_type.id_for_label }}">{{ form.lottery_type.label }}</label>
{{ form.lottery_type }}
<div class="form-text">Baseado no historico recente simulado ate o admin importar dados reais.</div>
{{ form.lottery_type.errors }}
</div>
<div class="row g-3">
<div class="col-md-6">
<label class="form-label" for="{{ form.draws_to_consider.id_for_label }}">{{ form.draws_to_consider.label }}</label>
{{ form.draws_to_consider }}
{{ form.draws_to_consider.errors }}
</div>
<div class="col-md-6">
<label class="form-label" for="{{ form.games_to_generate.id_for_label }}">{{ form.games_to_generate.label }}</label>
{{ form.games_to_generate }}
{{ form.games_to_generate.errors }}
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-brand btn-lg w-100">Gerar sugestoes</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
</main>
</div>
<section class="insights-section">
<div class="container">
<div class="section-header">
<h2>Resumo matematico</h2>
<p>Resultados calculados com base no recorte selecionado.</p>
</div>
<p class="hint">AppWizzy AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will refresh automatically as the plan is implemented.</p>
<p class="runtime">
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code>
— UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
</p>
{% if result %}
<div class="row g-4 align-items-stretch">
<div class="col-lg-6">
<div class="card-soft">
<div class="card-soft-header">
<h3>{{ result.lottery }}</h3>
<span class="pill">{{ result.draws_used }} sorteios analisados</span>
</div>
<div class="metrics">
<div class="metric">
<span class="metric-label">Combinacoes possiveis</span>
<span class="metric-value">{{ result.total_combinations }}</span>
</div>
<div class="metric">
<span class="metric-label">Odds de acerto total</span>
<span class="metric-value">{{ result.odds }}</span>
</div>
<div class="metric">
<span class="metric-label">Probabilidade</span>
<span class="metric-value">{{ result.percent }}</span>
</div>
</div>
<div class="number-groups">
<div>
<div class="group-title">Quentes no recorte</div>
<div class="badge-grid">
{% for number in result.hot_numbers %}
<span class="badge badge-hot">{{ number }}</span>
{% endfor %}
</div>
</div>
<div>
<div class="group-title">Frias no recorte</div>
<div class="badge-grid">
{% for number in result.cold_numbers %}
<span class="badge badge-cold">{{ number }}</span>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6">
<div class="card-soft">
<div class="card-soft-header">
<h3>Jogos sugeridos</h3>
<span class="pill">{{ result.suggestions|length }} combinacoes</span>
</div>
<div class="suggestions-grid">
{% for suggestion in result.suggestions %}
<div class="suggestion">
{% for number in suggestion %}
<span class="ball">{{ number }}</span>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% else %}
<div class="card-soft placeholder-card">
<div class="placeholder-icon">&middot;&middot;&middot;</div>
<div>
<h3>Simule para ver as probabilidades</h3>
<p>Escolha a loteria e o recorte no simulador acima para gerar os primeiros jogos sugeridos.</p>
</div>
</div>
{% endif %}
</div>
</section>
<section id="jogos" class="games-section">
<div class="container">
<div class="section-header">
<h2>Configuracoes por loteria</h2>
<p>Regras atuais e odds de acerto total para cada jogo.</p>
</div>
<div class="row g-4">
{% for lottery in lottery_cards %}
<div class="col-md-6 col-xl-4">
<div class="game-card">
<div class="game-card-header">
<h3>{{ lottery.label }}</h3>
<span class="pill">{{ lottery.tagline }}</span>
</div>
<div class="game-meta">
<span>Dezenas: {{ lottery.picks }}</span>
<span>Universo: {{ lottery.range_max }}</span>
</div>
<div class="game-odds">Odds de acerto total: <strong>{{ lottery.odds }}</strong></div>
<a class="btn btn-ghost w-100" href="#simulador">Simular {{ lottery.label }}</a>
</div>
</div>
{% endfor %}
</div>
</div>
</section>
<section id="como-funciona" class="process-section">
<div class="container">
<div class="section-header">
<h2>Como a inteligencia funciona</h2>
<p>Fluxo simples para gerar jogos com base matematica.</p>
</div>
<div class="row g-4">
<div class="col-md-4">
<div class="process-card">
<div class="step">01</div>
<h3>Importar sorteios</h3>
<p>O admin registra os ultimos concursos e atualiza o motor de analise.</p>
</div>
</div>
<div class="col-md-4">
<div class="process-card">
<div class="step">02</div>
<h3>Calcular pesos</h3>
<p>Frequencias e recencia criam o mapa de probabilidades por dezena.</p>
</div>
</div>
<div class="col-md-4">
<div class="process-card">
<div class="step">03</div>
<h3>Gerar combinacoes</h3>
<p>Jogos sugeridos sao montados com equilibrio matematico e transparencia.</p>
</div>
</div>
</div>
</div>
</section>
<section class="cta-section">
<div class="container">
<div class="cta-card">
<div>
<h2>Pronto para configurar seus sorteios?</h2>
<p>Acesse o painel de admin para registrar concursos reais e refinar a analise.</p>
</div>
<a class="btn btn-brand btn-lg" href="/admin/">Ir para admin</a>
</div>
</div>
</section>
<footer class="site-footer">
<div class="container">
<div>
<strong>{{ project_name }}</strong>
<span>Analise estatistica para loterias BR.</span>
</div>
<div class="footer-meta">Atualizado em {{ current_time|date:"d/m/Y H:i" }} (UTC)</div>
</div>
</main>
<footer>
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
</footer>
{% endblock %}
{% endblock %}

View File

@ -1,25 +1,194 @@
import math
import os
import platform
import random
from collections import Counter
from django import get_version as django_version
from django.shortcuts import render
from django.utils import timezone
from .forms import LotterySimulatorForm
LOTTERY_CONFIGS = {
"mega_sena": {
"label": "Mega-Sena",
"range_max": 60,
"picks": 6,
"sample_draws": 15,
"seed": 1982,
"tagline": "6 dezenas entre 60",
},
"quina": {
"label": "Quina",
"range_max": 80,
"picks": 5,
"sample_draws": 15,
"seed": 1971,
"tagline": "5 dezenas entre 80",
},
"dupla_sena": {
"label": "Dupla Sena",
"range_max": 50,
"picks": 6,
"sample_draws": 15,
"seed": 1990,
"tagline": "6 dezenas entre 50",
},
"lotomania": {
"label": "Lotomania",
"range_max": 100,
"picks": 50,
"sample_draws": 12,
"seed": 1999,
"tagline": "50 dezenas entre 100",
},
"lotofacil": {
"label": "Lotofacil",
"range_max": 25,
"picks": 15,
"sample_draws": 20,
"seed": 1994,
"tagline": "15 dezenas entre 25",
},
}
def _generate_sample_draws(config):
rng = random.Random(config["seed"])
draws = []
population = list(range(1, config["range_max"] + 1))
for _ in range(config["sample_draws"]):
draws.append(sorted(rng.sample(population, config["picks"])))
return draws
def _weighted_unique_sample(numbers, weights, picks, rng):
available = list(zip(numbers, weights))
selection = []
for _ in range(picks):
total_weight = sum(weight for _, weight in available)
if total_weight <= 0:
choice = rng.choice(available)
selection.append(choice[0])
available.remove(choice)
continue
pick = rng.uniform(0, total_weight)
cumulative = 0
for index, (number, weight) in enumerate(available):
cumulative += weight
if cumulative >= pick:
selection.append(number)
del available[index]
break
return selection
def _format_odds(total_combinations):
if total_combinations >= 1_000_000_000_000:
return f"1 em {total_combinations:.2e}"
return f"1 em {total_combinations:,}".replace(",", ".")
def _format_percent(odds):
percent = 100 / odds
if percent < 0.000001:
return "<0,000001%"
return f"{percent:.6f}%".replace(".", ",")
def home(request):
"""Render the landing screen with loader and environment details."""
"""Render the landing screen with lottery simulator and insights."""
host_name = request.get_host().lower()
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
now = timezone.now()
lottery_choices = [
(key, config["label"]) for key, config in LOTTERY_CONFIGS.items()
]
lottery_cards = []
for key, config in LOTTERY_CONFIGS.items():
total_combinations = math.comb(config["range_max"], config["picks"])
lottery_cards.append(
{
"key": key,
"label": config["label"],
"tagline": config["tagline"],
"range_max": config["range_max"],
"picks": config["picks"],
"odds": _format_odds(total_combinations),
}
)
form = LotterySimulatorForm(
request.POST or None,
lottery_choices=lottery_choices,
)
result = None
if form.is_valid():
lottery_key = form.cleaned_data["lottery_type"]
draws_to_consider = form.cleaned_data["draws_to_consider"]
games_to_generate = form.cleaned_data["games_to_generate"]
config = LOTTERY_CONFIGS[lottery_key]
draws = _generate_sample_draws(config)
draws_to_consider = min(draws_to_consider, len(draws))
recent_draws = draws[-draws_to_consider:]
frequency = Counter(
number for draw in recent_draws for number in draw
)
numbers = list(range(1, config["range_max"] + 1))
weights = [frequency.get(number, 0) + 1 for number in numbers]
rng = random.Random(f"{lottery_key}-{draws_to_consider}-{games_to_generate}")
suggestions = []
for _ in range(games_to_generate):
suggestion = _weighted_unique_sample(
numbers, weights, config["picks"], rng
)
suggestions.append(sorted(suggestion))
total_combinations = math.comb(config["range_max"], config["picks"])
hot_numbers = [
number for number, _ in frequency.most_common(8)
]
cold_numbers = [
number
for number, _ in sorted(
frequency.items(), key=lambda item: item[1]
)
]
missing_numbers = [
number for number in numbers if number not in frequency
]
cold_numbers = (missing_numbers + cold_numbers)[:8]
result = {
"lottery": config["label"],
"draws_used": draws_to_consider,
"total_combinations": f"{total_combinations:,}".replace(",", "."),
"odds": _format_odds(total_combinations),
"percent": _format_percent(total_combinations),
"suggestions": suggestions,
"hot_numbers": hot_numbers,
"cold_numbers": cold_numbers,
}
context = {
"project_name": "New Style",
"project_name": "LotoPulse",
"project_description": (
"Analise loterias brasileiras, gere jogos e acompanhe "
"probabilidades com base nos sorteios mais recentes."
),
"agent_brand": agent_brand,
"django_version": django_version(),
"python_version": platform.python_version(),
"current_time": now,
"host_name": host_name,
"project_description": os.getenv("PROJECT_DESCRIPTION", ""),
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
"deployment_timestamp": now.strftime("%Y%m%d%H%M%S"),
"form": form,
"result": result,
"lottery_cards": lottery_cards,
}
return render(request, "core/index.html", context)

View File

@ -1,4 +1,479 @@
/* Custom styles for the application */
body {
font-family: system-ui, -apple-system, sans-serif;
:root {
--ink: #0b1f2a;
--ink-soft: #123041;
--primary: #0f766e;
--primary-strong: #0b5f59;
--secondary: #f59e0b;
--accent: #ea580c;
--surface: #ffffff;
--surface-muted: #f4f7f7;
--line: rgba(12, 42, 58, 0.12);
--glow: rgba(15, 118, 110, 0.25);
}
* {
box-sizing: border-box;
}
body.app-body {
margin: 0;
font-family: "Work Sans", sans-serif;
color: var(--ink);
background: radial-gradient(circle at top, #e9f2f1 0%, #f7faf9 40%, #ffffff 100%);
}
body.app-body::before {
content: "";
position: fixed;
inset: 0;
background-image: radial-gradient(circle at 20% 20%, rgba(15, 118, 110, 0.1), transparent 45%),
radial-gradient(circle at 90% 10%, rgba(245, 158, 11, 0.12), transparent 40%),
linear-gradient(120deg, rgba(15, 118, 110, 0.07), transparent 50%);
z-index: -2;
}
.hero-shell {
position: relative;
background: linear-gradient(160deg, #0b1f2a 0%, #0f2f3d 60%, #113844 100%);
color: #f8fbfb;
overflow: hidden;
}
.hero-shell::after {
content: "";
position: absolute;
inset: 0;
background-image: radial-gradient(circle at 10% 20%, rgba(245, 158, 11, 0.2), transparent 40%),
radial-gradient(circle at 80% 20%, rgba(15, 118, 110, 0.3), transparent 45%);
opacity: 0.8;
pointer-events: none;
}
.site-header {
position: relative;
z-index: 1;
padding: 1.5rem 0 0.5rem;
}
.navbar-brand.brand {
font-family: "Space Grotesk", sans-serif;
font-size: 1.4rem;
font-weight: 700;
color: #fdfdfd;
letter-spacing: 0.02em;
}
.navbar .nav-link {
color: rgba(248, 251, 251, 0.85);
font-weight: 500;
}
.navbar .nav-link:hover,
.navbar .nav-link:focus {
color: #ffffff;
}
.btn-brand {
background: linear-gradient(130deg, var(--secondary), var(--accent));
border: none;
color: #1b1b1b;
font-weight: 600;
box-shadow: 0 10px 30px rgba(234, 88, 12, 0.3);
}
.btn-brand:hover,
.btn-brand:focus {
color: #1b1b1b;
transform: translateY(-1px);
box-shadow: 0 14px 35px rgba(234, 88, 12, 0.35);
}
.btn-ghost {
border: 1px solid rgba(248, 251, 251, 0.3);
color: #f8fbfb;
background: rgba(255, 255, 255, 0.05);
}
.btn-ghost:hover,
.btn-ghost:focus {
color: #f8fbfb;
border-color: rgba(248, 251, 251, 0.6);
}
.site-main {
position: relative;
z-index: 1;
padding: 2rem 0 5rem;
}
.hero-section {
padding: 2rem 0 4rem;
}
.eyebrow {
text-transform: uppercase;
letter-spacing: 0.24em;
font-size: 0.75rem;
color: rgba(248, 251, 251, 0.6);
margin-bottom: 1rem;
}
.hero-title {
font-family: "Space Grotesk", sans-serif;
font-size: clamp(2.5rem, 3.5vw, 3.6rem);
font-weight: 700;
line-height: 1.1;
margin-bottom: 1.5rem;
}
.hero-lead {
font-size: 1.1rem;
color: rgba(248, 251, 251, 0.75);
max-width: 36rem;
margin-bottom: 2rem;
}
.hero-actions {
display: flex;
gap: 1rem;
flex-wrap: wrap;
margin-bottom: 2rem;
}
.hero-stats {
display: grid;
gap: 1rem;
}
.stat-card {
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.08);
padding: 1rem 1.25rem;
border-radius: 16px;
}
.stat-value {
display: block;
font-weight: 600;
}
.stat-label {
font-size: 0.9rem;
color: rgba(248, 251, 251, 0.7);
}
.card-glass {
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 20px;
padding: 2rem;
box-shadow: 0 24px 50px rgba(3, 19, 29, 0.4);
backdrop-filter: blur(18px);
}
.card-glass-header {
margin-bottom: 1.5rem;
}
.card-title {
font-family: "Space Grotesk", sans-serif;
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.card-subtitle {
color: rgba(248, 251, 251, 0.7);
font-size: 0.95rem;
}
.generator-form .form-label,
.generator-form .form-text {
color: rgba(248, 251, 251, 0.75);
}
.generator-form .form-select,
.generator-form .form-control {
background: rgba(255, 255, 255, 0.12);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #fdfdfd;
}
.generator-form .form-select:focus,
.generator-form .form-control:focus {
border-color: var(--secondary);
box-shadow: 0 0 0 0.2rem rgba(245, 158, 11, 0.2);
}
.form-actions {
margin-top: 1.5rem;
}
.insights-section,
.games-section,
.process-section,
.cta-section {
padding: 4rem 0;
}
.section-header {
margin-bottom: 2rem;
}
.section-header h2 {
font-family: "Space Grotesk", sans-serif;
font-size: 2rem;
margin-bottom: 0.5rem;
}
.section-header p {
color: var(--ink-soft);
max-width: 36rem;
}
.card-soft {
background: var(--surface);
border-radius: 20px;
padding: 2rem;
box-shadow: 0 18px 40px rgba(11, 31, 42, 0.08);
border: 1px solid var(--line);
height: 100%;
}
.card-soft-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
margin-bottom: 1.5rem;
}
.pill {
display: inline-flex;
align-items: center;
padding: 0.35rem 0.8rem;
border-radius: 999px;
background: rgba(15, 118, 110, 0.1);
color: var(--primary-strong);
font-size: 0.8rem;
font-weight: 600;
}
.metrics {
display: grid;
gap: 1rem;
margin-bottom: 1.5rem;
}
.metric {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 1rem;
background: var(--surface-muted);
border-radius: 12px;
}
.metric-label {
color: var(--ink-soft);
font-size: 0.9rem;
}
.metric-value {
font-weight: 600;
}
.number-groups {
display: grid;
gap: 1rem;
}
.group-title {
font-weight: 600;
margin-bottom: 0.5rem;
}
.badge-grid {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.badge {
border-radius: 999px;
padding: 0.3rem 0.7rem;
font-size: 0.85rem;
font-weight: 600;
}
.badge-hot {
background: rgba(234, 88, 12, 0.15);
color: #c2410c;
}
.badge-cold {
background: rgba(15, 118, 110, 0.12);
color: var(--primary-strong);
}
.suggestions-grid {
display: grid;
gap: 1rem;
}
.suggestion {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
padding: 0.75rem;
background: var(--surface-muted);
border-radius: 12px;
}
.ball {
width: 36px;
height: 36px;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
background: #ffffff;
border: 1px solid var(--line);
font-weight: 600;
}
.placeholder-card {
display: flex;
gap: 1.5rem;
align-items: center;
background: var(--surface-muted);
}
.placeholder-icon {
font-size: 2.4rem;
color: var(--primary);
}
.games-section {
background: #f9fbfb;
}
.game-card {
background: #ffffff;
border-radius: 18px;
padding: 1.75rem;
border: 1px solid var(--line);
box-shadow: 0 14px 30px rgba(11, 31, 42, 0.08);
height: 100%;
display: flex;
flex-direction: column;
gap: 1rem;
}
.game-card-header h3 {
font-family: "Space Grotesk", sans-serif;
font-size: 1.4rem;
}
.game-meta {
display: flex;
justify-content: space-between;
color: var(--ink-soft);
font-size: 0.9rem;
}
.game-odds {
font-weight: 600;
color: var(--ink);
}
.process-card {
background: #ffffff;
border-radius: 18px;
padding: 2rem;
border: 1px solid var(--line);
box-shadow: 0 12px 28px rgba(11, 31, 42, 0.08);
height: 100%;
}
.process-card h3 {
font-family: "Space Grotesk", sans-serif;
font-size: 1.2rem;
margin-bottom: 0.6rem;
}
.step {
display: inline-flex;
align-items: center;
justify-content: center;
width: 42px;
height: 42px;
border-radius: 12px;
background: rgba(15, 118, 110, 0.15);
color: var(--primary-strong);
font-weight: 700;
margin-bottom: 1rem;
}
.cta-section {
background: linear-gradient(140deg, rgba(15, 118, 110, 0.12), rgba(245, 158, 11, 0.18));
}
.cta-card {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 2rem;
padding: 2.5rem;
border-radius: 20px;
background: #ffffff;
box-shadow: 0 18px 40px rgba(11, 31, 42, 0.08);
border: 1px solid var(--line);
}
.cta-card h2 {
font-family: "Space Grotesk", sans-serif;
font-size: 1.8rem;
margin-bottom: 0.5rem;
}
.site-footer {
padding: 2rem 0 3rem;
color: var(--ink-soft);
}
.site-footer .container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
justify-content: space-between;
}
.footer-meta {
font-size: 0.9rem;
}
@media (max-width: 992px) {
.hero-actions {
flex-direction: column;
}
.card-glass {
margin-top: 2rem;
}
}
@media (max-width: 768px) {
.hero-shell {
text-align: left;
}
.stat-card {
padding: 0.9rem 1rem;
}
.card-soft-header {
flex-direction: column;
align-items: flex-start;
}
}