Migrate to Stack A: PHP-fpm + nginx + supervisord, drop flat HTML + Python API
- Remove old flat HTML pages (index, about, blog, contact, reviews, services/*, locations/*) - Remove Python/Flask API container (api/) - Remove old root nginx.conf and components/ - Add infra/: full nginx.conf (http block at /etc/nginx/nginx.conf), php-fpm-pool.conf (TCP listen), supervisord.conf, entrypoint.sh (auto-generates ALTCHA_HMAC_KEY) - Add src/: PHP router, page/service/location/blog templates, contact handler, altcha handler, promo endpoint, SQLite data files - Rewrite Dockerfile: single container, tini PID 1, healthcheck, all env vars declared - Update docker-compose.yml: port 8096, env_file, healthcheck - Update .dockerignore: exclude .env.*, include robots.txt/sitemap.xml/404.html/500.html - Update assets: tokens.css, promo-popup.css/js, altcha.min.js, refactored form.js/main.js Verified: all 17 routes 200, protection audit PASS, Resend confirmed working Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
/* FLOOR IT HARDWOOD FLOORS. Summer Promo Topbar + Popup */
|
||||
|
||||
/* Topbar */
|
||||
#promo-topbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1001;
|
||||
height: 44px;
|
||||
background: #c8a96e;
|
||||
color: #1a1207;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0 1rem;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
#promo-topbar.visible { display: flex; }
|
||||
#promo-topbar-text { flex: 1; text-align: center; }
|
||||
#promo-topbar-btn {
|
||||
background: #1a1207;
|
||||
color: #c8a96e;
|
||||
border: none;
|
||||
padding: 0.3rem 0.85rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#promo-topbar-btn:hover { background: #0c0805; }
|
||||
#promo-topbar-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #1a1207;
|
||||
font-size: 1.3rem;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
opacity: 0.6;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
#promo-topbar-close:hover { opacity: 1; }
|
||||
|
||||
body.has-topbar #site-header { top: 44px; }
|
||||
|
||||
@media (max-width: 600px) {
|
||||
#promo-topbar-text { font-size: 0.72rem; }
|
||||
#promo-topbar { gap: 0.5rem; }
|
||||
}
|
||||
|
||||
/* Popup */
|
||||
#promo-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(30, 20, 10, 0.72);
|
||||
z-index: 9000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
pointer-events: none;
|
||||
}
|
||||
#promo-overlay.visible {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
#promo-box {
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
max-width: 480px;
|
||||
width: 100%;
|
||||
padding: 2.5rem 2rem 2rem;
|
||||
position: relative;
|
||||
box-shadow: 0 8px 40px rgba(0,0,0,0.3);
|
||||
}
|
||||
#promo-box .promo-badge {
|
||||
display: inline-block;
|
||||
background: #c8a96e;
|
||||
color: #fff;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
padding: 0.25rem 0.75rem;
|
||||
border-radius: 2px;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
#promo-box h2 {
|
||||
font-size: 1.45rem;
|
||||
line-height: 1.25;
|
||||
color: #1a1207;
|
||||
margin: 0 0 0.4rem;
|
||||
}
|
||||
#promo-box .promo-sub {
|
||||
font-size: 0.9rem;
|
||||
color: #6b5c3e;
|
||||
margin: 0 0 1.5rem;
|
||||
}
|
||||
#promo-box .promo-field {
|
||||
margin-bottom: 0.85rem;
|
||||
}
|
||||
#promo-box .promo-field label {
|
||||
display: block;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
color: #1a1207;
|
||||
margin-bottom: 0.3rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
#promo-box .promo-field input {
|
||||
width: 100%;
|
||||
padding: 0.65rem 0.85rem;
|
||||
border: 1.5px solid #d5c9b6;
|
||||
border-radius: 3px;
|
||||
font-size: 0.95rem;
|
||||
color: #1a1207;
|
||||
background: #faf8f5;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
#promo-box .promo-field input:focus {
|
||||
outline: none;
|
||||
border-color: #c8a96e;
|
||||
}
|
||||
#promo-box .promo-submit {
|
||||
width: 100%;
|
||||
padding: 0.85rem;
|
||||
background: #c8a96e;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
cursor: pointer;
|
||||
margin-top: 0.5rem;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
#promo-box .promo-submit:hover { background: #b5923d; }
|
||||
#promo-box .promo-submit:disabled { background: #ccc; cursor: default; }
|
||||
#promo-box .promo-error {
|
||||
font-size: 0.85rem;
|
||||
color: #b91c1c;
|
||||
margin-top: 0.5rem;
|
||||
display: none;
|
||||
}
|
||||
#promo-box .promo-success {
|
||||
text-align: center;
|
||||
padding: 1rem 0 0.5rem;
|
||||
display: none;
|
||||
}
|
||||
#promo-box .promo-success p {
|
||||
font-size: 1.05rem;
|
||||
color: #1a1207;
|
||||
margin: 0.5rem 0 0;
|
||||
}
|
||||
#promo-close {
|
||||
position: absolute;
|
||||
top: 0.85rem;
|
||||
right: 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
color: #9a8a72;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
}
|
||||
#promo-close:hover { color: #1a1207; }
|
||||
#promo-box .promo-fine {
|
||||
font-size: 0.72rem;
|
||||
color: #9a8a72;
|
||||
text-align: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
#promo-box { padding: 2rem 1.25rem 1.5rem; }
|
||||
#promo-box h2 { font-size: 1.2rem; }
|
||||
}
|
||||
Reference in New Issue
Block a user