Stream A: DW brand theme — Instrument Sans + IBM Plex Mono, light/dark mode, all hardcoded colors replaced
- Replace Solar Momentum palette with DiligenceWorks brand identity - Typography: Outfit → Instrument Sans, Plus Jakarta Sans → IBM Plex Mono (data/stats) - CSS variables: --orange* → --accent*, new DW blue #2952CC / #6B9BFF - Dark mode: prefers-color-scheme media query + manual data-theme override - Border radii: 14/10/20px → 8/6/12px (professional, less playful) - Font weights: 800/900 → 600/700 (DW uses lighter weights) - Fixed 30+ hardcoded hex values across 16 files (UI-06) - Gate banners, progress bars, category chips all use CSS variables
This commit is contained in:
parent
83e715dbc4
commit
c075eb9257
16 changed files with 240 additions and 140 deletions
|
|
@ -1,51 +1,49 @@
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&family=IBM+Plex+Mono:wght@400;500;600&display=swap');
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* === Solar Momentum Palette === */
|
/* === DW Brand — Light === */
|
||||||
--orange: #FF5722;
|
--accent: #2952CC;
|
||||||
--orange-dark: #E64A19;
|
--accent-dark: #1e3fa8;
|
||||||
--orange-light: #FF8A65;
|
--accent-light: #4A78E0;
|
||||||
--orange-ghost: rgba(255, 87, 34, 0.06);
|
--accent-bg: #edf1fc;
|
||||||
--orange-glow: rgba(255, 87, 34, 0.18);
|
--accent-glow: rgba(41, 82, 204, 0.18);
|
||||||
|
|
||||||
--green: #00C853;
|
--green: #0d7d5a;
|
||||||
--green-dark: #00A844;
|
--green-dark: #065c40;
|
||||||
--green-light: #69F0AE;
|
--green-light: #30C090;
|
||||||
--green-ghost: rgba(0, 200, 83, 0.06);
|
--green-bg: rgba(13, 125, 90, 0.08);
|
||||||
|
|
||||||
--blue: #2979FF;
|
--red: #C62828;
|
||||||
--blue-ghost: rgba(41, 121, 255, 0.06);
|
--red-bg: rgba(198, 40, 40, 0.06);
|
||||||
--purple: #7C4DFF;
|
|
||||||
--purple-ghost: rgba(124, 77, 255, 0.06);
|
|
||||||
|
|
||||||
--red: #FF1744;
|
--amber: #b07800;
|
||||||
--red-ghost: rgba(255, 23, 68, 0.06);
|
--amber-bg: rgba(176, 120, 0, 0.08);
|
||||||
--amber: #FFB300;
|
|
||||||
|
|
||||||
--text: #1B1B2F;
|
--text: #1a1f2e;
|
||||||
--text-2: #4A4A68;
|
--text-2: #3d4660;
|
||||||
--text-3: #8888A4;
|
--text-3: #6b7490;
|
||||||
--text-inv: #FFFFFF;
|
--text-inv: #FFFFFF;
|
||||||
|
|
||||||
--bg: #F5F3EF;
|
--bg: #fafbfe;
|
||||||
--bg-warm: linear-gradient(170deg, #FFF3E8 0%, #F5F3EF 50%, #EDF2FF 100%);
|
--bg-warm: linear-gradient(170deg, #f0f2fa 0%, #fafbfe 50%, #f5f7fd 100%);
|
||||||
--card: #FFFFFF;
|
--card: #FFFFFF;
|
||||||
--card-border: rgba(0,0,0,0.04);
|
--card-border: rgba(216, 220, 232, 0.6);
|
||||||
--divider: rgba(0,0,0,0.06);
|
--divider: rgba(216, 220, 232, 0.8);
|
||||||
|
|
||||||
--shadow-1: 0 1px 3px rgba(27,27,47,0.05);
|
--shadow-1: 0 1px 3px rgba(26, 31, 46, 0.06);
|
||||||
--shadow-2: 0 4px 16px rgba(27,27,47,0.08);
|
--shadow-2: 0 4px 16px rgba(26, 31, 46, 0.08);
|
||||||
--shadow-3: 0 12px 40px rgba(27,27,47,0.12);
|
--shadow-3: 0 12px 40px rgba(26, 31, 46, 0.12);
|
||||||
--shadow-orange: 0 4px 20px rgba(255,87,34,0.25);
|
--shadow-accent: 0 4px 20px rgba(41, 82, 204, 0.20);
|
||||||
--shadow-green: 0 4px 20px rgba(0,200,83,0.25);
|
--shadow-green: 0 4px 20px rgba(13, 125, 90, 0.20);
|
||||||
|
|
||||||
--r: 14px;
|
--r: 8px;
|
||||||
--r-sm: 10px;
|
--r-sm: 6px;
|
||||||
--r-lg: 20px;
|
--r-lg: 12px;
|
||||||
--r-full: 999px;
|
--r-full: 999px;
|
||||||
|
|
||||||
--font: 'Plus Jakarta Sans', system-ui, sans-serif;
|
--font: 'Instrument Sans', -apple-system, sans-serif;
|
||||||
--font-display: 'Outfit', system-ui, sans-serif;
|
--font-display: 'Instrument Sans', -apple-system, sans-serif;
|
||||||
|
--font-mono: 'IBM Plex Mono', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* === Reset === */
|
/* === Reset === */
|
||||||
|
|
@ -64,7 +62,7 @@ body {
|
||||||
/* === Typography === */
|
/* === Typography === */
|
||||||
h1, h2, h3 { font-family: var(--font-display); letter-spacing: -0.02em; line-height: 1.2; }
|
h1, h2, h3 { font-family: var(--font-display); letter-spacing: -0.02em; line-height: 1.2; }
|
||||||
|
|
||||||
a { color: var(--blue); text-decoration: none; font-weight: 600; }
|
a { color: var(--accent); text-decoration: none; font-weight: 600; }
|
||||||
a:hover { opacity: 0.8; }
|
a:hover { opacity: 0.8; }
|
||||||
|
|
||||||
/* === Buttons === */
|
/* === Buttons === */
|
||||||
|
|
@ -83,11 +81,11 @@ button {
|
||||||
button:active { transform: scale(0.97); }
|
button:active { transform: scale(0.97); }
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
background: var(--orange);
|
background: var(--accent);
|
||||||
color: var(--text-inv);
|
color: var(--text-inv);
|
||||||
box-shadow: var(--shadow-orange);
|
box-shadow: var(--shadow-accent);
|
||||||
}
|
}
|
||||||
.btn-primary:hover { background: var(--orange-dark); }
|
.btn-primary:hover { background: var(--accent-dark); }
|
||||||
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; transform: none; box-shadow: none; }
|
.btn-primary:disabled { opacity: 0.4; cursor: not-allowed; transform: none; box-shadow: none; }
|
||||||
|
|
||||||
.btn-success {
|
.btn-success {
|
||||||
|
|
@ -101,14 +99,14 @@ button:active { transform: scale(0.97); }
|
||||||
border: 2px solid var(--divider);
|
border: 2px solid var(--divider);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
}
|
}
|
||||||
.btn-outline:hover { border-color: var(--orange); color: var(--orange); }
|
.btn-outline:hover { border-color: var(--accent); color: var(--accent); }
|
||||||
|
|
||||||
.btn-ghost {
|
.btn-ghost {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: var(--text-2);
|
color: var(--text-2);
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
}
|
}
|
||||||
.btn-ghost:hover { background: var(--orange-ghost); color: var(--orange); }
|
.btn-ghost:hover { background: var(--accent-bg); color: var(--accent); }
|
||||||
|
|
||||||
.btn-danger { background: var(--red); color: var(--text-inv); }
|
.btn-danger { background: var(--red); color: var(--text-inv); }
|
||||||
.btn-sm { padding: 8px 16px; font-size: 0.82rem; border-radius: var(--r-sm); }
|
.btn-sm { padding: 8px 16px; font-size: 0.82rem; border-radius: var(--r-sm); }
|
||||||
|
|
@ -129,8 +127,8 @@ input, select, textarea {
|
||||||
transition: border-color 0.2s;
|
transition: border-color 0.2s;
|
||||||
}
|
}
|
||||||
input:focus, select:focus, textarea:focus {
|
input:focus, select:focus, textarea:focus {
|
||||||
border-color: var(--orange);
|
border-color: var(--accent);
|
||||||
box-shadow: 0 0 0 3px var(--orange-glow);
|
box-shadow: 0 0 0 3px var(--accent-glow);
|
||||||
}
|
}
|
||||||
input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 400; }
|
input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 400; }
|
||||||
|
|
||||||
|
|
@ -157,7 +155,7 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
.page-title {
|
.page-title {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-display);
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
font-weight: 800;
|
font-weight: 600;
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,8 +179,9 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
|
|
||||||
/* === Section Title (small label) === */
|
/* === Section Title (small label) === */
|
||||||
.section-label {
|
.section-label {
|
||||||
|
font-family: var(--font-mono);
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
font-weight: 800;
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.08em;
|
letter-spacing: 0.08em;
|
||||||
color: var(--text-3);
|
color: var(--text-3);
|
||||||
|
|
@ -203,6 +202,7 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
.checklist-check { font-size: 1.15rem; min-width: 26px; }
|
.checklist-check { font-size: 1.15rem; min-width: 26px; }
|
||||||
.checklist-points {
|
.checklist-points {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
font-family: var(--font-mono);
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text-3);
|
color: var(--text-3);
|
||||||
|
|
@ -239,13 +239,13 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
border-radius: var(--r-sm);
|
border-radius: var(--r-sm);
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.nav-item.active { color: var(--orange); }
|
.nav-item.active { color: var(--accent); }
|
||||||
.nav-item.active::before {
|
.nav-item.active::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -4px; left: 50%; transform: translateX(-50%);
|
top: -4px; left: 50%; transform: translateX(-50%);
|
||||||
width: 20px; height: 3px;
|
width: 20px; height: 3px;
|
||||||
background: var(--orange);
|
background: var(--accent);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
.nav-icon { font-size: 1.2rem; margin-bottom: 1px; }
|
.nav-icon { font-size: 1.2rem; margin-bottom: 1px; }
|
||||||
|
|
@ -280,11 +280,11 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
box-shadow: var(--shadow-1);
|
box-shadow: var(--shadow-1);
|
||||||
}
|
}
|
||||||
.option-btn:hover { border-color: var(--orange-light); transform: translateY(-2px); box-shadow: var(--shadow-2); }
|
.option-btn:hover { border-color: var(--accent-light); transform: translateY(-2px); box-shadow: var(--shadow-2); }
|
||||||
.option-btn.selected {
|
.option-btn.selected {
|
||||||
border-color: var(--orange);
|
border-color: var(--accent);
|
||||||
background: var(--orange-ghost);
|
background: var(--accent-bg);
|
||||||
box-shadow: 0 0 0 3px var(--orange-glow);
|
box-shadow: 0 0 0 3px var(--accent-glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* === Chips === */
|
/* === Chips === */
|
||||||
|
|
@ -299,10 +299,10 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
.chip:hover { border-color: var(--orange-light); }
|
.chip:hover { border-color: var(--accent-light); }
|
||||||
.chip.selected {
|
.chip.selected {
|
||||||
border-color: var(--orange);
|
border-color: var(--accent);
|
||||||
background: var(--orange);
|
background: var(--accent);
|
||||||
color: var(--text-inv);
|
color: var(--text-inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,19 +330,19 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
background: var(--card);
|
background: var(--card);
|
||||||
border: 2px solid var(--divider);
|
border: 2px solid var(--divider);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
font-weight: 800;
|
font-weight: 600;
|
||||||
font-size: 0.88rem;
|
font-size: 0.88rem;
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex; align-items: center; justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
box-shadow: var(--shadow-1);
|
box-shadow: var(--shadow-1);
|
||||||
}
|
}
|
||||||
.likert-btn:hover { border-color: var(--orange); transform: scale(1.1); }
|
.likert-btn:hover { border-color: var(--accent); transform: scale(1.1); }
|
||||||
.likert-btn.selected {
|
.likert-btn.selected {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
background: var(--orange);
|
background: var(--accent);
|
||||||
color: var(--text-inv);
|
color: var(--text-inv);
|
||||||
box-shadow: var(--shadow-orange);
|
box-shadow: var(--shadow-accent);
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
.likert-labels {
|
.likert-labels {
|
||||||
|
|
@ -372,9 +372,9 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
border: 2px solid rgba(255,87,34,0.15);
|
border: 2px solid rgba(255,87,34,0.15);
|
||||||
}
|
}
|
||||||
.gate-pts {
|
.gate-pts {
|
||||||
font-family: var(--font-display);
|
font-family: var(--font-mono);
|
||||||
font-size: 2.8rem;
|
font-size: 2.8rem;
|
||||||
font-weight: 900;
|
font-weight: 700;
|
||||||
letter-spacing: -0.04em;
|
letter-spacing: -0.04em;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
|
|
@ -384,7 +384,7 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
.meal-section { margin-bottom: 18px; }
|
.meal-section { margin-bottom: 18px; }
|
||||||
.meal-title {
|
.meal-title {
|
||||||
font-size: 0.72rem;
|
font-size: 0.72rem;
|
||||||
font-weight: 800;
|
font-weight: 600;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.06em;
|
letter-spacing: 0.06em;
|
||||||
color: var(--text-3);
|
color: var(--text-3);
|
||||||
|
|
@ -433,6 +433,106 @@ input::placeholder, textarea::placeholder { color: var(--text-3); font-weight: 4
|
||||||
.gate-banner { animation: popIn 0.35s cubic-bezier(.4,0,.2,1) both; }
|
.gate-banner { animation: popIn 0.35s cubic-bezier(.4,0,.2,1) both; }
|
||||||
.gate-pts { animation: countUp 0.4s ease-out 0.15s both; }
|
.gate-pts { animation: countUp 0.4s ease-out 0.15s both; }
|
||||||
|
|
||||||
|
|
||||||
|
/* === Dark Mode === */
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--accent: #6B9BFF;
|
||||||
|
--accent-dark: #4A78E0;
|
||||||
|
--accent-light: #8BB5FF;
|
||||||
|
--accent-bg: #101630;
|
||||||
|
--accent-glow: rgba(107, 155, 255, 0.18);
|
||||||
|
|
||||||
|
--green: #30C090;
|
||||||
|
--green-dark: #20A070;
|
||||||
|
--green-light: #50D8A8;
|
||||||
|
--green-bg: rgba(48, 192, 144, 0.10);
|
||||||
|
|
||||||
|
--red: #EF5350;
|
||||||
|
--red-bg: rgba(239, 83, 80, 0.10);
|
||||||
|
|
||||||
|
--amber: #F0B040;
|
||||||
|
--amber-bg: rgba(240, 176, 64, 0.10);
|
||||||
|
|
||||||
|
--text: #eaecf4;
|
||||||
|
--text-2: #b0b8d0;
|
||||||
|
--text-3: #7882a0;
|
||||||
|
--text-inv: #0a0b12;
|
||||||
|
|
||||||
|
--bg: #0a0b12;
|
||||||
|
--bg-warm: linear-gradient(170deg, #0e1020 0%, #0a0b12 50%, #0c0e1a 100%);
|
||||||
|
--card: #12131d;
|
||||||
|
--card-border: rgba(34, 40, 64, 0.8);
|
||||||
|
--divider: rgba(34, 40, 64, 0.8);
|
||||||
|
|
||||||
|
--shadow-1: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
--shadow-2: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||||||
|
--shadow-3: 0 12px 40px rgba(0, 0, 0, 0.5);
|
||||||
|
--shadow-accent: 0 4px 20px rgba(107, 155, 255, 0.15);
|
||||||
|
--shadow-green: 0 4px 20px rgba(48, 192, 144, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
body { background: var(--bg); color: var(--text); }
|
||||||
|
|
||||||
|
.nav-bar {
|
||||||
|
background: rgba(10, 11, 18, 0.92);
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, textarea {
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gate-earned {
|
||||||
|
background: linear-gradient(135deg, rgba(48,192,144,0.12) 0%, rgba(48,192,144,0.06) 100%);
|
||||||
|
border-color: rgba(48,192,144,0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gate-locked {
|
||||||
|
background: linear-gradient(135deg, rgba(107,155,255,0.10) 0%, rgba(107,155,255,0.05) 100%);
|
||||||
|
border-color: rgba(107,155,255,0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-btn, .chip {
|
||||||
|
background: var(--card);
|
||||||
|
}
|
||||||
|
|
||||||
|
.likert-btn {
|
||||||
|
background: var(--card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* === Manual theme override === */
|
||||||
|
:root[data-theme="dark"] {
|
||||||
|
--accent: #6B9BFF;
|
||||||
|
--accent-dark: #4A78E0;
|
||||||
|
--accent-light: #8BB5FF;
|
||||||
|
--accent-bg: #101630;
|
||||||
|
--accent-glow: rgba(107, 155, 255, 0.18);
|
||||||
|
--green: #30C090;
|
||||||
|
--green-dark: #20A070;
|
||||||
|
--green-light: #50D8A8;
|
||||||
|
--green-bg: rgba(48, 192, 144, 0.10);
|
||||||
|
--red: #EF5350;
|
||||||
|
--red-bg: rgba(239, 83, 80, 0.10);
|
||||||
|
--amber: #F0B040;
|
||||||
|
--amber-bg: rgba(240, 176, 64, 0.10);
|
||||||
|
--text: #eaecf4;
|
||||||
|
--text-2: #b0b8d0;
|
||||||
|
--text-3: #7882a0;
|
||||||
|
--text-inv: #0a0b12;
|
||||||
|
--bg: #0a0b12;
|
||||||
|
--bg-warm: linear-gradient(170deg, #0e1020 0%, #0a0b12 50%, #0c0e1a 100%);
|
||||||
|
--card: #12131d;
|
||||||
|
--card-border: rgba(34, 40, 64, 0.8);
|
||||||
|
--divider: rgba(34, 40, 64, 0.8);
|
||||||
|
--shadow-1: 0 1px 3px rgba(0, 0, 0, 0.3);
|
||||||
|
--shadow-2: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||||||
|
--shadow-3: 0 12px 40px rgba(0, 0, 0, 0.5);
|
||||||
|
--shadow-accent: 0 4px 20px rgba(107, 155, 255, 0.15);
|
||||||
|
--shadow-green: 0 4px 20px rgba(48, 192, 144, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
/* === Scrollbar === */
|
/* === Scrollbar === */
|
||||||
::-webkit-scrollbar { width: 4px; }
|
::-webkit-scrollbar { width: 4px; }
|
||||||
::-webkit-scrollbar-track { background: transparent; }
|
::-webkit-scrollbar-track { background: transparent; }
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import { api } from '../api'
|
||||||
|
|
||||||
const DIFFICULTY_COLORS = {
|
const DIFFICULTY_COLORS = {
|
||||||
beginner: 'var(--green)',
|
beginner: 'var(--green)',
|
||||||
intermediate: 'var(--blue)',
|
intermediate: 'var(--accent)',
|
||||||
advanced: 'var(--purple)',
|
advanced: 'var(--accent-light)',
|
||||||
}
|
}
|
||||||
|
|
||||||
const CATEGORY_ICONS = {
|
const CATEGORY_ICONS = {
|
||||||
|
|
@ -17,8 +17,8 @@ const CATEGORY_ICONS = {
|
||||||
|
|
||||||
const STATUS_LABELS = {
|
const STATUS_LABELS = {
|
||||||
pending: { label: 'Queued', color: 'var(--amber)' },
|
pending: { label: 'Queued', color: 'var(--amber)' },
|
||||||
crawling: { label: 'Fetching...', color: 'var(--blue)' },
|
crawling: { label: 'Fetching...', color: 'var(--accent)' },
|
||||||
extracting: { label: 'Analyzing...', color: 'var(--purple)' },
|
extracting: { label: 'Analyzing...', color: 'var(--accent-light)' },
|
||||||
ready: { label: 'Ready', color: 'var(--green)' },
|
ready: { label: 'Ready', color: 'var(--green)' },
|
||||||
failed: { label: 'Failed', color: 'var(--red)' },
|
failed: { label: 'Failed', color: 'var(--red)' },
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ export default function CatalogDetail() {
|
||||||
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
<div style={{ padding: '2rem', textAlign: 'center' }}>
|
||||||
<p style={{ color: 'var(--text-2)', marginBottom: '1rem' }}>Program not found.</p>
|
<p style={{ color: 'var(--text-2)', marginBottom: '1rem' }}>Program not found.</p>
|
||||||
<button onClick={() => navigate('/programs')} style={{
|
<button onClick={() => navigate('/programs')} style={{
|
||||||
background: 'var(--blue)', color: '#fff', padding: '10px 20px',
|
background: 'var(--accent)', color: '#fff', padding: '10px 20px',
|
||||||
}}>← Back to Programs</button>
|
}}>← Back to Programs</button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
@ -144,7 +144,7 @@ export default function CatalogDetail() {
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
style={{
|
style={{
|
||||||
display: 'inline-block', marginTop: '14px', fontSize: '0.78rem',
|
display: 'inline-block', marginTop: '14px', fontSize: '0.78rem',
|
||||||
color: 'var(--blue)', textDecoration: 'none',
|
color: 'var(--accent)', textDecoration: 'none',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
🔗 Original source ↗
|
🔗 Original source ↗
|
||||||
|
|
@ -157,7 +157,7 @@ export default function CatalogDetail() {
|
||||||
<div style={{
|
<div style={{
|
||||||
padding: '12px 16px', borderRadius: 'var(--r-sm)', marginBottom: '1rem',
|
padding: '12px 16px', borderRadius: 'var(--r-sm)', marginBottom: '1rem',
|
||||||
fontSize: '0.85rem', fontWeight: 600,
|
fontSize: '0.85rem', fontWeight: 600,
|
||||||
background: message.type === 'error' ? 'var(--red-ghost)' : 'var(--green-ghost)',
|
background: message.type === 'error' ? 'var(--red-ghost)' : 'var(--green-bg)',
|
||||||
color: message.type === 'error' ? 'var(--red)' : 'var(--green-dark)',
|
color: message.type === 'error' ? 'var(--red)' : 'var(--green-dark)',
|
||||||
}}>
|
}}>
|
||||||
{message.text}
|
{message.text}
|
||||||
|
|
@ -183,9 +183,9 @@ export default function CatalogDetail() {
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate(`/programs/${activeRecord.id}`)}
|
onClick={() => navigate(`/programs/${activeRecord.id}`)}
|
||||||
style={{
|
style={{
|
||||||
width: '100%', background: 'var(--orange)', color: '#fff',
|
width: '100%', background: 'var(--accent)', color: '#fff',
|
||||||
padding: '14px', fontSize: '0.95rem', fontWeight: 800,
|
padding: '14px', fontSize: '0.95rem', fontWeight: 800,
|
||||||
marginBottom: '1.25rem', boxShadow: 'var(--shadow-orange)',
|
marginBottom: '1.25rem', boxShadow: 'var(--shadow-accent)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
✓ Active — Open Your Program
|
✓ Active — Open Your Program
|
||||||
|
|
@ -194,8 +194,8 @@ export default function CatalogDetail() {
|
||||||
|
|
||||||
{program.crawl_status !== 'ready' && (
|
{program.crawl_status !== 'ready' && (
|
||||||
<div style={{
|
<div style={{
|
||||||
padding: '14px', borderRadius: 'var(--r)', background: 'var(--blue-ghost)',
|
padding: '14px', borderRadius: 'var(--r)', background: 'var(--accent-bg)',
|
||||||
color: 'var(--blue)', fontSize: '0.85rem', marginBottom: '1.25rem', textAlign: 'center',
|
color: 'var(--accent)', fontSize: '0.85rem', marginBottom: '1.25rem', textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
{program.crawl_status === 'failed'
|
{program.crawl_status === 'failed'
|
||||||
? `Crawl failed: ${program.crawl_error || 'unknown error'}`
|
? `Crawl failed: ${program.crawl_error || 'unknown error'}`
|
||||||
|
|
@ -210,7 +210,7 @@ export default function CatalogDetail() {
|
||||||
marginBottom: '1.25rem', boxShadow: 'var(--shadow-1)',
|
marginBottom: '1.25rem', boxShadow: 'var(--shadow-1)',
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
fontSize: '0.72rem', fontWeight: 700, color: 'var(--orange)',
|
fontSize: '0.72rem', fontWeight: 700, color: 'var(--accent)',
|
||||||
textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '8px',
|
textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '8px',
|
||||||
}}>📈 Progression</div>
|
}}>📈 Progression</div>
|
||||||
<p style={{ fontSize: '0.85rem', color: 'var(--text-2)', lineHeight: 1.5 }}>
|
<p style={{ fontSize: '0.85rem', color: 'var(--text-2)', lineHeight: 1.5 }}>
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ export default function Dashboard() {
|
||||||
const polarConnected = integrations?.polar?.connected
|
const polarConnected = integrations?.polar?.connected
|
||||||
|
|
||||||
const activities = [
|
const activities = [
|
||||||
{ key: 'workout', label: 'Workout', icon: '💪', pts: 50, color: '#FF5722', tip: 'Any exercise session — running, weights, yoga, etc. Logged manually or synced from Strava/Polar.' },
|
{ key: 'workout', label: 'Workout', icon: '💪', pts: 50, color: 'var(--accent)', tip: 'Any exercise session — running, weights, yoga, etc. Logged manually or synced from Strava/Polar.' },
|
||||||
{ key: 'food_log', label: 'Food logged', icon: '🥗', pts: 30, color: '#4CAF50', tip: 'Log what you eat. Barcode scan or manual entry. Building food awareness is a key habit.' },
|
{ key: 'food_log', label: 'Food logged', icon: '🥗', pts: 30, color: 'var(--green)', tip: 'Log what you eat. Barcode scan or manual entry. Building food awareness is a key habit.' },
|
||||||
{ key: 'steps_target', label: 'Steps target', icon: '👟', pts: 20, color: '#2979FF', tip: 'Hit your daily step goal. Steps are the foundation of an active lifestyle.' },
|
{ key: 'steps_target', label: 'Steps target', icon: '👟', pts: 20, color: '#2979FF', tip: 'Hit your daily step goal. Steps are the foundation of an active lifestyle.' },
|
||||||
{ key: 'screen_free', label: 'Screen-free', icon: '📖', pts: '20/hr', color: '#7C4DFF', tip: 'Time away from screens — reading, walking, hobbies. Points scale with hours logged.' },
|
{ key: 'screen_free', label: 'Screen-free', icon: '📖', pts: '20/hr', color: '#7C4DFF', tip: 'Time away from screens — reading, walking, hobbies. Points scale with hours logged.' },
|
||||||
{ key: 'daily_checkin', label: 'Check-in', icon: '✅', pts: 10, color: '#00BCD4', tip: 'Just show up and check in. The easiest points — consistency matters more than intensity.' },
|
{ key: 'daily_checkin', label: 'Check-in', icon: '✅', pts: 10, color: '#00BCD4', tip: 'Just show up and check in. The easiest points — consistency matters more than intensity.' },
|
||||||
|
|
@ -90,7 +90,7 @@ export default function Dashboard() {
|
||||||
<div
|
<div
|
||||||
onClick={() => status.program_id && navigate(`/programs/${status.program_id}`)}
|
onClick={() => status.program_id && navigate(`/programs/${status.program_id}`)}
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--blue-ghost)', borderRadius: 'var(--r)', padding: '12px 16px',
|
background: 'var(--accent-bg)', borderRadius: 'var(--r)', padding: '12px 16px',
|
||||||
marginBottom: '14px', display: 'flex', alignItems: 'center', gap: '12px',
|
marginBottom: '14px', display: 'flex', alignItems: 'center', gap: '12px',
|
||||||
border: '1px solid rgba(41,121,255,0.1)',
|
border: '1px solid rgba(41,121,255,0.1)',
|
||||||
cursor: status.program_id ? 'pointer' : 'default',
|
cursor: status.program_id ? 'pointer' : 'default',
|
||||||
|
|
@ -98,15 +98,15 @@ export default function Dashboard() {
|
||||||
>
|
>
|
||||||
<div style={{ fontSize: '1.1rem' }}>📋</div>
|
<div style={{ fontSize: '1.1rem' }}>📋</div>
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<div style={{ fontSize: '0.78rem', fontWeight: 700, color: 'var(--blue)' }}>{status.program_name}</div>
|
<div style={{ fontSize: '0.78rem', fontWeight: 700, color: 'var(--accent)' }}>{status.program_name}</div>
|
||||||
<div className="progress-bar" style={{ height: '5px', marginTop: '4px' }}>
|
<div className="progress-bar" style={{ height: '5px', marginTop: '4px' }}>
|
||||||
<div className="progress-bar-fill" style={{
|
<div className="progress-bar-fill" style={{
|
||||||
width: `${Math.round((status.program_day / status.program_total_days) * 100)}%`,
|
width: `${Math.round((status.program_day / status.program_total_days) * 100)}%`,
|
||||||
background: 'var(--blue)',
|
background: 'var(--accent)',
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '0.85rem', color: 'var(--blue)', whiteSpace: 'nowrap' }}>
|
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: '0.85rem', color: 'var(--accent)', whiteSpace: 'nowrap' }}>
|
||||||
{status.program_day}/{status.program_total_days}
|
{status.program_day}/{status.program_total_days}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -120,7 +120,7 @@ export default function Dashboard() {
|
||||||
</Tip>
|
</Tip>
|
||||||
</div>
|
</div>
|
||||||
<div className="gate-pts">
|
<div className="gate-pts">
|
||||||
<span style={{ color: status.gate_passed ? 'var(--green)' : 'var(--orange)' }}>
|
<span style={{ color: status.gate_passed ? 'var(--green)' : 'var(--accent)' }}>
|
||||||
{status.points_earned}
|
{status.points_earned}
|
||||||
</span>
|
</span>
|
||||||
<span style={{ fontFamily: 'var(--font)', fontSize: '1rem', fontWeight: 600, color: 'var(--text-3)' }}>
|
<span style={{ fontFamily: 'var(--font)', fontSize: '1rem', fontWeight: 600, color: 'var(--text-3)' }}>
|
||||||
|
|
@ -132,7 +132,7 @@ export default function Dashboard() {
|
||||||
width: `${pct}%`,
|
width: `${pct}%`,
|
||||||
background: status.gate_passed
|
background: status.gate_passed
|
||||||
? 'linear-gradient(90deg, #00C853, #69F0AE)'
|
? 'linear-gradient(90deg, #00C853, #69F0AE)'
|
||||||
: `linear-gradient(90deg, #FF5722, #FF8A65)`,
|
: `linear-gradient(90deg, var(--accent), var(--accent-light))`,
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginTop: '12px', fontSize: '0.88rem', fontWeight: 700 }}>
|
<div style={{ marginTop: '12px', fontSize: '0.88rem', fontWeight: 700 }}>
|
||||||
|
|
@ -178,7 +178,7 @@ export default function Dashboard() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* === Week Progress === */}
|
{/* === Week Progress === */}
|
||||||
<div className="card" style={{ background: 'var(--purple-ghost)' }}>
|
<div className="card" style={{ background: 'var(--accent-bg)' }}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '10px' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '10px' }}>
|
||||||
<div className="section-label" style={{ margin: 0 }}>
|
<div className="section-label" style={{ margin: 0 }}>
|
||||||
<Tip text={`Earn ${status.weekly_target} total points across the week for a bonus. Consistent daily effort beats one big day.`}>
|
<Tip text={`Earn ${status.weekly_target} total points across the week for a bonus. Consistent daily effort beats one big day.`}>
|
||||||
|
|
@ -202,7 +202,7 @@ export default function Dashboard() {
|
||||||
|
|
||||||
{/* === Rewards === */}
|
{/* === Rewards === */}
|
||||||
{status.gate_passed && status.rewards_available.length > 0 && (
|
{status.gate_passed && status.rewards_available.length > 0 && (
|
||||||
<div className="card" style={{ background: 'var(--green-ghost)', border: '2px solid rgba(0,200,83,0.15)' }}>
|
<div className="card" style={{ background: 'var(--green-bg)', border: '2px solid rgba(0,200,83,0.15)' }}>
|
||||||
<div className="section-label" style={{ color: 'var(--green-dark)' }}>🎮 Rewards Available</div>
|
<div className="section-label" style={{ color: 'var(--green-dark)' }}>🎮 Rewards Available</div>
|
||||||
{status.rewards_available.map(r => (
|
{status.rewards_available.map(r => (
|
||||||
<div className="reward-card" key={r.id}>
|
<div className="reward-card" key={r.id}>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom'
|
||||||
import { api } from '../api'
|
import { api } from '../api'
|
||||||
|
|
||||||
const CATEGORIES = [
|
const CATEGORIES = [
|
||||||
{ value: 'workout', label: 'Workout', icon: '💪', desc: 'Any exercise session', color: '#FF5722' },
|
{ value: 'workout', label: 'Workout', icon: '💪', desc: 'Any exercise session', color: 'var(--accent)' },
|
||||||
{ value: 'steps_target', label: 'Steps', icon: '👟', desc: 'Hit your daily goal', color: '#2979FF' },
|
{ value: 'steps_target', label: 'Steps', icon: '👟', desc: 'Hit your daily goal', color: '#2979FF' },
|
||||||
{ value: 'screen_free', label: 'Screen-Free', icon: '📖', desc: 'Reading, outdoors', color: '#7C4DFF' },
|
{ value: 'screen_free', label: 'Screen-Free', icon: '📖', desc: 'Reading, outdoors', color: '#7C4DFF' },
|
||||||
{ value: 'daily_checkin', label: 'Check-in', icon: '✅', desc: 'Just show up', color: '#00BCD4' },
|
{ value: 'daily_checkin', label: 'Check-in', icon: '✅', desc: 'Just show up', color: '#00BCD4' },
|
||||||
|
|
@ -100,7 +100,7 @@ export default function LogActivity() {
|
||||||
{success && (
|
{success && (
|
||||||
<div style={{
|
<div style={{
|
||||||
textAlign: 'center', padding: '24px', marginBottom: '14px',
|
textAlign: 'center', padding: '24px', marginBottom: '14px',
|
||||||
background: 'var(--green-ghost)', borderRadius: 'var(--r-lg)', border: '2px solid rgba(0,200,83,0.15)',
|
background: 'var(--green-bg)', borderRadius: 'var(--r-lg)', border: '2px solid rgba(0,200,83,0.15)',
|
||||||
}}>
|
}}>
|
||||||
<div style={{ fontSize: '2rem', marginBottom: '4px' }}>🎉</div>
|
<div style={{ fontSize: '2rem', marginBottom: '4px' }}>🎉</div>
|
||||||
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.3rem', color: 'var(--green-dark)' }}>{success}</div>
|
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.3rem', color: 'var(--green-dark)' }}>{success}</div>
|
||||||
|
|
@ -129,20 +129,20 @@ export default function LogActivity() {
|
||||||
<div
|
<div
|
||||||
onClick={() => navigate(`/programs/${activeProgram.id}`)}
|
onClick={() => navigate(`/programs/${activeProgram.id}`)}
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--blue-ghost)', borderRadius: 'var(--r-sm)', padding: '10px 14px',
|
background: 'var(--accent-bg)', borderRadius: 'var(--r-sm)', padding: '10px 14px',
|
||||||
marginBottom: '12px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
marginBottom: '12px', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||||
cursor: 'pointer', border: '1px solid rgba(41,121,255,0.15)',
|
cursor: 'pointer', border: '1px solid rgba(41,121,255,0.15)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div style={{ fontSize: '0.7rem', fontWeight: 700, color: 'var(--blue)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
|
<div style={{ fontSize: '0.7rem', fontWeight: 700, color: 'var(--accent)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
|
||||||
Active Program
|
Active Program
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontWeight: 800, fontSize: '0.92rem', color: 'var(--text-1)' }}>
|
<div style={{ fontWeight: 800, fontSize: '0.92rem', color: 'var(--text-1)' }}>
|
||||||
{activeProgram.name}
|
{activeProgram.name}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: '0.78rem', color: 'var(--blue)', fontWeight: 700 }}>
|
<div style={{ fontSize: '0.78rem', color: 'var(--accent)', fontWeight: 700 }}>
|
||||||
Week {activeProgram.current_week || 1} →
|
Week {activeProgram.current_week || 1} →
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -176,7 +176,7 @@ export default function LogActivity() {
|
||||||
|
|
||||||
{!todayWorkout && upcomingWorkouts.length === 0 && (
|
{!todayWorkout && upcomingWorkouts.length === 0 && (
|
||||||
<div style={{
|
<div style={{
|
||||||
padding: '14px', borderRadius: 'var(--r-sm)', background: 'var(--green-ghost)',
|
padding: '14px', borderRadius: 'var(--r-sm)', background: 'var(--green-bg)',
|
||||||
color: 'var(--green-dark)', fontSize: '0.85rem', textAlign: 'center', fontWeight: 600,
|
color: 'var(--green-dark)', fontSize: '0.85rem', textAlign: 'center', fontWeight: 600,
|
||||||
}}>
|
}}>
|
||||||
✓ All workouts for this week are complete. Log a freeform workout below or rest up.
|
✓ All workouts for this week are complete. Log a freeform workout below or rest up.
|
||||||
|
|
@ -223,11 +223,11 @@ function ProgramWorkoutCard({ workout, featured, completing, onComplete }) {
|
||||||
<div style={{
|
<div style={{
|
||||||
background: 'var(--card)', borderRadius: 'var(--r)', padding: '14px',
|
background: 'var(--card)', borderRadius: 'var(--r)', padding: '14px',
|
||||||
marginBottom: '10px', boxShadow: 'var(--shadow-1)',
|
marginBottom: '10px', boxShadow: 'var(--shadow-1)',
|
||||||
border: featured ? '2px solid var(--orange-glow)' : '1px solid var(--divider)',
|
border: featured ? '2px solid var(--accent-glow)' : '1px solid var(--divider)',
|
||||||
}}>
|
}}>
|
||||||
{featured && (
|
{featured && (
|
||||||
<div style={{
|
<div style={{
|
||||||
fontSize: '0.65rem', fontWeight: 800, color: 'var(--orange)',
|
fontSize: '0.65rem', fontWeight: 800, color: 'var(--accent)',
|
||||||
textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '4px',
|
textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '4px',
|
||||||
}}>
|
}}>
|
||||||
⭐ Today
|
⭐ Today
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ export default function LogFood() {
|
||||||
<div className="page">
|
<div className="page">
|
||||||
<h1 className="page-title">Food Log</h1>
|
<h1 className="page-title">Food Log</h1>
|
||||||
|
|
||||||
{success && <div style={{ padding: '12px', background: 'var(--green-ghost)', borderRadius: 'var(--radius-sm)', color: 'var(--green-dark)', textAlign: 'center', marginBottom: '12px', fontWeight: 600 }}>{success}</div>}
|
{success && <div style={{ padding: '12px', background: 'var(--green-bg)', borderRadius: 'var(--radius-sm)', color: 'var(--green-dark)', textAlign: 'center', marginBottom: '12px', fontWeight: 600 }}>{success}</div>}
|
||||||
|
|
||||||
{/* Tab bar */}
|
{/* Tab bar */}
|
||||||
<div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>
|
<div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ export default function Login() {
|
||||||
minHeight: '100dvh',
|
minHeight: '100dvh',
|
||||||
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
|
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
|
||||||
padding: '24px',
|
padding: '24px',
|
||||||
background: 'linear-gradient(170deg, #FF8A65 0%, #FF5722 30%, #E64A19 60%, #1B1B2F 100%)',
|
background: 'linear-gradient(170deg, var(--accent-light) 0%, var(--accent) 30%, var(--accent-dark) 60%, var(--text) 100%)',
|
||||||
}}>
|
}}>
|
||||||
<div style={{ width: '100%', maxWidth: '380px' }}>
|
<div style={{ width: '100%', maxWidth: '380px' }}>
|
||||||
{/* Brand */}
|
{/* Brand */}
|
||||||
|
|
@ -61,9 +61,9 @@ export default function Login() {
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 'var(--r-sm)', padding: '10px',
|
borderRadius: 'var(--r-sm)', padding: '10px',
|
||||||
fontWeight: 700, fontSize: '0.85rem',
|
fontWeight: 700, fontSize: '0.85rem',
|
||||||
background: mode === m ? 'var(--orange)' : 'transparent',
|
background: mode === m ? 'var(--accent)' : 'transparent',
|
||||||
color: mode === m ? '#fff' : 'var(--text-2)',
|
color: mode === m ? '#fff' : 'var(--text-2)',
|
||||||
boxShadow: mode === m ? 'var(--shadow-orange)' : 'none',
|
boxShadow: mode === m ? 'var(--shadow-accent)' : 'none',
|
||||||
}}>
|
}}>
|
||||||
{m === 'login' ? 'Sign In' : 'Sign Up'}
|
{m === 'login' ? 'Sign In' : 'Sign Up'}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -75,9 +75,9 @@ export default function MealPlan() {
|
||||||
<div key={meal.id} style={{
|
<div key={meal.id} style={{
|
||||||
background: 'var(--surface-2)', borderRadius: 'var(--r-md)', padding: 16,
|
background: 'var(--surface-2)', borderRadius: 'var(--r-md)', padding: 16,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
borderLeft: itemStatus === 'followed' ? '4px solid #4CAF50' :
|
borderLeft: itemStatus === 'followed' ? '4px solid var(--green)' :
|
||||||
itemStatus === 'skipped' ? '4px solid #F44336' :
|
itemStatus === 'skipped' ? '4px solid var(--red)' :
|
||||||
itemStatus === 'substituted' ? '4px solid #FF9800' : '4px solid transparent',
|
itemStatus === 'substituted' ? '4px solid var(--amber)' : '4px solid transparent',
|
||||||
}}>
|
}}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -141,8 +141,8 @@ export default function MealPlan() {
|
||||||
</div>
|
</div>
|
||||||
<span style={{
|
<span style={{
|
||||||
fontSize: '0.75rem', padding: '2px 8px', borderRadius: 12,
|
fontSize: '0.75rem', padding: '2px 8px', borderRadius: 12,
|
||||||
background: p.status === 'active' ? '#4CAF5022' : '#9E9E9E22',
|
background: p.status === 'active' ? 'var(--green)22' : 'var(--text-3)22',
|
||||||
color: p.status === 'active' ? '#4CAF50' : '#9E9E9E',
|
color: p.status === 'active' ? 'var(--green)' : 'var(--text-3)',
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
}}>
|
}}>
|
||||||
{p.status}
|
{p.status}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ export default function Nutrition() {
|
||||||
<div className={`gate-banner ${c.compliant_day ? 'gate-earned' : 'gate-locked'}`}>
|
<div className={`gate-banner ${c.compliant_day ? 'gate-earned' : 'gate-locked'}`}>
|
||||||
<div className="section-label" style={{ marginBottom: '4px' }}>Today's Keto Day</div>
|
<div className="section-label" style={{ marginBottom: '4px' }}>Today's Keto Day</div>
|
||||||
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.4rem',
|
<div style={{ fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.4rem',
|
||||||
color: c.compliant_day ? 'var(--green)' : 'var(--orange)' }}>
|
color: c.compliant_day ? 'var(--green)' : 'var(--accent)' }}>
|
||||||
{c.compliant_day ? '✓ Compliant' : '⏳ In progress'}
|
{c.compliant_day ? '✓ Compliant' : '⏳ In progress'}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: '0.82rem', color: 'var(--text-2)', marginTop: '6px' }}>
|
<div style={{ fontSize: '0.82rem', color: 'var(--text-2)', marginTop: '6px' }}>
|
||||||
|
|
@ -196,7 +196,7 @@ export default function Nutrition() {
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="section-label">Today's Macros</div>
|
<div className="section-label">Today's Macros</div>
|
||||||
<MacroBar label="Net carbs" value={m.net_carbs_g} target={t.net_carbs_cap} unit="g" inverse />
|
<MacroBar label="Net carbs" value={m.net_carbs_g} target={t.net_carbs_cap} unit="g" inverse />
|
||||||
<MacroBar label="Protein" value={m.protein_g} target={t.protein_g} unit="g" color="#FF5722" />
|
<MacroBar label="Protein" value={m.protein_g} target={t.protein_g} unit="g" color="var(--accent)" />
|
||||||
<MacroBar label="Fat" value={m.fat_g} target={t.fat_g} unit="g" color="#FFA726" />
|
<MacroBar label="Fat" value={m.fat_g} target={t.fat_g} unit="g" color="#FFA726" />
|
||||||
<MacroBar label="Calories" value={m.calories} target={t.calories} unit="kcal" color="#2979FF" />
|
<MacroBar label="Calories" value={m.calories} target={t.calories} unit="kcal" color="#2979FF" />
|
||||||
<button className="btn-outline btn-full btn-sm" onClick={() => navigate('/food')}
|
<button className="btn-outline btn-full btn-sm" onClick={() => navigate('/food')}
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ export default function Onboarding() {
|
||||||
return (
|
return (
|
||||||
<div className="page" style={{ paddingTop: '40px' }}>
|
<div className="page" style={{ paddingTop: '40px' }}>
|
||||||
<div className="progress-bar" style={{ marginBottom: '24px' }}>
|
<div className="progress-bar" style={{ marginBottom: '24px' }}>
|
||||||
<div className="progress-bar-fill" style={{ width: `${progress}%`, background: 'var(--orange)' }} />
|
<div className="progress-bar-fill" style={{ width: `${progress}%`, background: 'var(--accent)' }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Step 0: Goal */}
|
{/* Step 0: Goal */}
|
||||||
|
|
|
||||||
|
|
@ -63,13 +63,13 @@ export default function ProgramDetail() {
|
||||||
<div style={{ display: 'flex', gap: '1.5rem', marginTop: '10px', fontSize: '0.82rem', color: 'var(--text-2)' }}>
|
<div style={{ display: 'flex', gap: '1.5rem', marginTop: '10px', fontSize: '0.82rem', color: 'var(--text-2)' }}>
|
||||||
<span>Week {schedule.current_week}</span>
|
<span>Week {schedule.current_week}</span>
|
||||||
<span>{progress?.completed_workouts || 0}/{progress?.total_workouts || 0} workouts</span>
|
<span>{progress?.completed_workouts || 0}/{progress?.total_workouts || 0} workouts</span>
|
||||||
<span style={{ color: 'var(--orange)', fontWeight: 700 }}>{pct}%</span>
|
<span style={{ color: 'var(--accent)', fontWeight: 700 }}>{pct}%</span>
|
||||||
</div>
|
</div>
|
||||||
{/* Progress bar */}
|
{/* Progress bar */}
|
||||||
<div style={{ marginTop: '12px', height: '8px', borderRadius: '4px', background: 'var(--divider)' }}>
|
<div style={{ marginTop: '12px', height: '8px', borderRadius: '4px', background: 'var(--divider)' }}>
|
||||||
<div style={{
|
<div style={{
|
||||||
height: '100%', borderRadius: '4px',
|
height: '100%', borderRadius: '4px',
|
||||||
background: pct >= 100 ? 'var(--green)' : 'var(--orange)',
|
background: pct >= 100 ? 'var(--green)' : 'var(--accent)',
|
||||||
width: `${Math.min(100, pct)}%`, transition: 'width 0.4s ease',
|
width: `${Math.min(100, pct)}%`, transition: 'width 0.4s ease',
|
||||||
}} />
|
}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -86,7 +86,7 @@ export default function ProgramDetail() {
|
||||||
{/* Completion celebration */}
|
{/* Completion celebration */}
|
||||||
{completionResult && (
|
{completionResult && (
|
||||||
<div style={{
|
<div style={{
|
||||||
background: 'var(--green-ghost)', borderRadius: 'var(--r)', padding: '16px',
|
background: 'var(--green-bg)', borderRadius: 'var(--r)', padding: '16px',
|
||||||
marginBottom: '1rem', textAlign: 'center',
|
marginBottom: '1rem', textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
<div style={{ fontSize: '1.8rem', marginBottom: '4px' }}>🎉</div>
|
<div style={{ fontSize: '1.8rem', marginBottom: '4px' }}>🎉</div>
|
||||||
|
|
@ -110,10 +110,10 @@ export default function ProgramDetail() {
|
||||||
<div style={{
|
<div style={{
|
||||||
background: 'var(--card)', borderRadius: 'var(--r)', padding: '16px',
|
background: 'var(--card)', borderRadius: 'var(--r)', padding: '16px',
|
||||||
marginBottom: '1.5rem', boxShadow: 'var(--shadow-2)',
|
marginBottom: '1.5rem', boxShadow: 'var(--shadow-2)',
|
||||||
border: '2px solid var(--orange-glow)',
|
border: '2px solid var(--accent-glow)',
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
fontSize: '0.72rem', fontWeight: 700, color: 'var(--orange)',
|
fontSize: '0.72rem', fontWeight: 700, color: 'var(--accent)',
|
||||||
textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '6px',
|
textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: '6px',
|
||||||
}}>Today's Workout</div>
|
}}>Today's Workout</div>
|
||||||
<strong style={{ fontFamily: 'var(--font-display)', fontSize: '1.1rem' }}>
|
<strong style={{ fontFamily: 'var(--font-display)', fontSize: '1.1rem' }}>
|
||||||
|
|
@ -155,7 +155,7 @@ export default function ProgramDetail() {
|
||||||
Week {week}
|
Week {week}
|
||||||
{week === schedule.current_week && (
|
{week === schedule.current_week && (
|
||||||
<span style={{
|
<span style={{
|
||||||
fontSize: '0.65rem', background: 'var(--orange)', color: '#fff',
|
fontSize: '0.65rem', background: 'var(--accent)', color: '#fff',
|
||||||
padding: '2px 8px', borderRadius: 'var(--r-full)',
|
padding: '2px 8px', borderRadius: 'var(--r-full)',
|
||||||
}}>Current</span>
|
}}>Current</span>
|
||||||
)}
|
)}
|
||||||
|
|
@ -185,7 +185,7 @@ export default function ProgramDetail() {
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowComplete(w)}
|
onClick={() => setShowComplete(w)}
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--green-ghost)', color: 'var(--green-dark)',
|
background: 'var(--green-bg)', color: 'var(--green-dark)',
|
||||||
padding: '6px 12px', fontSize: '0.75rem', fontWeight: 700,
|
padding: '6px 12px', fontSize: '0.75rem', fontWeight: 700,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -223,7 +223,7 @@ export default function ProgramDetail() {
|
||||||
{showComplete.notes && (
|
{showComplete.notes && (
|
||||||
<p style={{
|
<p style={{
|
||||||
marginTop: '12px', fontSize: '0.8rem', color: 'var(--text-2)',
|
marginTop: '12px', fontSize: '0.8rem', color: 'var(--text-2)',
|
||||||
background: 'var(--blue-ghost)', padding: '10px 12px', borderRadius: 'var(--r-sm)',
|
background: 'var(--accent-bg)', padding: '10px 12px', borderRadius: 'var(--r-sm)',
|
||||||
}}>
|
}}>
|
||||||
💡 {showComplete.notes}
|
💡 {showComplete.notes}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -269,7 +269,7 @@ function ExerciseRow({ exercise, detailed }) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{detailed && exercise.weight_instruction && (
|
{detailed && exercise.weight_instruction && (
|
||||||
<div style={{ fontSize: '0.75rem', color: 'var(--blue)', marginTop: '2px' }}>
|
<div style={{ fontSize: '0.75rem', color: 'var(--accent)', marginTop: '2px' }}>
|
||||||
🏋️ {exercise.weight_instruction}
|
🏋️ {exercise.weight_instruction}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import { api } from '../api'
|
||||||
|
|
||||||
const DIFFICULTY_COLORS = {
|
const DIFFICULTY_COLORS = {
|
||||||
beginner: 'var(--green)',
|
beginner: 'var(--green)',
|
||||||
intermediate: 'var(--blue)',
|
intermediate: 'var(--accent)',
|
||||||
advanced: 'var(--purple)',
|
advanced: 'var(--accent-light)',
|
||||||
}
|
}
|
||||||
|
|
||||||
const CATEGORY_ICONS = {
|
const CATEGORY_ICONS = {
|
||||||
|
|
@ -17,8 +17,8 @@ const CATEGORY_ICONS = {
|
||||||
|
|
||||||
const STATUS_LABELS = {
|
const STATUS_LABELS = {
|
||||||
pending: { label: 'Queued', color: 'var(--amber)' },
|
pending: { label: 'Queued', color: 'var(--amber)' },
|
||||||
crawling: { label: 'Fetching...', color: 'var(--blue)' },
|
crawling: { label: 'Fetching...', color: 'var(--accent)' },
|
||||||
extracting: { label: 'Analyzing...', color: 'var(--purple)' },
|
extracting: { label: 'Analyzing...', color: 'var(--accent-light)' },
|
||||||
ready: { label: 'Ready', color: 'var(--green)' },
|
ready: { label: 'Ready', color: 'var(--green)' },
|
||||||
failed: { label: 'Failed', color: 'var(--red)' },
|
failed: { label: 'Failed', color: 'var(--red)' },
|
||||||
}
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ export default function ProgramSearch() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<button type="submit" style={{
|
<button type="submit" style={{
|
||||||
background: 'var(--blue)', color: '#fff', padding: '12px 18px',
|
background: 'var(--accent)', color: '#fff', padding: '12px 18px',
|
||||||
boxShadow: 'var(--shadow-1)',
|
boxShadow: 'var(--shadow-1)',
|
||||||
}}>Search</button>
|
}}>Search</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -126,9 +126,9 @@ export default function ProgramSearch() {
|
||||||
onClick={handleResearch}
|
onClick={handleResearch}
|
||||||
disabled={researching || !query.trim()}
|
disabled={researching || !query.trim()}
|
||||||
style={{
|
style={{
|
||||||
width: '100%', background: researching ? 'var(--text-3)' : 'var(--orange)',
|
width: '100%', background: researching ? 'var(--text-3)' : 'var(--accent)',
|
||||||
color: '#fff', padding: '14px', marginBottom: '1rem',
|
color: '#fff', padding: '14px', marginBottom: '1rem',
|
||||||
boxShadow: researching ? 'none' : 'var(--shadow-orange)',
|
boxShadow: researching ? 'none' : 'var(--shadow-accent)',
|
||||||
opacity: !query.trim() ? 0.5 : 1,
|
opacity: !query.trim() ? 0.5 : 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
@ -140,8 +140,8 @@ export default function ProgramSearch() {
|
||||||
<div style={{
|
<div style={{
|
||||||
padding: '12px 16px', borderRadius: 'var(--r-sm)', marginBottom: '1rem',
|
padding: '12px 16px', borderRadius: 'var(--r-sm)', marginBottom: '1rem',
|
||||||
fontSize: '0.85rem', fontWeight: 600,
|
fontSize: '0.85rem', fontWeight: 600,
|
||||||
background: message.type === 'error' ? 'var(--red-ghost)' : message.type === 'success' ? 'var(--green-ghost)' : 'var(--blue-ghost)',
|
background: message.type === 'error' ? 'var(--red-ghost)' : message.type === 'success' ? 'var(--green-bg)' : 'var(--accent-bg)',
|
||||||
color: message.type === 'error' ? 'var(--red)' : message.type === 'success' ? 'var(--green-dark)' : 'var(--blue)',
|
color: message.type === 'error' ? 'var(--red)' : message.type === 'success' ? 'var(--green-dark)' : 'var(--accent)',
|
||||||
}}>
|
}}>
|
||||||
{message.text}
|
{message.text}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -160,12 +160,12 @@ export default function ProgramSearch() {
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--card)', borderRadius: 'var(--r)', padding: '16px',
|
background: 'var(--card)', borderRadius: 'var(--r)', padding: '16px',
|
||||||
marginBottom: '0.75rem', boxShadow: 'var(--shadow-1)', cursor: 'pointer',
|
marginBottom: '0.75rem', boxShadow: 'var(--shadow-1)', cursor: 'pointer',
|
||||||
border: '2px solid var(--orange-glow)',
|
border: '2px solid var(--accent-glow)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
<strong style={{ fontFamily: 'var(--font-display)', fontSize: '1rem' }}>{p.name}</strong>
|
<strong style={{ fontFamily: 'var(--font-display)', fontSize: '1rem' }}>{p.name}</strong>
|
||||||
<span style={{ fontSize: '0.8rem', color: 'var(--orange)', fontWeight: 700 }}>
|
<span style={{ fontSize: '0.8rem', color: 'var(--accent)', fontWeight: 700 }}>
|
||||||
Day {p.current_day}/{p.total_days}
|
Day {p.current_day}/{p.total_days}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -173,7 +173,7 @@ export default function ProgramSearch() {
|
||||||
marginTop: '8px', height: '6px', borderRadius: '3px', background: 'var(--divider)',
|
marginTop: '8px', height: '6px', borderRadius: '3px', background: 'var(--divider)',
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
height: '100%', borderRadius: '3px', background: 'var(--orange)',
|
height: '100%', borderRadius: '3px', background: 'var(--accent)',
|
||||||
width: `${Math.min(100, (p.current_day / p.total_days) * 100)}%`,
|
width: `${Math.min(100, (p.current_day / p.total_days) * 100)}%`,
|
||||||
transition: 'width 0.3s ease',
|
transition: 'width 0.3s ease',
|
||||||
}} />
|
}} />
|
||||||
|
|
@ -272,7 +272,7 @@ export default function ProgramSearch() {
|
||||||
onClick={() => navigate(`/catalog/${p.id}`)}
|
onClick={() => navigate(`/catalog/${p.id}`)}
|
||||||
style={{
|
style={{
|
||||||
marginTop: adopted ? '4px' : '8px', width: '100%', background: 'transparent',
|
marginTop: adopted ? '4px' : '8px', width: '100%', background: 'transparent',
|
||||||
color: 'var(--blue)', padding: '8px', fontSize: '0.82rem',
|
color: 'var(--accent)', padding: '8px', fontSize: '0.82rem',
|
||||||
border: '1px solid var(--divider)',
|
border: '1px solid var(--divider)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ export default function Settings() {
|
||||||
<div className="card" style={{ display: 'flex', alignItems: 'center', gap: '14px' }}>
|
<div className="card" style={{ display: 'flex', alignItems: 'center', gap: '14px' }}>
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '48px', height: '48px', borderRadius: '14px',
|
width: '48px', height: '48px', borderRadius: '14px',
|
||||||
background: 'linear-gradient(135deg, #FF5722, #FF8A65)',
|
background: 'linear-gradient(135deg, var(--accent), var(--accent-light))',
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
color: '#fff', fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.2rem',
|
color: '#fff', fontFamily: 'var(--font-display)', fontWeight: 900, fontSize: '1.2rem',
|
||||||
}}>
|
}}>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ import { useState, useEffect } from 'react'
|
||||||
import { api } from '../api'
|
import { api } from '../api'
|
||||||
|
|
||||||
const STATUS_COLORS = {
|
const STATUS_COLORS = {
|
||||||
connected: '#4CAF50',
|
connected: 'var(--green)',
|
||||||
configured: '#FF9800',
|
configured: 'var(--amber)',
|
||||||
not_configured: '#9E9E9E',
|
not_configured: 'var(--text-3)',
|
||||||
}
|
}
|
||||||
|
|
||||||
const STATUS_LABELS = {
|
const STATUS_LABELS = {
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ export default function Support() {
|
||||||
borderRadius: m.sender === 'user'
|
borderRadius: m.sender === 'user'
|
||||||
? 'var(--r) var(--r) 4px var(--r)'
|
? 'var(--r) var(--r) 4px var(--r)'
|
||||||
: 'var(--r) var(--r) var(--r) 4px',
|
: 'var(--r) var(--r) var(--r) 4px',
|
||||||
background: m.sender === 'user' ? 'var(--orange)' : 'var(--card)',
|
background: m.sender === 'user' ? 'var(--accent)' : 'var(--card)',
|
||||||
color: m.sender === 'user' ? '#fff' : 'var(--text)',
|
color: m.sender === 'user' ? '#fff' : 'var(--text)',
|
||||||
boxShadow: 'var(--shadow-1)',
|
boxShadow: 'var(--shadow-1)',
|
||||||
fontSize: '0.88rem',
|
fontSize: '0.88rem',
|
||||||
|
|
@ -116,7 +116,7 @@ export default function Support() {
|
||||||
{confirmation && (
|
{confirmation && (
|
||||||
<div style={{
|
<div style={{
|
||||||
textAlign: 'center', fontSize: '0.8rem', color: 'var(--green-dark)',
|
textAlign: 'center', fontSize: '0.8rem', color: 'var(--green-dark)',
|
||||||
padding: '8px', background: 'var(--green-ghost)', borderRadius: 'var(--r-sm)',
|
padding: '8px', background: 'var(--green-bg)', borderRadius: 'var(--r-sm)',
|
||||||
}}>
|
}}>
|
||||||
{confirmation}
|
{confirmation}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -146,11 +146,11 @@ export default function Support() {
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!input.trim() || sending}
|
disabled={!input.trim() || sending}
|
||||||
style={{
|
style={{
|
||||||
background: sending ? 'var(--text-3)' : 'var(--orange)',
|
background: sending ? 'var(--text-3)' : 'var(--accent)',
|
||||||
color: '#fff', borderRadius: 'var(--r-full)',
|
color: '#fff', borderRadius: 'var(--r-full)',
|
||||||
width: '44px', height: '44px', padding: 0,
|
width: '44px', height: '44px', padding: 0,
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
fontSize: '1.1rem', boxShadow: 'var(--shadow-orange)',
|
fontSize: '1.1rem', boxShadow: 'var(--shadow-accent)',
|
||||||
opacity: !input.trim() ? 0.5 : 1,
|
opacity: !input.trim() ? 0.5 : 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ function AdminThreadList() {
|
||||||
style={{
|
style={{
|
||||||
background: 'var(--card)', borderRadius: 'var(--r)', padding: '14px 16px',
|
background: 'var(--card)', borderRadius: 'var(--r)', padding: '14px 16px',
|
||||||
marginBottom: '0.6rem', boxShadow: 'var(--shadow-1)', cursor: 'pointer',
|
marginBottom: '0.6rem', boxShadow: 'var(--shadow-1)', cursor: 'pointer',
|
||||||
border: t.unread_admin > 0 ? '2px solid var(--orange-glow)' : '1px solid var(--card-border)',
|
border: t.unread_admin > 0 ? '2px solid var(--accent-glow)' : '1px solid var(--card-border)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||||
|
|
@ -66,7 +66,7 @@ function AdminThreadList() {
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||||
{t.unread_admin > 0 && (
|
{t.unread_admin > 0 && (
|
||||||
<span style={{
|
<span style={{
|
||||||
background: 'var(--orange)', color: '#fff', fontSize: '0.65rem', fontWeight: 800,
|
background: 'var(--accent)', color: '#fff', fontSize: '0.65rem', fontWeight: 800,
|
||||||
width: '20px', height: '20px', borderRadius: '50%',
|
width: '20px', height: '20px', borderRadius: '50%',
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
}}>{t.unread_admin}</span>
|
}}>{t.unread_admin}</span>
|
||||||
|
|
@ -168,7 +168,7 @@ function AdminThread({ threadId }) {
|
||||||
)}
|
)}
|
||||||
<span style={{
|
<span style={{
|
||||||
...ctxTag,
|
...ctxTag,
|
||||||
background: ctx.gate_passed ? 'var(--green-ghost)' : 'var(--red-ghost)',
|
background: ctx.gate_passed ? 'var(--green-bg)' : 'var(--red-ghost)',
|
||||||
color: ctx.gate_passed ? 'var(--green-dark)' : 'var(--red)',
|
color: ctx.gate_passed ? 'var(--green-dark)' : 'var(--red)',
|
||||||
}}>
|
}}>
|
||||||
{ctx.points_today}/{ctx.daily_target} pts {ctx.gate_passed ? '✓' : '✗'}
|
{ctx.points_today}/{ctx.daily_target} pts {ctx.gate_passed ? '✓' : '✗'}
|
||||||
|
|
@ -193,7 +193,7 @@ function AdminThread({ threadId }) {
|
||||||
borderRadius: m.sender === 'admin'
|
borderRadius: m.sender === 'admin'
|
||||||
? 'var(--r) var(--r) 4px var(--r)'
|
? 'var(--r) var(--r) 4px var(--r)'
|
||||||
: 'var(--r) var(--r) var(--r) 4px',
|
: 'var(--r) var(--r) var(--r) 4px',
|
||||||
background: m.sender === 'admin' ? 'var(--blue)' : 'var(--card)',
|
background: m.sender === 'admin' ? 'var(--accent)' : 'var(--card)',
|
||||||
color: m.sender === 'admin' ? '#fff' : 'var(--text)',
|
color: m.sender === 'admin' ? '#fff' : 'var(--text)',
|
||||||
boxShadow: 'var(--shadow-1)',
|
boxShadow: 'var(--shadow-1)',
|
||||||
fontSize: '0.88rem',
|
fontSize: '0.88rem',
|
||||||
|
|
@ -233,7 +233,7 @@ function AdminThread({ threadId }) {
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!input.trim() || sending}
|
disabled={!input.trim() || sending}
|
||||||
style={{
|
style={{
|
||||||
background: sending ? 'var(--text-3)' : 'var(--blue)',
|
background: sending ? 'var(--text-3)' : 'var(--accent)',
|
||||||
color: '#fff', borderRadius: 'var(--r-full)',
|
color: '#fff', borderRadius: 'var(--r-full)',
|
||||||
width: '44px', height: '44px', padding: 0,
|
width: '44px', height: '44px', padding: 0,
|
||||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export default function WeekView() {
|
||||||
<h1 className="page-title">This Week</h1>
|
<h1 className="page-title">This Week</h1>
|
||||||
|
|
||||||
{/* Summary hero */}
|
{/* Summary hero */}
|
||||||
<div className="card" style={{ textAlign: 'center', background: 'var(--purple-ghost)' }}>
|
<div className="card" style={{ textAlign: 'center', background: 'var(--accent-bg)' }}>
|
||||||
<div className="section-label">Weekly Total</div>
|
<div className="section-label">Weekly Total</div>
|
||||||
<div style={{ fontFamily: 'var(--font-display)', fontSize: '2.6rem', fontWeight: 900, letterSpacing: '-0.03em' }}>
|
<div style={{ fontFamily: 'var(--font-display)', fontSize: '2.6rem', fontWeight: 900, letterSpacing: '-0.03em' }}>
|
||||||
{week.total_points_earned}
|
{week.total_points_earned}
|
||||||
|
|
@ -68,7 +68,7 @@ export default function WeekView() {
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
width: '38px', fontWeight: isToday ? 800 : 600, fontSize: '0.85rem',
|
width: '38px', fontWeight: isToday ? 800 : 600, fontSize: '0.85rem',
|
||||||
color: isToday ? 'var(--orange)' : 'var(--text)',
|
color: isToday ? 'var(--accent)' : 'var(--text)',
|
||||||
}}>
|
}}>
|
||||||
{days[i]}
|
{days[i]}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue