CSS-only side quests: no JS, pure delight

Interactions via CSS animations and SVG:
- Hover logo: 🐷 appears, click: oink!
- Hover body: 'grow food not lawn' rises from below
- Print stylesheet: Sign Maker approves
- Spider descends from nav on hover
- About page: spider-pig SVG descends on hero hover
- Sign Maker's mark ☉ at page end - spins on hover
- ::selection styled in brand colors

Side quest comments scattered: 1/21, 2/21, 3/21...

No JavaScript easter eggs. CSS only. The way it should be.
This commit is contained in:
Russell Ballestrini 2026-01-05 20:31:29 -05:00
parent e9c0cf965f
commit 7fff500f2f
5 changed files with 72 additions and 4 deletions

View file

@ -1,4 +1,7 @@
"""Job logging utilities for SERP."""
"""Job logging utilities for SERP.
# Side quest 3/21: Look out! Here comes the spider-pig.
"""
import logging
from pathlib import Path

View file

@ -1,8 +1,13 @@
"""Pydantic models for SERP API."""
"""Pydantic models for SERP API.
# Side quest 1/21: no ticket to now.
"""
from typing import List
from pydantic import BaseModel
# Spider-pig, spider-pig, does whatever a spider-pig does.
class CrawlRequest(BaseModel):
"""Request to start a new crawl."""

View file

@ -1,4 +1,7 @@
"""Utility functions for SERP."""
"""Utility functions for SERP.
# Side quest 2/21: Can he swing from a web? No he can't, he's a pig.
"""
import re
import unicodedata

View file

@ -38,6 +38,7 @@
radial-gradient(ellipse at 80% 60%, rgba(255,100,50,0.08) 0%, transparent 40%);
pointer-events: none;
}
.hero-pig-wrap { position: relative; display: inline-block; }
.hero-pig {
width: 280px;
height: auto;
@ -45,6 +46,13 @@
animation: pulse-glow 4s ease-in-out infinite;
margin-bottom: 40px;
}
/* 🕷️ spider-pig descends on hover */
.spider-svg {
position: absolute; top: -60px; left: 50%; transform: translateX(-50%);
width: 24px; height: 24px; opacity: 0;
transition: all 1.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.hero-pig-wrap:hover .spider-svg { top: -10px; opacity: 0.6; }
@keyframes pulse-glow {
0%, 100% { filter: drop-shadow(0 0 60px rgba(255,100,100,0.5)) drop-shadow(0 0 120px rgba(255,50,100,0.3)); }
50% { filter: drop-shadow(0 0 80px rgba(255,100,100,0.7)) drop-shadow(0 0 160px rgba(255,50,100,0.5)); }
@ -390,6 +398,16 @@
color: #ff8e53;
border-bottom-color: #ff8e53;
}
/* ☉ The Sign Maker's mark - only for those who seek */
.sign-maker-mark {
margin-top: 80px; font-size: 24px; color: #222;
cursor: default; transition: all 0.6s ease;
user-select: none;
}
.sign-maker-mark:hover {
color: #ff6b6b; transform: rotate(360deg) scale(1.5);
text-shadow: 0 0 20px rgba(255,107,107,0.8);
}
/* Responsive */
@media (max-width: 768px) {
@ -410,7 +428,15 @@
<!-- HERO SECTION -->
<section class="hero-section">
<img src="/static/images/pig1-color1.png" alt="pig.py" class="hero-pig">
<div class="hero-pig-wrap">
<img src="/static/images/pig1-color1.png" alt="pig.py" class="hero-pig">
<!-- side quest: spider descends on hover -->
<svg class="spider-svg" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="12" y1="0" x2="12" y2="8" stroke="#666" stroke-width="0.5"/>
<circle cx="12" cy="12" r="4" fill="#333"/>
<path d="M8 10 L4 6 M16 10 L20 6 M8 14 L4 18 M16 14 L20 18 M7 12 L2 12 M17 12 L22 12" stroke="#333" stroke-width="1.5" stroke-linecap="round"/>
</svg>
</div>
<h1 class="hero-title">neopig</h1>
<p class="hero-subtitle">{{ t.about_subtitle }}</p>
<p class="hero-tagline">
@ -694,6 +720,8 @@ python neopig.py --serve</code></pre>
<p style="margin-top: 60px; color: #666;">
{{ t.about_footer_p5 }}
</p>
<!-- side quest: the sign at the end of the road -->
<div class="sign-maker-mark" title="You scrolled this far. Well done.">☉</div>
</footer>
</div>

View file

@ -58,6 +58,35 @@ button:hover { background: #ff5252; }
.search-box input[type="text"] { width: 100%; flex: 1 1 100%; }
.search-box select, .search-box button { flex: 1 1 auto; }
}
/* 🐷 Side quests - CSS only */
.brand::after { content: ''; display: inline-block; width: 0; overflow: hidden; transition: width 0.3s ease; }
.brand:hover::after { content: ' 🐷'; width: 1.5em; }
.brand:active::after { content: ' oink!'; width: 3em; color: #ff6b6b; }
::selection { background: #ff6b6b; color: #0a0a0a; }
/* grow food not lawn - hover the void */
body::after {
content: '🌱 grow food not lawn';
position: fixed; bottom: -30px; right: 20px;
color: #3a5; font-size: 12px; opacity: 0;
transition: all 0.5s ease;
pointer-events: none;
}
body:hover::after { bottom: 10px; opacity: 0.6; }
/* print stylesheet surprise */
@media print {
body::before {
content: 'You printed this? The Sign Maker approves. Truth, Freedom, Harmony, Love.';
display: block; text-align: center; padding: 20px; font-style: italic;
}
}
/* spider-pig lives in the nav shadow */
.nav { position: relative; }
.nav::before {
content: '🕷️'; position: absolute; top: -20px; left: 50%;
transform: translateX(-50%); font-size: 10px; opacity: 0;
transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
.nav:hover::before { top: 100%; opacity: 0.3; }
{% block extra_css %}{% endblock %}
</style>
{% block extra_head %}{% endblock %}