- Add company module (3-tier org, CEO planning, parallel departments) - Add company orchestrator, knowledge extractor, presets, scheduler - Add company API endpoints, models, and frontend views - Add 今天吃啥 PWA app (69 dishes, real images, offline support) - Add team_projects output directory structure - Add unified manage.ps1 for service lifecycle - Add Windows startup guide v1.0 - Add TTS troubleshooting doc - Update frontend (AgentChat UX overhaul, new views) - Update backend (voice engine fix, multi-tenant, RBAC) - Remove deprecated startup scripts and old docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1257 lines
26 KiB
CSS
1257 lines
26 KiB
CSS
/* ============================================================
|
||
今天吃啥 · 渭南家常菜推荐助手
|
||
移动端优先 · 暖色主题 · 响应式三断点
|
||
============================================================ */
|
||
|
||
/* ---- CSS Custom Properties ---- */
|
||
:root {
|
||
/* 主色调 */
|
||
--color-primary: #FF9800;
|
||
--color-primary-dark: #F57C00;
|
||
--color-primary-light: #FFE0B2;
|
||
--color-primary-bg: #FFF3E0;
|
||
|
||
/* 中性色 */
|
||
--color-text: #4E342E;
|
||
--color-text-secondary: #8D6E63;
|
||
--color-text-muted: #A1887F;
|
||
--color-bg: #FFF8F0;
|
||
--color-surface: #FFFFFF;
|
||
--color-border: #E0D5C7;
|
||
|
||
/* 语义色 */
|
||
--color-danger: #E53935;
|
||
--color-success: #43A047;
|
||
--color-warning: #FFA000;
|
||
|
||
/* 阴影 */
|
||
--shadow-card: 0 2px 12px rgba(141, 110, 99, 0.12);
|
||
--shadow-card-hover: 0 6px 20px rgba(141, 110, 99, 0.18);
|
||
--shadow-modal: 0 12px 40px rgba(0, 0, 0, 0.2);
|
||
|
||
/* 圆角 */
|
||
--radius-sm: 6px;
|
||
--radius-md: 12px;
|
||
--radius-lg: 20px;
|
||
--radius-full: 9999px;
|
||
|
||
/* 字体 */
|
||
--font-base: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
||
"Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
|
||
--font-size-xs: 0.75rem; /* 12px */
|
||
--font-size-sm: 0.875rem; /* 14px */
|
||
--font-size-base: 1rem; /* 16px */
|
||
--font-size-lg: 1.125rem; /* 18px */
|
||
--font-size-xl: 1.5rem; /* 24px */
|
||
--font-size-2xl: 2rem; /* 32px */
|
||
|
||
/* 间距 */
|
||
--spacing-xs: 0.25rem;
|
||
--spacing-sm: 0.5rem;
|
||
--spacing-md: 1rem;
|
||
--spacing-lg: 1.5rem;
|
||
--spacing-xl: 2rem;
|
||
|
||
/* 动画 */
|
||
--transition-fast: 150ms ease;
|
||
--transition-normal: 250ms ease;
|
||
--transition-slow: 400ms ease;
|
||
|
||
/* 容器 */
|
||
--container-max: 1200px;
|
||
--header-height: 64px;
|
||
}
|
||
|
||
/* ---- Reset ---- */
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
html {
|
||
font-size: 16px;
|
||
-webkit-text-size-adjust: 100%;
|
||
scroll-behavior: smooth;
|
||
}
|
||
|
||
body {
|
||
font-family: var(--font-base);
|
||
font-size: var(--font-size-base);
|
||
line-height: 1.6;
|
||
color: var(--color-text);
|
||
background-color: var(--color-bg);
|
||
min-height: 100vh;
|
||
-webkit-font-smoothing: antialiased;
|
||
-moz-osx-font-smoothing: grayscale;
|
||
}
|
||
|
||
img {
|
||
max-width: 100%;
|
||
height: auto;
|
||
display: block;
|
||
}
|
||
|
||
button {
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
border: none;
|
||
background: none;
|
||
color: inherit;
|
||
font-size: inherit;
|
||
}
|
||
|
||
input, select, textarea {
|
||
font-family: inherit;
|
||
font-size: inherit;
|
||
color: inherit;
|
||
}
|
||
|
||
ul, ol {
|
||
list-style: none;
|
||
}
|
||
|
||
a {
|
||
color: inherit;
|
||
text-decoration: none;
|
||
}
|
||
|
||
/* ---- Screen Reader Only ---- */
|
||
.sr-only {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 1px;
|
||
padding: 0;
|
||
margin: -1px;
|
||
overflow: hidden;
|
||
clip: rect(0, 0, 0, 0);
|
||
white-space: nowrap;
|
||
border-width: 0;
|
||
}
|
||
|
||
/* ---- Focus Visible (键盘导航) ---- */
|
||
:focus-visible {
|
||
outline: 2px solid var(--color-primary);
|
||
outline-offset: 2px;
|
||
}
|
||
|
||
button:focus:not(:focus-visible) {
|
||
outline: none;
|
||
}
|
||
|
||
/* ============================================================
|
||
App Header
|
||
============================================================ */
|
||
.app-header {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
background: var(--color-surface);
|
||
border-bottom: 1px solid var(--color-border);
|
||
box-shadow: 0 1px 4px rgba(141, 110, 99, 0.08);
|
||
backdrop-filter: blur(8px);
|
||
-webkit-backdrop-filter: blur(8px);
|
||
}
|
||
|
||
.header-inner {
|
||
max-width: var(--container-max);
|
||
margin: 0 auto;
|
||
padding: 0 var(--spacing-md);
|
||
height: var(--header-height);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.app-title {
|
||
font-size: var(--font-size-xl);
|
||
font-weight: 700;
|
||
color: var(--color-primary-dark);
|
||
letter-spacing: 0.02em;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.title-icon {
|
||
margin-right: var(--spacing-sm);
|
||
font-size: 1.6rem;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
/* 顶部导航按钮 */
|
||
.header-nav {
|
||
display: flex;
|
||
gap: var(--spacing-xs);
|
||
}
|
||
|
||
.nav-btn {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 2px;
|
||
padding: var(--spacing-xs) var(--spacing-sm);
|
||
border-radius: var(--radius-md);
|
||
font-size: var(--font-size-xs);
|
||
color: var(--color-text-secondary);
|
||
transition: color var(--transition-fast), background var(--transition-fast);
|
||
min-width: 48px;
|
||
}
|
||
|
||
.nav-btn:hover {
|
||
color: var(--color-primary);
|
||
background: var(--color-primary-bg);
|
||
}
|
||
|
||
.nav-btn[aria-current="true"] {
|
||
color: var(--color-primary);
|
||
background: var(--color-primary-light);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.nav-icon {
|
||
display: block;
|
||
}
|
||
|
||
/* ============================================================
|
||
Main Layout
|
||
============================================================ */
|
||
.app-main {
|
||
max-width: var(--container-max);
|
||
margin: 0 auto;
|
||
padding: var(--spacing-lg) var(--spacing-md);
|
||
padding-bottom: calc(var(--spacing-xl) * 3);
|
||
}
|
||
|
||
/* ---- Section 通用 ---- */
|
||
.section {
|
||
margin-bottom: var(--spacing-xl);
|
||
}
|
||
|
||
.section[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
gap: var(--spacing-sm);
|
||
margin-bottom: var(--spacing-lg);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: var(--font-size-lg);
|
||
font-weight: 700;
|
||
color: var(--color-text);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.section-icon {
|
||
color: var(--color-primary);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.result-count {
|
||
font-size: var(--font-size-sm);
|
||
font-weight: 400;
|
||
color: var(--color-text-muted);
|
||
margin-left: var(--spacing-xs);
|
||
}
|
||
|
||
/* ============================================================
|
||
Buttons
|
||
============================================================ */
|
||
.btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: var(--spacing-sm);
|
||
padding: 0.6rem 1.4rem;
|
||
font-size: var(--font-size-sm);
|
||
font-weight: 600;
|
||
border-radius: var(--radius-full);
|
||
transition: transform var(--transition-fast),
|
||
box-shadow var(--transition-fast),
|
||
background var(--transition-fast);
|
||
white-space: nowrap;
|
||
user-select: none;
|
||
}
|
||
|
||
.btn:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.btn-primary {
|
||
background: var(--color-primary);
|
||
color: #fff;
|
||
box-shadow: 0 2px 8px rgba(255, 152, 0, 0.3);
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
background: var(--color-primary-dark);
|
||
box-shadow: 0 4px 12px rgba(255, 152, 0, 0.4);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: var(--color-surface);
|
||
color: var(--color-primary);
|
||
border: 1.5px solid var(--color-primary);
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: var(--color-primary-bg);
|
||
}
|
||
|
||
.btn-refresh {
|
||
background: var(--color-primary-bg);
|
||
color: var(--color-primary-dark);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.btn-refresh:hover {
|
||
background: var(--color-primary-light);
|
||
}
|
||
|
||
.btn-fav {
|
||
background: var(--color-surface);
|
||
color: var(--color-danger);
|
||
border: 1.5px solid var(--color-danger);
|
||
}
|
||
|
||
.btn-fav:hover {
|
||
background: #FFEBEE;
|
||
}
|
||
|
||
.btn-fav.btn-fav-active {
|
||
background: var(--color-danger);
|
||
color: #fff;
|
||
}
|
||
|
||
.btn-sm {
|
||
padding: 0.4rem 1rem;
|
||
font-size: var(--font-size-xs);
|
||
}
|
||
|
||
/* ============================================================
|
||
Chips (筛选标签)
|
||
============================================================ */
|
||
.chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 0.45rem 1rem;
|
||
font-size: var(--font-size-sm);
|
||
border-radius: var(--radius-full);
|
||
background: var(--color-surface);
|
||
color: var(--color-text-secondary);
|
||
border: 1.5px solid var(--color-border);
|
||
transition: all var(--transition-fast);
|
||
white-space: nowrap;
|
||
user-select: none;
|
||
}
|
||
|
||
.chip:hover {
|
||
border-color: var(--color-primary);
|
||
color: var(--color-primary);
|
||
}
|
||
|
||
.chip:active {
|
||
transform: scale(0.95);
|
||
}
|
||
|
||
.chip-active,
|
||
.chip[aria-pressed="true"] {
|
||
background: var(--color-primary);
|
||
color: #fff;
|
||
border-color: var(--color-primary);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.chip-sm {
|
||
padding: 0.3rem 0.75rem;
|
||
font-size: var(--font-size-xs);
|
||
}
|
||
|
||
/* ---- 筛选组 ---- */
|
||
.filter-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
margin-bottom: var(--spacing-md);
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: var(--font-size-sm);
|
||
color: var(--color-text-secondary);
|
||
font-weight: 600;
|
||
margin-right: var(--spacing-xs);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* 忌口 Toggle Switch */
|
||
.toggle-label {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
cursor: pointer;
|
||
user-select: none;
|
||
}
|
||
|
||
.toggle-input {
|
||
position: absolute;
|
||
opacity: 0;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
|
||
.toggle-switch {
|
||
position: relative;
|
||
width: 40px;
|
||
height: 22px;
|
||
background: var(--color-border);
|
||
border-radius: var(--radius-full);
|
||
transition: background var(--transition-normal);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.toggle-switch::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 3px;
|
||
left: 3px;
|
||
width: 16px;
|
||
height: 16px;
|
||
background: #fff;
|
||
border-radius: 50%;
|
||
transition: transform var(--transition-normal);
|
||
box-shadow: 0 1px 3px rgba(0,0,0,0.15);
|
||
}
|
||
|
||
.toggle-input:checked + .toggle-switch {
|
||
background: var(--color-primary);
|
||
}
|
||
|
||
.toggle-input:checked + .toggle-switch::after {
|
||
transform: translateX(18px);
|
||
}
|
||
|
||
.toggle-text {
|
||
font-size: var(--font-size-sm);
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
/* ---- 排序选择 ---- */
|
||
.sort-control {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.select-sort {
|
||
padding: 0.4rem 2rem 0.4rem 0.75rem;
|
||
font-size: var(--font-size-sm);
|
||
border: 1.5px solid var(--color-border);
|
||
border-radius: var(--radius-full);
|
||
background: var(--color-surface);
|
||
color: var(--color-text);
|
||
appearance: none;
|
||
-webkit-appearance: none;
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24'%3E%3Cpath fill='%238D6E63' d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
|
||
background-repeat: no-repeat;
|
||
background-position: right 0.6rem center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.select-sort:focus {
|
||
border-color: var(--color-primary);
|
||
outline: none;
|
||
}
|
||
|
||
/* ============================================================
|
||
推荐卡片
|
||
============================================================ */
|
||
.recommend-card {
|
||
background: var(--color-surface);
|
||
border-radius: var(--radius-lg);
|
||
box-shadow: var(--shadow-card);
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
transition: box-shadow var(--transition-normal);
|
||
}
|
||
|
||
.recommend-card:hover {
|
||
box-shadow: var(--shadow-card-hover);
|
||
}
|
||
|
||
.card-img-wrap {
|
||
position: relative;
|
||
background: var(--color-primary-bg);
|
||
overflow: hidden;
|
||
aspect-ratio: 3 / 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.card-img-placeholder {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.card-img-placeholder img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
display: block;
|
||
}
|
||
|
||
.card-badge {
|
||
position: absolute;
|
||
top: var(--spacing-sm);
|
||
right: var(--spacing-sm);
|
||
padding: 0.2rem 0.75rem;
|
||
font-size: var(--font-size-xs);
|
||
font-weight: 600;
|
||
border-radius: var(--radius-full);
|
||
color: #fff;
|
||
}
|
||
|
||
.card-badge-category {
|
||
background: var(--color-primary);
|
||
}
|
||
|
||
.card-badge-time {
|
||
background: var(--color-primary-dark);
|
||
}
|
||
|
||
.card-body {
|
||
padding: var(--spacing-md) var(--spacing-lg) var(--spacing-lg);
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.card-dish-name {
|
||
font-size: var(--font-size-xl);
|
||
font-weight: 700;
|
||
color: var(--color-text);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.card-dish-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--spacing-xs);
|
||
}
|
||
|
||
.tag {
|
||
display: inline-block;
|
||
padding: 0.15rem 0.6rem;
|
||
font-size: var(--font-size-xs);
|
||
background: var(--color-primary-bg);
|
||
color: var(--color-primary-dark);
|
||
border-radius: var(--radius-full);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.card-meta {
|
||
display: flex;
|
||
gap: var(--spacing-lg);
|
||
font-size: var(--font-size-sm);
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
.meta-item {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.btn-detail {
|
||
align-self: flex-start;
|
||
margin-top: var(--spacing-sm);
|
||
}
|
||
|
||
/* ============================================================
|
||
菜品卡片网格
|
||
============================================================ */
|
||
.dishes-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: var(--spacing-md);
|
||
}
|
||
|
||
.dish-card {
|
||
background: var(--color-surface);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-card);
|
||
overflow: hidden;
|
||
transition: box-shadow var(--transition-normal), transform var(--transition-fast);
|
||
cursor: pointer;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.dish-card:hover {
|
||
box-shadow: var(--shadow-card-hover);
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.dish-card:active {
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
.dish-card .card-img-wrap {
|
||
aspect-ratio: 3 / 2;
|
||
background: linear-gradient(135deg, var(--color-primary-bg), #FFCC80);
|
||
}
|
||
|
||
.dish-card .card-body {
|
||
padding: var(--spacing-md);
|
||
gap: var(--spacing-xs);
|
||
}
|
||
|
||
.dish-card .card-dish-name {
|
||
font-size: var(--font-size-base);
|
||
}
|
||
|
||
.dish-card .card-badge {
|
||
font-size: 0.65rem;
|
||
padding: 0.15rem 0.5rem;
|
||
}
|
||
|
||
/* ============================================================
|
||
空状态
|
||
============================================================ */
|
||
.empty-state {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 4rem 1rem;
|
||
text-align: center;
|
||
color: var(--color-text-muted);
|
||
gap: var(--spacing-md);
|
||
}
|
||
|
||
.empty-state[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
.empty-text {
|
||
font-size: var(--font-size-base);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.empty-hint {
|
||
font-size: var(--font-size-sm);
|
||
color: var(--color-text-muted);
|
||
}
|
||
|
||
/* ============================================================
|
||
周菜单
|
||
============================================================ */
|
||
.weekly-actions {
|
||
display: flex;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.weekly-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr;
|
||
gap: var(--spacing-md);
|
||
}
|
||
|
||
.weekly-day-card {
|
||
background: var(--color-surface);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-card);
|
||
overflow: hidden;
|
||
transition: box-shadow var(--transition-normal);
|
||
}
|
||
|
||
.weekly-day-card:hover {
|
||
box-shadow: var(--shadow-card-hover);
|
||
}
|
||
|
||
.day-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--spacing-sm) var(--spacing-md);
|
||
background: var(--color-primary);
|
||
color: #fff;
|
||
}
|
||
|
||
.day-name {
|
||
font-weight: 700;
|
||
font-size: var(--font-size-base);
|
||
}
|
||
|
||
.day-date {
|
||
font-size: var(--font-size-sm);
|
||
opacity: 0.85;
|
||
}
|
||
|
||
.day-meals {
|
||
padding: var(--spacing-sm) var(--spacing-md) var(--spacing-md);
|
||
}
|
||
|
||
.meal-slot {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
padding: var(--spacing-sm) 0;
|
||
border-bottom: 1px dashed var(--color-border);
|
||
}
|
||
|
||
.meal-slot:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.meal-label {
|
||
font-size: var(--font-size-xs);
|
||
font-weight: 600;
|
||
color: var(--color-primary-dark);
|
||
background: var(--color-primary-bg);
|
||
padding: 0.15rem 0.5rem;
|
||
border-radius: var(--radius-sm);
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.meal-dish {
|
||
font-size: var(--font-size-sm);
|
||
font-weight: 500;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
/* ============================================================
|
||
买菜清单
|
||
============================================================ */
|
||
.grocery-actions {
|
||
display: flex;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.grocery-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: var(--spacing-md);
|
||
}
|
||
|
||
.grocery-category {
|
||
background: var(--color-surface);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-card);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.grocery-category-header {
|
||
padding: var(--spacing-sm) var(--spacing-md);
|
||
background: var(--color-primary-bg);
|
||
font-weight: 700;
|
||
font-size: var(--font-size-sm);
|
||
color: var(--color-primary-dark);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.grocery-items {
|
||
padding: var(--spacing-sm) var(--spacing-md);
|
||
}
|
||
|
||
.grocery-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: var(--spacing-xs) 0;
|
||
border-bottom: 1px solid var(--color-border);
|
||
font-size: var(--font-size-sm);
|
||
}
|
||
|
||
.grocery-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.grocery-item-name {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.grocery-checkbox {
|
||
width: 18px;
|
||
height: 18px;
|
||
accent-color: var(--color-primary);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.grocery-item-checked {
|
||
text-decoration: line-through;
|
||
color: var(--color-text-muted);
|
||
}
|
||
|
||
.grocery-item-qty {
|
||
color: var(--color-text-muted);
|
||
font-size: var(--font-size-xs);
|
||
}
|
||
|
||
/* ============================================================
|
||
收藏 & 忌口管理
|
||
============================================================ */
|
||
.dietary-manager {
|
||
background: var(--color-surface);
|
||
border-radius: var(--radius-md);
|
||
box-shadow: var(--shadow-card);
|
||
padding: var(--spacing-lg);
|
||
}
|
||
|
||
.dietary-hint {
|
||
font-size: var(--font-size-sm);
|
||
color: var(--color-text-muted);
|
||
margin-bottom: var(--spacing-md);
|
||
}
|
||
|
||
.dietary-input-row {
|
||
display: flex;
|
||
gap: var(--spacing-sm);
|
||
margin-bottom: var(--spacing-md);
|
||
}
|
||
|
||
.input-text {
|
||
flex: 1;
|
||
padding: 0.5rem 0.75rem;
|
||
border: 1.5px solid var(--color-border);
|
||
border-radius: var(--radius-full);
|
||
font-size: var(--font-size-sm);
|
||
background: var(--color-bg);
|
||
transition: border-color var(--transition-fast);
|
||
}
|
||
|
||
.input-text:focus {
|
||
border-color: var(--color-primary);
|
||
outline: none;
|
||
box-shadow: 0 0 0 3px rgba(255, 152, 0, 0.15);
|
||
}
|
||
|
||
.dietary-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.dietary-tag {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: var(--spacing-xs);
|
||
padding: 0.3rem 0.75rem;
|
||
font-size: var(--font-size-sm);
|
||
background: #FFEBEE;
|
||
color: var(--color-danger);
|
||
border-radius: var(--radius-full);
|
||
font-weight: 500;
|
||
}
|
||
|
||
.dietary-tag-remove {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
background: var(--color-danger);
|
||
color: #fff;
|
||
font-size: 0.7rem;
|
||
cursor: pointer;
|
||
transition: transform var(--transition-fast);
|
||
}
|
||
|
||
.dietary-tag-remove:hover {
|
||
transform: scale(1.15);
|
||
}
|
||
|
||
/* ============================================================
|
||
Modal 弹窗
|
||
============================================================ */
|
||
.modal-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 200;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
align-items: flex-end;
|
||
justify-content: center;
|
||
animation: fadeIn var(--transition-normal);
|
||
}
|
||
|
||
.modal-overlay[hidden] {
|
||
display: none;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; }
|
||
to { opacity: 1; }
|
||
}
|
||
|
||
.modal-content {
|
||
background: var(--color-surface);
|
||
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
||
width: 100%;
|
||
max-height: 85vh;
|
||
overflow-y: auto;
|
||
animation: slideUp var(--transition-slow) ease;
|
||
box-shadow: var(--shadow-modal);
|
||
position: relative;
|
||
}
|
||
|
||
@keyframes slideUp {
|
||
from { transform: translateY(100%); }
|
||
to { transform: translateY(0); }
|
||
}
|
||
|
||
.modal-close {
|
||
position: sticky;
|
||
top: 0;
|
||
float: right;
|
||
z-index: 10;
|
||
margin: var(--spacing-sm);
|
||
padding: var(--spacing-sm);
|
||
border-radius: 50%;
|
||
background: rgba(0, 0, 0, 0.05);
|
||
color: var(--color-text);
|
||
transition: background var(--transition-fast);
|
||
}
|
||
|
||
.modal-close:hover {
|
||
background: rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.modal-body {
|
||
padding: var(--spacing-md) var(--spacing-lg) var(--spacing-xl);
|
||
}
|
||
|
||
.modal-img-placeholder {
|
||
width: 100%;
|
||
aspect-ratio: 3 / 2;
|
||
background: linear-gradient(135deg, var(--color-primary-bg), #FFCC80);
|
||
border-radius: var(--radius-md);
|
||
margin-bottom: var(--spacing-lg);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.modal-img-placeholder img {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
display: block;
|
||
}
|
||
|
||
.modal-dish-name {
|
||
font-size: var(--font-size-xl);
|
||
font-weight: 700;
|
||
margin-bottom: var(--spacing-sm);
|
||
}
|
||
|
||
.modal-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: var(--spacing-xs);
|
||
margin-bottom: var(--spacing-lg);
|
||
}
|
||
|
||
.modal-ingredients,
|
||
.modal-steps {
|
||
margin-bottom: var(--spacing-lg);
|
||
}
|
||
|
||
.modal-ingredients h3,
|
||
.modal-steps h3 {
|
||
font-size: var(--font-size-base);
|
||
font-weight: 700;
|
||
color: var(--color-primary-dark);
|
||
margin-bottom: var(--spacing-sm);
|
||
padding-bottom: var(--spacing-xs);
|
||
border-bottom: 2px solid var(--color-primary-light);
|
||
}
|
||
|
||
.modal-ingredients li,
|
||
.modal-steps li {
|
||
padding: var(--spacing-sm) 0;
|
||
border-bottom: 1px dashed var(--color-border);
|
||
font-size: var(--font-size-sm);
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.modal-steps li {
|
||
counter-increment: step-counter;
|
||
display: flex;
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.modal-steps li::before {
|
||
content: counter(step-counter);
|
||
flex-shrink: 0;
|
||
width: 24px;
|
||
height: 24px;
|
||
background: var(--color-primary);
|
||
color: #fff;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: var(--font-size-xs);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.modal-steps ol {
|
||
counter-reset: step-counter;
|
||
}
|
||
|
||
.modal-steps .step-time {
|
||
display: block;
|
||
font-size: var(--font-size-xs);
|
||
color: var(--color-text-muted);
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.modal-footer {
|
||
display: flex;
|
||
gap: var(--spacing-md);
|
||
padding-top: var(--spacing-md);
|
||
border-top: 1px solid var(--color-border);
|
||
}
|
||
|
||
/* ============================================================
|
||
Toast 提示
|
||
============================================================ */
|
||
.toast-container {
|
||
position: fixed;
|
||
bottom: var(--spacing-xl);
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
z-index: 300;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: var(--spacing-sm);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.toast {
|
||
padding: 0.6rem 1.4rem;
|
||
background: #323232;
|
||
color: #fff;
|
||
border-radius: var(--radius-full);
|
||
font-size: var(--font-size-sm);
|
||
font-weight: 500;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
||
animation: toastIn var(--transition-normal), toastOut var(--transition-normal) 2s forwards;
|
||
pointer-events: auto;
|
||
}
|
||
|
||
@keyframes toastIn {
|
||
from { opacity: 0; transform: translateY(1rem); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
@keyframes toastOut {
|
||
from { opacity: 1; transform: translateY(0); }
|
||
to { opacity: 0; transform: translateY(-0.5rem); }
|
||
}
|
||
|
||
/* ============================================================
|
||
Skeleton Loading (骨架屏)
|
||
============================================================ */
|
||
.skeleton-text {
|
||
display: inline-block;
|
||
background: linear-gradient(90deg, #eee 25%, #f5f5f5 50%, #eee 75%);
|
||
background-size: 200% 100%;
|
||
animation: shimmer 1.5s ease-in-out infinite;
|
||
border-radius: var(--radius-sm);
|
||
color: transparent !important;
|
||
user-select: none;
|
||
}
|
||
|
||
.skeleton-text-lg {
|
||
width: 70%;
|
||
height: 1.2em;
|
||
}
|
||
|
||
.skeleton-text:not(.skeleton-text-lg) {
|
||
width: 50%;
|
||
height: 0.9em;
|
||
}
|
||
|
||
.skeleton-pulse {
|
||
background: linear-gradient(90deg, #f0ece6 25%, #faf7f2 50%, #f0ece6 75%);
|
||
background-size: 200% 100%;
|
||
animation: shimmer 1.5s ease-in-out infinite;
|
||
border-radius: var(--radius-sm);
|
||
}
|
||
|
||
@keyframes shimmer {
|
||
0% { background-position: 200% 0; }
|
||
100% { background-position: -200% 0; }
|
||
}
|
||
|
||
.skeleton-loading .card-img-placeholder {
|
||
min-height: 120px;
|
||
}
|
||
|
||
.skeleton-loading.weekly-day-card .day-header {
|
||
background: #e0d5c7;
|
||
}
|
||
|
||
/* ============================================================
|
||
Reduced Motion (无障碍)
|
||
============================================================ */
|
||
@media (prefers-reduced-motion: reduce) {
|
||
*,
|
||
*::before,
|
||
*::after {
|
||
animation-duration: 0.01ms !important;
|
||
animation-iteration-count: 1 !important;
|
||
transition-duration: 0.01ms !important;
|
||
}
|
||
|
||
html {
|
||
scroll-behavior: auto;
|
||
}
|
||
}
|
||
|
||
/* ============================================================
|
||
响应式断点:≥768px 双列布局
|
||
============================================================ */
|
||
@media (min-width: 768px) {
|
||
.header-inner {
|
||
padding: 0 var(--spacing-lg);
|
||
}
|
||
|
||
.nav-btn {
|
||
flex-direction: row;
|
||
gap: var(--spacing-sm);
|
||
padding: var(--spacing-sm) var(--spacing-md);
|
||
font-size: var(--font-size-sm);
|
||
}
|
||
|
||
.app-main {
|
||
padding: var(--spacing-xl) var(--spacing-lg);
|
||
}
|
||
|
||
.recommend-card {
|
||
flex-direction: row;
|
||
}
|
||
|
||
.recommend-card .card-img-wrap {
|
||
width: 40%;
|
||
aspect-ratio: auto;
|
||
min-height: 200px;
|
||
}
|
||
|
||
.recommend-card .card-body {
|
||
flex: 1;
|
||
justify-content: center;
|
||
}
|
||
|
||
.dishes-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
.weekly-grid {
|
||
grid-template-columns: repeat(2, 1fr);
|
||
}
|
||
|
||
.modal-overlay {
|
||
align-items: center;
|
||
padding: var(--spacing-xl);
|
||
}
|
||
|
||
.modal-content {
|
||
border-radius: var(--radius-lg);
|
||
max-width: 640px;
|
||
max-height: 90vh;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
@keyframes slideUp {
|
||
from { transform: translateY(2rem); opacity: 0; }
|
||
to { transform: translateY(0); opacity: 1; }
|
||
}
|
||
}
|
||
|
||
/* ============================================================
|
||
响应式断点:≥1024px 三列布局
|
||
============================================================ */
|
||
@media (min-width: 1024px) {
|
||
.app-main {
|
||
padding: var(--spacing-xl);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: var(--font-size-xl);
|
||
}
|
||
|
||
.dishes-grid {
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: var(--spacing-lg);
|
||
}
|
||
|
||
.weekly-grid {
|
||
grid-template-columns: repeat(7, 1fr);
|
||
gap: var(--spacing-sm);
|
||
}
|
||
|
||
.weekly-day-card .day-header {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
gap: 2px;
|
||
}
|
||
|
||
.grocery-list {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: var(--spacing-md);
|
||
}
|
||
|
||
.recommend-card .card-img-wrap {
|
||
width: 35%;
|
||
}
|
||
|
||
.modal-content {
|
||
max-width: 800px;
|
||
}
|
||
}
|
||
|
||
/* ============================================================
|
||
打印样式
|
||
============================================================ */
|
||
@media print {
|
||
.app-header,
|
||
.section-filter,
|
||
.nav-btn,
|
||
.btn,
|
||
.toast-container,
|
||
.modal-overlay {
|
||
display: none !important;
|
||
}
|
||
|
||
body {
|
||
background: #fff;
|
||
color: #000;
|
||
}
|
||
|
||
.dish-card,
|
||
.weekly-day-card {
|
||
break-inside: avoid;
|
||
box-shadow: none;
|
||
border: 1px solid #ccc;
|
||
}
|
||
}
|