diff --git a/css/dashboard.css b/css/dashboard.css new file mode 100644 index 0000000..4e8caf1 --- /dev/null +++ b/css/dashboard.css @@ -0,0 +1,602 @@ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +:root { + --color-background-primary: #ffffff; + --color-background-secondary: #f7f7f5; + --color-background-tertiary: #efefec; + --color-text-primary: #1a1a18; + --color-text-secondary: #6b6b66; + --color-text-tertiary: #9c9a92; + --color-border-tertiary: rgba(0,0,0,0.08); + --color-border-secondary: rgba(0,0,0,0.15); + --color-border-primary: rgba(0,0,0,0.30); + + --color-danger-rgb: 163, 45, 45; + --color-info-rgb: 24, 95, 165; + --color-success-rgb: 22, 101, 52; + + --color-text-danger: #a32d2d; + --color-background-danger: #fcebeb; + --color-border-danger: rgba(var(--color-danger-rgb), 0.35); + + --color-text-info: #161717; + --color-background-info: #e6f1fb; + --color-border-info: rgba(var(--color-info-rgb), 0.35); + + --color-text-success: #166534; + --color-background-success: #eaf3de; + --color-border-success: rgba(var(--color-success-rgb), 0.35); + + --color-text-warning: #854f0b; + --color-background-warning: #faeeda; + + --color-text-purple: #3c3489; + --color-background-purple: #eeedfe; + + --border-radius-sm: 6px; + --border-radius-md: 10px; + --border-radius-lg: 16px; + --font-sans: 'Inter', system-ui, -apple-system, sans-serif; + + --shadow-sm: 0 2px 8px rgba(0,0,0,0.04); + --shadow-md: 0 4px 16px rgba(0,0,0,0.06); + --shadow-lg: 0 8px 32px rgba(0,0,0,0.08); +} + +body { + font-family: var(--font-sans); + background: #ffffff; + color: var(--color-text-primary); + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 32px 16px; + overflow-x: hidden; + position: relative; + cursor: none; +} + +.stars-container { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; + z-index: 0; +} + +.star { + position: absolute; + color: rgba(0, 0, 0, 1); + pointer-events: none; + /* animation: twinkle 3s ease-in-out infinite; */ +} + +/* @keyframes twinkle { + 0%, 100% { opacity: 0.3; transform: scale(0.8); } + 50% { opacity: 0.8; transform: scale(1.2); } +} */ + +@keyframes floatCrescent { + 0%, 100% { transform: translateY(0px) rotate(0deg); } + 50% { transform: translateY(-15px) rotate(-10deg); } +} + +.crescent { + position: fixed; + bottom: 5%; + right: 5%; + width: 80px; + height: 80px; + background: transparent; + border-radius: 50%; + box-shadow: -15px -15px 0 0 #1a1a18; + pointer-events: none; + z-index: 0; + animation: floatCrescent 8s ease-in-out infinite; +} + +.dashboard-card { + background: var(--color-background-secondary); + border: 1px solid var(--color-border-tertiary); + border-radius: var(--border-radius-md); + padding: 20px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.dashboard-card:hover { + background: #424242; + transform: translateY(-4px); + box-shadow: var(--shadow-lg); +} + +.dashboard-card:hover .card-title { + color: #ffffff; +} + +.dashboard-card:hover .deadline-name, +.dashboard-card:hover .priority-name, +.dashboard-card:hover .recent-text, +.dashboard-card:hover .streak-number, +.dashboard-card:hover .streak-label, +.dashboard-card:hover .streak-best-text { + color: #ffffff; +} + +.dashboard-card:hover .deadline-date { + color: #ff8888; +} + +.dashboard-card:hover .priority-badge { + background: rgba(255,255,255,0.2); + color: #ffffff; +} + +.dashboard-card:hover .recent-time { + color: #cccccc; +} + +.dashboard-card:hover .empty-state { + color: #aaaaaa; +} + +.dashboard-card:hover .deadline-item, +.dashboard-card:hover .priority-item, +.dashboard-card:hover .recent-item { + border-bottom-color: rgba(255,255,255,0.15); +} + +.stat-item:hover { + background: #343333; +} + +.stat-item:hover .stat-number, +.stat-item:hover .stat-label { + color: #ffffff; +} + +.dashboard-card:hover { + background: #3f3e3e; +} + +.dashboard-card:hover .card-title, +.dashboard-card:hover .deadline-name, +.dashboard-card:hover .priority-name, +.dashboard-card:hover .recent-text, +.dashboard-card:hover .recent-icon, +.dashboard-card:hover .recent-time, +.dashboard-card:hover .streak-number, +.dashboard-card:hover .streak-label, +.dashboard-card:hover .streak-best-text, +.dashboard-card:hover .empty-state, +.dashboard-card:hover .deadline-item { + color: #ffffff; +} + +.dashboard-card:hover .deadline-date { + color: #ffaaaa !important; +} + +.dashboard-card:hover .priority-badge { + background: rgba(255, 255, 255, 0.2) !important; + color: #ffffff !important; +} + +.dashboard-card:hover .recent-item { + border-bottom-color: rgba(255, 255, 255, 0.2); +} + +.deadline-item:hover{ + color: #ffffff; +} +@media (max-width: 768px) { + body { + cursor: auto; + padding: 24px 16px; + } + .custom-cursor { + display: none; + } + .crescent { + width: 50px; + height: 50px; + box-shadow: -10px -10px 0 0 #1a1a18; + bottom: 3%; + right: 3%; + } +} + +.custom-cursor { + position: fixed; + width: 32px; + height: 32px; + border-radius: 50%; + background: rgba(0, 0, 0, 0.7); + backdrop-filter: blur(4px); + pointer-events: none; + z-index: 9999; + transform: translate(-50%, -50%); + transition: width 0.2s ease, height 0.2s ease, background 0.2s ease; + border: 1px solid rgba(0,0,0,0.3); +} + +.custom-cursor.active { + width: 48px; + height: 48px; + background: rgba(255, 255, 255, 0.9); + border-color: rgba(255, 255, 255, 0.5); +} +.wrapper { + width: 100%; + max-width: 1200px; + animation: fadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1); + position: relative; + z-index: 1; +} + +.recent-list { + display: flex; + flex-direction: column; + gap: 12px; + min-height: 200px; +} + +.recent-item { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 0; + border-bottom: 1px solid var(--color-border-tertiary); + transition: all 0.2s ease; +} + +.recent-item:hover { + transform: translateX(4px); + border-bottom-color: var(--color-border-secondary); +} + +.recent-icon { + font-size: 16px; + width: 24px; + text-align: center; +} + +.recent-text { + flex: 1; + font-size: 13px; + font-weight: 500; + color: var(--color-text-primary); +} + +.recent-time { + font-size: 10px; + color: var(--color-text-tertiary); +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(5px); } + to { opacity: 1; transform: translateY(0); } +} + +.dashboard-header { + width: 100%; + margin: 0 auto 16px auto; + padding: 16px 24px; + background: var(--color-background-primary); + border: 1px solid var(--color-border-tertiary); + border-radius: var(--border-radius-lg); + box-shadow: var(--shadow-md); + display: flex; + align-items: center; + justify-content: space-between; +} + +.header-left { + display: flex; + align-items: center; + gap: 12px; +} + +.logo { + width: 40px; + height: 40px; + border-radius: 2px; +} + +.site-title { + font-size: 20px; + font-weight: 700; + color: var(--color-text-primary); +} + +.header-nav { + display: flex; + gap: 24px; +} + +.header-nav a { + text-decoration: none; + color: var(--color-text-secondary); + font-weight: 500; + transition: color 0.2s; +} + +.header-nav a:hover { + color: var(--color-text-primary); +} + +.dashboard-content { + background: var(--color-background-primary); + border: 1px solid var(--color-border-tertiary); + border-radius: var(--border-radius-lg); + padding: 32px; + box-shadow: var(--shadow-lg); + margin-top: 16px; +} + +.greeting-section { + margin-bottom: 48px; + text-align: center; +} + +.greeting-text { + font-size: 12px; + font-weight: 600; + color: var(--color-text-tertiary); + letter-spacing: .08em; + margin-bottom: 12px; + text-transform: uppercase; +} + +.user-name { + font-size: 36px; + font-weight: 600; + color: var(--color-text-primary); + letter-spacing: -0.02em; + margin-bottom: 8px; +} + +.date-text { + font-size: 14px; + color: var(--color-text-secondary); +} + +.stats-row { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 12px; + margin-bottom: 40px; +} + +.stat-item { + background: var(--color-background-secondary); + border: 1px solid var(--color-border-tertiary); + border-radius: var(--border-radius-md); + padding: 20px 12px; + text-align: center; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); +} + +.stat-item:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); + border-color: var(--color-border-secondary); +} + +.stat-number { + font-size: 32px; + font-weight: 700; + color: var(--color-text-primary); + margin-bottom: 6px; +} + +.stat-label { + font-size: 11px; + font-weight: 600; + color: var(--color-text-tertiary); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.dashboard-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; + margin-bottom: 32px; +} + +.dashboard-card { + background: var(--color-background-secondary); + border: 1px solid var(--color-border-tertiary); + border-radius: var(--border-radius-md); + padding: 20px; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); +} + +.dashboard-card:hover { + box-shadow: var(--shadow-sm); + border-color: var(--color-border-secondary); +} + +.card-header { + margin-bottom: 16px; + padding-bottom: 12px; + border-bottom: 1px solid var(--color-border-tertiary); +} + +.card-title { + font-size: 11px; + font-weight: 700; + color: var(--color-text-tertiary); + text-transform: uppercase; + letter-spacing: 0.08em; +} + +.deadline-list, +.priority-list { + display: flex; + flex-direction: column; + gap: 12px; + min-height: 200px; +} + +.deadline-item, +.priority-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 0; + border-bottom: 1px solid var(--color-border-tertiary); + transition: all 0.2s ease; + cursor: pointer; +} + +.deadline-item:hover, +.priority-item:hover { + transform: translateX(4px); + border-bottom-color: var(--color-border-secondary); +} + +.deadline-name, +.priority-name { + font-size: 14px; + font-weight: 500; + color: var(--color-text-primary); +} + +.deadline-date { + font-size: 11px; + font-weight: 600; + color: var(--color-text-danger); +} + +.priority-badge { + font-size: 10px; + font-weight: 600; + padding: 3px 10px; + border-radius: 20px; + background: var(--color-background-tertiary); + color: var(--color-text-secondary); +} + +.empty-state { + text-align: center; + padding: 32px 16px; + color: var(--color-text-tertiary); + font-size: 13px; +} + +.streak-content { + text-align: center; + padding: 8px 0; +} + +.streak-number { + font-size: 52px; + font-weight: 700; + color: var(--color-text-primary); + letter-spacing: -0.02em; + margin-bottom: 8px; +} + +.streak-label { + font-size: 12px; + color: var(--color-text-secondary); + margin-bottom: 20px; +} + +.streak-progress-bar { + background: var(--color-background-tertiary); + border-radius: 4px; + height: 4px; + margin-bottom: 12px; + overflow: hidden; +} + +.streak-progress-fill { + background: var(--color-text-primary); + height: 100%; + border-radius: 4px; + transition: width 0.6s ease; +} + +.streak-best-text { + font-size: 11px; + color: var(--color-text-tertiary); +} + +.start-planning-btn { + width: 100%; + padding: 14px 20px; + background: var(--color-text-primary); + color: var(--color-background-primary); + border: none; + border-radius: var(--border-radius-md); + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); + display: flex; + align-items: center; + justify-content: center; + gap: 8px; +} + +.start-planning-btn:hover { + background: var(--color-text-secondary); + transform: translateY(-2px); + box-shadow: var(--shadow-md); +} + +.start-planning-btn:active { + transform: translateY(0); +} + +.arrow { + transition: transform 0.2s ease; +} + +.start-planning-btn:hover .arrow { + transform: translateX(4px); +} + +@media (max-width: 768px) { + .stats-row { + grid-template-columns: repeat(2, 1fr); + gap: 10px; + } + + .dashboard-grid { + grid-template-columns: 1fr; + gap: 16px; + } + + .user-name { + font-size: 28px; + } + + .greeting-section { + margin-bottom: 32px; + } + + .stat-number { + font-size: 26px; + } + + .dashboard-header { + flex-direction: column; + gap: 16px; + } + + .header-nav { + flex-wrap: wrap; + justify-content: center; + } +} \ No newline at end of file diff --git a/css/index.css b/css/index.css index f5561bd..e17300c 100644 --- a/css/index.css +++ b/css/index.css @@ -15,9 +15,7 @@ --color-text-secondary: #6b6b66; --color-text-tertiary: #9c9a92; --color-border-tertiary: rgba(0, 0, 0, 0.08); - /* softer */ --color-border-secondary: rgba(0, 0, 0, 0.15); - /* softer */ --color-border-primary: rgba(0, 0, 0, 0.30); --color-danger-rgb: 163, 45, 45; @@ -96,13 +94,11 @@ body { overflow-x: hidden; } -/* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } - to { opacity: 1; transform: translateY(0); @@ -114,7 +110,6 @@ body { transform: scale(0.95); opacity: 0; } - 100% { transform: scale(1); opacity: 1; @@ -148,7 +143,6 @@ body { backdrop-filter: blur(20px); } -/* Sidebar */ .sidebar { background: var(--color-background-secondary); border-right: 1px solid var(--color-border-tertiary); @@ -251,7 +245,6 @@ body { color: var(--color-text-primary); } -/* Main */ .main { display: flex; flex-direction: column; @@ -317,17 +310,20 @@ body { background: var(--color-text-secondary); } -/* Calendar */ .cal-section { padding: 16px 24px; border-bottom: 1px solid var(--color-border-tertiary); flex-shrink: 0; + transition: max-height 0.3s ease; + overflow: hidden; + position: relative; } .cal-header { display: flex; align-items: center; margin-bottom: 16px; + position: relative; } .cal-title { @@ -344,6 +340,7 @@ body { padding: 4px 8px; border-radius: 4px; transition: background 0.2s; + margin-left: 4px; } .cal-nav:hover { @@ -351,6 +348,30 @@ body { color: var(--color-text-primary); } +.collapse-icon { + cursor: pointer; + font-size: 14px; + color: var(--color-text-tertiary); + padding: 4px 8px; + margin-left: 12px; + border-radius: 4px; + transition: all 0.2s; +} + +.collapse-icon:hover { + background: var(--color-background-secondary); + color: var(--color-text-primary); +} + +.cal-section.collapsed { + max-height: 60px; +} + +.cal-section.collapsed .cal-grid, +.cal-section.collapsed .cal-legend { + display: none; +} + .cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); @@ -370,8 +391,10 @@ body { .cal-day { font-size: 13px; font-weight: 500; - height: 32px; + min-height: 65px; + padding: 8px 4px 4px 4px; display: flex; + flex-direction: column; align-items: center; justify-content: center; border-radius: var(--border-radius-md); @@ -394,24 +417,30 @@ body { box-shadow: var(--shadow-sm); } +.cal-day.muted { + color: var(--color-border-secondary); +} + .cal-day-indicators { - position: absolute; - bottom: 3px; - left: 0; - right: 0; display: flex; + flex-wrap: wrap; justify-content: center; gap: 3px; + margin-top: 4px; + max-width: 100%; } .cal-day-indicator { width: 5px; height: 5px; border-radius: 50%; + flex-shrink: 0; } -.cal-day.muted { - color: var(--color-border-secondary); +.task-count { + font-size: 8px; + color: var(--color-text-tertiary); + margin-left: 2px; } .cal-legend { @@ -437,7 +466,34 @@ body { display: inline-block; } -/* Tasks */ +.cal-week-view .cal-day { + min-height: 100px; + font-size: 18px; + font-weight: 700; + color: var(--color-text-primary); + padding-top: 12px; +} + +.cal-week-view .cal-day-indicators { + position: absolute; + bottom: 8px; + left: 0; + right: 0; +} + +.cal-week-view .cal-day-indicator { + width: 8px; + height: 8px; +} + +.cal-month-view .cal-day { + min-height: 55px; +} + +.cal-grid:has(.day-view-checklist) { + display: block; +} + .tasks-section { flex: 1; overflow-y: auto; @@ -521,7 +577,6 @@ body { animation: float 3s ease-in-out infinite; } -/* Soft gradient glow behind the icon */ .empty-state-icon::before { content: ''; position: absolute; @@ -579,7 +634,6 @@ body { transform: translateY(-1px) scale(0.98); } -/* Subtle shine effect on hover */ .empty-state-cta::after { content: ''; position: absolute; @@ -604,36 +658,6 @@ body { margin-top: 24px; animation: fadeIn 0.4s ease forwards; } -.task-item:hover { background: var(--color-background-secondary); transform: translateX(4px); border-color: var(--color-border-secondary); box-shadow: var(--shadow-sm); } -.task-item.urgent, .task-item.high-priority { - border-color: var(--color-border-danger); - background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.08) 0%, var(--color-background-primary) 100%); -} -.task-item.overdue { - border-color: var(--color-border-danger); - background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.12) 0%, var(--color-background-primary) 100%); -} -.task-item.done { - background: linear-gradient(135deg, rgba(var(--color-success-rgb), 0.08) 0%, var(--color-background-primary) 100%); - border-color: var(--color-border-success); -} -.task-check { width: 18px; height: 18px; border-radius: 5px; border: 2px solid var(--color-border-secondary); flex-shrink: 0; margin-top: 2px; transition: all 0.2s; position: relative; cursor: pointer; } -.task-check:hover { border-color: var(--color-text-primary); } -.task-check.done { background: var(--color-text-success); border-color: var(--color-text-success); } -.task-check.done::after { content: ''; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg); } -.task-info { flex: 1; min-width: 0; } -.task-name { font-size: 14px; font-weight: 500; color: var(--color-text-primary); line-height: 1.4; transition: color 0.2s; margin-bottom: 6px; } -.task-item.done .task-name { text-decoration: line-through; color: var(--color-text-tertiary); } -.task-meta { font-size: 12px; color: var(--color-text-tertiary); margin-top: 6px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; font-weight: 500; } -.task-pill { font-size: 11px; padding: 2px 8px; border-radius: 12px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; border: 1px solid transparent; } -.pill-red { background: var(--color-background-danger); color: var(--color-text-danger); border-color: var(--color-border-danger); } -.pill-blue { background: var(--color-background-info); color: var(--color-text-info); border-color: var(--color-border-info); } -.pill-green{ background: var(--color-background-success); color: var(--color-text-success); border-color: var(--color-border-success); } -.pill-amber{ background: var(--color-background-warning); color: var(--color-text-warning); border-color: rgba(133, 79, 11, 0.2); } -.pill-purple{ background: var(--color-background-purple); color: var(--color-text-purple); border-color: rgba(60, 52, 137, 0.2); } - -.conflict-card { font-size: 13px; font-weight: 500; color: var(--color-text-warning); background: var(--color-background-warning); border: 1px solid rgba(133, 79, 11, 0.3); border-radius: var(--border-radius-md); padding: 12px 16px; line-height: 1.5; display: flex; gap: 12px; align-items: flex-start; box-shadow: var(--shadow-sm); } -.conflict-icon { font-size: 18px; line-height: 1; } .tasks-group-header { display: flex; @@ -657,7 +681,6 @@ body { border-radius: var(--border-radius-md); cursor: pointer; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - border: 1px solid transparent; background: var(--color-background-primary); margin-bottom: 6px; border: 1px solid var(--color-border-tertiary); @@ -672,7 +695,22 @@ body { .task-item.urgent { border-color: var(--color-border-danger); - background: linear-gradient(to right, var(--color-background-danger) 0%, var(--color-background-primary) 100%); + background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.08) 0%, var(--color-background-primary) 100%); +} + +.task-item.overdue { + border-color: var(--color-border-danger); + background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.12) 0%, var(--color-background-primary) 100%); +} + +.task-item.done { + background: linear-gradient(135deg, rgba(var(--color-success-rgb), 0.08) 0%, var(--color-background-primary) 100%); + border-color: var(--color-border-success); +} + +.task-item.done .task-name { + text-decoration: line-through; + color: var(--color-text-tertiary); } .task-check { @@ -722,11 +760,6 @@ body { margin-bottom: 6px; } -.task-item.done .task-name { - text-decoration: line-through; - color: var(--color-text-tertiary); -} - .task-meta { font-size: 12px; color: var(--color-text-tertiary); @@ -799,6 +832,60 @@ body { line-height: 1; } +.smart-workload-card { + margin-bottom: 14px; + padding: 14px; + border-radius: 14px; + background: rgba(255, 184, 77, 0.08); + border: 1px solid rgba(255, 184, 77, 0.25); + backdrop-filter: blur(10px); + display: flex; + justify-content: space-between; + gap: 18px; + align-items: flex-start; + flex-wrap: wrap; +} + +.smart-workload-title { + font-size: 14px; + font-weight: 700; + margin-bottom: 8px; + color: #ffcc66; +} + +.smart-workload-score { + min-width: 90px; + font-size: 12px; + margin-bottom: 10px; + color: #cfcfcf; +} + +.smart-suggestion-list { + margin: 0; + padding-left: 18px; +} + +.smart-suggestion-list li { + margin-bottom: 6px; + color: #e6e6e6; + line-height: 1.5; + font-size: 13px; +} + +.smart-workload-card.high { + border-color: rgba(255, 77, 77, 0.5); + background: rgba(255, 77, 77, 0.08); +} + +.smart-workload-card.medium { + border-color: rgba(255, 184, 77, 0.25); +} + +.smart-highlight { + color: #ffcc66; + font-weight: 600; +} + .task-actions { display: flex; gap: 8px; @@ -840,7 +927,37 @@ body { border-color: var(--color-text-info); } -/* Right Panel */ +.view-toggle-group { + display: flex; + gap: 4px; + background: var(--color-background-secondary); + padding: 4px; + border-radius: 12px; +} + +.view-btn { + padding: 6px 16px; + font-size: 13px; + font-weight: 500; + background: transparent; + border: none; + border-radius: 8px; + cursor: pointer; + color: var(--color-text-secondary); + transition: all 0.2s ease; +} + +.view-btn.active { + background: var(--color-background-primary); + color: var(--color-text-primary); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.view-btn:hover:not(.active) { + background: var(--color-background-secondary); + color: var(--color-text-primary); +} + .panel { border-left: 1px solid var(--color-border-tertiary); display: flex; @@ -850,9 +967,7 @@ body { } .panel.panel-collapsed { - overflow: hidden; - width: 48px; - min-width: 48px; + overflow: visible; } .panel.panel-collapsed .panel-title, @@ -878,7 +993,6 @@ body { padding: 12px; justify-content: center; border-bottom: none; - overflow: hidden; } .panel-toggle-btn { @@ -1015,10 +1129,10 @@ body { } .extract-preview { + flex: 1; overflow-y: auto; - padding: 0 20px 12px; + padding: 0 20px 20px; scroll-behavior: smooth; - max-height: 280px; } .extract-preview::-webkit-scrollbar { @@ -1118,6 +1232,17 @@ body { color: var(--color-text-primary); } +.summary-box { + margin: 0 20px 16px; + padding: 14px; + background: linear-gradient(135deg, var(--color-background-secondary), var(--color-background-tertiary)); + border-radius: 12px; + font-size: 14px; + line-height: 1.6; + border: 1px solid var(--color-border-tertiary); + color: var(--color-text-primary); +} + .add-btn { margin: 0 20px 20px; padding: 12px; @@ -1125,3844 +1250,4 @@ body { border-radius: var(--border-radius-md); background: var(--color-text-primary); color: var(--color-background-primary); - font-size: 14px; - font-weight: 600; - cursor: pointer; - text-align: center; - flex-shrink: 0; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} - -.add-btn:hover:not(:disabled) { - background: var(--color-text-secondary); - transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); -} - -.add-btn:active:not(:disabled) { - transform: translateY(0); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); -} - -.add-btn:disabled { - background: var(--color-border-secondary); - cursor: not-allowed; - transform: none; - box-shadow: none; - color: var(--color-text-tertiary); -} - -/* Loader */ -.loader-spinner { - display: inline-block; - width: 16px; - height: 16px; - border: 2px solid rgba(0, 0, 0, 0.1); - border-radius: 50%; - border-top-color: var(--color-text-primary); - animation: spin 0.8s linear infinite; -} - -@media (prefers-color-scheme: dark) { - .loader-spinner { - border-color: rgba(255, 255, 255, 0.1); - border-top-color: #fff; - } -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -/* Utility classes */ -.hidden { - display: none !important; -} - -/* Timer duration input */ -.timer-duration-row { - display: flex; - align-items: center; - gap: 10px; -} - -.timer-duration-label { - font-size: 12px; - font-weight: 600; - color: var(--color-text-tertiary); - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.timer-duration-input { - width: 64px; - padding: 6px 10px; - border: 1px solid var(--color-border-secondary); - border-radius: var(--border-radius-sm); - background: var(--color-background-primary); - color: var(--color-text-primary); - font-size: 14px; - font-weight: 600; - font-family: inherit; - text-align: center; - transition: border-color 0.2s; -} - -.timer-duration-input:focus { - outline: none; - border-color: var(--color-text-primary); -} - -.timer-duration-input:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -/* Focus Mode */ -.focus-section { - flex: 1; - display: flex; - flex-direction: column; - padding: 24px; - overflow-y: auto; - gap: 32px; -} - -.focus-dashboard { - display: flex; - flex-direction: column; - align-items: center; - gap: 24px; -} - -.timer-container { - position: relative; - width: 240px; - height: 240px; - display: flex; - align-items: center; - justify-content: center; -} - -.timer-svg { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - transform: rotate(-90deg); -} - -.timer-path-elapsed { - fill: none; - stroke: var(--color-border-tertiary); - stroke-width: 4; -} - -.timer-path-remaining { - fill: none; - stroke: var(--color-text-primary); - stroke-width: 6; - stroke-linecap: round; - transition: stroke-dashoffset 1s linear; -} - -.timer-text { - font-size: 48px; - font-weight: 700; - color: var(--color-text-primary); - font-variant-numeric: tabular-nums; - letter-spacing: -0.02em; - z-index: 1; -} - -.timer-controls { - display: flex; - gap: 12px; -} - -.focus-task-container, -.focus-task-selector { - width: 100%; - max-width: 600px; - margin: 0 auto; -} - -.focus-task-header { - font-size: 13px; - font-weight: 600; - color: var(--color-text-tertiary); - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 12px; -} - -.active-focus-task { - background: var(--color-background-primary); - border: 1px solid var(--color-border-primary); - border-radius: var(--border-radius-md); - padding: 20px; - box-shadow: var(--shadow-md); - min-height: 80px; - display: flex; - align-items: center; - justify-content: center; -} - -.no-task-selected { - color: var(--color-text-secondary); - font-size: 14px; - font-weight: 500; -} - -.focus-task-list { - display: flex; - flex-direction: column; - gap: 8px; -} - -.focus-task-item { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-md); - cursor: pointer; - transition: all 0.2s; -} - -.focus-task-item:hover { - background: var(--color-background-secondary); - border-color: var(--color-text-info); - transform: translateY(-1px); -} - -.focus-task-item .task-name { - margin-bottom: 0; - flex: 1; -} - - -/* Header */ -.site-header { - width: 100%; - max-width: 1200px; - margin: 0 auto 16px auto; - padding: 16px 24px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-md); - - display: flex; - align-items: center; - justify-content: space-between; -} - -.header-left { - display: flex; - align-items: center; - gap: 12px; -} - -.logo { - width: 40px; - height: 40px; - border-radius: 2px; -} - -.site-title { - font-size: 20px; - font-weight: 700; - color: var(--color-text-primary); -} - -.header-nav { - display: flex; - gap: 24px; -} - -.header-nav a { - text-decoration: none; - color: var(--color-text-secondary); - font-weight: 500; - transition: color 0.2s; -} - -.header-nav a:hover { - color: var(--color-text-primary); -} - -.profile-btn { - padding: 8px 16px; - border: none; - border-radius: var(--border-radius-md); - background: var(--color-text-primary); - color: var(--color-background-primary); - cursor: pointer; - font-weight: 600; -} - -/* Footer */ -.site-footer { - width: 100%; - max-width: 1200px; - margin: 16px auto 0 auto; - padding: 16px 24px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-md); - - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-text-secondary); - font-size: 14px; -} - -.footer-links { - display: flex; - gap: 16px; -} - -.footer-links a { - text-decoration: none; - color: var(--color-text-secondary); -} - -.footer-links a:hover { - color: var(--color-text-primary); -} - -/* Global crash boundary UI */ -.crash-screen { - min-height: 100vh; - width: 100%; - display: flex; - align-items: center; - justify-content: center; - padding: 24px; - background: - radial-gradient(circle at 20% 20%, rgba(24, 95, 165, 0.16), transparent 40%), - radial-gradient(circle at 80% 0%, rgba(22, 101, 52, 0.14), transparent 42%), - var(--color-background-tertiary); -} - -.crash-card { - width: min(560px, 100%); - border-radius: var(--border-radius-lg); - border: 1px solid var(--color-border-tertiary); - background: var(--color-background-primary); - box-shadow: var(--shadow-lg); - padding: 28px; -} - -.crash-illustration { - font-size: 30px; - margin-bottom: 12px; -} - -.crash-title { - font-size: 28px; - margin-bottom: 10px; -} - -.crash-copy { - color: var(--color-text-secondary); - line-height: 1.5; - margin-bottom: 8px; -} - -.crash-quote { - color: var(--color-text-info); - font-weight: 600; - margin-bottom: 16px; -} - -.crash-refresh { - border: none; - border-radius: var(--border-radius-md); - padding: 10px 16px; - font-size: 14px; - font-weight: 700; - color: var(--color-background-primary); - background: var(--color-text-primary); - cursor: pointer; -} - -.crash-refresh:hover { - background: var(--color-text-secondary); -} - -.crash-details { - margin-top: 14px; - color: var(--color-text-secondary); -} - -.crash-details pre { - margin-top: 8px; - white-space: pre-wrap; - overflow-wrap: anywhere; - font-size: 12px; - background: var(--color-background-secondary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-sm); - padding: 10px; -} - -/* Task Addition Model */ - - -#new-task-modal, -#new-subject-modal { - - position: fixed; - inset: 0; - z-index: 9998; - display: none; - align-items: center; - justify-content: center; - background-color: rgba(0, 0, 0, 0.55) !important; -} - - -#new-task-modal .modal-card, -#new-subject-modal .modal-card { - width: 100%; - max-width: 360px; - background-color: #0f172a; - border-radius: 14px; - padding: 20px 20px 16px; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6) !important; - color: #e5e7eb; - box-sizing: border-box; - border: 1px solid rgba(148, 163, 184, 0.35) !important; -} - - -#new-task-modal .modal-card h3, -#new-subject-modal .modal-card h3 { - margin: 0 0 12px; - font-size: 18px; - font-weight: 600; - letter-spacing: 0.01em; - color: #f9fafb; -} - - -#new-task-modal label, -#new-subject-modal label { - display: block; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.06em; - color: #9ca3af; - /* muted */ - margin-bottom: 4px; -} - - -#new-task-modal input, -#new-task-modal select, -#new-subject-modal input, -#new-subject-modal select { - width: 100%; - box-sizing: border-box; - font-size: 13px; - padding: 7px 8px; - margin-bottom: 10px; - border-radius: 6px; - border: 1px solid #4b5563; - background-color: #111827 !important; - color: #e5e7eb; - transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; - color-scheme: dark; -} - - -#new-task-modal input::placeholder, -#new-subject-modal input::placeholder { - color: #6b7280; -} - - -#new-task-modal input:focus, -#new-task-modal select:focus, -#new-subject-modal input:focus, -#new-subject-modal select:focus { - outline: none; - border-color: #4f46e5; - box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.35); - background: #020617; -} - - -#new-task-modal .modal-card>div:last-child, -#new-subject-modal .modal-card>div:last-child { - display: flex; - justify-content: flex-end; - gap: 8px; - margin-top: 6px; -} - - -#new-task-modal .btn, -#new-subject-modal .btn { - font-size: 12px; - padding: 6px 10px; - border-radius: 999px; -} - -#new-task-modal .btn:not(.btn-primary), -#new-subject-modal .btn:not(.btn-primary) { - background: rgba(15, 23, 42, 0.9); - color: #e5e7eb; - border: 1px solid #4b5563; -} - -#new-task-modal .btn:not(.btn-primary):hover, -#new-subject-modal .btn:not(.btn-primary):hover { - background: #020617; -} - - -#new-task-modal.showing .modal-card { - animation: new-task-modal-in 0.16s ease-out; -} - -@keyframes new-task-modal-in { - from { - opacity: 0; - transform: translateY(6px) scale(0.97); - } - - to { - opacity: 1; - transform: translateY(0) scale(1); - } -} - - -@media (max-width: 480px) { - - #new-task-modal .modal-card, - #new-subject-modal .modal-card { - max-width: 90vw; - padding: 16px 14px 12px; - } -} - -#new-subject-modal .subject-color-swatches { - display: flex; - flex-wrap: wrap; - gap: 8px; - margin-bottom: 4px; -} - -#new-subject-modal .subject-color-swatch { - width: 28px; - height: 28px; - border-radius: 50%; - border: 2px solid rgba(255, 255, 255, 0.25); - cursor: pointer; - padding: 0; - flex-shrink: 0; - box-sizing: border-box; - transition: transform 0.12s ease, box-shadow 0.12s ease; -} - -#new-subject-modal .subject-color-swatch:hover { - transform: scale(1.06); -} - -#new-subject-modal .subject-color-swatch--selected { - box-shadow: 0 0 0 2px #0f172a, 0 0 0 4px #a5b4fc; -} - -/* css/index.css */ -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -:root { - --color-background-primary: #ffffff; - --color-background-secondary: #f7f7f5; - --color-background-tertiary: #efefec; - --color-text-primary: #1a1a18; - --color-text-secondary: #6b6b66; - --color-text-tertiary: #9c9a92; - --color-border-tertiary: rgba(0, 0, 0, 0.08); - /* softer */ - --color-border-secondary: rgba(0, 0, 0, 0.15); - /* softer */ - --color-border-primary: rgba(0, 0, 0, 0.30); - - --color-danger-rgb: 163, 45, 45; - --color-info-rgb: 24, 95, 165; - --color-success-rgb: 22, 101, 52; - - --color-text-danger: #a32d2d; - --color-background-danger: #fcebeb; - --color-border-danger: rgba(var(--color-danger-rgb), 0.35); - - --color-text-info: #185fa5; - --color-background-info: #e6f1fb; - --color-border-info: rgba(var(--color-info-rgb), 0.35); - - --color-text-success: #166534; - --color-background-success: #eaf3de; - --color-border-success: rgba(var(--color-success-rgb), 0.35); - - --color-text-warning: #854f0b; - --color-background-warning: #faeeda; - - --color-text-purple: #3c3489; - --color-background-purple: #eeedfe; - - --border-radius-sm: 6px; - --border-radius-md: 10px; - --border-radius-lg: 16px; - --font-sans: 'Inter', system-ui, -apple-system, sans-serif; - - --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.04); - --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.06); - --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.08); -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background-primary: #181816; - --color-background-secondary: #20201e; - --color-background-tertiary: #272725; - --color-text-primary: #efede5; - --color-text-secondary: #a3a198; - --color-text-tertiary: #73726c; - --color-border-tertiary: rgba(255, 255, 255, 0.06); - --color-border-secondary: rgba(255, 255, 255, 0.12); - --color-border-primary: rgba(255, 255, 255, 0.22); - --color-text-danger: #fc9c9c; - --color-background-danger: rgba(252, 156, 156, 0.15); - --color-border-danger: rgba(252, 156, 156, 0.3); - - --color-text-info: #9ecdfc; - --color-background-info: rgba(158, 205, 252, 0.15); - --color-border-info: rgba(158, 205, 252, 0.3); - - --color-text-success: #a0d45a; - --color-background-success: rgba(160, 212, 90, 0.15); - --color-border-success: rgba(160, 212, 90, 0.3); - - --color-text-warning: #fab35e; - --color-background-warning: rgba(250, 179, 94, 0.15); - - --color-text-purple: #b9b5f5; - --color-background-purple: rgba(185, 181, 245, 0.15); - } -} - -:root[data-theme="dark"] { - --color-background-primary: #181816; - --color-background-secondary: #20201e; - --color-background-tertiary: #272725; - --color-text-primary: #efede5; - --color-text-secondary: #a3a198; - --color-text-tertiary: #73726c; - --color-border-tertiary: rgba(255, 255, 255, 0.06); - --color-border-secondary: rgba(255, 255, 255, 0.12); - --color-border-primary: rgba(255, 255, 255, 0.22); - --color-text-danger: #fc9c9c; - --color-background-danger: rgba(252, 156, 156, 0.15); - --color-border-danger: rgba(252, 156, 156, 0.3); - - --color-text-info: #9ecdfc; - --color-background-info: rgba(158, 205, 252, 0.15); - --color-border-info: rgba(158, 205, 252, 0.3); - - --color-text-success: #a0d45a; - --color-background-success: rgba(160, 212, 90, 0.15); - --color-border-success: rgba(160, 212, 90, 0.3); - - --color-text-warning: #fab35e; - --color-background-warning: rgba(250, 179, 94, 0.15); - - --color-text-purple: #b9b5f5; - --color-background-purple: rgba(185, 181, 245, 0.15); -} - -:root[data-theme="light"] { - --color-background-primary: #ffffff; - --color-background-secondary: #f7f7f5; - --color-background-tertiary: #efefec; - --color-text-primary: #1a1a18; - --color-text-secondary: #6b6b66; - --color-text-tertiary: #9c9a92; - --color-border-tertiary: rgba(0, 0, 0, 0.08); - --color-border-secondary: rgba(0, 0, 0, 0.15); - --color-border-primary: rgba(0, 0, 0, 0.30); - - --color-text-danger: #a32d2d; - --color-background-danger: #fcebeb; - --color-border-danger: rgba(163, 45, 45, 0.35); - - --color-text-info: #185fa5; - --color-background-info: #e6f1fb; - --color-border-info: rgba(24, 95, 165, 0.35); - - --color-text-success: #166534; - --color-background-success: #eaf3de; - --color-border-success: rgba(22, 101, 52, 0.35); - - --color-text-warning: #854f0b; - --color-background-warning: #faeeda; - - --color-text-purple: #3c3489; - --color-background-purple: #eeedfe; -} - -body { - font-family: var(--font-sans); - background: var(--color-background-tertiary); - color: var(--color-text-primary); - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 32px 16px; - overflow-x: hidden; -} - -/* Animations */ -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(5px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes popIn { - 0% { - transform: scale(0.95); - opacity: 0; - } - - 100% { - transform: scale(1); - opacity: 1; - } -} - -.wrapper { - width: 100%; - max-width: 1200px; - animation: fadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1); -} - -.label { - font-size: 12px; - font-weight: 600; - color: var(--color-text-tertiary); - letter-spacing: .08em; - margin-bottom: 12px; - text-transform: uppercase; -} - -.app { - display: grid; - grid-template-columns: 240px 1fr 340px; - height: 720px; - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - overflow: hidden; - background: var(--color-background-primary); - box-shadow: var(--shadow-lg); - backdrop-filter: blur(20px); -} - -/* Sidebar */ -.sidebar { - background: var(--color-background-secondary); - border-right: 1px solid var(--color-border-tertiary); - padding: 20px 16px; - display: flex; - flex-direction: column; - gap: 4px; -} - -.sidebar-header { - font-size: 11px; - font-weight: 700; - color: var(--color-text-tertiary); - padding: 8px 12px; - margin-bottom: 2px; - letter-spacing: .06em; - text-transform: uppercase; -} - -.nav-item { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 12px; - border-radius: var(--border-radius-md); - cursor: pointer; - font-size: 14px; - font-weight: 500; - color: var(--color-text-secondary); - transition: all 0.2s ease; - position: relative; -} - -.nav-item:hover { - background: var(--color-background-primary); - color: var(--color-text-primary); - transform: translateX(2px); -} - -.nav-item.active { - background: var(--color-background-primary); - color: var(--color-text-primary); - box-shadow: var(--shadow-sm); -} - -.nav-item.active::before { - content: ''; - position: absolute; - left: 0; - top: 15%; - height: 70%; - width: 3px; - background: var(--color-text-primary); - border-radius: 4px; -} - -.nav-dot { - width: 10px; - height: 10px; - border-radius: 50%; - flex-shrink: 0; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); -} - -.badge { - margin-left: auto; - font-size: 12px; - font-weight: 600; - background: var(--color-background-tertiary); - color: var(--color-text-secondary); - padding: 2px 8px; - border-radius: 12px; - transition: all 0.2s; -} - -.nav-item:hover .badge { - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); -} - -.sidebar-divider { - height: 1px; - background: var(--color-border-tertiary); - margin: 12px 0; -} - -.add-subject { - font-size: 13px; - font-weight: 500; - color: var(--color-text-tertiary); - padding: 8px 12px; - cursor: pointer; - transition: color 0.2s; - display: flex; - align-items: center; - gap: 8px; -} - -.add-subject:hover { - color: var(--color-text-primary); -} - -/* Main */ -.main { - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} - -.topbar { - display: flex; - align-items: center; - gap: 12px; - padding: 16px 24px; - border-bottom: 1px solid var(--color-border-tertiary); - flex-shrink: 0; - background: rgba(var(--color-background-primary), 0.8); - backdrop-filter: blur(10px); - z-index: 10; -} - -.topbar-title { - font-size: 18px; - font-weight: 600; - color: var(--color-text-primary); - flex: 1; -} - -.btn { - font-family: inherit; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border: 1px solid var(--color-border-secondary); - border-radius: var(--border-radius-sm); - background: var(--color-background-primary); - color: var(--color-text-primary); - cursor: pointer; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: var(--shadow-sm); - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; -} - -.btn:hover { - background: var(--color-background-secondary); - transform: translateY(-1px); - box-shadow: var(--shadow-md); -} - -.btn:active { - transform: translateY(0); - box-shadow: 0 0 0; -} - -.btn-primary { - background: var(--color-text-primary); - color: var(--color-background-primary); - border-color: transparent; -} - -.btn-primary:hover { - background: var(--color-text-secondary); -} - -/* Calendar */ -.cal-section { - padding: 16px 24px; - border-bottom: 1px solid var(--color-border-tertiary); - flex-shrink: 0; -} - -.cal-header { - display: flex; - align-items: center; - margin-bottom: 16px; -} - -.cal-title { - font-size: 15px; - font-weight: 600; - flex: 1; - color: var(--color-text-primary); -} - -.cal-nav { - font-size: 18px; - color: var(--color-text-secondary); - cursor: pointer; - padding: 4px 8px; - border-radius: 4px; - transition: background 0.2s; -} - -.cal-nav:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); -} - -.cal-grid { - display: grid; - grid-template-columns: repeat(7, 1fr); - gap: 4px; - text-align: center; -} - -.cal-day-label { - font-size: 11px; - color: var(--color-text-tertiary); - padding-bottom: 8px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.cal-day { - font-size: 13px; - font-weight: 500; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--border-radius-md); - cursor: pointer; - color: var(--color-text-secondary); - position: relative; - transition: all 0.2s; -} - -.cal-day:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); - transform: scale(1.1); - z-index: 1; -} - -.cal-day.today { - background: var(--color-text-primary); - color: var(--color-background-primary); - box-shadow: var(--shadow-sm); -} - -.cal-day-indicators { - position: absolute; - bottom: 3px; - left: 0; - right: 0; - display: flex; - justify-content: center; - gap: 3px; -} - -.cal-day-indicator { - width: 5px; - height: 5px; - border-radius: 50%; -} - -.cal-day.muted { - color: var(--color-border-secondary); -} - -.cal-legend { - display: flex; - gap: 16px; - margin-top: 16px; - font-size: 11px; - font-weight: 500; - color: var(--color-text-tertiary); - justify-content: flex-end; -} - -.cal-legend span { - display: flex; - align-items: center; - gap: 6px; -} - -.legend-dot { - width: 8px; - height: 8px; - border-radius: 50%; - display: inline-block; -} - -/* Tasks */ -.tasks-section { - flex: 1; - overflow-y: auto; - padding: 0 24px 24px; - scroll-behavior: smooth; -} - -.tasks-section::-webkit-scrollbar { - width: 6px; -} - -.tasks-section::-webkit-scrollbar-thumb { - background: var(--color-border-secondary); - border-radius: 10px; -} - -.tasks-actions-bar { - margin-top: 18px; - display: flex; - gap: 10px; - flex-wrap: wrap; -} - -.task-action-btn { - border: 1px solid var(--color-border-success); - background: var(--color-background-success); - color: var(--color-text-success); - border-radius: var(--border-radius-sm); - padding: 7px 12px; - font-size: 12px; - font-weight: 700; - cursor: pointer; - transition: all 0.2s ease; -} - -.task-action-btn:hover { - filter: brightness(0.98); - transform: translateY(-1px); -} - -.task-action-btn:disabled { - opacity: 0.55; - cursor: not-allowed; - transform: none; - filter: none; -} - -.task-action-btn-secondary { - border-color: var(--color-border-info); - background: var(--color-background-info); - color: var(--color-text-info); -} - -.tasks-empty-state { - margin-top: 14px; - padding: 14px; - border-radius: var(--border-radius-md); - border: 1px dashed var(--color-border-secondary); - color: var(--color-text-secondary); - font-size: 13px; - background: var(--color-background-secondary); -} - -.tasks-group { - margin-top: 24px; - animation: fadeIn 0.4s ease forwards; -} - -.tasks-group-header { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 12px; -} - -.tasks-group-header span { - font-size: 12px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.task-item { - display: flex; - align-items: flex-start; - gap: 14px; - padding: 12px 14px; - border-radius: var(--border-radius-md); - cursor: pointer; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - border: 1px solid transparent; - background: var(--color-background-primary); - margin-bottom: 6px; - border: 1px solid var(--color-border-tertiary); -} - -.task-item:hover { - background: var(--color-background-secondary); - transform: translateX(4px); - border-color: var(--color-border-secondary); - box-shadow: var(--shadow-sm); -} - -.task-item.urgent { - border-color: var(--color-border-danger); - background: linear-gradient(to right, var(--color-background-danger) 0%, var(--color-background-primary) 100%); -} - -.task-check { - width: 18px; - height: 18px; - border-radius: 5px; - border: 2px solid var(--color-border-secondary); - flex-shrink: 0; - margin-top: 2px; - transition: all 0.2s; - position: relative; - cursor: pointer; -} - -.task-check:hover { - border-color: var(--color-text-primary); -} - -.task-check.done { - background: var(--color-text-success); - border-color: var(--color-text-success); -} - -.task-check.done::after { - content: ''; - position: absolute; - left: 4px; - top: 1px; - width: 4px; - height: 8px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); -} - -.task-info { - flex: 1; - min-width: 0; -} - -.task-name { - font-size: 14px; - font-weight: 500; - color: var(--color-text-primary); - line-height: 1.4; - transition: color 0.2s; - margin-bottom: 6px; -} - -.task-item.done .task-name { - text-decoration: line-through; - color: var(--color-text-tertiary); -} - -.task-meta { - font-size: 12px; - color: var(--color-text-tertiary); - margin-top: 6px; - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; - font-weight: 500; -} - -.task-pill { - font-size: 11px; - padding: 2px 8px; - border-radius: 12px; - font-weight: 600; - display: inline-flex; - align-items: center; - gap: 4px; - border: 1px solid transparent; -} - -.pill-red { - background: var(--color-background-danger); - color: var(--color-text-danger); - border-color: var(--color-border-danger); -} - -.pill-blue { - background: var(--color-background-info); - color: var(--color-text-info); - border-color: var(--color-border-info); -} - -.pill-green { - background: var(--color-background-success); - color: var(--color-text-success); - border-color: var(--color-border-success); -} - -.pill-amber { - background: var(--color-background-warning); - color: var(--color-text-warning); - border-color: rgba(133, 79, 11, 0.2); -} - -.pill-purple { - background: var(--color-background-purple); - color: var(--color-text-purple); - border-color: rgba(60, 52, 137, 0.2); -} - -.conflict-card { - font-size: 13px; - font-weight: 500; - color: var(--color-text-warning); - background: var(--color-background-warning); - border: 1px solid rgba(133, 79, 11, 0.3); - border-radius: var(--border-radius-md); - padding: 12px 16px; - line-height: 1.5; - display: flex; - gap: 12px; - align-items: flex-start; - box-shadow: var(--shadow-sm); -} - -.conflict-icon { - font-size: 18px; - line-height: 1; -} - -.task-actions { - display: flex; - gap: 8px; - opacity: 0; - transition: opacity 0.2s; -} - -.task-item:hover .task-actions { - opacity: 1; -} - -.task-btn { - padding: 4px 8px; - border-radius: 4px; - font-size: 11px; - font-weight: 600; - cursor: pointer; - border: 1px solid var(--color-border-secondary); - background: var(--color-background-primary); - color: var(--color-text-secondary); - transition: all 0.2s; -} - -.task-btn:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); - border-color: var(--color-border-primary); -} - -.task-btn-danger:hover { - background: var(--color-background-danger); - color: var(--color-text-danger); - border-color: var(--color-text-danger); -} - -.task-btn-info:hover { - background: var(--color-background-info); - color: var(--color-text-info); - border-color: var(--color-text-info); -} - -/* Right Panel */ -.panel { - border-left: 1px solid var(--color-border-tertiary); - display: flex; - flex-direction: column; - background: var(--color-background-secondary); - overflow: hidden; -} - -.panel-header { - padding: 20px 24px 16px; - border-bottom: 1px solid var(--color-border-tertiary); - background: var(--color-background-primary); - flex-shrink: 0; -} - -.panel-title { - font-size: 16px; - font-weight: 600; - color: var(--color-text-primary); - display: flex; - align-items: center; - gap: 8px; -} - -.panel-title svg { - opacity: 0.8; -} - -.panel-subtitle { - font-size: 12px; - font-weight: 500; - color: var(--color-text-tertiary); - margin-top: 4px; -} - -.paste-zone { - margin: 20px 20px 12px; - border: 2px dashed var(--color-border-secondary); - border-radius: var(--border-radius-lg); - padding: 24px 20px; - text-align: center; - cursor: text; - transition: all 0.2s; - background: var(--color-background-primary); - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; - min-height: 120px; - overflow: hidden; -} - -.paste-zone:hover { - border-color: var(--color-text-info); - background: var(--color-background-info); -} - -.paste-zone:focus-within { - border-color: var(--color-text-primary); - border-style: solid; - box-shadow: inset 0 0 0 1px var(--color-text-primary); - outline: none; -} - -.paste-icon { - font-size: 24px; - margin-bottom: 8px; - color: var(--color-text-secondary); - transition: color 0.2s; -} - -.paste-zone:hover .paste-icon { - color: var(--color-text-info); -} - -.paste-input { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - width: 100%; - height: 100%; - opacity: 0; - resize: none; - border: none; - padding: 20px; - font-family: inherit; - font-size: 13px; - z-index: 2; -} - -.summary-box { - margin: 0 20px 16px; - padding: 14px; - background: linear-gradient(135deg, #eef2ff, #f8fafc); - border-radius: 12px; - font-size: 14px; - line-height: 1.6; - border: 1px solid #e5e7eb; - flex-shrink: 0; - overflow-y: auto; - max-height: 200px; -} - -.paste-input:focus, -.paste-input:not(:placeholder-shown) { - opacity: 1; - z-index: 10; - background: var(--color-background-primary); - color: var(--color-text-primary); - outline: none; -} - -.paste-label { - font-size: 14px; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 4px; - pointer-events: none; -} - -.paste-hint { - font-size: 12px; - color: var(--color-text-tertiary); - line-height: 1.5; - pointer-events: none; -} - -.paste-actions { - padding: 0 20px 16px; - display: flex; - gap: 12px; -} - -.extract-preview { - overflow-y: auto; - padding: 0 20px 12px; - scroll-behavior: smooth; - max-height: 280px; -} - -.extract-preview::-webkit-scrollbar { - width: 6px; -} - -.extract-preview::-webkit-scrollbar-thumb { - background: var(--color-border-secondary); - border-radius: 10px; -} - -.extract-title { - font-size: 11px; - font-weight: 700; - color: var(--color-text-tertiary); - margin-bottom: 12px; - letter-spacing: .06em; - text-transform: uppercase; - display: flex; - align-items: center; - justify-content: space-between; -} - -.extract-card { - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-md); - padding: 14px 16px; - margin-bottom: 12px; - box-shadow: var(--shadow-sm); - animation: popIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; - transform-origin: center; - position: relative; - overflow: hidden; -} - -.extract-subject { - font-size: 11px; - font-weight: 700; - margin-bottom: 6px; - letter-spacing: .04em; - text-transform: uppercase; -} - -.extract-task-name { - font-size: 14px; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 8px; - line-height: 1.4; -} - -.extract-row { - display: flex; - align-items: center; - gap: 8px; - font-size: 12px; - font-weight: 500; - color: var(--color-text-secondary); - margin-top: 4px; -} - -.extract-icon { - font-size: 14px; -} - -.conf-bar { - height: 4px; - border-radius: 2px; - margin-top: 12px; - background: var(--color-border-tertiary); - overflow: hidden; -} - -.conf-fill { - height: 100%; - border-radius: 2px; - transition: width 1s cubic-bezier(0.16, 1, 0.3, 1); -} - -.conf-label { - font-size: 11px; - font-weight: 600; - color: var(--color-text-tertiary); - margin-top: 6px; - display: flex; - justify-content: space-between; -} - -.conf-edit { - color: var(--color-text-info); - cursor: pointer; - transition: color 0.2s; -} - -.conf-edit:hover { - color: var(--color-text-primary); -} - -.add-btn { - margin: 0 20px 20px; - padding: 12px; - border: none; - border-radius: var(--border-radius-md); - background: var(--color-text-primary); - color: var(--color-background-primary); - font-size: 14px; - font-weight: 600; - cursor: pointer; - text-align: center; - flex-shrink: 0; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} - -.add-btn:hover:not(:disabled) { - background: var(--color-text-secondary); - transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); -} - -.add-btn:active:not(:disabled) { - transform: translateY(0); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); -} - -.add-btn:disabled { - background: var(--color-border-secondary); - cursor: not-allowed; - transform: none; - box-shadow: none; - color: var(--color-text-tertiary); -} - -/* Loader */ -.loader-spinner { - display: inline-block; - width: 16px; - height: 16px; - border: 2px solid rgba(0, 0, 0, 0.1); - border-radius: 50%; - border-top-color: var(--color-text-primary); - animation: spin 0.8s linear infinite; -} - -@media (prefers-color-scheme: dark) { - .loader-spinner { - border-color: rgba(255, 255, 255, 0.1); - border-top-color: #fff; - } -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -/* Utility classes */ -.hidden { - display: none !important; -} - - - -/* Header */ -.site-header { - width: 100%; - max-width: 1200px; - margin: 0 auto 16px auto; - padding: 16px 24px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-md); - - display: flex; - align-items: center; - justify-content: space-between; -} - -.header-left { - display: flex; - align-items: center; - gap: 12px; -} - -.logo { - width: 40px; - height: 40px; - border-radius: 2px; -} - -.site-title { - font-size: 20px; - font-weight: 700; - color: var(--color-text-primary); -} - -.header-nav { - display: flex; - gap: 24px; -} - -.header-nav a { - text-decoration: none; - color: var(--color-text-secondary); - font-weight: 500; - transition: color 0.2s; -} - -.header-nav a:hover { - color: var(--color-text-primary); -} - -.profile-btn { - padding: 8px 16px; - border: none; - border-radius: var(--border-radius-md); - background: var(--color-text-primary); - color: var(--color-background-primary); - cursor: pointer; - font-weight: 600; -} - -/* Footer */ -.site-footer { - width: 100%; - max-width: 1200px; - margin: 16px auto 0 auto; - padding: 16px 24px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-md); - - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-text-secondary); - font-size: 14px; -} - -.footer-links { - display: flex; - gap: 16px; -} - -.footer-links a { - text-decoration: none; - color: var(--color-text-secondary); -} - -.footer-links a:hover { - color: var(--color-text-primary); -} - -/* Settings Toggle Switch */ -.toggle-switch { - position: relative; - display: inline-block; - width: 44px; - height: 24px; -} - -.toggle-switch input { - opacity: 0; - width: 0; - height: 0; -} - -.toggle-slider { - position: absolute; - cursor: pointer; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: var(--color-border-primary); - transition: .3s; - border-radius: 24px; -} - -.toggle-slider:before { - position: absolute; - content: ""; - height: 18px; - width: 18px; - left: 3px; - bottom: 3px; - background-color: var(--color-background-primary); - transition: .3s; - border-radius: 50%; -} - -.toggle-switch input:checked+.toggle-slider { - background-color: var(--color-text-success); -} - -.toggle-switch input:checked+.toggle-slider:before { - transform: translateX(20px); -} - -/* Compact View utility classes */ -body.compact-view { - padding: 16px 8px; -} - -body.compact-view .app { - height: 600px; -} - -body.compact-view .task-item { - padding: 8px 10px; - margin-bottom: 4px; -} - -body.compact-view .nav-item { - padding: 8px 10px; - font-size: 13px; -} - -body.compact-view .topbar { - padding: 12px 16px; -} - -body.compact-view .cal-section, -body.compact-view .tasks-section { - padding: 12px 16px; -} - -/* css/index.css */ -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -:root { - --color-background-primary: #ffffff; - --color-background-secondary: #f7f7f5; - --color-background-tertiary: #efefec; - --color-text-primary: #1a1a18; - --color-text-secondary: #6b6b66; - --color-text-tertiary: #9c9a92; - --color-border-tertiary: rgba(0, 0, 0, 0.08); - /* softer */ - --color-border-secondary: rgba(0, 0, 0, 0.15); - /* softer */ - --color-border-primary: rgba(0, 0, 0, 0.30); - - --color-danger-rgb: 163, 45, 45; - --color-info-rgb: 24, 95, 165; - --color-success-rgb: 22, 101, 52; - - --color-text-danger: #a32d2d; - --color-background-danger: #fcebeb; - --color-border-danger: rgba(var(--color-danger-rgb), 0.35); - - --color-text-info: #185fa5; - --color-background-info: #e6f1fb; - --color-border-info: rgba(var(--color-info-rgb), 0.35); - - --color-text-success: #166534; - --color-background-success: #eaf3de; - --color-border-success: rgba(var(--color-success-rgb), 0.35); - - --color-text-warning: #854f0b; - --color-background-warning: #faeeda; - - --color-text-purple: #3c3489; - --color-background-purple: #eeedfe; - - --border-radius-sm: 6px; - --border-radius-md: 10px; - --border-radius-lg: 16px; - --font-sans: 'Inter', system-ui, -apple-system, sans-serif; - - --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.04); - --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.06); - --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.08); -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background-primary: #181816; - --color-background-secondary: #20201e; - --color-background-tertiary: #272725; - --color-text-primary: #efede5; - --color-text-secondary: #a3a198; - --color-text-tertiary: #73726c; - --color-border-tertiary: rgba(255, 255, 255, 0.06); - --color-border-secondary: rgba(255, 255, 255, 0.12); - --color-border-primary: rgba(255, 255, 255, 0.22); - --color-text-danger: #fc9c9c; - --color-background-danger: rgba(252, 156, 156, 0.15); - --color-border-danger: rgba(252, 156, 156, 0.3); - - --color-text-info: #9ecdfc; - --color-background-info: rgba(158, 205, 252, 0.15); - --color-border-info: rgba(158, 205, 252, 0.3); - - --color-text-success: #a0d45a; - --color-background-success: rgba(160, 212, 90, 0.15); - --color-border-success: rgba(160, 212, 90, 0.3); - - --color-text-warning: #fab35e; - --color-background-warning: rgba(250, 179, 94, 0.15); - - --color-text-purple: #b9b5f5; - --color-background-purple: rgba(185, 181, 245, 0.15); - } -} - -body { - font-family: var(--font-sans); - background: var(--color-background-tertiary); - color: var(--color-text-primary); - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 32px 16px; - overflow-x: hidden; -} - -/* Animations */ -@keyframes fadeIn { - from { - opacity: 0; - transform: translateY(5px); - } - - to { - opacity: 1; - transform: translateY(0); - } -} - -@keyframes popIn { - 0% { - transform: scale(0.95); - opacity: 0; - } - - 100% { - transform: scale(1); - opacity: 1; - } -} - -.wrapper { - width: 100%; - max-width: 1200px; - animation: fadeIn 0.6s cubic-bezier(0.16, 1, 0.3, 1); -} - -.label { - font-size: 12px; - font-weight: 600; - color: var(--color-text-tertiary); - letter-spacing: .08em; - margin-bottom: 12px; - text-transform: uppercase; -} - -.app { - display: grid; - grid-template-columns: 240px 1fr var(--panel-width, 340px); - height: 720px; - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - overflow: hidden; - background: var(--color-background-primary); - box-shadow: var(--shadow-lg); - backdrop-filter: blur(20px); -} - -/* Sidebar */ -.sidebar { - background: var(--color-background-secondary); - border-right: 1px solid var(--color-border-tertiary); - padding: 20px 16px; - display: flex; - flex-direction: column; - gap: 4px; -} - -.sidebar-header { - font-size: 11px; - font-weight: 700; - color: var(--color-text-tertiary); - padding: 8px 12px; - margin-bottom: 2px; - letter-spacing: .06em; - text-transform: uppercase; -} - -.nav-item { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 12px; - border-radius: var(--border-radius-md); - cursor: pointer; - font-size: 14px; - font-weight: 500; - color: var(--color-text-secondary); - transition: all 0.2s ease; - position: relative; -} - -.nav-item:hover { - background: var(--color-background-primary); - color: var(--color-text-primary); - transform: translateX(2px); -} - -.nav-item.active { - background: var(--color-background-primary); - color: var(--color-text-primary); - box-shadow: var(--shadow-sm); -} - -.nav-item.active::before { - content: ''; - position: absolute; - left: 0; - top: 15%; - height: 70%; - width: 3px; - background: var(--color-text-primary); - border-radius: 4px; -} - -.nav-dot { - width: 10px; - height: 10px; - border-radius: 50%; - flex-shrink: 0; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); -} - -.badge { - margin-left: auto; - font-size: 12px; - font-weight: 600; - background: var(--color-background-tertiary); - color: var(--color-text-secondary); - padding: 2px 8px; - border-radius: 12px; - transition: all 0.2s; -} - -.nav-item:hover .badge { - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); -} - -.sidebar-divider { - height: 1px; - background: var(--color-border-tertiary); - margin: 12px 0; -} - -.add-subject { - font-size: 13px; - font-weight: 500; - color: var(--color-text-tertiary); - padding: 8px 12px; - cursor: pointer; - transition: color 0.2s; - display: flex; - align-items: center; - gap: 8px; -} - -.add-subject:hover { - color: var(--color-text-primary); -} - -/* Main */ -.main { - display: flex; - flex-direction: column; - overflow: hidden; - position: relative; -} - -.topbar { - display: flex; - align-items: center; - gap: 12px; - padding: 16px 24px; - border-bottom: 1px solid var(--color-border-tertiary); - flex-shrink: 0; - background: rgba(var(--color-background-primary), 0.8); - backdrop-filter: blur(10px); - z-index: 10; -} - -.topbar-title { - font-size: 18px; - font-weight: 600; - color: var(--color-text-primary); - flex: 1; -} - -.btn { - font-family: inherit; - font-size: 13px; - font-weight: 600; - padding: 8px 16px; - border: 1px solid var(--color-border-secondary); - border-radius: var(--border-radius-sm); - background: var(--color-background-primary); - color: var(--color-text-primary); - cursor: pointer; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - box-shadow: var(--shadow-sm); - display: inline-flex; - align-items: center; - justify-content: center; - gap: 6px; -} - -.btn:hover { - background: var(--color-background-secondary); - transform: translateY(-1px); - box-shadow: var(--shadow-md); -} - -.btn:active { - transform: translateY(0); - box-shadow: 0 0 0; -} - -.btn-primary { - background: var(--color-text-primary); - color: var(--color-background-primary); - border-color: transparent; -} - -.btn-primary:hover { - background: var(--color-text-secondary); -} - -/* Calendar */ -.cal-section { - padding: 16px 24px; - border-bottom: 1px solid var(--color-border-tertiary); - flex-shrink: 0; -} - -.cal-header { - display: flex; - align-items: center; - margin-bottom: 16px; -} - -.cal-title { - font-size: 15px; - font-weight: 600; - flex: 1; - color: var(--color-text-primary); -} - -.cal-nav { - font-size: 18px; - color: var(--color-text-secondary); - cursor: pointer; - padding: 4px 8px; - border-radius: 4px; - transition: background 0.2s; -} - -.cal-nav:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); -} - -.cal-grid { - display: grid; - grid-template-columns: repeat(7, 1fr); - gap: 4px; - text-align: center; -} - -.cal-day-label { - font-size: 11px; - color: var(--color-text-tertiary); - padding-bottom: 8px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.cal-day { - font-size: 13px; - font-weight: 500; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - border-radius: var(--border-radius-md); - cursor: pointer; - color: var(--color-text-secondary); - position: relative; - transition: all 0.2s; -} - -.cal-day:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); - transform: scale(1.1); - z-index: 1; -} - -.cal-day.today { - background: var(--color-text-primary); - color: var(--color-background-primary); - box-shadow: var(--shadow-sm); -} - -.cal-day-indicators { - position: absolute; - bottom: 3px; - left: 0; - right: 0; - display: flex; - justify-content: center; - gap: 3px; -} - -.cal-day-indicator { - width: 5px; - height: 5px; - border-radius: 50%; -} - -.cal-day.muted { - color: var(--color-border-secondary); -} - -.cal-legend { - display: flex; - gap: 16px; - margin-top: 16px; - font-size: 11px; - font-weight: 500; - color: var(--color-text-tertiary); - justify-content: flex-end; -} - -.cal-legend span { - display: flex; - align-items: center; - gap: 6px; -} - -.legend-dot { - width: 8px; - height: 8px; - border-radius: 50%; - display: inline-block; -} - -/* Tasks */ -.tasks-section { - flex: 1; - overflow-y: auto; - padding: 0 24px 24px; - scroll-behavior: smooth; -} - -.tasks-section::-webkit-scrollbar { - width: 6px; -} - -.tasks-section::-webkit-scrollbar-thumb { - background: var(--color-border-secondary); - border-radius: 10px; -} - -.tasks-actions-bar { - margin-top: 18px; - display: flex; - gap: 10px; - flex-wrap: wrap; -} - -.task-action-btn { - border: 1px solid var(--color-border-success); - background: var(--color-background-success); - color: var(--color-text-success); - border-radius: var(--border-radius-sm); - padding: 7px 12px; - font-size: 12px; - font-weight: 700; - cursor: pointer; - transition: all 0.2s ease; -} - -.task-action-btn:hover { - filter: brightness(0.98); - transform: translateY(-1px); -} - -.task-action-btn:disabled { - opacity: 0.55; - cursor: not-allowed; - transform: none; - filter: none; -} - -.task-action-btn-secondary { - border-color: var(--color-border-info); - background: var(--color-background-info); - color: var(--color-text-info); -} - -.tasks-empty-state { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - padding: 60px 24px; - margin-top: 24px; - background: var(--color-background-secondary); - border: 1px dashed var(--color-border-secondary); - border-radius: var(--border-radius-lg); - position: relative; - overflow: hidden; - animation: emptyStateFadeIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards; -} - -@keyframes emptyStateFadeIn { - from { opacity: 0; transform: translateY(10px); } - to { opacity: 1; transform: translateY(0); } -} - -.empty-state-icon { - font-size: 48px; - margin-bottom: 16px; - position: relative; - z-index: 1; - filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.05)); - animation: float 3s ease-in-out infinite; -} - -/* Soft gradient glow behind the icon */ -.empty-state-icon::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 80px; - height: 80px; - background: radial-gradient(circle, rgba(79, 70, 229, 0.15) 0%, transparent 70%); - z-index: -1; - border-radius: 50%; -} - -.empty-state-title { - font-size: 18px; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 8px; -} - -.empty-state-text { - font-size: 14px; - color: var(--color-text-secondary); - max-width: 300px; - line-height: 1.5; - margin-bottom: 24px; -} - -.empty-state-cta { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 10px 20px; - background: var(--color-text-primary); - color: var(--color-background-primary); - border-radius: 8px; - font-size: 14px; - font-weight: 600; - text-decoration: none; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - border: none; - cursor: pointer; - box-shadow: var(--shadow-sm); - position: relative; - overflow: hidden; -} - -.empty-state-cta:hover { - transform: translateY(-3px) scale(1.02); - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12); - filter: brightness(1.2); -} - -.empty-state-cta:active { - transform: translateY(-1px) scale(0.98); -} - -/* Subtle shine effect on hover */ -.empty-state-cta::after { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 50%; - height: 100%; - background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.2), transparent); - transition: left 0.6s ease; -} - -.empty-state-cta:hover::after { - left: 150%; -} - -@keyframes float { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-10px); } -} - -.tasks-group { - margin-top: 24px; - animation: fadeIn 0.4s ease forwards; -} - -.tasks-group-header { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 12px; -} - -.tasks-group-header span { - font-size: 12px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.task-item { - display: flex; - align-items: flex-start; - gap: 14px; - padding: 12px 14px; - border-radius: var(--border-radius-md); - cursor: pointer; - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); - border: 1px solid transparent; - background: var(--color-background-primary); - margin-bottom: 6px; - border: 1px solid var(--color-border-tertiary); -} - -.task-item:hover { - background: var(--color-background-secondary); - transform: translateX(4px); - border-color: var(--color-border-secondary); - box-shadow: var(--shadow-sm); -} - -.task-item.urgent { - border-color: var(--color-border-danger); - background: linear-gradient(to right, var(--color-background-danger) 0%, var(--color-background-primary) 100%); -} - -.task-check { - width: 18px; - height: 18px; - border-radius: 5px; - border: 2px solid var(--color-border-secondary); - flex-shrink: 0; - margin-top: 2px; - transition: all 0.2s; - position: relative; - cursor: pointer; -} - -.task-check:hover { - border-color: var(--color-text-primary); -} - -.task-check.done { - background: var(--color-text-success); - border-color: var(--color-text-success); -} - -.task-check.done::after { - content: ''; - position: absolute; - left: 4px; - top: 1px; - width: 4px; - height: 8px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); -} - -.task-info { - flex: 1; - min-width: 0; -} - -.task-name { - font-size: 14px; - font-weight: 500; - color: var(--color-text-primary); - line-height: 1.4; - transition: color 0.2s; - margin-bottom: 6px; -} - -.task-item.done .task-name { - text-decoration: line-through; - color: var(--color-text-tertiary); -} - -.task-meta { - font-size: 12px; - color: var(--color-text-tertiary); - margin-top: 6px; - display: flex; - gap: 8px; - flex-wrap: wrap; - align-items: center; - font-weight: 500; -} - -.task-pill { - font-size: 11px; - padding: 2px 8px; - border-radius: 12px; - font-weight: 600; - display: inline-flex; - align-items: center; - gap: 4px; - border: 1px solid transparent; -} - -.pill-red { - background: var(--color-background-danger); - color: var(--color-text-danger); - border-color: var(--color-border-danger); -} - -.pill-blue { - background: var(--color-background-info); - color: var(--color-text-info); - border-color: var(--color-border-info); -} - -.pill-green { - background: var(--color-background-success); - color: var(--color-text-success); - border-color: var(--color-border-success); -} - -.pill-amber { - background: var(--color-background-warning); - color: var(--color-text-warning); - border-color: rgba(133, 79, 11, 0.2); -} - -.pill-purple { - background: var(--color-background-purple); - color: var(--color-text-purple); - border-color: rgba(60, 52, 137, 0.2); -} - -.conflict-card { - font-size: 13px; - font-weight: 500; - color: var(--color-text-warning); - background: var(--color-background-warning); - border: 1px solid rgba(133, 79, 11, 0.3); - border-radius: var(--border-radius-md); - padding: 12px 16px; - line-height: 1.5; - display: flex; - gap: 12px; - align-items: flex-start; - box-shadow: var(--shadow-sm); -} - -.conflict-icon { - font-size: 18px; - line-height: 1; -} -.task-item:hover { background: var(--color-background-secondary); transform: translateX(4px); border-color: var(--color-border-secondary); box-shadow: var(--shadow-sm); } -.task-item.urgent, .task-item.high-priority { - border-color: var(--color-border-danger); - background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.08) 0%, var(--color-background-primary) 100%); -} -.task-item.overdue { - border-color: var(--color-border-danger); - background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.12) 0%, var(--color-background-primary) 100%); -} -.task-item.done { - background: linear-gradient(135deg, rgba(var(--color-success-rgb), 0.08) 0%, var(--color-background-primary) 100%); - border-color: var(--color-border-success); -} -.task-check { width: 18px; height: 18px; border-radius: 5px; border: 2px solid var(--color-border-secondary); flex-shrink: 0; margin-top: 2px; transition: all 0.2s; position: relative; cursor: pointer; } -.task-check:hover { border-color: var(--color-text-primary); } -.task-check.done { background: var(--color-text-success); border-color: var(--color-text-success); } -.task-check.done::after { content: ''; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg); } -.task-info { flex: 1; min-width: 0; } -.task-name { font-size: 14px; font-weight: 500; color: var(--color-text-primary); line-height: 1.4; transition: color 0.2s; margin-bottom: 6px; } -.task-item.done .task-name { text-decoration: line-through; color: var(--color-text-tertiary); } -.task-meta { font-size: 12px; color: var(--color-text-tertiary); margin-top: 6px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; font-weight: 500; } -.task-pill { font-size: 11px; padding: 2px 8px; border-radius: 12px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; border: 1px solid transparent; } -.pill-red { background: var(--color-background-danger); color: var(--color-text-danger); border-color: var(--color-border-danger); } -.pill-blue { background: var(--color-background-info); color: var(--color-text-info); border-color: var(--color-border-info); } -.pill-green{ background: var(--color-background-success); color: var(--color-text-success); border-color: var(--color-border-success); } -.pill-amber{ background: var(--color-background-warning); color: var(--color-text-warning); border-color: rgba(133, 79, 11, 0.2); } -.pill-purple{ background: var(--color-background-purple); color: var(--color-text-purple); border-color: rgba(60, 52, 137, 0.2); } - -.conflict-card { font-size: 13px; font-weight: 500; color: var(--color-text-warning); background: var(--color-background-warning); border: 1px solid rgba(133, 79, 11, 0.3); border-radius: var(--border-radius-md); padding: 12px 16px; line-height: 1.5; display: flex; gap: 12px; align-items: flex-start; box-shadow: var(--shadow-sm); } -.conflict-icon { font-size: 18px; line-height: 1; } - -.task-actions { - display: flex; - gap: 8px; - opacity: 0; - transition: opacity 0.2s; -} - -.task-item:hover .task-actions { - opacity: 1; -} - -.task-btn { - padding: 4px 8px; - border-radius: 4px; - font-size: 11px; - font-weight: 600; - cursor: pointer; - border: 1px solid var(--color-border-secondary); - background: var(--color-background-primary); - color: var(--color-text-secondary); - transition: all 0.2s; -} - -.task-btn:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); - border-color: var(--color-border-primary); -} - -.task-btn-danger:hover { - background: var(--color-background-danger); - color: var(--color-text-danger); - border-color: var(--color-text-danger); -} - -.task-btn-info:hover { - background: var(--color-background-info); - color: var(--color-text-info); - border-color: var(--color-text-info); -} - -/* Right Panel */ -.panel { - border-left: 1px solid var(--color-border-tertiary); - display: flex; - flex-direction: column; - background: var(--color-background-secondary); - overflow: hidden; -} - -.panel.panel-collapsed { - overflow: hidden; - width: 48px; - min-width: 48px; -} -.summary-box { - margin-top: 16px; - padding: 14px; - background: var(--color-background-secondary); - color: var(--color-text-primary); - border-radius: 12px; - font-size: 14px; - line-height: 1.6; - border: 1px solid var(--color-border-tertiary); -} - -.panel.panel-collapsed .panel-title, -.panel.panel-collapsed .panel-subtitle, -.panel.panel-collapsed .paste-zone, -.panel.panel-collapsed .paste-actions, -.panel.panel-collapsed .extract-preview, -.panel.panel-collapsed .add-btn { - display: none; -} - -.panel-header { - padding: 20px 24px 16px; - border-bottom: 1px solid var(--color-border-tertiary); - background: var(--color-background-primary); - flex-shrink: 0; - display: flex; - align-items: flex-start; - gap: 10px; -} - -.panel.panel-collapsed .panel-header { - padding: 12px; - justify-content: center; - border-bottom: none; - overflow: hidden; -} - -.panel-toggle-btn { - flex-shrink: 0; - background: none; - border: 1px solid var(--color-border-secondary); - border-radius: var(--border-radius-sm); - width: 28px; - height: 28px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - color: var(--color-text-secondary); - transition: all 0.2s; - margin-top: 2px; -} - -.panel-toggle-btn:hover { - background: var(--color-background-secondary); - color: var(--color-text-primary); -} - -.panel-toggle-icon { - transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); -} - -.panel-title { - font-size: 16px; - font-weight: 600; - color: var(--color-text-primary); - display: flex; - align-items: center; - gap: 8px; -} - -.panel-title svg { - opacity: 0.8; -} - -.panel-subtitle { - font-size: 12px; - font-weight: 500; - color: var(--color-text-tertiary); - margin-top: 4px; -} - -.paste-zone { - margin: 20px 20px 12px; - border: 2px dashed var(--color-border-secondary); - border-radius: var(--border-radius-lg); - padding: 24px 20px; - text-align: center; - cursor: text; - transition: all 0.2s; - background: var(--color-background-primary); - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; - min-height: 120px; - overflow: hidden; -} - -.paste-zone:hover { - border-color: var(--color-text-info); - background: var(--color-background-info); -} - -.paste-zone:focus-within { - border-color: var(--color-text-primary); - border-style: solid; - box-shadow: inset 0 0 0 1px var(--color-text-primary); - outline: none; -} - -.paste-icon { - font-size: 24px; - margin-bottom: 8px; - color: var(--color-text-secondary); - transition: color 0.2s; -} - -.paste-zone:hover .paste-icon { - color: var(--color-text-info); -} - -.paste-input { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - width: 100%; - height: 100%; - opacity: 0; - resize: none; - border: none; - padding: 20px; - font-family: inherit; - font-size: 13px; - z-index: 2; -} - -.paste-input:focus, -.paste-input:not(:placeholder-shown) { - opacity: 1; - z-index: 10; - background: var(--color-background-primary); - color: var(--color-text-primary); - outline: none; -} - -.paste-label { - font-size: 14px; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 4px; - pointer-events: none; -} - -.paste-hint { - font-size: 12px; - color: var(--color-text-tertiary); - line-height: 1.5; - pointer-events: none; -} - -.paste-actions { - padding: 0 20px 16px; -} -/* Main */ -.main { display: flex; flex-direction: column; overflow: hidden; position: relative; } -.topbar { position: relative; display: flex; align-items: center; justify-content: space-between; padding: 16px 24px; border-bottom: 1px solid var(--color-border-tertiary); flex-shrink: 0; background: rgba(var(--color-background-primary), 0.8); backdrop-filter: blur(10px); z-index: 10; } -.topbar-title { font-size: 18px; font-weight: 700; color: var(--color-text-primary); } -.btn { font-family: inherit; font-size: 13px; font-weight: 600; padding: 8px 16px; border: 1px solid var(--color-border-secondary); border-radius: var(--border-radius-sm); background: var(--color-background-primary); color: var(--color-text-primary); cursor: pointer; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: var(--shadow-sm); display: inline-flex; align-items: center; justify-content: center; gap: 6px; } -.btn:hover { background: var(--color-background-secondary); transform: translateY(-1px); box-shadow: var(--shadow-md); } -.btn:active { transform: translateY(0); box-shadow: 0 0 0; } -.btn-primary { background: var(--color-text-primary); color: var(--color-background-primary); border-color: transparent; } -.btn-primary:hover { background: var(--color-text-secondary); } - -/* Calendar */ -.cal-section { padding: 16px 24px; border-bottom: 1px solid var(--color-border-tertiary); flex-shrink: 0; } -.cal-header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 16px; } -.cal-header-left { display: flex; flex-direction: column; flex: 1; align-items: flex-start; gap: 4px; } -.cal-header-right { display: flex; align-items: center; } -.cal-title { font-size: 15px; font-weight: 600; color: var(--color-text-primary); } -.cal-nav { font-size: 18px; color: var(--color-text-secondary); cursor: pointer; padding: 4px 8px; border-radius: 4px; transition: background 0.2s; } -.cal-nav:hover { background: var(--color-background-secondary); color: var(--color-text-primary); } -.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; text-align: center; } -.cal-day-label { font-size: 11px; color: var(--color-text-tertiary); padding-bottom: 8px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; } -.cal-day { font-size: 13px; font-weight: 500; height: 32px; display: flex; align-items: center; justify-content: center; border-radius: var(--border-radius-md); cursor: pointer; color: var(--color-text-secondary); position: relative; transition: all 0.2s; } -.cal-day:hover { background: var(--color-background-secondary); color: var(--color-text-primary); transform: scale(1.1); z-index: 1; } -.cal-day.today { background: var(--color-text-primary); color: var(--color-background-primary); box-shadow: var(--shadow-sm); } -.cal-day-indicators { position: absolute; bottom: 3px; left: 0; right: 0; display: flex; justify-content: center; gap: 3px; } -.cal-day-indicator { width: 5px; height: 5px; border-radius: 50%; } -.cal-day.muted { color: var(--color-border-secondary); } -.cal-legend { display: flex; gap: 16px; margin-top: 16px; font-size: 11px; font-weight: 500; color: var(--color-text-tertiary); justify-content: flex-end; } -.cal-legend span { display: flex; align-items: center; gap: 6px; } -.legend-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; } - -/* Quote Widget */ -.quote-widget { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 6px 12px; - background: var(--color-background-secondary); - border: 1px solid var(--color-border-tertiary); - border-radius: 100px; - transition: all 0.2s ease; -} -.quote-widget:hover { - background: var(--color-background-tertiary); - transform: translateY(-1px); -} -.quote-icon { - color: var(--color-text-tertiary); -} -.quote-widget p { - margin: 0; - font-size: 11px; - color: var(--color-text-secondary); - font-weight: 600; - line-height: 1; - letter-spacing: 0.02em; -} - -/* Tasks */ -.tasks-section { flex: 1; overflow-y: auto; padding: 0 24px 24px; scroll-behavior: smooth; } -.tasks-section::-webkit-scrollbar { width: 6px; } -.tasks-section::-webkit-scrollbar-thumb { background: var(--color-border-secondary); border-radius: 10px; } -.tasks-actions-bar { - margin-top: 18px; - display: flex; - gap: 12px; -} - -.extract-preview { - overflow-y: auto; - padding: 0 20px 12px; - scroll-behavior: smooth; - max-height: 280px; -} - -.extract-preview::-webkit-scrollbar { - width: 6px; -} - -.extract-preview::-webkit-scrollbar-thumb { - background: var(--color-border-secondary); - border-radius: 10px; -} - -.extract-title { - font-size: 11px; - font-weight: 700; - color: var(--color-text-tertiary); - margin-bottom: 12px; - letter-spacing: .06em; - text-transform: uppercase; - display: flex; - align-items: center; - justify-content: space-between; -} - -.extract-card { - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-md); - padding: 14px 16px; - margin-bottom: 12px; - box-shadow: var(--shadow-sm); - animation: popIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; - transform-origin: center; - position: relative; - overflow: hidden; -} - -.tasks-empty-state { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; - padding: 60px 24px; - margin-top: 24px; - background: var(--color-background-secondary); - border: 1px dashed var(--color-border-secondary); - border-radius: var(--border-radius-lg); - position: relative; - overflow: hidden; - animation: emptyStateFadeIn 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards; -} - -@keyframes emptyStateFadeIn { - from { opacity: 0; transform: translateY(10px); } - to { opacity: 1; transform: translateY(0); } -} - -.empty-state-icon { - font-size: 48px; - margin-bottom: 16px; - position: relative; - z-index: 1; - filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.05)); - animation: float 3s ease-in-out infinite; -} - -/* Soft gradient glow behind the icon */ -.empty-state-icon::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 80px; - height: 80px; - background: radial-gradient(circle, rgba(79, 70, 229, 0.15) 0%, transparent 70%); - z-index: -1; - border-radius: 50%; -} - -.empty-state-title { - font-size: 18px; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 8px; -} - -.empty-state-text { - font-size: 14px; - color: var(--color-text-secondary); - max-width: 300px; - line-height: 1.5; - margin-bottom: 24px; -} - -.empty-state-cta { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 10px 20px; - background: var(--color-text-primary); - color: var(--color-background-primary); - border-radius: 8px; - font-size: 14px; - font-weight: 600; - text-decoration: none; - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); - border: none; - cursor: pointer; - box-shadow: var(--shadow-sm); - position: relative; - overflow: hidden; -} - -.empty-state-cta:hover { - transform: translateY(-3px) scale(1.02); - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12); - filter: brightness(1.2); -} - -.empty-state-cta:active { - transform: translateY(-1px) scale(0.98); -} - -/* Subtle shine effect on hover */ -.empty-state-cta::after { - content: ''; - position: absolute; - top: 0; - left: -100%; - width: 50%; - height: 100%; - background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.2), transparent); - transition: left 0.6s ease; -} - -.empty-state-cta:hover::after { - left: 150%; -} - -@keyframes float { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-10px); } -} - -.extract-subject { - font-size: 11px; - font-weight: 700; - margin-bottom: 6px; - letter-spacing: .04em; - text-transform: uppercase; -} -.task-item:hover { background: var(--color-background-secondary); transform: translateX(4px); border-color: var(--color-border-secondary); box-shadow: var(--shadow-sm); } -.task-item.urgent, .task-item.high-priority { - border-color: var(--color-border-danger); - background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.08) 0%, var(--color-background-primary) 100%); -} -.task-item.overdue { - border-color: var(--color-border-danger); - background: linear-gradient(135deg, rgba(var(--color-danger-rgb), 0.12) 0%, var(--color-background-primary) 100%); -} -.task-item.done { - background: linear-gradient(135deg, rgba(var(--color-success-rgb), 0.08) 0%, var(--color-background-primary) 100%); - border-color: var(--color-border-success); -} -.task-check { width: 18px; height: 18px; border-radius: 5px; border: 2px solid var(--color-border-secondary); flex-shrink: 0; margin-top: 2px; transition: all 0.2s; position: relative; cursor: pointer; } -.task-check:hover { border-color: var(--color-text-primary); } -.task-check.done { background: var(--color-text-success); border-color: var(--color-text-success); } -.task-check.done::after { content: ''; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px; border: solid white; border-width: 0 2px 2px 0; transform: rotate(45deg); } -.task-info { flex: 1; min-width: 0; } -.task-name { font-size: 14px; font-weight: 500; color: var(--color-text-primary); line-height: 1.4; transition: color 0.2s; margin-bottom: 6px; } -.task-item.done .task-name { text-decoration: line-through; color: var(--color-text-tertiary); } -.task-meta { font-size: 12px; color: var(--color-text-tertiary); margin-top: 6px; display: flex; gap: 8px; flex-wrap: wrap; align-items: center; font-weight: 500; } -.task-pill { font-size: 11px; padding: 2px 8px; border-radius: 12px; font-weight: 600; display: inline-flex; align-items: center; gap: 4px; border: 1px solid transparent; } -.pill-red { background: var(--color-background-danger); color: var(--color-text-danger); border-color: var(--color-border-danger); } -.pill-blue { background: var(--color-background-info); color: var(--color-text-info); border-color: var(--color-border-info); } -.pill-green{ background: var(--color-background-success); color: var(--color-text-success); border-color: var(--color-border-success); } -.pill-amber{ background: var(--color-background-warning); color: var(--color-text-warning); border-color: rgba(133, 79, 11, 0.2); } -.pill-purple{ background: var(--color-background-purple); color: var(--color-text-purple); border-color: rgba(60, 52, 137, 0.2); } - -.conflict-card { font-size: 13px; font-weight: 500; color: var(--color-text-warning); background: var(--color-background-warning); border: 1px solid rgba(133, 79, 11, 0.3); border-radius: var(--border-radius-md); padding: 12px 16px; line-height: 1.5; display: flex; gap: 12px; align-items: flex-start; box-shadow: var(--shadow-sm); } -.conflict-icon { font-size: 18px; line-height: 1; } - -.extract-task-name { - font-size: 14px; - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 8px; - line-height: 1.4; -} - -.extract-row { - display: flex; - align-items: center; - gap: 8px; - font-size: 12px; - font-weight: 500; - color: var(--color-text-secondary); - margin-top: 4px; -} - -.extract-icon { - font-size: 14px; -} - -.conf-bar { - height: 4px; - border-radius: 2px; - margin-top: 12px; - background: var(--color-border-tertiary); - overflow: hidden; -} - -.conf-fill { - height: 100%; - border-radius: 2px; - transition: width 1s cubic-bezier(0.16, 1, 0.3, 1); -} - -.conf-label { - font-size: 11px; - font-weight: 600; - color: var(--color-text-tertiary); - margin-top: 6px; - display: flex; - justify-content: space-between; -} - -.conf-edit { - color: var(--color-text-info); - cursor: pointer; - transition: color 0.2s; -} - -.conf-edit:hover { - color: var(--color-text-primary); -} - -.add-btn { - margin: 0 20px 20px; - padding: 12px; - border: none; - border-radius: var(--border-radius-md); - background: var(--color-text-primary); - color: var(--color-background-primary); - font-size: 14px; - font-weight: 600; - cursor: pointer; - text-align: center; - flex-shrink: 0; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1); -} - -.add-btn:hover:not(:disabled) { - background: var(--color-text-secondary); - transform: translateY(-2px); - box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); -} - -.add-btn:active:not(:disabled) { - transform: translateY(0); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); -} - -.add-btn:disabled { - background: var(--color-border-secondary); - cursor: not-allowed; - transform: none; - box-shadow: none; - color: var(--color-text-tertiary); -} - -/* Loader */ -.loader-spinner { - display: inline-block; - width: 16px; - height: 16px; - border: 2px solid rgba(0, 0, 0, 0.1); - border-radius: 50%; - border-top-color: var(--color-text-primary); - animation: spin 0.8s linear infinite; -} - -@media (prefers-color-scheme: dark) { - .loader-spinner { - border-color: rgba(255, 255, 255, 0.1); - border-top-color: #fff; - } -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -/* Utility classes */ -.hidden { - display: none !important; -} - -/* Timer duration input */ -.timer-duration-row { - display: flex; - align-items: center; - gap: 10px; -} - -.timer-duration-label { - font-size: 12px; - font-weight: 600; - color: var(--color-text-tertiary); - text-transform: uppercase; - letter-spacing: 0.05em; -} - -.timer-duration-input { - width: 64px; - padding: 6px 10px; - border: 1px solid var(--color-border-secondary); - border-radius: var(--border-radius-sm); - background: var(--color-background-primary); - color: var(--color-text-primary); - font-size: 14px; - font-weight: 600; - font-family: inherit; - text-align: center; - transition: border-color 0.2s; -} - -.timer-duration-input:focus { - outline: none; - border-color: var(--color-text-primary); -} - -.timer-duration-input:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -/* Focus Mode */ -.focus-section { - flex: 1; - display: flex; - flex-direction: column; - padding: 24px; - overflow-y: auto; - gap: 32px; -} - -.focus-dashboard { - display: flex; - flex-direction: column; - align-items: center; - gap: 24px; -} - -.timer-container { - position: relative; - width: 240px; - height: 240px; - display: flex; - align-items: center; - justify-content: center; -} - -.timer-svg { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - transform: rotate(-90deg); -} - -.timer-path-elapsed { - fill: none; - stroke: var(--color-border-tertiary); - stroke-width: 4; -} - -.timer-path-remaining { - fill: none; - stroke: var(--color-text-primary); - stroke-width: 6; - stroke-linecap: round; - transition: stroke-dashoffset 1s linear; -} - -.timer-text { - font-size: 48px; - font-weight: 700; - color: var(--color-text-primary); - font-variant-numeric: tabular-nums; - letter-spacing: -0.02em; - z-index: 1; -} - -.timer-controls { - display: flex; - gap: 12px; -} - -.focus-task-container, -.focus-task-selector { - width: 100%; - max-width: 600px; - margin: 0 auto; -} - -.focus-task-header { - font-size: 13px; - font-weight: 600; - color: var(--color-text-tertiary); - text-transform: uppercase; - letter-spacing: 0.05em; - margin-bottom: 12px; -} - -.active-focus-task { - background: var(--color-background-primary); - border: 1px solid var(--color-border-primary); - border-radius: var(--border-radius-md); - padding: 20px; - box-shadow: var(--shadow-md); - min-height: 80px; - display: flex; - align-items: center; - justify-content: center; -} - -.no-task-selected { - color: var(--color-text-secondary); - font-size: 14px; - font-weight: 500; -} - -.focus-task-list { - display: flex; - flex-direction: column; - gap: 8px; -} - -.focus-task-item { - display: flex; - align-items: center; - gap: 12px; - padding: 12px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-md); - cursor: pointer; - transition: all 0.2s; -} - -.focus-task-item:hover { - background: var(--color-background-secondary); - border-color: var(--color-text-info); - transform: translateY(-1px); -} - -.focus-task-item .task-name { - margin-bottom: 0; - flex: 1; -} - - -/* Header */ -.site-header { - width: 100%; - max-width: 1200px; - margin: 0 auto 16px auto; - padding: 16px 24px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-md); - - display: flex; - align-items: center; - justify-content: space-between; -} - -.header-left { - display: flex; - align-items: center; - gap: 12px; -} - -.logo { - width: 40px; - height: 40px; - border-radius: 2px; -} - -.site-title { - font-size: 20px; - font-weight: 700; - color: var(--color-text-primary); -} - -.header-nav { - display: flex; - gap: 24px; -} - -.header-nav a { - text-decoration: none; - color: var(--color-text-secondary); - font-weight: 500; - transition: color 0.2s; -} - -.header-nav a:hover { - color: var(--color-text-primary); -} - -.profile-btn { - padding: 8px 16px; - border: none; - border-radius: var(--border-radius-md); - background: var(--color-text-primary); - color: var(--color-background-primary); - cursor: pointer; - font-weight: 600; -} - -/* Footer */ -.site-footer { - width: 100%; - max-width: 1200px; - margin: 16px auto 0 auto; - padding: 16px 24px; - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-lg); - box-shadow: var(--shadow-md); - - display: flex; - align-items: center; - justify-content: space-between; - color: var(--color-text-secondary); - font-size: 14px; -} - -.footer-links { - display: flex; - gap: 16px; -} - -.footer-links a { - text-decoration: none; - color: var(--color-text-secondary); -} - -.footer-links a:hover { - color: var(--color-text-primary); -} - -/* Global crash boundary UI */ -.crash-screen { - min-height: 100vh; - width: 100%; - display: flex; - align-items: center; - justify-content: center; - padding: 24px; - background: - radial-gradient(circle at 20% 20%, rgba(24, 95, 165, 0.16), transparent 40%), - radial-gradient(circle at 80% 0%, rgba(22, 101, 52, 0.14), transparent 42%), - var(--color-background-tertiary); -} - -.crash-card { - width: min(560px, 100%); - border-radius: var(--border-radius-lg); - border: 1px solid var(--color-border-tertiary); - background: var(--color-background-primary); - box-shadow: var(--shadow-lg); - padding: 28px; -} - -.crash-illustration { - font-size: 30px; - margin-bottom: 12px; -} - -.crash-title { - font-size: 28px; - margin-bottom: 10px; -} - -.crash-copy { - color: var(--color-text-secondary); - line-height: 1.5; - margin-bottom: 8px; -} - -.crash-quote { - color: var(--color-text-info); - font-weight: 600; - margin-bottom: 16px; -} - -.crash-refresh { - border: none; - border-radius: var(--border-radius-md); - padding: 10px 16px; - font-size: 14px; - font-weight: 700; - color: var(--color-background-primary); - background: var(--color-text-primary); - cursor: pointer; -} - -.crash-refresh:hover { - background: var(--color-text-secondary); -} - -.crash-details { - margin-top: 14px; - color: var(--color-text-secondary); -} - -.crash-details pre { - margin-top: 8px; - white-space: pre-wrap; - overflow-wrap: anywhere; - font-size: 12px; - background: var(--color-background-secondary); - border: 1px solid var(--color-border-tertiary); - border-radius: var(--border-radius-sm); - padding: 10px; -} - -/* Task Addition Model */ - - -#new-task-modal { - - position: fixed; - inset: 0; - z-index: 9998; - display: none; - align-items: center; - justify-content: center; - background-color: rgba(0, 0, 0, 0.55) !important; -} - - -#new-task-modal .modal-card { - width: 100%; - max-width: 360px; - background-color: #0f172a; - border-radius: 14px; - padding: 20px 20px 16px; - box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6) !important; - color: #e5e7eb; - box-sizing: border-box; - border: 1px solid rgba(148, 163, 184, 0.35) !important; -} - - -#new-task-modal .modal-card h3 { - margin: 0 0 12px; - font-size: 18px; - font-weight: 600; - letter-spacing: 0.01em; - color: #f9fafb; -} - - -#new-task-modal label { - display: block; - font-size: 11px; - font-weight: 600; - text-transform: uppercase; - letter-spacing: 0.06em; - color: #9ca3af; - /* muted */ - margin-bottom: 4px; -} - - -#new-task-modal input, -#new-task-modal select { - width: 100%; - box-sizing: border-box; - font-size: 13px; - padding: 7px 8px; - margin-bottom: 10px; - border-radius: 6px; - border: 1px solid #4b5563; - background-color: #111827 !important; - color: #e5e7eb; - transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; - color-scheme: dark; -} - - -#new-task-modal input::placeholder { - color: #6b7280; -} - - -#new-task-modal input:focus, -#new-task-modal select:focus { - outline: none; - border-color: #4f46e5; - box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.35); - background: #020617; -} - - -#new-task-modal .modal-card>div:last-child { - display: flex; - justify-content: flex-end; - gap: 8px; - margin-top: 6px; -} - - -#new-task-modal .btn { - font-size: 12px; - padding: 6px 10px; - border-radius: 999px; -} - -#new-task-modal .btn:not(.btn-primary) { - background: rgba(15, 23, 42, 0.9); - color: #e5e7eb; - border: 1px solid #4b5563; -} - -#new-task-modal .btn:not(.btn-primary):hover { - background: #020617; -} - - -#new-task-modal.showing .modal-card { - animation: new-task-modal-in 0.16s ease-out; -} - -@keyframes new-task-modal-in { - from { - opacity: 0; - transform: translateY(6px) scale(0.97); - } - - to { - opacity: 1; - transform: translateY(0) scale(1); - } -} - - -@media (max-width: 480px) { - #new-task-modal .modal-card { - max-width: 90vw; - padding: 16px 14px 12px; - } -} - - -.smart-workload-card { - margin-bottom: 14px; - padding: 14px; - border-radius: 14px; - background: rgba(255, 184, 77, 0.08); - border: 1px solid rgba(255, 184, 77, 0.25); - backdrop-filter: blur(10px); - display: flex; - justify-content: space-between; - gap: 18px; - align-items: flex-start; - flex-wrap: wrap; -} - -.smart-workload-title { - font-size: 14px; - font-weight: 700; - margin-bottom: 8px; - color: #ffcc66; -} - -.smart-workload-score { - min-width: 90px; - font-size: 12px; - margin-bottom: 10px; - color: #cfcfcf; -} - -.smart-suggestion-list { - margin: 0; - padding-left: 18px; -} - -.smart-suggestion-list li { - margin-bottom: 6px; - color: #e6e6e6; - line-height: 1.5; - font-size: 13px; -} - -.smart-workload-card.high { - border-color: rgba(255, 77, 77, 0.5); - background: rgba(255, 77, 77, 0.08); -} - -.smart-workload-card.medium { - border-color: rgba(255, 184, 77, 0.25); -} - -.smart-highlight { - color: #ffcc66; - font-weight: 600; -} - -/* ========================================================================== - Modern Toast Notifications - ========================================================================== */ - -.toast-container { - position: fixed; - top: 24px; - right: 24px; - z-index: 10000; - display: flex; - flex-direction: column; - gap: 12px; - pointer-events: none; -} - -.toast-notification { - pointer-events: auto; - display: flex; - align-items: center; - gap: 12px; - background: var(--color-background-primary); - color: var(--color-text-primary); - padding: 12px 16px; - border-radius: 12px; - box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2); - border: 1px solid var(--color-border-secondary); - font-family: 'Inter', sans-serif; - font-size: 14px; - font-weight: 500; - animation: toastSlideIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; - max-width: 350px; - transform-origin: top right; -} - -.toast-notification.toast-hiding { - animation: toastSlideOut 0.2s ease-in forwards; -} - -.toast-icon { - font-size: 18px; - flex-shrink: 0; -} - -.toast-message { - flex-grow: 1; - line-height: 1.4; -} - -.toast-close { - background: none; - border: none; - color: var(--color-text-tertiary); - font-size: 18px; - cursor: pointer; - padding: 0; - margin-left: 8px; - flex-shrink: 0; - display: flex; - align-items: center; - justify-content: center; - transition: color 0.2s; -} - -.toast-close:hover { - color: var(--color-text-primary); -} - -/* Toast Themes */ -.toast-success { border-left: 4px solid var(--color-text-success); } -.toast-error { border-left: 4px solid var(--color-text-danger); } -.toast-warning { border-left: 4px solid var(--color-text-warning); } -.toast-info { border-left: 4px solid var(--color-text-info); } - -@keyframes toastSlideIn { - from { opacity: 0; transform: translateY(-20px) scale(0.95); } - to { opacity: 1; transform: translateY(0) scale(1); } -} - -@keyframes toastSlideOut { - from { opacity: 1; transform: scale(1); } - to { opacity: 0; transform: scale(0.9); } -} - -/* ========================================================================== - Modern Confirm Modal - ========================================================================== */ -.custom-confirm-backdrop { - position: fixed; - inset: 0; - background: rgba(0,0,0,0.5); - z-index: 10001; - display: flex; - align-items: center; - justify-content: center; - backdrop-filter: blur(4px); - opacity: 0; -} - -.custom-confirm-modal { - background: var(--color-background-primary); - border: 1px solid var(--color-border-tertiary); - color: var(--color-text-primary); - opacity: 0; - transform: translateY(10px); -} - -@keyframes fadeIn { - to { opacity: 1; } -} - -@keyframes fadeOut { - to { opacity: 0; } -} - -@keyframes slideUp { - to { opacity: 1; transform: translateY(0); } -} - -@keyframes slideDown { - to { opacity: 0; transform: translateY(10px); } -} + font-size: 14px; \ No newline at end of file diff --git a/dashboard.html b/dashboard.html new file mode 100644 index 0000000..88b0c44 --- /dev/null +++ b/dashboard.html @@ -0,0 +1,138 @@ + + + + + + StudyPlan - Dashboard + + + + +
+
+ +
+
+
+ +

StudyPlan

+
+ +
+ +
+
+
Good morning
+
Chinmayee
+
+
+ +
+
+
0
+
total tasks
+
+
+
0
+
completed
+
+
+
0
+
pending
+
+
+
0
+
due soon
+
+
+ +
+
+
+ Upcoming Deadlines +
+
+
No upcoming deadlines
+
+
+ +
+
+ Today's Priority +
+
+
No tasks for today
+
+
+ +
+
+ Recent Activity +
+
+
No recent activity
+
+
+
+ + +
+
+ +
+ + + + + \ No newline at end of file diff --git a/index.html b/index.html index 3333d17..b9bdbf5 100644 --- a/index.html +++ b/index.html @@ -53,12 +53,12 @@

Wel

StudyPlan

- +
@@ -114,11 +114,12 @@

StudyPlan

April 2026
- - - + + +
+
@@ -137,8 +138,13 @@

StudyPlan

+
+
April 2026
+ + +
@@ -236,8 +242,8 @@

StudyPlan

- - +
diff --git a/js/app.js b/js/app.js index 787d08a..c44f4bf 100644 --- a/js/app.js +++ b/js/app.js @@ -42,12 +42,10 @@ function generateSummary(tasks, subjects) { const d = new Date(t.due_at); - // today if (d.toDateString() === now.toDateString()) { todayCount++; } - // this week if (d >= now && d <= weekEnd) { weekCount++; } @@ -64,20 +62,19 @@ function generateSummary(tasks, subjects) { : 'no specific subject'; return ` - 📅 Daily
+ Daily
Today you have ${todayCount} task(s).
Focus on ${topSubject}.

- 📊 Weekly
+ Weekly
This week you have ${weekCount} task(s).
Most work is in ${topSubject}. `; } - let currentMonthDate = new Date(); let selectedDate = null; let currentView = 'calendar'; // 'calendar', 'all-tasks', 'archived' - +let currentCalendarView = 'month'; const tasksSection = document.getElementById('tasks-section'); const focusSection = document.getElementById('focus-section'); const extractPreview = document.getElementById('extract-preview'); @@ -484,12 +481,13 @@ function renderTasks() { const sorted = [...displayTasks].sort((a,b) => new Date(a.due_at) - new Date(b.due_at)); const now = new Date(); - + + const overdue = []; const dueSoon = []; const thisWeek = []; const completed = []; const pending = []; - + if (currentView === 'calendar' && selectedDate) { sorted.forEach(t => { const d = new Date(t.due_at); @@ -510,18 +508,24 @@ function renderTasks() { pending.push(t); const d = new Date(t.due_at); const diffDays = (d - now) / (1000 * 60 * 60 * 24); - if (diffDays <= 3) dueSoon.push(t); - else thisWeek.push(t); + if (diffDays < 0) { + overdue.push(t); + } else if (diffDays <= 3) { + dueSoon.push(t); + } else { + thisWeek.push(t); + } }); } - - const renderGroup = (title, items, titleColor, showConflict = false) => { - if (items.length === 0) return ''; - let html = `
-
- ${title} -
`; + + const renderGroup = (title, items, titleColor, showConflict = false) => { + if (items.length === 0) return ''; + let html = `
+
+ ${title} +
`; + if (showConflict) { const workloadSuggestions = analyzeWorkload(items); workloadSuggestions.forEach(workload => { @@ -546,70 +550,103 @@ function renderTasks() { else if(sub.short_code === 'Maths') pillClass = 'pill-green'; else if(sub.short_code === 'English') pillClass = 'pill-purple'; else pillClass = 'pill-amber'; + - if (t._isEditing) { - let subjectOptions = subjects.map(s => - `` - ).join(''); + if (showConflict && items.length >= 3) { + html += `
+ +
Multiple deadlines detected. Consider starting early to spread the load.
+
`; + } - const localDate = t.due_at ? new Date(t.due_at).toISOString().substring(0, 16) : ''; + items.forEach(t => { + const sub = subjects.find(s => s.id === t.subject_id) || subjects[0]; + const isUrgent = t.priority === 'high' && title === '⚠ Due soon'; + const isDone = t.status === 'Done'; - html += ` -
- - - - - - - - - - - - - - - -
- - -
-
- `; - } else { - const actionButtons = !t.archived - ? ` - - ` - : ` - - `; - - let labelsHtml = ''; - if (t.labels && Array.isArray(t.labels)) { - labelsHtml = t.labels.map(l => `${l}`).join(' '); - } - - html += ` -
-
-
-
${t.title}
-
- ${isDone ? 'Done' : 'Due ' + formatDate(t.due_at)} - ${sub.short_code} - ${labelsHtml} + let pillClass = ''; + if(sub.short_code === 'CS') pillClass = 'pill-blue'; + else if(sub.short_code === 'Maths') pillClass = 'pill-green'; + else if(sub.short_code === 'English') pillClass = 'pill-purple'; + else pillClass = 'pill-amber'; + + if (t._isEditing) { + let subjectOptions = subjects.map(s => + `` + ).join(''); + + const localDate = t.due_at ? new Date(t.due_at).toISOString().substring(0, 16) : ''; + const isHighPriority = t.priority === 'high'; + + html += ` +
+ + + + + + + + + + + + + + + +
+ +
-
- ${actionButtons} + `; + } else { + const archiveBtn = !t.archived + ? ` + ` + : ` + + `; + + html += ` +
+
+
+
${t.title}
+
+ ${isDone ? 'Done' : 'Due ' + formatDate(t.due_at)} + ${sub.short_code} +
+
+
+ ${archiveBtn} +
+ + `; + } + }); + html += `
`; + return html; + }; + + if (currentView === 'calendar' && selectedDate) { + const selStr = selectedDate.toLocaleDateString('en-US', {month:'short', day:'numeric'}); + const actionBar = `
+ + +
`; + + const emptyState = dueSoon.length === 0 && completed.length === 0 + ? `
No tasks for this day yet.
` + : ''; +
`; } @@ -688,102 +725,243 @@ function renderTasks() { const taskId = el.dataset.id; const task = store.tasks.find(t => String(t.id) === String(taskId)); if (task && task._isEditing) return; + - store.toggleTaskStatus(taskId); + tasksSection.innerHTML = actionBar + + renderGroup('⚠ Overdue', overdue, 'var(--color-text-danger)') + + renderGroup('⚠ Due soon', dueSoon, 'var(--color-text-warning)') + + renderGroup('This week', thisWeek, 'var(--color-text-secondary)', true) + + renderGroup('Completed', completed, 'var(--color-text-tertiary)') + + emptyState; + } else { + const actionBar = currentView === 'archived' ? '' : `
+ +
`; + + const titlePrefix = currentView === 'archived' ? 'Archived: ' : ''; + const emptyStateText = currentView === 'archived' ? 'No archived tasks.' : 'No tasks yet. Add tasks from Smart Paste to get started.'; + + const emptyState = dueSoon.length === 0 && thisWeek.length === 0 && completed.length === 0 + ? `
${emptyStateText}
` + : ''; + + tasksSection.innerHTML = actionBar + + renderGroup(titlePrefix + '⚠ Overdue', overdue, 'var(--color-text-danger)') + + renderGroup(titlePrefix + '⚠ Due soon', dueSoon, 'var(--color-text-warning)') + + renderGroup(titlePrefix + 'This week', thisWeek, 'var(--color-text-secondary)', true) + + renderGroup(titlePrefix + 'Completed', completed, 'var(--color-text-tertiary)') + + emptyState; + } + + document.querySelectorAll('.task-item').forEach(el => { + el.addEventListener('click', (e) => { + if (e.target.closest('.task-actions') || e.target.closest('.task-check')) return; + + const taskId = el.dataset.id; + const task = store.tasks.find(t => String(t.id) === String(taskId)); + if (task && task._isEditing) return; + + store.toggleTaskStatus(taskId); + }); }); - }); - document.querySelectorAll('.edit-task-btn').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - store.setTaskEditing(el.dataset.id, true); + document.querySelectorAll('.edit-task-btn').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + store.setTaskEditing(el.dataset.id, true); + }); }); - }); - document.querySelectorAll('.cancel-board-edit-btn').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - store.setTaskEditing(el.dataset.id, false); + document.querySelectorAll('.cancel-board-edit-btn').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + store.setTaskEditing(el.dataset.id, false); + }); }); - }); - document.querySelectorAll('.save-board-edit-btn').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - const taskId = el.dataset.id; - const itemEl = el.closest('.task-item'); - - const rawTitle = itemEl.querySelector('.board-edit-title').value; - const subject_id = itemEl.querySelector('.board-edit-subject').value; - let dateVal = itemEl.querySelector('.board-edit-date').value; - const notes = itemEl.querySelector('.board-edit-notes').value; - const priority = itemEl.querySelector('.board-edit-priority').value; - - const { cleanTitle, labels } = extractLabels(rawTitle); - - store.updateTask(taskId, { - title: cleanTitle || rawTitle, - subject_id, - due_at: dateVal ? new Date(dateVal).toISOString() : '', - notes, - priority, - labels + document.querySelectorAll('.save-board-edit-btn').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + const taskId = el.dataset.id; + const itemEl = el.closest('.task-item'); + + const title = itemEl.querySelector('.board-edit-title').value; + const subject_id = itemEl.querySelector('.board-edit-subject').value; + let dateVal = itemEl.querySelector('.board-edit-date').value; + const notes = itemEl.querySelector('.board-edit-notes').value; + const priority = itemEl.querySelector('.board-edit-priority').value; + + store.updateTask(taskId, { + title, + subject_id, + due_at: dateVal ? new Date(dateVal).toISOString() : '', + notes, + priority + }); }); }); - }); - document.querySelectorAll('.task-check').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - const taskId = el.closest('.task-item').dataset.id; - store.toggleTaskStatus(taskId); + document.querySelectorAll('.task-check').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + const taskId = el.closest('.task-item').dataset.id; + store.toggleTaskStatus(taskId); + }); }); - }); - document.querySelectorAll('.archive-task-btn').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - store.archiveTask(el.dataset.id); + document.querySelectorAll('.archive-task-btn').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + store.archiveTask(el.dataset.id); + }); }); - }); - document.querySelectorAll('.restore-task-btn').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - store.restoreTask(el.dataset.id); + document.querySelectorAll('.restore-task-btn').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + store.restoreTask(el.dataset.id); + }); }); - }); - document.querySelectorAll('.delete-task-btn').forEach(el => { - el.addEventListener('click', (e) => { - e.stopPropagation(); - store.deleteTask(el.dataset.id); + document.querySelectorAll('.delete-task-btn').forEach(el => { + el.addEventListener('click', (e) => { + e.stopPropagation(); + store.deleteTask(el.dataset.id); + }); }); - }); - const markAllPendingBtn = document.getElementById('mark-all-pending-btn'); - if (markAllPendingBtn) { - markAllPendingBtn.addEventListener('click', (e) => { - e.stopPropagation(); - store.markAllPendingCompleted(); + const markAllPendingBtn = document.getElementById('mark-all-pending-btn'); + if (markAllPendingBtn) { + markAllPendingBtn.addEventListener('click', (e) => { + e.stopPropagation(); + store.markAllPendingCompleted(); + }); + } + + const markDayCompleteBtn = document.getElementById('mark-day-complete-btn'); + if (markDayCompleteBtn) { + markDayCompleteBtn.addEventListener('click', (e) => { + e.stopPropagation(); + store.markPendingTasksForDateCompleted(selectedDate); + }); + } +} + + +function renderDayView() { + const targetDate = selectedDate || currentMonthDate; + const year = targetDate.getFullYear(); + const month = targetDate.getMonth(); + const day = targetDate.getDate(); + + const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + + const topbarTitle = document.querySelector('.topbar-title'); + if(topbarTitle) { + topbarTitle.textContent = `${monthNames[month]} ${day}, ${year}`; + } + document.getElementById('cal-month-title').textContent = `${monthNames[month]} ${day}, ${year}`; + + const dayTasks = store.tasks.filter(t => { + if (t.archived) return false; + if (!t.due_at) return false; + const d = new Date(t.due_at); + return d.getDate() === day && d.getMonth() === month && d.getFullYear() === year; + }); + + const pending = dayTasks.filter(t => t.status !== 'Done'); + const completed = dayTasks.filter(t => t.status === 'Done'); + pending.sort((a, b) => new Date(a.due_at) - new Date(b.due_at)); + + let html = '
'; + + html += '
'; + html += 'Tasks on ' + monthNames[month] + ' ' + day + ', ' + year; + html += '
'; + + if (pending.length === 0 && completed.length === 0) { + html += '
No tasks for this day
'; + html += ''; + } else { + if (pending.length > 0) { + for (let i = 0; i < pending.length; i++) { + const task = pending[i]; + const sub = store.subjects.find(s => s.id === task.subject_id) || store.subjects[0]; + html += '
'; + html += '
'; + html += '
'; + html += '' + escapeHtml(task.title) + ''; + html += '' + (sub?.short_code || 'Task') + ''; + html += '
'; + html += '
'; + } + } + + if (completed.length > 0) { + for (let i = 0; i < completed.length; i++) { + const task = completed[i]; + const sub = store.subjects.find(s => s.id === task.subject_id) || store.subjects[0]; + html += '
'; + html += '
'; + html += '
'; + html += '' + escapeHtml(task.title) + ''; + html += '' + (sub?.short_code || 'Task') + ''; + html += '
'; + html += '
'; + } + } + } + + html += '
'; + document.getElementById('cal-grid').innerHTML = html; + + const items = document.querySelectorAll('.checklist-item'); + for (let i = 0; i < items.length; i++) { + const item = items[i]; + item.addEventListener('click', function(e) { + if (e.target.classList.contains('checklist-box')) return; + const taskId = this.dataset.id; + if (taskId) { + store.toggleTaskStatus(taskId); + setTimeout(function() { renderDayView(); }, 50); + } }); + + const box = item.querySelector('.checklist-box'); + if (box) { + box.addEventListener('click', function(e) { + e.stopPropagation(); + const taskId = item.dataset.id; + if (taskId) { + store.toggleTaskStatus(taskId); + setTimeout(function() { renderDayView(); }, 50); + } + }); + } } - - const markDayCompleteBtn = document.getElementById('mark-day-complete-btn'); - if (markDayCompleteBtn) { - markDayCompleteBtn.addEventListener('click', (e) => { - e.stopPropagation(); - store.markPendingTasksForDateCompleted(selectedDate); + + const addBtn = document.getElementById('day-add-task-btn'); + if (addBtn) { + addBtn.addEventListener('click', function() { + document.getElementById('add-task-btn').click(); }); } } +window.toggleTask = function(taskId) { + store.toggleTaskStatus(taskId); + setTimeout(() => { + if (currentCalendarView === 'day') renderDayView(); + else if (currentCalendarView === 'week') renderWeekCalendar(); + else if (currentCalendarView === 'month') renderCalendar(); + renderTasks(); + }, 50); +}; - +// Summary box from main branch const summaryBox = document.getElementById('summary-box'); if (summaryBox) { summaryBox.innerHTML = generateSummary(store.tasks, store.subjects); } - function renderCalendar() { const calTitle = document.getElementById('cal-month-title'); const calGrid = document.getElementById('cal-grid'); @@ -825,15 +1003,27 @@ function renderCalendar() { let indicatorHtml = ''; if (dayTasks.length > 0) { + const maxDots = 3; + const hasMore = dayTasks.length > maxDots; + const dotsToShow = hasMore ? maxDots - 1 : dayTasks.length; + indicatorHtml = `
`; - dayTasks.forEach((t, idx) => { - if (idx > 2) return; - const sub = store.subjects.find(s => s.id === t.subject_id) || store.subjects[0]; - indicatorHtml += `
`; - }); + + for (let i = 0; i < dotsToShow; i++) { + const sub = store.subjects.find(s => s.id === dayTasks[i].subject_id) || store.subjects[0]; + indicatorHtml += `
`; + } + + if (hasMore) { + indicatorHtml += `
+${dayTasks.length - (maxDots - 1)}
`; + } else if (dayTasks.length <= maxDots) { + indicatorHtml += `
${dayTasks.length}
`; + } + indicatorHtml += `
`; } + document.getElementById('cal-grid').className = 'cal-grid cal-month-view'; const extraStyle = isSelected ? `border: 1.5px solid var(--color-text-primary);` : ''; html += `
@@ -867,6 +1057,105 @@ function renderCalendar() { }); } + +function renderWeekCalendar() { + const year = currentMonthDate.getFullYear(); + const month = currentMonthDate.getMonth(); + const today = currentMonthDate.getDate(); + + const currentDay = new Date(year, month, today); + const dayOfWeek = currentDay.getDay(); + const monday = new Date(currentDay); + monday.setDate(currentDay.getDate() - dayOfWeek + (dayOfWeek === 0 ? -6 : 1)); + + const monthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"]; + + // Update the title to show week range + const weekEnd = new Date(monday); + weekEnd.setDate(monday.getDate() + 6); + const topbarTitle = document.querySelector('.topbar-title'); + if(topbarTitle) { + topbarTitle.textContent = `${monthNames[monday.getMonth()]} ${monday.getDate()} - ${monthNames[weekEnd.getMonth()]} ${weekEnd.getDate()}, ${monday.getFullYear()}`; + } + + document.getElementById('cal-month-title').textContent = `${monthNames[month]} ${year}`; + + let html = `
Mon
+
Tue
+
Wed
+
Thu
+
Fri
+
Sat
+
Sun
`; + + for(let i = 0; i < 7; i++){ + const date = new Date(monday); + date.setDate(monday.getDate() + i); + const dayNum = date.getDate(); + const isToday = dayNum === new Date().getDate() && + date.getMonth() === new Date().getMonth() && + date.getFullYear() === new Date().getFullYear(); + + // Check if this day has tasks + const dayTasks = store.tasks.filter(t => { + if (t.archived) return false; + if (t.status === 'Done') return false; + if (!t.due_at) return false; + const d = new Date(t.due_at); + return d.getDate() === dayNum && d.getMonth() === date.getMonth() && d.getFullYear() === date.getFullYear(); + }); + + let indicatorHtml = ''; + if (dayTasks.length > 0) { + const maxDots = 3; + const hasMore = dayTasks.length > maxDots; + const dotsToShow = hasMore ? maxDots - 1 : dayTasks.length; + + indicatorHtml = `
`; + + for (let j = 0; j < dotsToShow; j++) { + const sub = store.subjects.find(s => s.id === dayTasks[j].subject_id) || store.subjects[0]; + indicatorHtml += `
`; + } + + if (hasMore) { + indicatorHtml += `
+${dayTasks.length - (maxDots - 1)}
`; + } else if (dayTasks.length <= maxDots) { + indicatorHtml += `
${dayTasks.length}
`; + } + + indicatorHtml += `
`; + } + + html += `
+ ${dayNum} + ${indicatorHtml} +
`; + + } + + document.getElementById('cal-grid').innerHTML = html; + + document.querySelectorAll('#cal-grid .interactive-day').forEach(el => { + el.addEventListener('click', (e) => { + const day = parseInt(el.dataset.day); + const month = parseInt(el.dataset.month); + const year = parseInt(el.dataset.year); + selectedDate = new Date(year, month, day); + currentCalendarView = 'day'; + + document.querySelectorAll('.view-btn').forEach(btn => { + btn.classList.remove('active'); + if(btn.dataset.view === 'day') btn.classList.add('active'); + }); + + renderDayView(); + renderTasks(); + }); +}); +} + + function renderExtraction() { const pasteItems = store.currentPaste; if (!pasteItems || pasteItems.length === 0) { @@ -971,6 +1260,11 @@ store.subscribe(renderExtraction); store.subscribe(renderCalendar); store.subscribe(renderFocusTasks); store.subscribe(renderSidebarSubjects); +store.subscribe(() => { + if (currentCalendarView === 'month') renderCalendar(); + else if (currentCalendarView === 'week') renderWeekCalendar(); + else if (currentCalendarView === 'day') renderDayView(); +}); document.addEventListener('DOMContentLoaded', () => { if (newSubjectColorsEl) { @@ -1018,6 +1312,8 @@ document.addEventListener('DOMContentLoaded', () => { }); } + + if (newSubjectName) { newSubjectName.addEventListener('keydown', (e) => { if (e.key === 'Enter') { @@ -1029,11 +1325,75 @@ document.addEventListener('DOMContentLoaded', () => { store.fetchInitialData(); + + + const calSection = document.querySelector('.cal-section'); + const collapseIcon = document.querySelector('.collapse-icon'); + let calendarCollapsed = false; + + if (collapseIcon) { + collapseIcon.addEventListener('click', (e) => { + e.stopPropagation(); + calendarCollapsed = !calendarCollapsed; + if (calendarCollapsed) { + calSection.classList.add('collapsed'); + collapseIcon.textContent = '▶'; + } else { + calSection.classList.remove('collapsed'); + collapseIcon.textContent = '▼'; + } + }); + } + const calendarBtn = document.getElementById('calendar-btn'); const allTasksBtn = document.getElementById('all-tasks-btn'); const archivedTasksBtn = document.getElementById('archived-tasks-btn'); const focusModeBtn = document.getElementById('focus-mode-btn'); +const viewBtns = document.querySelectorAll('.view-btn'); +if(viewBtns.length > 0) { + viewBtns.forEach(btn => { + btn.addEventListener('click', () => { + currentCalendarView = btn.dataset.view; + + viewBtns.forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + + if(currentCalendarView === 'month') { + selectedDate = null; + renderCalendar(); + } else if(currentCalendarView === 'week') { + selectedDate = null; + renderWeekCalendar(); + } else if(currentCalendarView === 'day') { + if (!selectedDate) { + selectedDate = new Date(); + } + renderDayView(); + } + renderTasks(); + }); + }); +} else { + + + const weekBtn = document.querySelector('.topbar .btn'); + if(weekBtn && weekBtn.textContent === 'Week') { + weekBtn.addEventListener('click', () => { + if(currentCalendarView === 'month') { + currentCalendarView = 'week'; + renderWeekCalendar(); + weekBtn.textContent = 'Month'; + } else { + currentCalendarView = 'month'; + renderCalendar(); + weekBtn.textContent = 'Week'; + } + renderTasks(); + }); + } +} + function updateSidebarActive(id) { document.querySelectorAll('.sidebar .nav-item').forEach(el => el.classList.remove('active')); document.getElementById(id).classList.add('active'); @@ -1066,6 +1426,7 @@ document.addEventListener('DOMContentLoaded', () => { renderTasks(); }); + if(focusModeBtn) { focusModeBtn.addEventListener('click', () => { currentView = 'focus'; @@ -1077,18 +1438,41 @@ document.addEventListener('DOMContentLoaded', () => { }); } - document.getElementById('cal-prev').addEventListener('click', () => { +document.getElementById('cal-prev').addEventListener('click', () => { + if(currentCalendarView === 'month') { currentMonthDate.setMonth(currentMonthDate.getMonth() - 1); renderCalendar(); - }); + } else if(currentCalendarView === 'week') { + currentMonthDate.setDate(currentMonthDate.getDate() - 7); + renderWeekCalendar(); + } else if(currentCalendarView === 'day') { + const currentDate = selectedDate || currentMonthDate; + const newDate = new Date(currentDate); + newDate.setDate(currentDate.getDate() - 1); + selectedDate = newDate; + renderDayView(); + } + renderTasks(); +}); - document.getElementById('cal-next').addEventListener('click', () => { +document.getElementById('cal-next').addEventListener('click', () => { + if(currentCalendarView === 'month') { currentMonthDate.setMonth(currentMonthDate.getMonth() + 1); renderCalendar(); - }); + } else if(currentCalendarView === 'week') { + currentMonthDate.setDate(currentMonthDate.getDate() + 7); + renderWeekCalendar(); + } else if(currentCalendarView === 'day') { + const currentDate = selectedDate || currentMonthDate; + const newDate = new Date(currentDate); + newDate.setDate(currentDate.getDate() + 1); + selectedDate = newDate; + renderDayView(); + } + renderTasks(); +}); -//NEw Task addition event listeners newTaskBtn.addEventListener('click', () => { if (!store.subjects || store.subjects.length === 0) { diff --git a/js/dashboard.js b/js/dashboard.js new file mode 100644 index 0000000..e89beb1 --- /dev/null +++ b/js/dashboard.js @@ -0,0 +1,274 @@ +import { store } from './store.js'; +import { initGlobalErrorBoundary } from './utils/errorBoundary.js'; + +initGlobalErrorBoundary(); + +function formatDate(dateStr) { + if (!dateStr) return ''; + const d = new Date(dateStr); + return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }); +} + +function getTimeAgo(date) { + const now = new Date(); + const diffMs = now - date; + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) return 'just now'; + if (diffMins < 60) return diffMins + 'm ago'; + if (diffHours < 24) return diffHours + 'h ago'; + return diffDays + 'd ago'; +} + +function calculateStreak(tasks) { + const completedTasks = tasks.filter(t => t.status === 'Done' && !t.archived); + const today = new Date(); + today.setHours(0, 0, 0, 0); + + let streak = 0; + let currentDate = new Date(today); + + for (let i = 0; i < 365; i++) { + const dateStr = currentDate.toDateString(); + const hasTaskOnDate = completedTasks.some(t => { + if (!t.due_at) return false; + const taskDate = new Date(t.due_at); + taskDate.setHours(0, 0, 0, 0); + return taskDate.toDateString() === dateStr; + }); + + if (hasTaskOnDate) { + streak++; + currentDate.setDate(currentDate.getDate() - 1); + } else { + break; + } + } + + const allDates = completedTasks.map(t => { + if (!t.due_at) return null; + const d = new Date(t.due_at); + d.setHours(0, 0, 0, 0); + return d.toDateString(); + }).filter(d => d); + + const uniqueDates = [...new Set(allDates)].sort(); + let bestStreak = 0; + let currentStreak = 1; + + for (let i = 1; i < uniqueDates.length; i++) { + const prev = new Date(uniqueDates[i-1]); + const curr = new Date(uniqueDates[i]); + const diffDays = (curr - prev) / (1000 * 60 * 60 * 24); + if (diffDays === 1) { + currentStreak++; + } else { + bestStreak = Math.max(bestStreak, currentStreak); + currentStreak = 1; + } + } + bestStreak = Math.max(bestStreak, currentStreak); + + return { current: streak, best: bestStreak }; +} + +function updateDashboard() { + const tasks = store.tasks; + const subjects = store.subjects; + + const now = new Date(); + const weekStart = new Date(now); + weekStart.setDate(now.getDate() - now.getDay()); + weekStart.setHours(0, 0, 0, 0); + + const weekEnd = new Date(weekStart); + weekEnd.setDate(weekStart.getDate() + 7); + + const thisWeekTasks = tasks.filter(t => { + if (t.archived) return false; + if (!t.due_at) return false; + const d = new Date(t.due_at); + return d >= weekStart && d < weekEnd; + }); + + const totalThisWeek = thisWeekTasks.length; + const completedThisWeek = thisWeekTasks.filter(t => t.status === 'Done').length; + const pendingTasks = tasks.filter(t => !t.archived && t.status !== 'Done').length; + + const dueSoonTasks = tasks.filter(t => { + if (t.archived || t.status === 'Done') return false; + if (!t.due_at) return false; + const d = new Date(t.due_at); + const diffDays = (d - now) / (1000 * 60 * 60 * 24); + return diffDays <= 3 && diffDays >= 0; + }).length; + + const totalTasksElem = document.getElementById('total-tasks'); + const completedTasksElem = document.getElementById('completed-tasks'); + const pendingTasksElem = document.getElementById('pending-tasks'); + const dueTasksElem = document.getElementById('due-tasks'); + + if (totalTasksElem) totalTasksElem.textContent = totalThisWeek; + if (completedTasksElem) completedTasksElem.textContent = completedThisWeek; + if (pendingTasksElem) pendingTasksElem.textContent = totalThisWeek - completedThisWeek; + if (dueTasksElem) dueTasksElem.textContent = dueSoonTasks; + + const todayTasks = tasks.filter(t => { + if (t.archived || t.status === 'Done') return false; + if (!t.due_at) return false; + const d = new Date(t.due_at); + return d.toDateString() === now.toDateString(); + }).sort((a, b) => new Date(a.due_at) - new Date(b.due_at)); + + const priorityList = document.getElementById('priority-list'); + if (priorityList) { + if (todayTasks.length === 0) { + priorityList.innerHTML = '
No tasks for today
'; + } else { + priorityList.innerHTML = todayTasks.slice(0, 5).map(task => { + const sub = subjects.find(s => s.id === task.subject_id) || subjects[0]; + const timeStr = new Date(task.due_at).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }); + return ` +
+ ${escapeHtml(task.title)} + ${timeStr} +
+ `; + }).join(''); + + document.querySelectorAll('.priority-item').forEach(el => { + el.addEventListener('click', () => { + window.location.href = '/index.html'; + }); + }); + } + } + + const upcomingTasks = tasks.filter(t => { + if (t.archived || t.status === 'Done') return false; + if (!t.due_at) return false; + const d = new Date(t.due_at); + return d > now; + }).sort((a, b) => new Date(a.due_at) - new Date(b.due_at)).slice(0, 5); + + const deadlineList = document.getElementById('deadline-list'); + if (deadlineList) { + if (upcomingTasks.length === 0) { + deadlineList.innerHTML = '
No upcoming deadlines
'; + } else { + deadlineList.innerHTML = upcomingTasks.map(task => { + const daysDiff = Math.ceil((new Date(task.due_at) - now) / (1000 * 60 * 60 * 24)); + let dateClass = ''; + let dateText = formatDate(task.due_at); + if (daysDiff === 0) dateText = 'Today'; + else if (daysDiff === 1) dateText = 'Tomorrow'; + else if (daysDiff <= 3) dateClass = 'deadline-date'; + return ` +
+ ${escapeHtml(task.title)} + ${dateText} +
+ `; + }).join(''); + + document.querySelectorAll('.deadline-item').forEach(el => { + el.addEventListener('click', () => { + window.location.href = '/index.html'; + }); + }); + } + } + + const allTasks = [...tasks].filter(t => !t.archived).sort((a, b) => { + const dateA = new Date(a.due_at || a.created_at || 0); + const dateB = new Date(b.due_at || b.created_at || 0); + return dateB - dateA; + }).slice(0, 5); + + const recentList = document.getElementById('recent-list'); + if (recentList) { + if (allTasks.length === 0) { + recentList.innerHTML = '
No recent activity
'; + } else { + recentList.innerHTML = allTasks.map(task => { + const statusIcon = task.status === 'Done' ? '✓' : '○'; + const statusClass = task.status === 'Done' ? 'recent-text' : 'recent-text'; + const date = new Date(task.due_at || task.created_at || Date.now()); + const timeAgo = getTimeAgo(date); + const sub = subjects.find(s => s.id === task.subject_id) || subjects[0]; + return ` +
+
${statusIcon}
+
${escapeHtml(task.title)}
+
${timeAgo}
+
+ `; + }).join(''); + + document.querySelectorAll('.recent-item').forEach(el => { + el.addEventListener('click', () => { + window.location.href = '/index.html'; + }); + }); + } + } + + const streak = calculateStreak(tasks); + const streakElem = document.getElementById('streak-days'); + const streakBarElem = document.getElementById('streak-bar'); + const streakBestElem = document.getElementById('streak-best'); + + if (streakElem) streakElem.textContent = streak.current; + if (streakBarElem) { + const percent = streak.best > 0 ? (streak.current / streak.best) * 100 : 0; + streakBarElem.style.width = percent + '%'; + } + if (streakBestElem) streakBestElem.textContent = 'Best: ' + streak.best + ' days'; +} + +function escapeHtml(str) { + if (!str) return ''; + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +const startBtn = document.getElementById('start-planning-btn'); +if (startBtn) { + startBtn.addEventListener('click', () => { + window.location.href = '/index.html'; + }); +} + +store.subscribe(() => { + updateDashboard(); +}); + +store.fetchInitialData().then(() => { + updateDashboard(); +}); + +const greetingElem = document.querySelector('.greeting-text'); +if (greetingElem) { + const hour = new Date().getHours(); + let greeting = 'Good evening'; + if (hour < 12) greeting = 'Good morning'; + else if (hour < 18) greeting = 'Good afternoon'; + greetingElem.textContent = greeting; +} + +function setDate() { + const dateElem = document.getElementById('date-text'); + if (dateElem) { + const now = new Date(); + const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; + dateElem.textContent = now.toLocaleDateString('en-US', options); + } +} + +setDate(); \ No newline at end of file diff --git a/server.js b/server.js index 47e1429..abb1cae 100644 --- a/server.js +++ b/server.js @@ -13,11 +13,23 @@ app.use(express.json()); const page404Path = path.join(__dirname, '404.html'); const page500Path = path.join(__dirname, 'error.html'); +app.get('/', (req, res) => { + res.sendFile(path.join(__dirname, 'dashboard.html')); +}); + +app.get('/index.html', (req, res) => { + res.sendFile(path.join(__dirname, 'index.html')); +}); + +app.get('/dashboard.html', (req, res) => { + res.sendFile(path.join(__dirname, 'dashboard.html')); +}); + + // Static app.use('/css', express.static(path.join(__dirname, 'css'))); app.use('/js', express.static(path.join(__dirname, 'js'))); app.use(express.static(__dirname)); - initDb(); // Environment Validation @@ -568,7 +580,9 @@ app.use((err, req, res, next) => { return res.status(500).sendFile(page500Path); }); -// ================= SERVER ================= + + +// // ================= SERVER ================= const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log('Server running on port ' + PORT);