Liven up parent and student login screens

Parent: floating card with box-shadow over a soft multi-radial gradient background; decorative emoji header above PIN form.
Student: each kid card gets a colored top border matching their saved theme; subtle floating emoji (stars, books, pencil, rainbow) drift in the background.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-08-04 16:42:20 -04:00
1 parent 538522cfe7
commit 8d6bcbe132
4 files changed
+75 -9

No files matched your search

+1
View File
@@ -9,6 +9,7 @@
<body>
<section id="pin-gate" class="view parent">
<div class="pin-deco" aria-hidden="true">📚 ✏️ 🎓</div>
<h1>👩‍🏫 Parent Dashboard</h1>
<form id="pin-form">
<input id="pin-input" type="password" inputmode="numeric" placeholder="Enter PIN" aria-label="Parent PIN">
+5 -4
View File
@@ -246,10 +246,11 @@ async function loadHome() {
const students = await api('/api/students');
$('#no-kids').hidden = students.length > 0;
$('#kid-cards').innerHTML = students
.map(
(s, i) => `<button class="kid-card" data-id="${s.id}" data-theme="${esc(s.theme || 'blue')}" style="animation-delay:${i * 100}ms">
<span class="avatar">${esc(s.emoji)}</span>${esc(s.name)}</button>`
)
.map((s, i) => {
const accent = (THEMES[s.theme || 'blue'] || {})['--accent'] || DEFAULT_VARS['--accent'];
return `<button class="kid-card" data-id="${s.id}" data-theme="${esc(s.theme || 'blue')}" style="--kid-accent:${accent};animation-delay:${i * 100}ms">
<span class="avatar">${esc(s.emoji)}</span>${esc(s.name)}</button>`;
})
.join('');
document.querySelectorAll('.kid-card').forEach((card) =>
card.addEventListener('click', () => openKid(Number(card.dataset.id), 'today', true))
+12
View File
@@ -8,6 +8,18 @@
</head>
<body>
<!-- Background decorations -->
<div class="page-confetti" aria-hidden="true">
<span style="left:4%;top:12%;animation-duration:4.2s;animation-delay:0s">⭐</span>
<span style="left:89%;top:7%;animation-duration:5.1s;animation-delay:1.3s">📚</span>
<span style="left:13%;top:78%;animation-duration:3.8s;animation-delay:2.2s">✏️</span>
<span style="left:80%;top:72%;animation-duration:4.7s;animation-delay:0.6s">🌈</span>
<span style="left:47%;top:4%;animation-duration:5.5s;animation-delay:1.9s">🎨</span>
<span style="left:93%;top:44%;animation-duration:3.5s;animation-delay:3.1s">⭐</span>
<span style="left:2%;top:52%;animation-duration:4.9s;animation-delay:0.3s">🌟</span>
<span style="left:60%;top:90%;animation-duration:4.4s;animation-delay:2.7s">📝</span>
</div>
<!-- Kid picker -->
<section id="view-home" class="view">
<h1 class="app-title">🎓 Homeschool</h1>
+57 -5
View File
@@ -54,7 +54,56 @@ body {
.hint { color: var(--muted); margin: 1rem 0; }
.error { color: var(--bad); margin: 0.5rem 0; }
/* ---------- parent lock screen ---------- */
body:has(#console[hidden]) {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background:
radial-gradient(ellipse at 20% 75%, rgba(79,134,247,0.13) 0%, transparent 55%),
radial-gradient(ellipse at 80% 25%, rgba(246,185,59,0.11) 0%, transparent 55%),
radial-gradient(ellipse at 55% 90%, rgba(46,158,91,0.08) 0%, transparent 45%),
var(--bg);
}
body:has(#console[hidden])::before {
content: '';
position: fixed; inset: 0; pointer-events: none;
background:
radial-gradient(circle 180px at 10% 15%, rgba(79,134,247,0.09) 0%, transparent 100%),
radial-gradient(circle 140px at 90% 85%, rgba(246,185,59,0.1) 0%, transparent 100%);
}
#pin-gate {
background: var(--card);
border-radius: 28px;
padding: 2.5rem 2.5rem 2rem;
box-shadow: 0 8px 48px rgba(45,49,66,0.14), 0 1px 0 rgba(45,49,66,0.06);
max-width: 360px;
width: calc(100% - 2.5rem);
margin: 0;
position: relative;
}
.pin-deco {
font-size: 2rem;
letter-spacing: 0.5rem;
margin-bottom: 1rem;
}
/* ---------- kid picker ---------- */
@keyframes confetti-float {
0%, 100% { transform: translateY(0px) rotate(-4deg); opacity: 0.28; }
50% { transform: translateY(-20px) rotate(6deg); opacity: 0.52; }
}
.page-confetti {
position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden;
}
.page-confetti span {
position: absolute; font-size: 1.8rem; user-select: none;
animation: confetti-float ease-in-out infinite;
}
@keyframes card-enter {
from { opacity: 0; transform: translateY(26px) scale(0.93); }
to { opacity: 1; transform: translateY(0) scale(1); }
@@ -70,28 +119,31 @@ body {
.kid-cards {
display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center;
margin-bottom: 2.5rem;
position: relative; z-index: 1;
}
.kid-card {
background: var(--card);
border: 3px solid transparent;
border-top: 5px solid var(--kid-accent, var(--accent));
border-radius: var(--radius);
padding: 1.5rem 2rem;
font-size: 1.2rem;
font-weight: 700;
cursor: pointer;
box-shadow: 0 4px 12px rgba(45, 49, 66, 0.08);
transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
box-shadow: 0 4px 16px rgba(45, 49, 66, 0.1);
transition: transform 0.18s ease, box-shadow 0.2s ease;
min-width: 140px;
animation: card-enter 0.42s ease backwards;
}
.kid-card:hover {
transform: translateY(-7px) scale(1.07);
border-color: var(--accent);
box-shadow: 0 12px 30px rgba(45, 49, 66, 0.18);
transform: translateY(-8px) scale(1.07);
box-shadow: 0 14px 36px color-mix(in srgb, var(--kid-accent, var(--accent)) 28%, rgba(45,49,66,0.15));
}
.kid-card:hover .avatar { animation: emoji-wobble 0.48s ease; }
.kid-card .avatar { display: block; font-size: 3rem; margin-bottom: 0.5rem; }
.app-title, .subtitle { position: relative; z-index: 1; }
/* ---------- kid home ---------- */
.back-btn {
display: inline-block;