CSS es un llenguatge de programació que s’utilitza per donar estil a una pàgina web.
La definició es: Cascading Style Sheets
El nostre css per al registre de la LAN Party es el seguent:
<style>
:root {
--neon-blue: #00f2ff;
--neon-purple: #bc13fe;
--bg-color: #0d0d0d;
}
body {
font-family: 'Segoe UI', Tahoma, sans-serif;
background-color: var(--bg-color);
color: white;
display: flex;
justify-content: center;
padding: 40px 20px;
margin: 0;
}
.container {
background: #1a1a1a;
padding: 30px;
border-radius: 15px;
box-shadow: 0 0 20px var(--neon-blue);
width: 100%;
max-width: 500px;
}
h2 { text-align: center; color: var(--neon-blue); text-transform: uppercase; margin-bottom: 25px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; font-size: 0.9rem; color: #ccc; }
input[type="text"], input[type="email"], input[type="tel"], textarea {
width: 100%;
padding: 10px;
background: #2a2a2a;
border: 1px solid var(--neon-purple);
color: white;
border-radius: 5px;
box-sizing: border-box;
}
.days-group {
display: flex;
gap: 15px;
background: #2a2a2a;
padding: 10px;
border-radius: 5px;
border: 1px solid var(--neon-purple);
}
.day-option { display: flex; align-items: center; gap: 5px; cursor: pointer; }
button {
width: 100%;
padding: 15px;
background: var(--neon-purple);
border: none;
color: white;
font-weight: bold;
text-transform: uppercase;
cursor: pointer;
border-radius: 5px;
margin-top: 20px;
transition: 0.3s;
}
button:hover { background: var(--neon-blue); color: black; }
.success-msg {
background: rgba(0, 255, 136, 0.2);
color: #00ff88;
padding: 10px;
border-radius: 5px;
text-align: center;
margin-bottom: 20px;
}
</style>Hem decidit fer amb un estil neó ja que ens quadra amb la LAN Party i així es veu millor quan es fosc
El codi al que s’aplica es el següent:
import http.server
import socketserver
import sqlite3
from urllib.parse import parse_qs
PORT = 8000
def init_db():
conn = sqlite3.connect('dades.db')
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS registres (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT, cognom TEXT, institut TEXT,
email TEXT, assistents INTEGER, horari TEXT
)
""")
conn.commit()
conn.close()
class MyHandler(http.server.SimpleHTTPRequestHandler):
def get_template(self, content):
"""Embolcalla qualsevol contingut amb l'estructura base (CSS, fons, etc.)"""
return f"""
<!DOCTYPE html>
<html lang='ca'>
<head>
<meta charset='UTF-8'>
<link rel='stylesheet' href='style.css'>
<title>Portes Obertes 2026</title>
</head>
<body>
{content}
</body>
</html>
"""
def do_GET(self):
# RUTA D'ADMINISTRACIÓ
if self.path == '/databaseadmin':
conn = sqlite3.connect('dades.db')
cursor = conn.cursor()
cursor.execute("SELECT nom, cognom, institut, email, assistents, horari FROM registres ORDER BY horari ASC")
rows = cursor.fetchall()
conn.close()
rows_html = ""
for r in rows:
rows_html += f"""
<tr>
<td>{r[0]}</td>
<td>{r[1]}</td>
<td>{r[2]}</td>
<td>{r[3]}</td>
<td style='text-align:center;'><span class='badge'>{r[4]}</span></td>
<td><strong>{r[5]}</strong></td>
</tr>
"""
admin_content = f"""
<div class='admin-wrapper'>
<div class='admin-header'>
<h2>Llista d'Inscrits</h2>
<p>Gestió d'assistència i aforament</p>
</div>
<div class='table-container'>
<table class='admin-table'>
<thead>
<tr>
<th>Nom</th>
<th>Cognom</th>
<th>Institut</th>
<th>Email</th>
<th style='text-align:center;'>Gent</th>
<th>Horari</th>
</tr>
</thead>
<tbody>
{rows_html if rows_html else "<tr><td colspan='6' style='text-align:center;'>No hi ha registres.</td></tr>"}
</tbody>
</table>
</div>
<div style='text-align:center; margin-top: 30px;'>
<a href='/' class='btn-back'>← Tornar al Registre</a>
</div>
</div>
"""
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(self.get_template(admin_content).encode('utf-8'))
# RUTA PRINCIPAL
elif self.path == '/' or self.path == '/index.html':
conn = sqlite3.connect('dades.db')
cursor = conn.cursor()
torns = ["16:45", "17:00", "17:15", "17:30", "17:45", "18:00", "18:15", "18:30"]
torns_html = ""
for t in torns:
cursor.execute("SELECT SUM(assistents) FROM registres WHERE horari = ?", (t,))
ocupat = cursor.fetchone()[0] or 0
lliures = 20 - ocupat
classe_ple = "torn-ple" if lliures <= 0 else ""
desactivat = "disabled" if lliures <= 0 else ""
color_places = "#4dff88" if lliures > 0 else "#ff4d4d"
text_places = f"{lliures} places restants" if lliures > 0 else "COMPLET"
torns_html += f"""
<label class="torn-card {classe_ple}">
<input type="radio" name="horari" value="{t}" {desactivat} required>
<div class="torn-info">
<span class="hora">{t}</span>
<span class="places" style="color: {color_places};">{text_places}</span>
</div>
</label>
"""
conn.close()
try:
with open('index.html', 'r', encoding='utf-8') as f:
content = f.read()
# Marcador per injectar el codi
final_html = content.replace("", torns_html)
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(final_html.encode('utf-8'))
except FileNotFoundError:
self.send_error(404, "index.html no trobat")
else:
super().do_GET()
def do_POST(self):
if self.path == '/submit':
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length).decode('utf-8')
params = parse_qs(post_data)
nom = params.get('nom', [''])[0]
cognom = params.get('cognom', [''])[0]
institut = params.get('institut', [''])[0]
email = params.get('email', [''])[0]
try:
assistents = int(params.get('assistents', [1])[0])
except (ValueError, TypeError):
assistents = 1
horari = params.get('horari', [''])[0]
conn = sqlite3.connect('dades.db')
cursor = conn.cursor()
cursor.execute("SELECT SUM(assistents) FROM registres WHERE horari = ?", (horari,))
resultat = cursor.fetchone()[0]
total_ara = resultat if resultat is not None else 0
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
if total_ara + assistents > 20:
msg = f"""
<div class='msg-box'>
<h1 style='color:#ff4d4d;'>⚠ Torn Complet</h1>
<p>Ho sentim, el torn de les <strong>{horari}</strong> no té espai per a {assistents} persones més.</p>
<a href='/'><button>Tornar a intentar</button></a>
</div>
"""
else:
cursor.execute("INSERT INTO registres (nom, cognom, institut, email, assistents, horari) VALUES (?, ?, ?, ?, ?, ?)",
(nom, cognom, institut, email, assistents, horari))
conn.commit()
msg = f"""
<div class='msg-box'>
<h1 style='color:#4dff88;'>✅ Registre Correcte</h1>
<p style="color:white;">Hola <strong>{nom}</strong>, t'esperem el 2 de març a les <strong>{horari}</strong>.</p>
<a href='/'><button style='background:#1e3a8a;'>Finalitzar</button></a>
</div>
"""
conn.close()
self.wfile.write(self.get_template(msg).encode('utf-8'))
if __name__ == "__main__":
init_db()
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", PORT), MyHandler) as httpd:
print(f"Servidor actiu a: http://localhost:{PORT}")
httpd.serve_forever()La nostra pàgina sense css es veu així:

En canvi amb css es veu així:

i en móvil es veuria una cosa així:

També hem afegit una animació que al clicar el botó de finalitzar registre també es posi en blau

les linea de codi que fa aixó
button:hover { background: var(--neon-blue); color: black; }el :hover fa que el button quan estàs a sobre façi el que estigui entre { }