fix(tasks): enable editing goals and tasks

This commit is contained in:
Codex committed 2026-10-02 10:48:13 +00:00
1 parent 139e4c5198
commit 0a68782172
23 files changed
+191 -34

No files matched your search

+22 -9
View File
@@ -29,12 +29,12 @@
<nav class="task-filters" aria-label="${t('eyebrow')}">${['all','today','upcoming','done'].map(key => `<button class="chip ${filter === key ? 'selected' : ''}" aria-pressed="${filter === key}" onclick="setTaskFilter('${key}')">${t(key)}</button>`).join('')}</nav>
<section class="task-list" aria-live="polite">${visible.length ? visible.map(task => {
const goal = data.goals.find(item => item.id === task.goalId);
return `<article class="task-row ${task.done ? 'is-done' : ''} ${isOverdue(task) ? 'is-overdue' : ''}"><button class="task-check" type="button" aria-label="${task.done ? t('reopen') : t('complete')}: ${esc(task.title)}" aria-pressed="${task.done}" onclick="toggleTask('${esc(task.id)}')">${task.done ? '✓' : ''}</button><div class="task-copy"><strong>${esc(task.title)}</strong><div class="task-meta"><span class="task-priority ${esc(task.priority)}">${t(`priority.${task.priority}`)}</span>${goal ? `<span>${esc(goal.title)}</span>` : ''}<span>${isOverdue(task) ? `<b>${t('overdue')} · </b>` : ''}${task.dueDate ? t('due', { date: dateLabel(task.dueDate) }) : t('noDate')}</span></div></div><button class="task-delete" aria-label="${t('delete')}: ${esc(task.title)}" onclick="deleteTask('${esc(task.id)}')">×</button></article>`;
return `<article class="task-row ${task.done ? 'is-done' : ''} ${isOverdue(task) ? 'is-overdue' : ''}"><button class="task-check" type="button" aria-label="${task.done ? t('reopen') : t('complete')}: ${esc(task.title)}" aria-pressed="${task.done}" onclick="toggleTask('${esc(task.id)}')">${task.done ? '✓' : ''}</button><div class="task-copy"><strong>${esc(task.title)}</strong><div class="task-meta"><span class="task-priority ${esc(task.priority)}">${t(`priority.${task.priority}`)}</span>${goal ? `<span>${esc(goal.title)}</span>` : ''}<span>${isOverdue(task) ? `<b>${t('overdue')} · </b>` : ''}${task.dueDate ? t('due', { date: dateLabel(task.dueDate) }) : t('noDate')}</span></div></div><button class="task-edit" type="button" data-id="${esc(task.id)}" aria-label="${t('editTask')}: ${esc(task.title)}" onclick="openTaskEdit(this.dataset.id)">${t('edit')}</button><button class="task-delete" aria-label="${t('delete')}: ${esc(task.title)}" onclick="deleteTask('${esc(task.id)}')">×</button></article>`;
}).join('') : `<div class="task-empty"><span>○</span><p>${t('noTasks')}</p></div>`}</section>
<section class="goal-section"><div class="goal-section-head"><div><div class="eyebrow">${t('activeGoals')}</div></div><span class="goal-count">${activeGoals.length}</span></div>${activeGoals.length ? `<div class="goal-grid">${activeGoals.map(goal => {
const linked = data.tasks.filter(task => task.goalId === goal.id), completed = linked.filter(task => task.done).length, progress = linked.length ? Math.round(completed / linked.length * 100) : 0;
return `<article class="goal-card"><div class="goal-card-top"><div class="goal-mark">◎</div><div class="goal-actions">${goal.targetDate ? `<button class="goal-desktop-toggle ${goal.showOnDesktop ? 'selected' : ''}" aria-pressed="${Boolean(goal.showOnDesktop)}" onclick="toggleGoalDesktop('${esc(goal.id)}')">${t(goal.showOnDesktop ? 'desktopHide' : 'desktopShow')}</button>` : ''}<button class="goal-finish" aria-label="${t('goalComplete')}: ${esc(goal.title)}" onclick="setGoalDone('${esc(goal.id)}',true)">${t('goalComplete')}</button><button class="task-delete" aria-label="${t('delete')}: ${esc(goal.title)}" onclick="deleteGoal('${esc(goal.id)}')">×</button></div></div><h3>${esc(goal.title)}</h3>${goal.description ? `<p>${esc(goal.description)}</p>` : ''}<div class="goal-progress-line"><span>${t('progress', { done: completed, total: linked.length })}</span><span>${progress}%</span></div><div class="goal-progress"><i style="width:${progress}%"></i></div>${goal.targetDate ? `<div class="goal-date">${t('target')} · ${dateLabel(goal.targetDate)}</div>` : ''}</article>`;
}).join('')}</div>` : `<div class="goal-empty">${t('noGoals')}</div>`}${finishedGoals.length ? `<details class="finished-goals"><summary>${t('finishedGoals')} · ${finishedGoals.length}</summary><div class="goal-grid">${finishedGoals.map(goal => `<article class="goal-card is-goal-done"><div class="goal-card-top"><div class="goal-mark">✓</div><button class="goal-finish" onclick="setGoalDone('${esc(goal.id)}',false)">${t('goalReopen')}</button></div><h3>${esc(goal.title)}</h3></article>`).join('')}</div></details>` : ''}</section>`;
return `<article class="goal-card"><div class="goal-card-top"><div class="goal-mark">◎</div><div class="goal-actions">${goal.targetDate ? `<button class="goal-desktop-toggle ${goal.showOnDesktop ? 'selected' : ''}" aria-pressed="${Boolean(goal.showOnDesktop)}" onclick="toggleGoalDesktop('${esc(goal.id)}')">${t(goal.showOnDesktop ? 'desktopHide' : 'desktopShow')}</button>` : ''}<button class="task-edit" type="button" data-id="${esc(goal.id)}" aria-label="${t('editGoal')}: ${esc(goal.title)}" onclick="openGoalForm(this.dataset.id)">${t('edit')}</button><button class="goal-finish" aria-label="${t('goalComplete')}: ${esc(goal.title)}" onclick="setGoalDone('${esc(goal.id)}',true)">${t('goalComplete')}</button><button class="task-delete" aria-label="${t('delete')}: ${esc(goal.title)}" onclick="deleteGoal('${esc(goal.id)}')">×</button></div></div><h3>${esc(goal.title)}</h3>${goal.description ? `<p>${esc(goal.description)}</p>` : ''}<div class="goal-progress-line"><span>${t('progress', { done: completed, total: linked.length })}</span><span>${progress}%</span></div><div class="goal-progress"><i style="width:${progress}%"></i></div>${goal.targetDate ? `<div class="goal-date">${t('target')} · ${dateLabel(goal.targetDate)}</div>` : ''}</article>`;
}).join('')}</div>` : `<div class="goal-empty">${t('noGoals')}</div>`}${finishedGoals.length ? `<details class="finished-goals"><summary>${t('finishedGoals')} · ${finishedGoals.length}</summary><div class="goal-grid">${finishedGoals.map(goal => `<article class="goal-card is-goal-done"><div class="goal-card-top"><div class="goal-mark">✓</div><div class="goal-actions"><button class="task-edit" type="button" data-id="${esc(goal.id)}" aria-label="${t('editGoal')}: ${esc(goal.title)}" onclick="openGoalForm(this.dataset.id)">${t('edit')}</button><button class="goal-finish" onclick="setGoalDone('${esc(goal.id)}',false)">${t('goalReopen')}</button></div></div><h3>${esc(goal.title)}</h3></article>`).join('')}</div></details>` : ''}</section>`;
}
window.tasksApp = renderTasks;
@@ -47,14 +47,27 @@
};
window.toggleTask = id => { const task = board().tasks.find(item => item.id === id); if (task) window.LifeOSActions.setTaskDone(id, !task.done); };
window.deleteTask = id => { window.LifeOSActions.deleteTask(id); toast('tasks.taskRemoved'); };
window.openGoalForm = () => {
document.querySelector('#modal').innerHTML = `<div class="modal" onclick="if(event.target===this) closeModal()"><form class="modalbox goal-form" onsubmit="saveGoal(event)" role="dialog" aria-modal="true" aria-labelledby="goal-form-title"><button type="button" class="modal-close" onclick="closeModal()" aria-label="${LifeI18n.t('common.close')}">×</button><div class="eyebrow">${t('eyebrow')}</div><h2 id="goal-form-title">${t('goalTitle')}</h2><label>${t('goalPlaceholder')}<input id="goal-new-title" maxlength="100" required autofocus></label><label>${t('goalDescription')}<textarea id="goal-new-description" maxlength="240" rows="3"></textarea></label><label>${t('target')}<input id="goal-new-date" type="date" oninput="document.querySelector('#goal-new-desktop').disabled=!this.value"></label><label class="goal-pin-option"><input id="goal-new-desktop" type="checkbox" disabled>${t('pinOnCreate')}</label><div class="actions"><button class="primary" type="submit">${t('save')}</button><button class="secondary" type="button" onclick="closeModal()">${t('cancel')}</button></div></form></div>`;
window.openTaskEdit = id => {
const task = board().tasks.find(item => item.id === id); if (!task) return;
const goals = board().goals.map(goal => `<option value="${esc(goal.id)}" ${goal.id === task.goalId ? 'selected' : ''}>${esc(goal.title)}</option>`).join('');
document.querySelector('#modal').innerHTML = `<div class="modal" onclick="if(event.target===this) closeModal()"><form class="modalbox goal-form" data-id="${esc(id)}" onsubmit="saveTaskEdit(event)" role="dialog" aria-modal="true" aria-labelledby="task-edit-title"><button type="button" class="modal-close" onclick="closeModal()" aria-label="${LifeI18n.t('common.close')}">×</button><div class="eyebrow">${t('eyebrow')}</div><h2 id="task-edit-title">${t('editTask')}</h2><label>${t('taskPlaceholder')}<input id="task-edit-title-input" maxlength="140" required value="${esc(task.title)}"></label><label>${t('dueDate')}<input id="task-edit-date" type="date" value="${esc(task.dueDate || '')}"></label><label>${t('goal')}<select id="task-edit-goal"><option value="">${t('anyGoal')}</option>${goals}</select></label><label>${t('priorityLabel')}<select id="task-edit-priority">${['normal','high','low'].map(value => `<option value="${value}" ${task.priority === value ? 'selected' : ''}>${t(`priority.${value}`)}</option>`).join('')}</select></label><div class="actions"><button class="primary" type="submit">${t('save')}</button><button class="secondary" type="button" onclick="closeModal()">${t('cancel')}</button></div></form></div>`;
setTimeout(() => document.querySelector('#task-edit-title-input')?.focus(), 0);
};
window.saveTaskEdit = event => {
event.preventDefault(); const form = event.currentTarget, id = form.dataset.id;
window.LifeOSActions.updateTask(id, { title: form.querySelector('#task-edit-title-input').value, dueDate: form.querySelector('#task-edit-date').value, goalId: form.querySelector('#task-edit-goal').value, priority: form.querySelector('#task-edit-priority').value });
closeModal(); toast('tasks.taskUpdated');
};
window.openGoalForm = (id = '') => {
const goal = id ? board().goals.find(item => item.id === id) : null; if (id && !goal) return;
document.querySelector('#modal').innerHTML = `<div class="modal" onclick="if(event.target===this) closeModal()"><form class="modalbox goal-form" data-id="${esc(id)}" onsubmit="saveGoal(event)" role="dialog" aria-modal="true" aria-labelledby="goal-form-title"><button type="button" class="modal-close" onclick="closeModal()" aria-label="${LifeI18n.t('common.close')}">×</button><div class="eyebrow">${t('eyebrow')}</div><h2 id="goal-form-title">${t(goal ? 'editGoal' : 'goalTitle')}</h2><label>${t('goalPlaceholder')}<input id="goal-new-title" maxlength="100" required value="${esc(goal?.title || '')}"></label><label>${t('goalDescription')}<textarea id="goal-new-description" maxlength="240" rows="3">${esc(goal?.description || '')}</textarea></label><label>${t('target')}<input id="goal-new-date" type="date" value="${esc(goal?.targetDate || '')}" oninput="document.querySelector('#goal-new-desktop').disabled=!this.value;if(!this.value)document.querySelector('#goal-new-desktop').checked=false"></label><label class="goal-pin-option"><input id="goal-new-desktop" type="checkbox" ${goal?.showOnDesktop ? 'checked' : ''} ${goal?.targetDate ? '' : 'disabled'}>${t('pinOnCreate')}</label><div class="actions"><button class="primary" type="submit">${t('save')}</button><button class="secondary" type="button" onclick="closeModal()">${t('cancel')}</button></div></form></div>`;
setTimeout(() => document.querySelector('#goal-new-title')?.focus(), 0);
};
window.saveGoal = event => {
event.preventDefault(); const title = document.querySelector('#goal-new-title').value.trim(); if (!title) return;
window.LifeOSActions.createGoal({ title, description: document.querySelector('#goal-new-description').value.trim(), targetDate: document.querySelector('#goal-new-date').value || '', showOnDesktop: document.querySelector('#goal-new-desktop').checked });
document.querySelector('#modal').innerHTML = ''; toast('tasks.goalCreated');
event.preventDefault(); const form = event.currentTarget, title = form.querySelector('#goal-new-title').value.trim(); if (!title) return;
const values = { title, description: form.querySelector('#goal-new-description').value, targetDate: form.querySelector('#goal-new-date').value, showOnDesktop: form.querySelector('#goal-new-desktop').checked };
if (form.dataset.id) window.LifeOSActions.updateGoal(form.dataset.id, values); else window.LifeOSActions.createGoal(values);
closeModal(); toast(form.dataset.id ? 'tasks.goalUpdated' : 'tasks.goalCreated');
};
window.toggleGoalDesktop = id => { const data = board(), goal = data.goals.find(item => item.id === id); if (!goal || !goal.targetDate) return; goal.showOnDesktop = !goal.showOnDesktop; persist(data); };
window.renderDesktopGoalCountdowns = () => { const container = document.querySelector('#desktop-goal-countdowns'); if (!container) return; const goals = board().goals.filter(goal => !goal.done && goal.targetDate && goal.showOnDesktop); if (!goals.length) { container.innerHTML = ''; container.classList.add('hidden'); return; } container.classList.remove('hidden'); const now = new Date(), todayUtc = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()); container.innerHTML = `<div class="desktop-goal-heading">${t('countdown')}</div>${goals.map(goal => { const [year, month, date] = goal.targetDate.split('-').map(Number), delta = Math.round((Date.UTC(year, month - 1, date) - todayUtc) / 864e5), count = Math.abs(delta), label = delta === 0 ? t('todayTarget') : delta > 0 ? t('daysLeft', { count }) : t('daysOverdue', { count }); return `<button class="desktop-goal-card" onclick="openApp('tasks')"><span>${esc(goal.title)}</span><strong>${label}</strong><small>${dateLabel(goal.targetDate)}</small></button>`; }).join('')}`; };
@@ -66,6 +79,6 @@
window.confirmDeleteGoal = id => { window.LifeOSActions.deleteGoal(id); document.querySelector('#modal').innerHTML = ''; toast('tasks.goalRemoved'); };
const style = document.createElement('style');
style.textContent = `.task-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.task-head h1{max-width:430px}.task-head .secondary{white-space:nowrap}.task-focus{display:flex;align-items:center;justify-content:space-between;margin:18px 0;padding:18px 20px;background:linear-gradient(115deg,color-mix(in srgb,var(--accent) 15%,var(--panel2)),var(--panel2));border:1px solid var(--line);border-radius:13px}.task-focus .eyebrow{margin-bottom:5px}.task-focus strong{font-size:30px;letter-spacing:-.06em}.task-focus span{margin-left:10px;color:var(--muted);font-size:12px}.task-focus-mark{font-size:26px;color:var(--accent)}.task-quick{display:grid;grid-template-columns:minmax(130px,1fr) 145px 120px 95px auto;gap:7px}.task-quick input,.task-quick select,.goal-form input,.goal-form textarea{min-width:0;border:1px solid var(--line);background:var(--panel2);border-radius:8px;padding:10px 11px;outline:none}.task-quick input:focus,.task-quick select:focus,.goal-form input:focus,.goal-form textarea:focus{border-color:var(--accent)}.task-quick select{font-size:12px}.task-quick .primary{padding:10px 11px;white-space:nowrap}.task-filters{display:flex;gap:7px;flex-wrap:wrap;margin:19px 0 8px}.task-filters .chip{padding:7px 12px}.task-list{display:grid;gap:7px}.task-row{display:flex;align-items:center;gap:12px;padding:12px;background:color-mix(in srgb,var(--panel2) 55%,transparent);border:1px solid var(--line);border-radius:10px}.task-check{flex:none;width:21px;height:21px;border:1px solid var(--muted);border-radius:7px;background:transparent;color:var(--accent);font-weight:700}.task-check[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:var(--bg)}.task-copy{min-width:0;flex:1}.task-copy>strong{display:block;font-size:13px;font-weight:550;overflow-wrap:anywhere}.task-meta{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:5px;color:var(--muted);font-size:10px}.task-meta span{display:inline-flex;align-items:center;gap:4px}.task-meta b,.is-overdue .task-meta{color:#df8a70}.task-priority{font:9px 'DM Mono';letter-spacing:.05em}.task-priority.high{color:#df8a70}.task-priority.low{color:var(--muted)}.is-done .task-copy>strong{text-decoration:line-through;color:var(--muted)}.task-delete{width:28px;height:28px;border:0;border-radius:7px;background:transparent;color:var(--muted);font-size:19px;line-height:1}.task-delete:hover{background:var(--panel2);color:var(--ink)}.task-empty,.goal-empty{padding:21px;text-align:center;color:var(--muted);font-size:13px}.task-empty span{font-size:23px;color:var(--accent)}.goal-section{margin-top:24px;padding-top:16px;border-top:1px solid var(--line)}.goal-section-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.goal-section-head .eyebrow{margin:0}.goal-count{font:11px 'DM Mono';color:var(--muted)}.goal-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.goal-card{min-width:0;padding:14px;border:1px solid var(--line);border-radius:11px;background:color-mix(in srgb,var(--panel2) 55%,transparent)}.goal-card-top{display:flex;justify-content:space-between;align-items:center}.goal-actions{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}.goal-desktop-toggle{border:1px solid var(--line);border-radius:7px;background:transparent;color:var(--muted);font:9px 'DM Mono';padding:6px 8px;white-space:nowrap}.goal-desktop-toggle.selected{color:var(--accent);border-color:var(--accent)}.goal-form label.goal-pin-option{display:flex!important;grid-template-columns:18px 1fr;align-items:center;gap:8px!important}.goal-form label.goal-pin-option input{width:16px;height:16px;min-width:16px;padding:0;accent-color:var(--accent)}.goal-finish{border:0;background:transparent;color:var(--muted);font:9px 'DM Mono';letter-spacing:.04em;padding:5px}.goal-finish:hover{color:var(--accent)}.finished-goals{margin-top:14px}.finished-goals summary{cursor:pointer;color:var(--muted);font:10px 'DM Mono';letter-spacing:.08em;margin-bottom:9px}.is-goal-done{opacity:.72}.goal-mark{font-size:20px;color:var(--accent)}.goal-card h3{margin:8px 0 4px;font-size:15px;letter-spacing:-.025em;overflow-wrap:anywhere}.goal-card p{margin:0 0 12px;color:var(--muted);font-size:11px;line-height:1.5}.goal-progress-line{display:flex;justify-content:space-between;gap:8px;margin-top:11px;font:9px 'DM Mono';color:var(--muted)}.goal-progress{height:4px;background:var(--line);border-radius:5px;margin-top:5px;overflow:hidden}.goal-progress i{display:block;height:100%;background:var(--accent);border-radius:5px}.goal-date{margin-top:10px;color:var(--muted);font-size:10px}.goal-form{display:grid;gap:13px}.goal-form h2{font-size:21px;margin-bottom:0}.goal-form label{display:grid;gap:6px;color:var(--muted);font-size:12px}.goal-form textarea{resize:vertical}.goal-form .actions{margin:0}.desktop-goal-countdowns{position:absolute;z-index:1;top:24px;right:28px;width:min(310px,30vw);max-height:72vh;overflow:auto;display:gr Line truncated
style.textContent = `.task-head{display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.task-head h1{max-width:430px}.task-head .secondary{white-space:nowrap}.task-focus{display:flex;align-items:center;justify-content:space-between;margin:18px 0;padding:18px 20px;background:linear-gradient(115deg,color-mix(in srgb,var(--accent) 15%,var(--panel2)),var(--panel2));border:1px solid var(--line);border-radius:13px}.task-focus .eyebrow{margin-bottom:5px}.task-focus strong{font-size:30px;letter-spacing:-.06em}.task-focus span{margin-left:10px;color:var(--muted);font-size:12px}.task-focus-mark{font-size:26px;color:var(--accent)}.task-quick{display:grid;grid-template-columns:minmax(130px,1fr) 145px 120px 95px auto;gap:7px}.task-quick input,.task-quick select,.goal-form input,.goal-form textarea,.goal-form select{min-width:0;border:1px solid var(--line);background:var(--panel2);border-radius:8px;padding:10px 11px;outline:none}.task-quick input:focus,.task-quick select:focus,.goal-form input:focus,.goal-form textarea:focus,.goal-form select:focus{border-color:var(--accent)}.task-quick select{font-size:12px}.task-quick .primary{padding:10px 11px;white-space:nowrap}.task-filters{display:flex;gap:7px;flex-wrap:wrap;margin:19px 0 8px}.task-filters .chip{padding:7px 12px}.task-list{display:grid;gap:7px}.task-row{display:flex;align-items:center;gap:12px;padding:12px;background:color-mix(in srgb,var(--panel2) 55%,transparent);border:1px solid var(--line);border-radius:10px}.task-check{flex:none;width:21px;height:21px;border:1px solid var(--muted);border-radius:7px;background:transparent;color:var(--accent);font-weight:700}.task-check[aria-pressed=true]{background:var(--accent);border-color:var(--accent);color:var(--bg)}.task-copy{min-width:0;flex:1}.task-copy>strong{display:block;font-size:13px;font-weight:550;overflow-wrap:anywhere}.task-meta{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-top:5px;color:var(--muted);font-size:10px}.task-meta span{display:inline-flex;align-items:center;gap:4px}.task-meta b,.is-overdue .task-meta{color:#df8a70}.task-priority{font:9px 'DM Mono';letter-spacing:.05em}.task-priority.high{color:#df8a70}.task-priority.low{color:var(--muted)}.is-done .task-copy>strong{text-decoration:line-through;color:var(--muted)}.task-edit{border:1px solid var(--line);border-radius:7px;background:transparent;color:var(--muted);font:10px 'DM Mono';padding:6px 8px;white-space:nowrap}.task-edit:hover,.task-edit:focus-visible{color:var(--accent);border-color:var(--accent)}.task-delete{width:28px;height:28px;border:0;border-radius:7px;background:transparent;color:var(--muted);font-size:19px;line-height:1}.task-delete:hover{background:var(--panel2);color:var(--ink)}.task-empty,.goal-empty{padding:21px;text-align:center;color:var(--muted);font-size:13px}.task-empty span{font-size:23px;color:var(--accent)}.goal-section{margin-top:24px;padding-top:16px;border-top:1px solid var(--line)}.goal-section-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.goal-section-head .eyebrow{margin:0}.goal-count{font:11px 'DM Mono';color:var(--muted)}.goal-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.goal-card{min-width:0;padding:14px;border:1px solid var(--line);border-radius:11px;background:color-mix(in srgb,var(--panel2) 55%,transparent)}.goal-card-top{display:flex;justify-content:space-between;align-items:center}.goal-actions{display:flex;align-items:center;gap:4px;flex-wrap:wrap;justify-content:flex-end}.goal-desktop-toggle{border:1px solid var(--line);border-radius:7px;background:transparent;color:var(--muted);font:9px 'DM Mono';padding:6px 8px;white-space:nowrap}.goal-desktop-toggle.selected{color:var(--accent);border-color:var(--accent)}.goal-form label.goal-pin-option{display:flex!important;grid-template-columns:18px 1fr;align-items:center;gap:8px!important}.goal-form label.goal-pin-option input{width:16px;height:16px;min-width:16px;padding:0;accent-color:var(--accent)}.goal-finish{border:0;background:transparent;color:var(--muted);font:9px 'DM Mono';letter-spacing:.04em;padding:5px}.goal-finish:hover{color:var(--accent)}.finished-goals{margin-top:14px}.finished-goals summary{cursor:pointer;color:var(--muted);font:10px 'DM Mono';letter-spacing:.08em;margin-bottom:9px}.is-goal-done{opacity:.72}.goal-mark{font-size:20px;color:var(--accent)}.goal-card h3{margin:8px 0 4px;font-size:15px;letter-spacing:-.025em;overflow-wrap:anywhere}.goal-card p{margin:0 0 12px;color:var(--muted);font-size:11px;line-height:1.5}.goal-progress-line{display:flex;justify-content:space-between;gap:8px;margin-top:11px;font:9px 'DM Mono';color:var(--muted)}.goal-progress{height:4px;background:var(--line);border-radius:5px;margin-top:5px;overflow:hidden}.goal-progress i{display:block;height:100%;background:var(--accent);border-radius:5px}.goal-date{margin-top:10px;color:var(--muted);font-size:10px}.goal-form{display:grid;gap:13px}.goal-form h2{font-size:21px;ma Line truncated
document.head.append(style);
})();