chris 50680a323f Major overhaul: shared nav, admin improvements, email enhancements, routing fixes
Navigation & layout
- Replace per-page hardcoded nav/footer with shared nav.js (client-side injection)
- Add nginx reverse proxy back to docker-compose for clean localhost routing
- Rename /color-picker/ to /color/ across nav, directory, and references

eStore admin
- Add variation hiding controls (mirrors existing modifier hiding)
- Add delivery rate editor (base fee + per-mile per tier, persisted to data/)
- Fix all missing BASE prefix on fetch calls (admin PATCH/DELETE, availability, slots, colors)
- Mount estore/data/ as a Docker volume so admin config survives rebuilds

Booking & calendar
- Set pickup calendar events to TRANSPARENT (free) so they don't block delivery slots
- Skip CANCELLED events in busy-time calculation
- Re-check slot availability at checkout before charging (409 on conflict)

Phone & email validation
- Auto-format phone as (XXX) XXX-XXXX as user types
- Require exactly 10 digits; tighten email regex

Confirmation emails (store alert + customer)
- Full item detail per line: name, price, add-ons, colors, note
- Charges breakdown: subtotal, delivery fee, tax, total
- Delivery window: simplified M/D/YY h:mm – h:mm AM/PM format
- .ics calendar attachment on customer confirmation

Delivery rates
- Extract configurable rates to delivery-rates.ts (server-only, no fs in client bundle)
- calcDelivery() accepts optional rates param; delivery-quote route passes configured rates

Content
- Change all "40+ latex colors" references to "70+"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 21:14:06 -04:00

142 lines
3.9 KiB
CSS

/* ── Hero override: slim down the header ───────────────────────────────────── */
.admin-hero.admin-hero-slim {
padding: 0.85rem 1.5rem;
margin-bottom: 0;
}
.admin-hero.admin-hero-slim .title {
line-height: 1.2;
}
/* ── File input ─────────────────────────────────────────────────────────────── */
.admin-file-input .file-cta {
background: #e8f4fb;
border-color: #b5d9ef;
color: #2e7dbf;
font-weight: 600;
}
.admin-file-input .file-name {
max-width: none;
flex: 1;
color: #555;
border-color: #b5d9ef;
}
.admin-file-input:hover .file-cta {
background: #cde8f5;
}
/* ── Gallery cards ──────────────────────────────────────────────────────────── */
.low-tag-card {
box-shadow: 0 0 0 2px #ffdd57 inset;
}
.admin-gallery-grid .card {
transition: box-shadow 0.15s ease, transform 0.15s ease;
}
.admin-gallery-grid .card:hover {
box-shadow: 0 6px 20px rgba(24, 40, 72, 0.13);
transform: translateY(-2px);
}
/* Selected card: blue ring */
.admin-gallery-grid .card:has(.select-photo-checkbox:checked) {
box-shadow: 0 0 0 2.5px #2e7dbf inset, 0 6px 20px rgba(24, 40, 72, 0.1);
}
/* Card top bar (checkbox + tag count row) */
.admin-gallery-grid .card-content.py-2 {
background: rgba(0, 0, 0, 0.03);
border-bottom: 1px solid #ebe5d2;
}
/* Action buttons in card footer */
.admin-gallery-grid .card-footer-item {
font-weight: 600;
transition: background 0.12s ease, color 0.12s ease;
gap: 0.35em;
}
.admin-gallery-grid .card-footer-item.edit-button {
color: #2e7dbf;
}
.admin-gallery-grid .card-footer-item.edit-button:hover {
background: #e8f4fb;
color: #1a5a8a;
}
.admin-gallery-grid .card-footer-item.delete-button {
color: #cc3333;
}
.admin-gallery-grid .card-footer-item.delete-button:hover {
background: #fdf0f0;
color: #991111;
}
/* ── Bulk panel ─────────────────────────────────────────────────────────────── */
#bulkPanel {
position: sticky;
top: 16px;
z-index: 10;
box-shadow: 0 12px 24px rgba(17, 17, 17, 0.08);
}
@media (max-width: 768px) {
#bulkPanel {
top: 8px;
}
}
#clearSelection:hover {
color: #f14668;
}
/* ── Store status: toggle switch ────────────────────────────────────────────── */
.admin-toggle {
display: inline-flex;
align-items: center;
gap: 0.65rem;
cursor: pointer;
user-select: none;
}
.admin-toggle input[type="checkbox"] {
display: none;
}
.admin-toggle-track {
display: inline-block;
width: 42px;
height: 24px;
border-radius: 12px;
background: #ccc;
position: relative;
transition: background 0.2s ease;
flex-shrink: 0;
}
.admin-toggle-track::after {
content: '';
position: absolute;
top: 3px;
left: 3px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 3px rgba(0,0,0,0.25);
transition: transform 0.2s ease;
}
.admin-toggle input:checked ~ .admin-toggle-track {
background: #e53e3e;
}
.admin-toggle input:checked ~ .admin-toggle-track::after {
transform: translateX(18px);
}
.admin-toggle-label {
font-size: 0.875rem;
color: #555;
}
.admin-toggle input:checked ~ .admin-toggle-track + .admin-toggle-label,
.admin-toggle input:checked ~ .admin-toggle-label {
color: #c53030;
font-weight: 600;
}
/* Response notification */
#response {
border-radius: 10px;
}