- Style/category filter panel with active chip display - Dismiss (excluded_ids) support — recipes don't reappear until next fresh search - Load more appends next batch without full re-fetch - Prep notes 'Before you start:' section above directions - Nutrition macro chips (kcal, fat, protein, carbs, fiber, sugar, sodium) - Composables extracted for reuse
844 lines
19 KiB
CSS
844 lines
19 KiB
CSS
/**
|
|
* Central Theme System for Kiwi
|
|
*
|
|
* This file contains all reusable, theme-aware, responsive CSS classes.
|
|
* Components should use these classes instead of custom styles where possible.
|
|
*/
|
|
|
|
/* ============================================
|
|
LAYOUT UTILITIES - RESPONSIVE GRIDS
|
|
============================================ */
|
|
|
|
.grid-responsive {
|
|
display: grid;
|
|
gap: var(--spacing-md);
|
|
}
|
|
|
|
.grid-auto {
|
|
display: grid;
|
|
gap: var(--spacing-md);
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
/* Stats grid — horizontal strip of compact stats */
|
|
.grid-stats {
|
|
display: grid;
|
|
gap: var(--spacing-md);
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.grid-stats-strip {
|
|
display: flex;
|
|
gap: 0;
|
|
overflow: hidden;
|
|
border-radius: var(--radius-lg);
|
|
background: var(--color-bg-secondary);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.grid-stats-strip .stat-strip-item {
|
|
flex: 1;
|
|
text-align: center;
|
|
padding: var(--spacing-sm) var(--spacing-xs);
|
|
border-right: 1px solid var(--color-border);
|
|
}
|
|
|
|
.grid-stats-strip .stat-strip-item:last-child {
|
|
border-right: none;
|
|
}
|
|
|
|
/* Force specific column counts */
|
|
.grid-1 { grid-template-columns: 1fr; }
|
|
.grid-2 { grid-template-columns: repeat(2, 1fr); }
|
|
.grid-3 { grid-template-columns: repeat(3, 1fr); }
|
|
.grid-4 { grid-template-columns: repeat(4, 1fr); }
|
|
|
|
/* ============================================
|
|
FLEXBOX UTILITIES
|
|
============================================ */
|
|
|
|
.flex { display: flex; }
|
|
.flex-col { display: flex; flex-direction: column; }
|
|
.flex-wrap { flex-wrap: wrap; }
|
|
.flex-center {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
.flex-between {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
.flex-start {
|
|
display: flex;
|
|
justify-content: flex-start;
|
|
align-items: center;
|
|
}
|
|
.flex-end {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
align-items: center;
|
|
}
|
|
|
|
.flex-responsive {
|
|
display: flex;
|
|
gap: var(--spacing-md);
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
/* ============================================
|
|
SPACING UTILITIES
|
|
============================================ */
|
|
|
|
.gap-xs { gap: var(--spacing-xs); }
|
|
.gap-sm { gap: var(--spacing-sm); }
|
|
.gap-md { gap: var(--spacing-md); }
|
|
.gap-lg { gap: var(--spacing-lg); }
|
|
.gap-xl { gap: var(--spacing-xl); }
|
|
|
|
.p-0 { padding: 0; }
|
|
.p-xs { padding: var(--spacing-xs); }
|
|
.p-sm { padding: var(--spacing-sm); }
|
|
.p-md { padding: var(--spacing-md); }
|
|
.p-lg { padding: var(--spacing-lg); }
|
|
.p-xl { padding: var(--spacing-xl); }
|
|
|
|
.m-0 { margin: 0; }
|
|
.m-xs { margin: var(--spacing-xs); }
|
|
.m-sm { margin: var(--spacing-sm); }
|
|
.m-md { margin: var(--spacing-md); }
|
|
.m-lg { margin: var(--spacing-lg); }
|
|
.m-xl { margin: var(--spacing-xl); }
|
|
|
|
.mt-xs { margin-top: var(--spacing-xs); }
|
|
.mt-sm { margin-top: var(--spacing-sm); }
|
|
.mt-md { margin-top: var(--spacing-md); }
|
|
.mb-xs { margin-bottom: var(--spacing-xs); }
|
|
.mb-sm { margin-bottom: var(--spacing-sm); }
|
|
.mb-md { margin-bottom: var(--spacing-md); }
|
|
.mb-lg { margin-bottom: var(--spacing-lg); }
|
|
.ml-xs { margin-left: var(--spacing-xs); }
|
|
.ml-md { margin-left: var(--spacing-md); }
|
|
.mr-md { margin-right: var(--spacing-md); }
|
|
|
|
.pt-md { padding-top: var(--spacing-md); }
|
|
.pb-md { padding-bottom: var(--spacing-md); }
|
|
.pl-md { padding-left: var(--spacing-md); }
|
|
.pr-md { padding-right: var(--spacing-md); }
|
|
|
|
/* ============================================
|
|
CARD COMPONENTS - THEME AWARE
|
|
============================================ */
|
|
|
|
.card {
|
|
background: var(--color-bg-card);
|
|
border-radius: var(--radius-xl);
|
|
padding: var(--spacing-lg);
|
|
box-shadow: var(--shadow-md);
|
|
border: 1px solid var(--color-border);
|
|
transition: box-shadow 0.2s ease;
|
|
}
|
|
|
|
.card:hover {
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.card-sm {
|
|
background: var(--color-bg-card);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--spacing-md);
|
|
box-shadow: var(--shadow-sm);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.card-secondary {
|
|
background: var(--color-bg-secondary);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--spacing-md);
|
|
box-shadow: var(--shadow-sm);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
/* Status border variants */
|
|
.card-success { border-left: 3px solid var(--color-success); }
|
|
.card-warning { border-left: 3px solid var(--color-warning); }
|
|
.card-error { border-left: 3px solid var(--color-error); }
|
|
.card-info { border-left: 3px solid var(--color-info); }
|
|
|
|
/* ============================================
|
|
BUTTON COMPONENTS - THEME AWARE
|
|
============================================ */
|
|
|
|
.btn {
|
|
padding: var(--spacing-sm) var(--spacing-md);
|
|
border: 1px solid transparent;
|
|
border-radius: var(--radius-md);
|
|
font-size: var(--font-size-sm);
|
|
font-weight: 600;
|
|
font-family: var(--font-body);
|
|
cursor: pointer;
|
|
transition: all 0.18s ease;
|
|
white-space: nowrap;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--spacing-xs);
|
|
}
|
|
|
|
.btn:hover {
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.btn:active {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.btn:disabled {
|
|
opacity: 0.45;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
/* Button variants */
|
|
.btn-primary {
|
|
background: var(--gradient-primary);
|
|
color: #1e1c1a;
|
|
border: none;
|
|
font-weight: 700;
|
|
box-shadow: var(--shadow-amber);
|
|
}
|
|
|
|
.btn-primary:hover:not(:disabled) {
|
|
box-shadow: 0 6px 20px rgba(232, 168, 32, 0.35);
|
|
}
|
|
|
|
.btn-success {
|
|
background: var(--color-success);
|
|
color: white;
|
|
}
|
|
|
|
.btn-success:hover:not(:disabled) {
|
|
background: var(--color-success-dark);
|
|
}
|
|
|
|
.btn-error {
|
|
background: var(--color-error);
|
|
color: white;
|
|
}
|
|
|
|
.btn-error:hover:not(:disabled) {
|
|
background: var(--color-error-dark);
|
|
}
|
|
|
|
.btn-info {
|
|
background: var(--color-info);
|
|
color: white;
|
|
}
|
|
|
|
.btn-info:hover:not(:disabled) {
|
|
background: var(--color-info-dark);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: var(--color-bg-elevated);
|
|
color: var(--color-text-secondary);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.btn-secondary:hover:not(:disabled) {
|
|
background: var(--color-bg-primary);
|
|
border-color: var(--color-primary);
|
|
color: var(--color-primary);
|
|
}
|
|
|
|
.btn-secondary.active {
|
|
background: var(--color-primary);
|
|
color: #1e1c1a;
|
|
border-color: var(--color-primary);
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Pill chip button — for filter chips */
|
|
.btn-chip {
|
|
padding: var(--spacing-xs) var(--spacing-sm);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-pill);
|
|
font-size: var(--font-size-xs);
|
|
font-weight: 500;
|
|
font-family: var(--font-body);
|
|
background: var(--color-bg-elevated);
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
transition: all 0.18s ease;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.btn-chip:hover {
|
|
border-color: var(--color-primary);
|
|
color: var(--color-primary);
|
|
}
|
|
|
|
.btn-chip.active {
|
|
background: var(--color-primary);
|
|
color: #1e1c1a;
|
|
border-color: var(--color-primary);
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Button sizes */
|
|
.btn-sm {
|
|
padding: var(--spacing-xs) var(--spacing-sm);
|
|
font-size: var(--font-size-xs);
|
|
}
|
|
|
|
.btn-lg {
|
|
padding: var(--spacing-md) var(--spacing-xl);
|
|
font-size: var(--font-size-base);
|
|
}
|
|
|
|
/* Icon-only action button */
|
|
.btn-icon {
|
|
width: 32px;
|
|
height: 32px;
|
|
padding: 0;
|
|
border: none;
|
|
border-radius: var(--radius-md);
|
|
background: transparent;
|
|
color: var(--color-text-muted);
|
|
cursor: pointer;
|
|
transition: all 0.18s ease;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.btn-icon:hover {
|
|
background: var(--color-bg-primary);
|
|
color: var(--color-text-primary);
|
|
transform: none;
|
|
}
|
|
|
|
.btn-icon.btn-icon-danger:hover {
|
|
color: var(--color-error);
|
|
}
|
|
|
|
.btn-icon.btn-icon-success:hover {
|
|
color: var(--color-success);
|
|
}
|
|
|
|
/* ============================================
|
|
FORM COMPONENTS - THEME AWARE
|
|
============================================ */
|
|
|
|
.form-group {
|
|
margin-bottom: var(--spacing-md);
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
margin-bottom: var(--spacing-xs);
|
|
font-weight: 600;
|
|
color: var(--color-text-secondary);
|
|
font-size: var(--font-size-xs);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.06em;
|
|
font-family: var(--font-body);
|
|
}
|
|
|
|
.form-input,
|
|
.form-select,
|
|
.form-textarea {
|
|
width: 100%;
|
|
padding: var(--spacing-sm) var(--spacing-md);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
background: var(--color-bg-input);
|
|
color: var(--color-text-primary);
|
|
font-size: var(--font-size-sm);
|
|
font-family: var(--font-body);
|
|
transition: border-color 0.18s ease, box-shadow 0.18s ease;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.form-input:focus,
|
|
.form-select:focus,
|
|
.form-textarea:focus {
|
|
outline: none;
|
|
border-color: var(--color-primary);
|
|
box-shadow: 0 0 0 3px var(--color-warning-bg);
|
|
}
|
|
|
|
.form-textarea {
|
|
resize: vertical;
|
|
min-height: 80px;
|
|
font-family: var(--font-body);
|
|
}
|
|
|
|
.form-row {
|
|
display: grid;
|
|
gap: var(--spacing-md);
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
/* Chip row filter bar — horizontal scroll */
|
|
.filter-chip-row {
|
|
display: flex;
|
|
gap: var(--spacing-xs);
|
|
overflow-x: auto;
|
|
padding-bottom: var(--spacing-xs);
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
.filter-chip-row::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
/* ============================================
|
|
TEXT UTILITIES
|
|
============================================ */
|
|
|
|
.text-xs { font-size: var(--font-size-xs); }
|
|
.text-sm { font-size: var(--font-size-sm); }
|
|
.text-base { font-size: var(--font-size-base); }
|
|
.text-lg { font-size: var(--font-size-lg); }
|
|
.text-xl { font-size: var(--font-size-xl); }
|
|
.text-2xl { font-size: var(--font-size-2xl); }
|
|
|
|
/* Display font */
|
|
.text-display {
|
|
font-family: var(--font-display);
|
|
font-style: italic;
|
|
}
|
|
|
|
/* Mono font */
|
|
.text-mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
.text-primary { color: var(--color-text-primary); }
|
|
.text-secondary { color: var(--color-text-secondary); }
|
|
.text-muted { color: var(--color-text-muted); }
|
|
|
|
.text-success { color: var(--color-success); }
|
|
.text-warning { color: var(--color-warning); }
|
|
.text-error { color: var(--color-error); }
|
|
.text-info { color: var(--color-info); }
|
|
.text-amber { color: var(--color-primary); }
|
|
|
|
.text-center { text-align: center; }
|
|
.text-left { text-align: left; }
|
|
.text-right { text-align: right; }
|
|
|
|
.font-bold { font-weight: 700; }
|
|
.font-semibold { font-weight: 600; }
|
|
.font-normal { font-weight: 400; }
|
|
|
|
/* ============================================
|
|
LOCATION DOT INDICATORS
|
|
============================================ */
|
|
|
|
.loc-dot {
|
|
width: 10px;
|
|
height: 10px;
|
|
border-radius: 50%;
|
|
flex-shrink: 0;
|
|
display: inline-block;
|
|
}
|
|
|
|
.loc-dot-fridge { background: var(--color-loc-fridge); }
|
|
.loc-dot-freezer { background: var(--color-loc-freezer); }
|
|
.loc-dot-garage_freezer { background: var(--color-loc-garage-freezer); }
|
|
.loc-dot-pantry { background: var(--color-loc-pantry); }
|
|
.loc-dot-cabinet { background: var(--color-loc-cabinet); }
|
|
|
|
/* Location left-border strip on inventory rows */
|
|
.inv-row-fridge { border-left-color: var(--color-loc-fridge) !important; }
|
|
.inv-row-freezer { border-left-color: var(--color-loc-freezer) !important; }
|
|
.inv-row-garage_freezer { border-left-color: var(--color-loc-garage-freezer) !important; }
|
|
.inv-row-pantry { border-left-color: var(--color-loc-pantry) !important; }
|
|
.inv-row-cabinet { border-left-color: var(--color-loc-cabinet) !important; }
|
|
|
|
/* ============================================
|
|
RESPONSIVE UTILITIES
|
|
============================================ */
|
|
|
|
.mobile-only { display: none; }
|
|
.desktop-only { display: block; }
|
|
|
|
.w-full { width: 100%; }
|
|
.w-auto { width: auto; }
|
|
|
|
.h-full { height: 100%; }
|
|
.h-auto { height: auto; }
|
|
|
|
/* ============================================
|
|
MOBILE BREAKPOINTS (<=480px)
|
|
============================================ */
|
|
|
|
@media (max-width: 480px) {
|
|
.mobile-only { display: block; }
|
|
.desktop-only { display: none; }
|
|
|
|
.grid-2,
|
|
.grid-3,
|
|
.grid-4 {
|
|
grid-template-columns: 1fr !important;
|
|
}
|
|
|
|
.flex-responsive {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.btn-mobile-full {
|
|
width: 100%;
|
|
min-width: 100%;
|
|
}
|
|
|
|
.card {
|
|
padding: var(--spacing-md);
|
|
border-radius: var(--radius-lg);
|
|
}
|
|
|
|
.card-sm {
|
|
padding: var(--spacing-sm);
|
|
}
|
|
|
|
.btn {
|
|
white-space: normal;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
/* ============================================
|
|
TABLET BREAKPOINTS (481px - 768px)
|
|
============================================ */
|
|
|
|
@media (min-width: 481px) and (max-width: 768px) {
|
|
.grid-3,
|
|
.grid-4 {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
|
|
.grid-auto {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
|
|
.grid-stats {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
|
|
.form-row {
|
|
grid-template-columns: 1fr 1fr;
|
|
}
|
|
}
|
|
|
|
/* ============================================
|
|
DESKTOP BREAKPOINTS (769px - 1024px)
|
|
============================================ */
|
|
|
|
@media (min-width: 769px) and (max-width: 1024px) {
|
|
.grid-auto {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
}
|
|
|
|
.grid-stats {
|
|
grid-template-columns: repeat(4, 1fr);
|
|
}
|
|
|
|
.grid-4 {
|
|
grid-template-columns: repeat(3, 1fr);
|
|
}
|
|
}
|
|
|
|
/* ============================================
|
|
LARGE DESKTOP (>=1025px)
|
|
============================================ */
|
|
|
|
@media (min-width: 1025px) {
|
|
.grid-auto {
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
}
|
|
|
|
.grid-stats {
|
|
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
|
}
|
|
|
|
.form-row {
|
|
grid-template-columns: 1fr 1fr;
|
|
}
|
|
}
|
|
|
|
/* ============================================
|
|
STATUS & STATE UTILITIES
|
|
============================================ */
|
|
|
|
.status-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 3px var(--spacing-sm);
|
|
border-radius: var(--radius-pill);
|
|
font-size: var(--font-size-xs);
|
|
font-weight: 600;
|
|
font-family: var(--font-mono);
|
|
letter-spacing: 0.02em;
|
|
}
|
|
|
|
.status-success {
|
|
background: var(--color-success-bg);
|
|
color: var(--color-success-light);
|
|
border: 1px solid var(--color-success-border);
|
|
}
|
|
|
|
.status-warning {
|
|
background: var(--color-warning-bg);
|
|
color: var(--color-warning-light);
|
|
border: 1px solid var(--color-warning-border);
|
|
}
|
|
|
|
.status-error {
|
|
background: var(--color-error-bg);
|
|
color: var(--color-error-light);
|
|
border: 1px solid var(--color-error-border);
|
|
}
|
|
|
|
.status-info {
|
|
background: var(--color-info-bg);
|
|
color: var(--color-info-light);
|
|
border: 1px solid var(--color-info-border);
|
|
}
|
|
|
|
/* ============================================
|
|
ANIMATION UTILITIES
|
|
============================================ */
|
|
|
|
.fade-in {
|
|
animation: fadeIn 0.3s ease-in;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; }
|
|
to { opacity: 1; }
|
|
}
|
|
|
|
.slide-up {
|
|
animation: slideUp 0.3s ease-out;
|
|
}
|
|
|
|
@keyframes slideUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(16px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Urgency pulse — for items expiring very soon */
|
|
@keyframes urgencyPulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.6; }
|
|
}
|
|
|
|
.pulse-urgent {
|
|
animation: urgencyPulse 1.8s ease-in-out infinite;
|
|
}
|
|
|
|
/* ============================================
|
|
LOADING UTILITIES
|
|
============================================ */
|
|
|
|
.spinner {
|
|
border: 2px solid var(--color-border);
|
|
border-top: 2px solid var(--color-primary);
|
|
border-radius: 50%;
|
|
width: 36px;
|
|
height: 36px;
|
|
animation: spin 0.9s linear infinite;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.spinner-sm {
|
|
width: 18px;
|
|
height: 18px;
|
|
border-width: 2px;
|
|
}
|
|
|
|
@keyframes spin {
|
|
0% { transform: rotate(0deg); }
|
|
100% { transform: rotate(360deg); }
|
|
}
|
|
|
|
/* ============================================
|
|
DIVIDER
|
|
============================================ */
|
|
|
|
.divider {
|
|
height: 1px;
|
|
background: var(--color-border);
|
|
margin: var(--spacing-lg) 0;
|
|
}
|
|
|
|
.divider-md {
|
|
margin: var(--spacing-md) 0;
|
|
}
|
|
|
|
/* ============================================
|
|
SECTION HEADERS (display font)
|
|
============================================ */
|
|
|
|
.section-title {
|
|
font-family: var(--font-display);
|
|
font-style: italic;
|
|
font-weight: 600;
|
|
color: var(--color-text-primary);
|
|
margin: 0;
|
|
}
|
|
|
|
/* ============================================
|
|
EASTER EGG — GRID KITCHEN NEON MODE
|
|
Activated via Konami code
|
|
============================================ */
|
|
|
|
body.neon-mode .card,
|
|
body.neon-mode .card-sm,
|
|
body.neon-mode .card-secondary {
|
|
box-shadow:
|
|
0 0 0 1px rgba(255, 0, 110, 0.35),
|
|
0 0 12px rgba(255, 0, 110, 0.18),
|
|
0 2px 20px rgba(131, 56, 236, 0.15);
|
|
}
|
|
|
|
body.neon-mode .btn-primary {
|
|
box-shadow: 0 0 18px rgba(255, 0, 110, 0.55), 0 0 36px rgba(131, 56, 236, 0.25);
|
|
color: #fff;
|
|
}
|
|
|
|
body.neon-mode .wordmark-kiwi {
|
|
text-shadow: 0 0 10px rgba(255, 0, 110, 0.7), 0 0 24px rgba(131, 56, 236, 0.5);
|
|
}
|
|
|
|
body.neon-mode .sidebar,
|
|
body.neon-mode .bottom-nav {
|
|
border-color: rgba(255, 0, 110, 0.3);
|
|
box-shadow: 4px 0 20px rgba(255, 0, 110, 0.12);
|
|
}
|
|
|
|
body.neon-mode .sidebar-item.active,
|
|
body.neon-mode .nav-item.active {
|
|
text-shadow: 0 0 8px currentColor;
|
|
}
|
|
|
|
/* Scanline overlay */
|
|
body.neon-mode::after {
|
|
content: '';
|
|
position: fixed;
|
|
inset: 0;
|
|
background: repeating-linear-gradient(
|
|
0deg,
|
|
transparent,
|
|
transparent 3px,
|
|
rgba(0, 0, 0, 0.08) 3px,
|
|
rgba(0, 0, 0, 0.08) 4px
|
|
);
|
|
pointer-events: none;
|
|
z-index: 9998;
|
|
animation: scanlineScroll 8s linear infinite;
|
|
}
|
|
|
|
@keyframes scanlineScroll {
|
|
0% { background-position: 0 0; }
|
|
100% { background-position: 0 80px; }
|
|
}
|
|
|
|
/* CRT flicker on wordmark */
|
|
body.neon-mode .wordmark-kiwi {
|
|
animation: crtFlicker 6s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes crtFlicker {
|
|
0%, 94%, 100% { opacity: 1; }
|
|
95% { opacity: 0.88; }
|
|
97% { opacity: 0.95; }
|
|
98% { opacity: 0.82; }
|
|
}
|
|
|
|
/* ============================================
|
|
EASTER EGG — KIWI BIRD SPRITE
|
|
============================================ */
|
|
|
|
.kiwi-bird-stage {
|
|
position: fixed;
|
|
bottom: 72px; /* above bottom nav */
|
|
left: 0;
|
|
right: 0;
|
|
height: 72px;
|
|
pointer-events: none;
|
|
z-index: 9999;
|
|
overflow: hidden;
|
|
}
|
|
|
|
@media (min-width: 769px) {
|
|
.kiwi-bird-stage {
|
|
bottom: 0;
|
|
left: 200px; /* clear the sidebar */
|
|
}
|
|
}
|
|
|
|
.kiwi-bird {
|
|
position: absolute;
|
|
bottom: 8px;
|
|
width: 64px;
|
|
height: 64px;
|
|
will-change: transform;
|
|
}
|
|
|
|
/* Enters from right, walks left */
|
|
.kiwi-bird.rtl {
|
|
animation: kiwiWalkRtl 5.5s ease-in-out forwards;
|
|
}
|
|
.kiwi-bird.rtl .kiwi-svg {
|
|
transform: scaleX(1); /* faces left */
|
|
}
|
|
|
|
/* Enters from left, walks right */
|
|
.kiwi-bird.ltr {
|
|
animation: kiwiWalkLtr 5.5s ease-in-out forwards;
|
|
}
|
|
.kiwi-bird.ltr .kiwi-svg {
|
|
transform: scaleX(-1); /* faces right */
|
|
}
|
|
|
|
/* Bob on each step */
|
|
.kiwi-svg {
|
|
display: block;
|
|
animation: kiwiBob 0.38s steps(1) infinite;
|
|
}
|
|
|
|
@keyframes kiwiWalkRtl {
|
|
0% { right: -80px; }
|
|
15% { right: 35%; } /* enter and slow */
|
|
40% { right: 35%; } /* pause — sniffing */
|
|
55% { right: 38%; } /* tiny shuffle */
|
|
60% { right: 35%; }
|
|
85% { right: 35%; }
|
|
100% { right: calc(100% + 80px); } /* exit left */
|
|
}
|
|
|
|
@keyframes kiwiWalkLtr {
|
|
0% { left: -80px; }
|
|
15% { left: 35%; }
|
|
40% { left: 35%; }
|
|
55% { left: 38%; }
|
|
60% { left: 35%; }
|
|
85% { left: 35%; }
|
|
100% { left: calc(100% + 80px); }
|
|
}
|
|
|
|
@keyframes kiwiBob {
|
|
0% { transform: translateY(0) scaleX(var(--bird-flip, 1)); }
|
|
50% { transform: translateY(-4px) scaleX(var(--bird-flip, 1)); }
|
|
}
|