@zaclinley/dsh-mailharbor 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.zh.md +17 -17
- package/lib/client.js +305 -5
- package/lib/client.js.map +3 -3
- package/lib/index.js +172 -3
- package/lib/index.js.map +3 -3
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -35,7 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// src/client/styles.css
|
|
38
|
-
var styles_default = "/* MailHarbor panel + settings.\n Tokens come from the DSH shell (dark by default); fallbacks match the\n default dark theme so the panel also renders in a bare host page.\n Component rules are all scoped under `.mailharbor` and the generic element\n reset lives in `:where()` so it cannot outrank a component class. */\n\n.mailharbor {\n --m-bg: var(--dsw-alias-bg-base, #151517);\n --m-bg-1: var(--dsw-alias-bg-layer-1, #232324);\n --m-bg-2: var(--dsw-alias-bg-layer-2, #2c2c2e);\n --m-bg-3: var(--dsw-alias-bg-layer-3, #353638);\n --m-line: var(--dsw-alias-border-l2, #ffffff1f);\n --m-line-soft: var(--dsw-alias-border-l1, #ffffff0f);\n --m-line-strong: var(--dsw-alias-border-l3, #ffffff29);\n --m-text: var(--dsw-alias-label-primary, #f9fafb);\n --m-text-2: var(--dsw-alias-label-secondary, #cfd3d6);\n --m-text-3: var(--dsw-alias-label-tertiary, #adb2b8);\n --m-caption: var(--dsw-alias-label-caption, #81858c);\n --m-accent: #5686fe;\n --m-accent-soft: rgba(86, 134, 254, 0.14);\n --m-primary-bg: var(--dsw-alias-brand-primary, #f9fafb);\n --m-primary-fg: var(--dsw-alias-label-primary-foreground, #0f1115);\n --m-hover: var(--dsw-alias-interactive-bg-hover, #ffffff14);\n --m-danger: #f25a5a;\n --m-ok: #3fbf7f;\n --m-warn: var(--dsw-alias-state-warn-label, #dd8629);\n --m-radius: 8px;\n --m-shadow: 0 18px 60px rgba(0, 0, 0, 0.5);\n\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--m-bg);\n color: var(--m-text);\n font-size: 13px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n\n.mailharbor *,\n.mailharbor *::before,\n.mailharbor *::after {\n box-sizing: border-box;\n}\n\n/* ---------- base controls ---------- */\n\n.mailharbor :where(button) {\n font: inherit;\n color: inherit;\n background: transparent;\n border: 0;\n margin: 0;\n cursor: pointer;\n}\n\n.mailharbor button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 30px;\n padding: 0 12px;\n border-radius: var(--m-radius);\n border: 1px solid transparent;\n color: var(--m-text-2);\n font-size: 12.5px;\n font-weight: 500;\n white-space: nowrap;\n transition:\n background 120ms ease,\n color 120ms ease,\n border-color 120ms ease;\n}\n\n.mailharbor button:hover:not(:disabled) {\n background: var(--m-hover);\n color: var(--m-text);\n}\n\n.mailharbor button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.mailharbor button.primary {\n background: var(--m-primary-bg);\n color: var(--m-primary-fg);\n border-color: transparent;\n}\n\n.mailharbor button.primary:hover:not(:disabled) {\n background: var(--m-primary-bg);\n filter: brightness(0.94);\n color: var(--m-primary-fg);\n}\n\n.mailharbor button.ghost {\n border-color: var(--m-line);\n color: var(--m-text-2);\n}\n\n.mailharbor button.ghost:hover:not(:disabled) {\n border-color: var(--m-line-strong);\n color: var(--m-text);\n}\n\n.mailharbor button.subtle {\n color: var(--m-text-3);\n padding: 0 8px;\n}\n\n.mailharbor button.icon {\n width: 30px;\n padding: 0;\n}\n\n.mailharbor button.danger {\n color: var(--m-danger);\n}\n\n.mailharbor input,\n.mailharbor select,\n.mailharbor textarea {\n font: inherit;\n color: var(--m-text);\n background: var(--m-bg-1);\n border: 1px solid var(--m-line);\n border-radius: var(--m-radius);\n padding: 0 10px;\n height: 32px;\n min-width: 0;\n}\n\n.mailharbor textarea {\n height: auto;\n padding: 8px 10px;\n resize: vertical;\n line-height: 1.6;\n}\n\n.mailharbor select {\n padding-right: 26px;\n appearance: none;\n background-image:\n linear-gradient(45deg, transparent 50%, var(--m-text-3) 50%),\n linear-gradient(135deg, var(--m-text-3) 50%, transparent 50%);\n background-position:\n calc(100% - 15px) 14px,\n calc(100% - 10px) 14px;\n background-size:\n 5px 5px,\n 5px 5px;\n background-repeat: no-repeat;\n}\n\n.mailharbor ::placeholder {\n color: var(--m-caption);\n}\n\n.mailharbor input:focus-visible,\n.mailharbor select:focus-visible,\n.mailharbor textarea:focus-visible,\n.mailharbor button:focus-visible,\n.mailharbor [contenteditable='true']:focus-visible {\n outline: 2px solid rgba(86, 134, 254, 0.55);\n outline-offset: -1px;\n}\n\n.mailharbor .spacer {\n flex: 1;\n}\n\n.mailharbor .muted {\n color: var(--m-text-3);\n}\n\n.mailharbor .small {\n font-size: 12px;\n}\n\n.mailharbor .badge {\n display: inline-flex;\n align-items: center;\n height: 18px;\n padding: 0 6px;\n border-radius: 999px;\n font-size: 10.5px;\n font-weight: 500;\n background: var(--m-bg-3);\n color: var(--m-text-2);\n}\n\n.mailharbor .badge.ok {\n background: rgba(63, 191, 127, 0.16);\n color: var(--m-ok);\n}\n\n.mailharbor .badge.warn {\n background: rgba(221, 134, 41, 0.16);\n color: var(--m-warn);\n}\n\n.mailharbor .error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.1);\n border-bottom: 1px solid rgba(242, 90, 90, 0.2);\n font-size: 12.5px;\n}\n\n/* ---------- shell ---------- */\n\n.mailharbor-topbar {\n display: flex;\n align-items: center;\n gap: 10px;\n height: 52px;\n padding: 0 14px;\n border-bottom: 1px solid var(--m-line-soft);\n background: var(--m-bg);\n flex: none;\n}\n\n.mailharbor-account {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n max-width: 220px;\n padding: 4px 8px 4px 4px;\n border-radius: 999px;\n border: 1px solid transparent;\n cursor: default;\n}\n\n.mailharbor-account:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-account .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.mailharbor-account select {\n height: 26px;\n background: transparent;\n border-color: transparent;\n font-weight: 500;\n}\n\n.mailharbor-body {\n display: flex;\n flex: 1;\n min-height: 0;\n position: relative;\n}\n\n.mailharbor button.active {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-list {\n display: flex;\n flex-direction: column;\n width: clamp(280px, 28vw, 360px);\n flex: none;\n border-right: 1px solid var(--m-line-soft);\n min-height: 0;\n}\n\n.mailharbor-reader {\n flex: 1;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='reader'] .mailharbor-list {\n display: none;\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='list'] .mailharbor-reader {\n display: none;\n}\n\n/* ---------- segmented control ---------- */\n\n.mailharbor-segment {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n border-radius: 9px;\n background: var(--m-bg-2);\n}\n\n.mailharbor-segment button {\n height: 26px;\n padding: 0 12px;\n border-radius: 7px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor-segment button:hover:not(.active) {\n color: var(--m-text-2);\n background: transparent;\n}\n\n.mailharbor-segment button.active {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n/* ---------- list ---------- */\n\n.mailharbor-filters {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-filters select {\n width: 128px;\n flex: none;\n font-size: 12px;\n}\n\n.mailharbor-filters input[type='search'] {\n flex: 1;\n height: 30px;\n font-size: 12.5px;\n}\n\n.mailharbor-rows {\n flex: 1;\n overflow: auto;\n min-height: 0;\n}\n\n.mailharbor-row {\n display: flex;\n flex-direction: column;\n gap: 3px;\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-bottom: 1px solid var(--m-line-soft);\n border-left: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n text-align: left;\n cursor: pointer;\n user-select: none;\n}\n\n.mailharbor-row:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-row.selected {\n background: var(--m-accent-soft);\n border-left-color: var(--m-accent);\n}\n\n.mailharbor-row .line-1,\n.mailharbor-row .line-2 {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n width: 100%;\n}\n\n.mailharbor-row .from {\n font-weight: 600;\n font-size: 12.5px;\n color: var(--m-text-2);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-row .date {\n margin-left: auto;\n color: var(--m-caption);\n font-size: 11px;\n flex: none;\n}\n\n.mailharbor-row .subject {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n.mailharbor-row .snippet {\n color: var(--m-caption);\n font-size: 11.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n width: 100%;\n}\n\n.mailharbor-row.unread .from,\n.mailharbor-row.unread .subject {\n color: var(--m-text);\n}\n\n.mailharbor-row .dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--m-accent);\n flex: none;\n}\n\n.mailharbor-row .paperclip {\n color: var(--m-caption);\n flex: none;\n display: inline-flex;\n}\n\n.mailharbor-list-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-top: 1px solid var(--m-line-soft);\n color: var(--m-text-3);\n font-size: 11.5px;\n flex: none;\n}\n\n.mailharbor-empty {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 48px 24px;\n color: var(--m-text-3);\n text-align: center;\n}\n\n.mailharbor-empty svg {\n opacity: 0.5;\n}\n\n.mailharbor-empty .title {\n color: var(--m-text-2);\n font-size: 13px;\n font-weight: 500;\n}\n\n/* ---------- reader ---------- */\n\n.mailharbor-reader-head {\n padding: 16px 20px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.mailharbor-reader-title {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.mailharbor-reader-title h2 {\n margin: 0;\n font-size: 17px;\n line-height: 1.35;\n font-weight: 600;\n letter-spacing: -0.01em;\n word-break: break-word;\n}\n\n.mailharbor-reader-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px 10px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor-reader-meta .who {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: var(--m-text-2);\n}\n\n.mailharbor-reader-meta .who strong {\n color: var(--m-text);\n font-weight: 600;\n}\n\n.mailharbor-reader-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.mailharbor-reader-body {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding: 14px 18px 18px;\n background: var(--m-bg-2);\n}\n\n.mailharbor-reader-body iframe {\n flex: 1;\n width: 100%;\n border: 0;\n border-radius: 10px;\n background: #fff;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n}\n\n.mailharbor-reader-body pre {\n flex: 1;\n overflow: auto;\n margin: 0;\n padding: 20px 22px;\n white-space: pre-wrap;\n word-break: break-word;\n background: #fff;\n border-radius: 10px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n color: #171a21;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12.5px;\n line-height: 1.7;\n}\n\n.mailharbor-attachments {\n padding: 10px 18px;\n border-top: 1px solid var(--m-line-soft);\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n flex: none;\n background: var(--m-bg);\n}\n\n.mailharbor-attachment {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 30px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: var(--m-radius);\n font-size: 12px;\n text-decoration: none;\n color: var(--m-text-2);\n max-width: 260px;\n background: var(--m-bg-1);\n}\n\n.mailharbor-attachment:hover {\n border-color: var(--m-line-strong);\n color: var(--m-text);\n}\n\n.mailharbor-attachment .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* ---------- AI rail ---------- */\n\n.mailharbor-ai {\n display: flex;\n flex-direction: column;\n width: 340px;\n flex: none;\n min-height: 0;\n border-left: 1px solid var(--m-line-soft);\n background: var(--m-bg);\n}\n\n.mailharbor-ai-head {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 46px;\n padding: 0 8px 0 14px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-head strong {\n font-size: 13px;\n font-weight: 600;\n}\n\n.mailharbor-ai-confirm {\n display: inline-flex;\n gap: 2px;\n}\n\n.mailharbor-ai-context {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 9px 14px 10px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-context strong {\n font-size: 12.5px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-ai-warn {\n padding: 8px 14px;\n color: var(--m-warn);\n background: rgba(221, 134, 41, 0.1);\n font-size: 12px;\n flex: none;\n}\n\n.mailharbor-ai-quick {\n display: flex;\n gap: 6px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-quick button {\n flex: 1;\n padding: 0 6px;\n}\n\n.mailharbor-ai-list {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px 14px;\n}\n\n.mailharbor-ai-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 30px 12px;\n text-align: center;\n color: var(--m-text-3);\n}\n\n.mailharbor-ai-empty .title {\n color: var(--m-text-2);\n font-weight: 500;\n font-size: 12.5px;\n}\n\n.mailharbor-ai-card {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n overflow: hidden;\n}\n\n.mailharbor-ai-card.generating {\n opacity: 0.7;\n}\n\n.mailharbor-ai-card-head {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 8px 7px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-ai-card-head > span:first-child {\n color: var(--m-text-2);\n font-weight: 600;\n}\n\n.mailharbor-ai-summary {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 10px 12px;\n}\n\n.mailharbor-ai-summary section h4 {\n margin: 0 0 3px;\n font-size: 11px;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.mailharbor-ai-summary section p {\n margin: 0;\n white-space: pre-wrap;\n font-size: 12.5px;\n line-height: 1.65;\n color: var(--m-text);\n}\n\n.mailharbor-ai-text {\n padding: 10px 12px;\n\n white-space: pre-wrap;\n font-size: 12.5px;\n line-height: 1.65;\n color: var(--m-text);\n}\n\n.mailharbor-ai-card-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n padding: 6px 8px;\n border-top: 1px solid var(--m-line-soft);\n}\n\n.mailharbor-ai-card-actions button {\n height: 26px;\n padding: 0 8px;\n font-size: 11.5px;\n}\n\n.mailharbor-ai-ask {\n display: flex;\n gap: 6px;\n padding: 10px 12px;\n border-top: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-ask input {\n flex: 1;\n height: 32px;\n}\n\n.mailharbor-ai-error {\n color: var(--m-danger);\n font-size: 12px;\n padding: 0 2px;\n}\n\n@media (max-width: 1540px) {\n .mailharbor-ai {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(420px, 94%);\n z-index: 6;\n border-left: 1px solid var(--m-line);\n box-shadow: -12px 0 40px rgba(0, 0, 0, 0.45);\n }\n}\n\n/* ---------- AI summary ---------- */\n\n.mailharbor-divider {\n width: 1px;\n height: 18px;\n margin: 0 4px;\n background: var(--m-line);\n}\n\n.mailharbor-summary {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.mailharbor-summary section h4 {\n margin: 0 0 6px;\n font-size: 11.5px;\n font-weight: 600;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.mailharbor-summary section p {\n margin: 0;\n white-space: pre-wrap;\n line-height: 1.75;\n color: var(--m-text);\n}\n\n/* ---------- modal / forms ---------- */\n\n.mailharbor-portal {\n position: fixed;\n inset: 0;\n z-index: 80;\n height: auto;\n background: transparent;\n pointer-events: none;\n}\n\n.mailharbor-portal .mailharbor-modal-mask {\n pointer-events: auto;\n}\n\n.mailharbor-modal-mask {\n position: fixed;\n inset: 0;\n z-index: 60;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: rgba(0, 0, 0, 0.55);\n backdrop-filter: blur(2px);\n}\n\n.mailharbor-modal {\n display: flex;\n flex-direction: column;\n width: min(720px, 100%);\n max-height: 86vh;\n overflow: hidden;\n border: 1px solid var(--m-line);\n border-radius: 14px;\n background: var(--m-bg-1);\n color: var(--m-text);\n box-shadow: var(--m-shadow);\n}\n\n.mailharbor-modal > header {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 52px;\n padding: 0 14px 0 18px;\n border-bottom: 1px solid var(--m-line-soft);\n font-size: 14px;\n font-weight: 600;\n}\n\n.mailharbor-modal .content {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 18px;\n overflow: auto;\n}\n\n.mailharbor-modal > footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 18px;\n border-top: 1px solid var(--m-line-soft);\n}\n\n.mailharbor-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n}\n\n.mailharbor-field > input,\n.mailharbor-field > select,\n.mailharbor-field > textarea,\n.mailharbor-card > textarea {\n width: 100%;\n min-width: 0;\n}\n\n.mailharbor-field > label {\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: 10px;\n min-width: 0;\n}\n\n.mailharbor-grid.three {\n grid-template-columns: minmax(0, 2fr) minmax(72px, 90px) auto;\n align-items: end;\n min-width: 0;\n}\n\n.mailharbor-toggle {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n color: var(--m-text-2);\n font-size: 12.5px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.mailharbor-toggle input[type='checkbox'] {\n width: 14px;\n height: 14px;\n accent-color: var(--m-accent);\n}\n\n/* ---------- composer ---------- */\n\n.mailharbor-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-wrap: wrap;\n padding: 6px;\n border: 1px solid var(--m-line-soft);\n border-bottom: 0;\n border-radius: 10px 10px 0 0;\n background: var(--m-bg-2);\n}\n\n.mailharbor-toolbar button {\n height: 26px;\n padding: 0 9px;\n border-radius: 6px;\n color: var(--m-text-2);\n font-size: 12px;\n}\n\n.mailharbor-toolbar button:hover {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n.mailharbor-editor {\n min-height: 240px;\n max-height: 44vh;\n overflow: auto;\n padding: 14px 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 0 0 10px 10px;\n background: #fff;\n color: #171a21;\n outline: none;\n font-size: 13.5px;\n line-height: 1.7;\n}\n\n.mailharbor-editor:empty::before {\n content: attr(data-placeholder);\n color: #9aa0ab;\n}\n\n/* ---------- inline confirm ---------- */\n\n.mailharbor-confirm {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid var(--m-line);\n background: var(--m-bg-2);\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n/* ---------- selection / extraction ---------- */\n\n.mailharbor-selectbar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 5px 6px;\n padding: 8px 10px;\n margin: 0 10px 8px;\n border: 1px solid var(--m-accent);\n border-radius: 9px;\n background: var(--m-bg-1);\n}\n\n.mailharbor-select-count {\n flex: none;\n white-space: nowrap;\n}\n\n.mailharbor-selectbar button {\n padding: 0 8px;\n}\n\n.mailharbor-selectbar .spacer {\n flex: 1 1 0;\n}\n\n.mailharbor-selectbar select {\n flex: 1 1 110px;\n min-width: 0;\n}\n\n.mailharbor-selectbar select {\n height: 28px;\n max-width: 200px;\n}\n\n.mailharbor-row.selectable input[type='checkbox'] {\n width: 15px;\n height: 15px;\n flex: none;\n accent-color: var(--m-accent);\n}\n\n.mailharbor-extract-row {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 9px 10px;\n border: 1px solid var(--m-line-soft);\n border-radius: 9px;\n background: var(--m-bg-1);\n cursor: pointer;\n}\n\n.mailharbor-extract-row input {\n margin-top: 2px;\n accent-color: var(--m-accent);\n}\n\n.mailharbor-extract-row > span {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n}\n\n.mailharbor-kv {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n gap: 6px 12px;\n margin: 0;\n font-size: 12.5px;\n}\n\n.mailharbor-kv dt {\n color: var(--m-text-3);\n}\n\n.mailharbor-kv dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n\n/* ---------- tasks panel ---------- */\n\n.mailharbor .chip {\n height: 26px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: 999px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor .chip.active {\n background: var(--m-accent-soft);\n border-color: transparent;\n color: var(--m-text);\n}\n\n.tasks-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 18px 20px 48px;\n width: 100%;\n max-width: 940px;\n margin: 0 auto;\n}\n\n.tasks-overview {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));\n gap: 12px;\n}\n\n.tasks-progress,\n.tasks-project {\n display: flex;\n flex-direction: column;\n gap: 7px;\n padding: 12px 14px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n min-width: 0;\n}\n\n.tasks-progress-head,\n.tasks-project-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n min-width: 0;\n}\n\n.tasks-project-head .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12.5px;\n font-weight: 500;\n}\n\n.tasks-bar {\n height: 6px;\n border-radius: 999px;\n background: var(--m-bg-3);\n overflow: hidden;\n}\n\n.tasks-bar span {\n display: block;\n height: 100%;\n border-radius: 999px;\n background: var(--m-accent);\n transition: width 200ms ease;\n}\n\n.tasks-bar.small {\n height: 4px;\n}\n\n.tasks-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.tasks-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.tasks-row {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 9px 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.tasks-row input[type='checkbox'] {\n width: 16px;\n height: 16px;\n flex: none;\n accent-color: var(--m-accent);\n}\n\n.tasks-row .tasks-title {\n flex: 1;\n min-width: 0;\n height: auto;\n padding: 0;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n text-align: left;\n border: 0;\n background: transparent;\n}\n\n.tasks-row .tasks-title:hover {\n background: transparent;\n}\n\n.tasks-row .tasks-title > span:first-child {\n font-size: 13px;\n color: var(--m-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n}\n\n.tasks-row.done .tasks-title > span:first-child {\n color: var(--m-text-3);\n text-decoration: line-through;\n}\n\n.tasks-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.tasks-meta .due.overdue {\n color: var(--m-danger);\n}\n\n.tasks-list-wrap {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n/* ---------- markdown ---------- */\n\n.mailharbor-markdown {\n display: flex;\n flex-direction: column;\n gap: 8px;\n font-size: 12.5px;\n line-height: 1.68;\n overflow-wrap: anywhere;\n}\n\n.mailharbor-markdown > *:first-child {\n margin-top: 0;\n}\n\n.mailharbor-markdown > *:last-child {\n margin-bottom: 0;\n}\n\n.mailharbor-markdown p {\n margin: 0;\n white-space: pre-wrap;\n}\n\n.mailharbor-markdown h1,\n.mailharbor-markdown h2,\n.mailharbor-markdown h3,\n.mailharbor-markdown h4,\n.mailharbor-markdown h5,\n.mailharbor-markdown h6 {\n margin: 4px 0 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--m-text);\n}\n\n.mailharbor-markdown ul,\n.mailharbor-markdown ol {\n margin: 0;\n padding-left: 20px;\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.mailharbor-markdown li::marker {\n color: var(--m-text-3);\n}\n\n.mailharbor-markdown a {\n color: var(--m-accent);\n text-decoration: none;\n}\n\n.mailharbor-markdown a:hover {\n text-decoration: underline;\n}\n\n.mailharbor-markdown code {\n padding: 1px 4px;\n border-radius: 4px;\n background: var(--m-bg-2);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11.5px;\n}\n\n.mailharbor-markdown pre {\n margin: 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--m-bg);\n border: 1px solid var(--m-line-soft);\n overflow: auto;\n}\n\n.mailharbor-markdown pre code {\n padding: 0;\n background: transparent;\n}\n\n.mailharbor-markdown blockquote {\n margin: 0;\n padding-left: 10px;\n border-left: 2px solid var(--m-line);\n color: var(--m-text-2);\n}\n\n.mailharbor-markdown hr {\n width: 100%;\n margin: 4px 0;\n border: 0;\n border-top: 1px solid var(--m-line-soft);\n}\n\n/* ---------- composer AI ---------- */\n\n.mailharbor-toolbar button.ai {\n color: var(--m-accent);\n}\n\n.mailharbor-compose-foot {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n flex-wrap: wrap;\n}\n\n.mailharbor-versions {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n padding-top: 8px;\n}\n\n.mailharbor-versions .chip {\n height: 22px;\n padding: 0 8px;\n border: 1px solid var(--m-line);\n border-radius: 999px;\n color: var(--m-text-3);\n font-size: 11px;\n}\n\n.mailharbor-versions .chip.active {\n background: var(--m-accent-soft);\n border-color: transparent;\n color: var(--m-text);\n}\n\n/* ---------- settings ---------- */\n\n.mailharbor.mailharbor-settings-page {\n height: auto;\n min-height: 100%;\n overflow: visible;\n}\n\n.mailharbor-settings {\n flex: 0 0 auto;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding: 18px 20px 48px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n overflow-x: hidden;\n}\n\n.mailharbor-settings > * {\n min-width: 0;\n}\n\n.mailharbor-settings h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n\n.mailharbor-settings h3 {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.mailharbor-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n min-width: 0;\n overflow: hidden;\n}\n\n.mailharbor-account-row {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.mailharbor-account-row .meta {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.mailharbor-account-row .meta strong {\n font-weight: 600;\n}\n\n.mailharbor-account-row .meta span {\n color: var(--m-text-3);\n font-size: 11.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mailharbor .avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n border-radius: 50%;\n background: var(--m-accent-soft);\n color: var(--m-accent);\n font-weight: 600;\n}\n\n.mailharbor-log {\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--m-bg);\n border: 1px solid var(--m-line-soft);\n color: var(--m-text-2);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 1.6;\n max-height: 220px;\n overflow: auto;\n white-space: pre-wrap;\n}\n\n.mailharbor-kv {\n display: grid;\n grid-template-columns: minmax(120px, 170px) 1fr;\n gap: 6px 14px;\n font-size: 12px;\n margin: 0;\n}\n\n.mailharbor-kv dt {\n color: var(--m-text-3);\n}\n\n.mailharbor-kv dd {\n margin: 0;\n color: var(--m-text-2);\n word-break: break-all;\n}\n\n.mailharbor hr {\n border: 0;\n border-top: 1px solid var(--m-line-soft);\n margin: 2px 0;\n}\n\n/* ---------- conversation rows ---------- */\n\n.mailharbor-thread {\n display: flex;\n flex-direction: column;\n}\n\n.mailharbor-row.compact {\n padding-top: 6px;\n padding-bottom: 6px;\n padding-left: 34px;\n background: var(--m-bg);\n}\n\n.mailharbor-row.compact .line-1 {\n opacity: 0.85;\n}\n\n.mailharbor-row.compact .snippet {\n -webkit-line-clamp: 1;\n}\n\n.mailharbor .to-label {\n font-size: 10.5px;\n color: var(--m-text-3);\n flex: none;\n}\n\n.mailharbor .thread-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-3);\n color: var(--m-text-2);\n font-size: 10.5px;\n flex: none;\n}\n\n.mailharbor .thread-count:hover {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-account {\n height: auto;\n padding: 3px 8px 3px 3px;\n border-radius: 8px;\n gap: 8px;\n}\n\n.mailharbor-account:hover {\n background: var(--m-hover);\n}\n\n/* ---------- mailbox sidebar ---------- */\n\n.mailharbor-side {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 214px;\n flex: none;\n padding: 10px 8px;\n overflow: auto;\n border-right: 1px solid var(--m-line-soft);\n background: var(--m-bg);\n}\n\n.mailharbor-side-section {\n padding: 12px 8px 4px;\n font-size: 10.5px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--m-text-3);\n}\n\n.mailharbor-side-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px;\n border-radius: 8px;\n color: var(--m-text-2);\n font-size: 12.5px;\n text-align: left;\n flex: none;\n}\n\n.mailharbor-side-item:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-side-item.active {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-side-item .name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-side-item .sub {\n display: block;\n font-size: 10.5px;\n color: var(--m-text-3);\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mailharbor-side-item .count {\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.mailharbor-side-item svg {\n flex: none;\n color: var(--m-text-3);\n}\n\n.mailharbor-side-item.active svg {\n color: var(--m-accent);\n}\n\n/* ---------- task board ---------- */\n\n.tasks-board-wrap {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 16px 18px 40px;\n}\n\n.tasks-summary {\n display: flex;\n align-items: center;\n gap: 20px;\n padding: 14px 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n}\n\n.tasks-summary-main {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 7px;\n}\n\n.tasks-summary-labels {\n display: flex;\n align-items: baseline;\n gap: 10px;\n}\n\n.tasks-stats {\n display: flex;\n gap: 18px;\n}\n\n.tasks-stat {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 42px;\n}\n\n.tasks-stat strong {\n font-size: 16px;\n font-weight: 600;\n color: var(--m-text);\n}\n\n.tasks-stat span {\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.tasks-stat.danger strong {\n color: var(--m-danger);\n}\n\n.tasks-toolbar {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.tasks-board {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 14px;\n align-items: start;\n}\n\n.task-column {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-height: 140px;\n padding: 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n}\n\n.task-column-head {\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 2px 4px 6px;\n}\n\n.task-column-head strong {\n font-size: 12.5px;\n font-weight: 600;\n}\n\n.task-column-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-3);\n color: var(--m-text-3);\n font-size: 10.5px;\n}\n\n.task-dot {\n width: 7px;\n height: 7px;\n border-radius: 999px;\n background: var(--m-text-3);\n}\n\n.task-dot.TODO {\n background: #8a8f98;\n}\n\n.task-dot.IN-PROCESS {\n background: var(--m-accent);\n}\n\n.task-dot.COMPLETED {\n background: var(--m-ok);\n}\n\n.task-dot.CANCELLED {\n background: var(--m-danger);\n opacity: 0.7;\n}\n\n.task-column-body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-height: 60px;\n}\n\n.task-column-empty {\n padding: 18px 8px;\n text-align: center;\n color: var(--m-text-3);\n font-size: 11.5px;\n border: 1px dashed var(--m-line-soft);\n border-radius: 9px;\n}\n\n.task-card {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 11px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg);\n cursor: grab;\n transition:\n border-color 120ms ease,\n box-shadow 120ms ease;\n}\n\n.task-card:hover {\n border-color: var(--m-line);\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16);\n}\n\n.task-card.dragging {\n opacity: 0.5;\n}\n\n.task-card-top {\n display: flex;\n align-items: flex-start;\n gap: 7px;\n}\n\n.task-card-title {\n flex: 1;\n min-width: 0;\n font-size: 12.5px;\n line-height: 1.45;\n color: var(--m-text);\n overflow-wrap: anywhere;\n}\n\n.task-priority {\n width: 3px;\n height: 14px;\n margin-top: 2px;\n border-radius: 999px;\n background: transparent;\n flex: none;\n}\n\n.task-priority.p5 {\n background: #d9a441;\n}\n\n.task-priority.p9 {\n background: var(--m-danger);\n}\n\n.task-card-delete {\n width: 18px;\n height: 18px;\n flex: none;\n border-radius: 5px;\n color: var(--m-text-3);\n opacity: 0;\n}\n\n.task-card:hover .task-card-delete {\n opacity: 1;\n}\n\n.task-card-notes {\n margin: 0;\n font-size: 11.5px;\n line-height: 1.55;\n color: var(--m-text-3);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.task-card-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-size: 10.5px;\n color: var(--m-text-3);\n}\n\n.task-due,\n.task-owner,\n.task-project,\n.task-priority-label {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px;\n border-radius: 5px;\n background: var(--m-bg-2);\n}\n\n.task-due.overdue {\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.12);\n}\n\n.task-project {\n color: var(--m-accent);\n background: var(--m-accent-soft);\n}\n\n.task-source {\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 22px;\n padding: 0 6px;\n border-radius: 5px;\n color: var(--m-text-3);\n font-size: 10.5px;\n}\n\n.task-source:hover {\n background: var(--m-hover);\n color: var(--m-text-2);\n}\n\n@media (max-width: 1180px) {\n .tasks-board {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n@media (max-width: 720px) {\n .tasks-board {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* ---------- AI search ---------- */\n\n.mailharbor-ai-search {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 12px 8px;\n padding: 7px 10px;\n border-radius: 8px;\n background: var(--m-accent-soft);\n color: var(--m-text-2);\n font-size: 12px;\n}\n\n.mailharbor-ai-search.searching {\n background: var(--m-bg-2);\n color: var(--m-text-3);\n}\n\n/* ---------- task editor ---------- */\n\n.mailharbor-tasks .mailharbor-modal {\n max-width: 760px;\n}\n\n.task-editor {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 230px;\n gap: 18px;\n}\n\n.task-editor-main {\n display: flex;\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n}\n\n.task-editor-title input {\n width: 100%;\n height: 38px;\n font-size: 15px;\n font-weight: 500;\n}\n\n.task-editor-section {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.task-editor-section label,\n.task-editor-field label {\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.task-editor-section textarea {\n width: 100%;\n resize: vertical;\n}\n\n.task-editor-side {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n align-self: start;\n}\n\n.task-editor-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n}\n\n.task-editor-field input,\n.task-editor-field select {\n width: 100%;\n}\n\n.task-priority-picker {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n padding: 3px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n}\n\n.task-priority-picker button {\n height: 26px;\n border-radius: 6px;\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.task-priority-picker button.active {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.task-editor-foot {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n}\n\n/* ---------- project manager ---------- */\n\n.project-manager {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.project-manager-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.project-manager-main {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.project-manager-main strong {\n font-size: 13px;\n}\n\n.project-manager-main .small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.project-manager-main input {\n width: 100%;\n height: 28px;\n}\n\n.project-manager-actions {\n display: flex;\n gap: 4px;\n flex: none;\n align-items: center;\n}\n\n/* ---------- task editor v2 ---------- */\n\n.task-editor-v2 {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.task-editor-head {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.task-editor-head .task-title-input {\n width: 100%;\n height: 42px;\n padding: 0 12px;\n border-radius: 10px;\n border: 1px solid var(--m-line);\n background: var(--m-bg);\n color: var(--m-text);\n font-size: 16px;\n font-weight: 500;\n}\n\n.task-editor-head .task-title-input:focus {\n outline: none;\n border-color: var(--m-accent);\n}\n\n.task-status-picker {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 4px;\n padding: 4px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.task-status-picker button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 30px;\n border-radius: 7px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.task-status-picker button:hover {\n background: var(--m-hover);\n}\n\n.task-status-picker button.active {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n.task-editor-columns {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 250px;\n gap: 18px;\n}\n\n.task-editor-col {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n}\n\n.task-editor-col textarea {\n width: 100%;\n resize: vertical;\n min-height: 120px;\n}\n\n.task-editor-col.side {\n padding: 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n align-self: start;\n}\n\n.task-label {\n font-size: 11px;\n color: var(--m-text-3);\n margin-top: 2px;\n}\n\n.task-hint {\n margin: 0;\n font-size: 11.5px;\n color: var(--m-text-3);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.task-hint.danger {\n color: var(--m-danger);\n white-space: normal;\n}\n\n.task-source-row {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.task-due {\n position: relative;\n}\n\n.task-due-trigger {\n display: flex;\n align-items: center;\n gap: 7px;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n.task-due-trigger.empty {\n color: var(--m-text-3);\n}\n\n.task-due-trigger span {\n flex: 1;\n text-align: left;\n}\n\n.task-due-popover {\n position: absolute;\n z-index: 20;\n top: calc(100% + 6px);\n left: 0;\n width: 250px;\n padding: 10px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-2);\n box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.task-due-quick {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 5px;\n}\n\n.task-due-quick button {\n height: 28px;\n border-radius: 7px;\n background: var(--m-bg-1);\n border: 1px solid var(--m-line-soft);\n font-size: 11.5px;\n color: var(--m-text-2);\n}\n\n.task-due-quick button.active {\n background: var(--m-accent-soft);\n border-color: transparent;\n color: var(--m-text);\n}\n\n.task-due-popover input[type='date'] {\n width: 100%;\n}\n\n.task-due-foot {\n display: flex;\n justify-content: space-between;\n}\n\n.task-priority-picker {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 4px;\n padding: 3px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n}\n\n.task-priority-picker button {\n height: 28px;\n border-radius: 6px;\n font-size: 11.5px;\n color: var(--m-text-3);\n border: 1px solid transparent;\n}\n\n.task-priority-picker button.p3 {\n color: #5aa7f0;\n}\n\n.task-priority-picker button.p5 {\n color: #d9a441;\n}\n\n.task-priority-picker button.p9 {\n color: var(--m-danger);\n}\n\n.task-priority-picker button.active {\n background: var(--m-bg-3);\n border-color: var(--m-line);\n color: var(--m-text);\n}\n\n.task-priority-picker button.p9.active {\n background: rgba(242, 90, 90, 0.16);\n border-color: rgba(242, 90, 90, 0.35);\n color: var(--m-danger);\n}\n\n.task-priority-picker button.p5.active {\n background: rgba(217, 164, 65, 0.16);\n border-color: rgba(217, 164, 65, 0.35);\n color: #d9a441;\n}\n\n.task-priority-picker button.p3.active {\n background: rgba(90, 167, 240, 0.16);\n border-color: rgba(90, 167, 240, 0.35);\n color: #5aa7f0;\n}\n\n.task-priority.p3 {\n background: #5aa7f0;\n}\n\n.task-priority-label.p9 {\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.12);\n}\n\n.task-priority-label.p5 {\n color: #d9a441;\n background: rgba(217, 164, 65, 0.12);\n}\n\n.task-priority-label.p3 {\n color: #5aa7f0;\n background: rgba(90, 167, 240, 0.12);\n}\n\n@media (max-width: 720px) {\n .task-editor-columns {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.mailharbor-spinner {\n display: inline-block;\n width: 13px;\n height: 13px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: mailharbor-spin 0.7s linear infinite;\n opacity: 0.8;\n vertical-align: -2px;\n flex: none;\n}\n\n@keyframes mailharbor-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.extract-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.extract-title {\n width: 100%;\n height: 30px;\n font-size: 13px;\n font-weight: 500;\n}\n\n.extract-meta {\n display: grid;\n grid-template-columns: 150px 110px minmax(0, 1fr);\n gap: 6px;\n}\n\n.extract-meta input,\n.extract-meta select {\n height: 28px;\n font-size: 11.5px;\n width: 100%;\n}\n\n.extract-owner {\n width: 100%;\n}\n\n@media (max-width: 720px) {\n .extract-meta {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* ---------- conversation reading ---------- */\n\n.mailharbor-thread-view {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px 18px 32px;\n background: var(--m-bg);\n}\n\n.mailharbor-thread-hint {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 4px 2px;\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-thread-msg {\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n overflow: hidden;\n}\n\n.mailharbor-thread-msg.selected {\n border-color: var(--m-accent);\n box-shadow: 0 0 0 1px var(--m-accent-soft);\n}\n\n.mailharbor-thread-head {\n display: flex;\n align-items: center;\n gap: 9px;\n width: 100%;\n height: auto;\n padding: 9px 12px;\n text-align: left;\n border-radius: 0;\n}\n\n.mailharbor-thread-head:hover {\n background: var(--m-hover);\n}\n\n.thread-who {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.thread-who strong {\n font-size: 12.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.thread-to {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-thread-preview {\n padding: 0 14px 10px 47px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-thread-body {\n padding: 0 12px 12px;\n}\n\n.mailharbor-thread-frame {\n height: 380px;\n border: 1px solid var(--m-line-soft);\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n}\n\n.mailharbor-thread-frame iframe {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n background: #fff;\n}\n\n.thread-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 4px 12px;\n}\n\n@media (max-width: 900px) {\n .thread-to {\n display: none;\n }\n}\n\n/* ---------- compact reader ---------- */\n\n.mailharbor-reader-head {\n padding: 10px 16px 8px;\n gap: 6px;\n}\n\n.mailharbor-reader-title h2 {\n font-size: 15px;\n}\n\n.mailharbor-reader-meta.compact {\n gap: 10px;\n align-items: center;\n}\n\n.mailharbor-reader-meta.compact .who {\n gap: 6px;\n}\n\n.mailharbor-reader-recipients {\n display: flex;\n flex-wrap: wrap;\n gap: 6px 14px;\n font-size: 11.5px;\n color: var(--m-text-3);\n padding: 0 2px;\n}\n\n.mailharbor-reader-actions {\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.mailharbor-reader-actions button {\n height: 28px;\n padding: 0 8px;\n}\n\n.mailharbor-attachments.compact {\n display: flex;\n gap: 6px;\n padding: 6px 16px;\n overflow-x: auto;\n border-top: 1px solid var(--m-line-soft);\n flex-wrap: nowrap;\n}\n\n.mailharbor-attachments.compact .mailharbor-attachment {\n flex: none;\n padding: 4px 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 6px;\n max-width: 260px;\n}\n\n.mailharbor-reader-body {\n flex: 1;\n min-height: 0;\n}\n\n.thread-who {\n flex-direction: row;\n align-items: baseline;\n gap: 6px;\n min-width: 0;\n}\n\n.thread-who strong {\n max-width: 45%;\n}\n\n.thread-who .small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n.thread-date {\n flex: none;\n}\n\n.mailharbor button.mailharbor-thread-head {\n justify-content: flex-start;\n padding: 7px 10px;\n gap: 8px;\n}\n\n.mailharbor-thread-preview {\n padding: 0 12px 8px 40px;\n}\n\n.mailharbor-thread-frame {\n height: clamp(220px, 42vh, 420px);\n}\n\n.mailharbor-refreshing {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 14px 6px;\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.mailharbor-attachment-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 0 2px;\n}\n\n.mailharbor-attachment-chips .mailharbor-attachment {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n max-width: 280px;\n padding: 4px 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 6px;\n background: var(--m-bg-1);\n font-size: 11.5px;\n}\n\n.mailharbor-attachment-chips .mailharbor-attachment .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-thread-recipients {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n padding: 0 2px 8px;\n}\n\n.mailharbor-thread-frame {\n height: clamp(260px, 55vh, 640px);\n}\n\n.mailharbor-thread-body {\n padding: 8px 12px 12px;\n}\n\n.mailharbor-ai-summary.clamp,\n.mailharbor-ai-text.clamp {\n max-height: 150px;\n overflow: hidden;\n mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);\n -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);\n}\n\n.mailharbor-ai-full {\n display: flex;\n flex-direction: column;\n gap: 14px;\n max-height: 66vh;\n overflow: auto;\n padding-right: 4px;\n font-size: 13px;\n line-height: 1.7;\n color: var(--m-text);\n}\n\n.mailharbor-ai-full h4 {\n margin: 0 0 4px;\n font-size: 11px;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--m-text-3);\n}\n\n.mailharbor-ai-full .mailharbor-markdown {\n font-size: 13px;\n line-height: 1.7;\n}\n\n/* ---------- sync popover ---------- */\n\n.mailharbor-sync {\n position: relative;\n}\n\n.mailharbor-sync-pop {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n z-index: 30;\n width: 320px;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-2);\n box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);\n}\n\n.mailharbor-sync-head {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n\n.mailharbor-sync-stats {\n display: flex;\n justify-content: space-between;\n gap: 8px;\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-sync-log {\n max-height: 110px;\n overflow: auto;\n padding: 6px 8px;\n border-radius: 6px;\n background: var(--m-bg);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 10.5px;\n white-space: pre-wrap;\n color: var(--m-text-3);\n}\n\n.mailharbor-sync-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mailharbor-thread-msg,\n.mailharbor-ai-card {\n flex: none;\n}\n\n.mailharbor-unread-banner {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0 10px 8px;\n padding: 6px 10px;\n border-radius: 8px;\n background: var(--m-accent-soft);\n color: var(--m-text-2);\n font-size: 11.5px;\n text-align: left;\n}\n\n.mailharbor-unread-banner:hover {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-starred {\n display: inline-flex;\n align-items: center;\n color: #e0b341;\n flex: none;\n}\n\n.mailharbor-reader-actions select {\n height: 28px;\n max-width: 130px;\n font-size: 11.5px;\n}\n\n.mailharbor-sync-error {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 12px 6px;\n padding: 6px 10px;\n border-radius: 8px;\n background: rgba(242, 90, 90, 0.12);\n color: var(--m-danger);\n font-size: 11.5px;\n}\n\n.mailharbor-onboarding {\n display: grid;\n gap: 6px;\n margin: 12px 0;\n padding: 10px 12px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-2);\n font-size: 12px;\n}\n\n.mailharbor-onboarding strong {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n margin-right: 6px;\n border-radius: 50%;\n background: var(--m-accent-soft);\n color: var(--m-text);\n font-size: 11px;\n}\n\n/* ---------- responsive shell ---------- */\n\n.mailharbor-scrim,\n.mailharbor-ai-scrim {\n display: none;\n}\n\n.mailharbor-account {\n flex: 0 1 auto;\n}\n\n.mailharbor-account > div {\n min-width: 0;\n}\n\n.mailharbor-account .small {\n display: block;\n max-width: 150px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-action-label {\n display: inline;\n}\n\n@media (max-width: 1540px) {\n .mailharbor-ai-scrim {\n display: block;\n position: absolute;\n inset: 0;\n z-index: 5;\n border: 0;\n background: rgba(0, 0, 0, 0.32);\n backdrop-filter: blur(1px);\n }\n\n .mailharbor-ai {\n z-index: 6;\n }\n}\n\n@media (max-width: 1220px) {\n .mailharbor-scrim {\n display: block;\n position: absolute;\n inset: 0;\n z-index: 25;\n border: 0;\n background: rgba(0, 0, 0, 0.38);\n }\n\n .mailharbor-side {\n position: absolute;\n inset: 0 auto 0 0;\n z-index: 30;\n display: flex;\n width: min(290px, 86%);\n box-shadow: 20px 0 50px rgba(0, 0, 0, 0.45);\n animation: mailharbor-drawer 160ms ease-out;\n }\n\n .mailharbor-list {\n width: clamp(260px, 36vw, 320px);\n }\n}\n\n@keyframes mailharbor-drawer {\n from {\n transform: translateX(-12px);\n opacity: 0.4;\n }\n to {\n transform: none;\n opacity: 1;\n }\n}\n\n@media (max-width: 900px) {\n .mailharbor-narrow .mailharbor-list {\n width: 100%;\n flex: 1;\n min-width: 0;\n border-right: 0;\n }\n\n .mailharbor-narrow .mailharbor-body[data-mode='reader'] .mailharbor-reader {\n width: 100%;\n flex: 1;\n }\n\n .mailharbor-reader-head {\n padding: 12px 14px 10px;\n gap: 8px;\n }\n\n .mailharbor-reader-title h2 {\n font-size: 16px;\n }\n\n .mailharbor-reader-body {\n padding: 10px 12px 12px;\n }\n\n .mailharbor-ai {\n width: min(420px, 100%);\n }\n}\n\n@media (max-width: 760px) {\n .mailharbor-topbar {\n flex-wrap: wrap;\n height: auto;\n min-height: 52px;\n padding: 8px 10px;\n gap: 6px;\n }\n\n .mailharbor-account {\n max-width: 170px;\n }\n\n .mailharbor-account .small {\n max-width: 105px;\n }\n\n .mailharbor-action-label {\n display: none;\n }\n\n .mailharbor-topbar button.ghost,\n .mailharbor-topbar button.primary {\n padding: 0 9px;\n }\n\n .mailharbor-filters {\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n }\n\n .mailharbor-filters input[type='search'] {\n flex: 1 1 100%;\n order: -1;\n }\n\n .mailharbor-settings-page {\n padding: 16px 12px;\n }\n\n .mailharbor-grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .mailharbor-grid.three {\n grid-template-columns: minmax(0, 1fr) minmax(64px, 80px) auto;\n }\n\n .mailharbor-sync-pop {\n position: fixed;\n top: 56px;\n left: 10px;\n right: 10px;\n width: auto;\n }\n}\n\n@media (max-width: 560px) {\n .mailharbor-topbar {\n gap: 4px;\n }\n\n .mailharbor-account {\n max-width: 132px;\n }\n\n .mailharbor-account .small {\n display: none;\n }\n\n .mailharbor-account .badge {\n display: none;\n }\n\n .mailharbor-row {\n padding: 9px 12px;\n }\n\n .mailharbor-row .snippet {\n -webkit-line-clamp: 1;\n }\n\n .mailharbor-reader-actions {\n gap: 4px;\n }\n\n .mailharbor-reader-actions button {\n padding: 0 7px;\n }\n}\n\n/* Reader actions collapse on phones: keep reply/forward, put the rest behind \u66F4\u591A. */\n.mailharbor .mailharbor-more-toggle {\n display: none;\n}\n\n@media (max-width: 760px) {\n .mailharbor-reader-actions .mailharbor-secondary {\n display: none;\n }\n\n .mailharbor-reader-actions.expanded .mailharbor-secondary {\n display: inline-flex;\n }\n\n .mailharbor-reader-actions .mailharbor-more-toggle {\n display: inline-flex;\n }\n\n .mailharbor-reader-actions .mailharbor-divider.mailharbor-secondary {\n display: none;\n }\n}\n\n/* Subtle scrollbars keep long lists readable without stealing width. */\n.mailharbor ::-webkit-scrollbar {\n width: 9px;\n height: 9px;\n}\n\n.mailharbor ::-webkit-scrollbar-thumb {\n background: var(--m-line-strong);\n border: 2px solid transparent;\n border-radius: 999px;\n background-clip: padding-box;\n}\n\n.mailharbor ::-webkit-scrollbar-thumb:hover {\n background: var(--m-text-3);\n background-clip: padding-box;\n}\n\n/* ---------- attachment preview & drop target ---------- */\n\n.mailharbor-preview {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 320px;\n max-height: 68vh;\n overflow: auto;\n border-radius: 10px;\n background: var(--m-bg);\n}\n\n.mailharbor-preview.text {\n align-items: stretch;\n justify-content: flex-start;\n}\n\n.mailharbor-preview img {\n display: block;\n max-width: 100%;\n max-height: 66vh;\n object-fit: contain;\n}\n\n.mailharbor-preview iframe {\n width: 100%;\n height: 66vh;\n border: 0;\n border-radius: 10px;\n background: #fff;\n}\n\n.mailharbor-preview-text {\n width: 100%;\n max-height: 66vh;\n margin: 0;\n padding: 16px;\n overflow: auto;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12px;\n color: var(--m-text-2);\n}\n\n.mailharbor-editor.dragging {\n outline: 2px dashed var(--m-accent);\n outline-offset: -2px;\n background: var(--m-accent-soft);\n}\n\n/* Rows off screen skip layout/paint work in large mailboxes. */\n.mailharbor-row {\n content-visibility: auto;\n contain-intrinsic-size: auto 68px;\n}\n\n/* ---------- structured filters ---------- */\n\n.mailharbor-filter-wrap {\n position: relative;\n flex: none;\n}\n\n.mailharbor-filter-pop {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 25;\n width: 290px;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-1);\n box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);\n}\n\n.mailharbor-filter-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.mailharbor-filter-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: 8px;\n}\n\n.mailharbor-filter-check {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--m-text-2);\n}\n\n.mailharbor-filter-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mailharbor-filter-actions .primary {\n margin-left: auto;\n}\n\n@media (max-width: 560px) {\n .mailharbor-filter-pop {\n position: fixed;\n top: 120px;\n left: 10px;\n right: 10px;\n width: auto;\n }\n}\n\n/* Thread cards: sender + snippet, recipients only when expanded. */\n.thread-main {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.thread-line {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.thread-name {\n font-size: 12.5px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 60%;\n}\n\n.thread-count {\n flex: none;\n font-size: 10.5px;\n color: var(--m-text-3);\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-2);\n}\n\n.thread-snippet {\n font-size: 11.5px;\n line-height: 1.45;\n color: var(--m-text-3);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.thread-line .dot {\n flex: none;\n width: 6px;\n height: 6px;\n}\n\n.thread-date {\n flex: none;\n margin-left: auto;\n font-size: 10.5px;\n color: var(--m-caption);\n font-variant-numeric: tabular-nums;\n}\n\n.mailharbor-thread-head {\n align-items: center;\n}\n\n.thread-main {\n justify-content: center;\n}\n\n.mailharbor mark {\n background: rgba(224, 179, 65, 0.32);\n color: inherit;\n border-radius: 2px;\n padding: 0 1px;\n}\n\n/* Saved searches */\n.mailharbor-saved {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n}\n\n.mailharbor-saved-list {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.mailharbor-saved-chip {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--m-line);\n border-radius: 999px;\n overflow: hidden;\n}\n\n.mailharbor-saved-chip button {\n height: 22px;\n padding: 0 6px;\n font-size: 11px;\n}\n\n/* Project task progress */\n.project-progress {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 2px 0;\n}\n\n.project-progress-bar {\n width: 90px;\n height: 5px;\n border-radius: 999px;\n background: var(--m-bg-2);\n overflow: hidden;\n}\n\n.project-progress-bar span {\n display: block;\n height: 100%;\n background: var(--m-accent);\n}\n\n.tasks-filters .chip-count {\n margin-left: 5px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-2);\n font-size: 10px;\n}\n\n/* Project detail */\n.project-manager-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 3px;\n}\n\n.badge.project-done {\n color: var(--m-ok);\n border-color: var(--m-ok);\n}\n\n.badge.project-archived {\n color: var(--m-text-3);\n}\n\n.project-detail-head {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 10px;\n}\n\n.project-detail-tabs {\n display: flex;\n gap: 6px;\n}\n\n.project-detail-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.project-note-compose {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.project-note-compose textarea {\n border: 0;\n background: transparent;\n resize: vertical;\n}\n\n.project-note-compose-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.project-note {\n margin-top: 10px;\n padding: 10px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.project-note-head {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.project-note-body {\n margin-top: 6px;\n white-space: pre-wrap;\n font-size: 12.5px;\n color: var(--m-text-2);\n}\n\n.project-note-edit {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-top: 6px;\n}\n\n.project-note-selection {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 10px 0;\n padding: 6px 8px;\n border-radius: 8px;\n background: var(--m-accent-soft);\n}\n\n.project-tasks {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.project-task-add {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.project-task-add input {\n flex: 1;\n}\n\n.project-task-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 8px;\n background: var(--m-bg-1);\n}\n\n.project-task-row.child {\n margin-left: 24px;\n background: var(--m-bg);\n}\n\n.project-task-row select {\n width: 90px;\n flex: none;\n}\n\n.project-task-title {\n font-size: 12.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.project-task-waiting {\n display: flex;\n gap: 6px;\n margin: 4px 0 4px 24px;\n}\n\n.project-task-waiting input {\n flex: 1;\n}\n\n.project-convert-list {\n margin: 0;\n padding-left: 20px;\n font-size: 12.5px;\n}\n\n@media (max-width: 620px) {\n .project-task-row {\n flex-wrap: wrap;\n }\n}\n\n.task-dot.WAITING {\n background: var(--m-warn);\n}\n";
|
|
38
|
+
var styles_default = "/* MailHarbor panel + settings.\n Tokens come from the DSH shell (dark by default); fallbacks match the\n default dark theme so the panel also renders in a bare host page.\n Component rules are all scoped under `.mailharbor` and the generic element\n reset lives in `:where()` so it cannot outrank a component class. */\n\n.mailharbor {\n --m-bg: var(--dsw-alias-bg-base, #151517);\n --m-bg-1: var(--dsw-alias-bg-layer-1, #232324);\n --m-bg-2: var(--dsw-alias-bg-layer-2, #2c2c2e);\n --m-bg-3: var(--dsw-alias-bg-layer-3, #353638);\n --m-line: var(--dsw-alias-border-l2, #ffffff1f);\n --m-line-soft: var(--dsw-alias-border-l1, #ffffff0f);\n --m-line-strong: var(--dsw-alias-border-l3, #ffffff29);\n --m-text: var(--dsw-alias-label-primary, #f9fafb);\n --m-text-2: var(--dsw-alias-label-secondary, #cfd3d6);\n --m-text-3: var(--dsw-alias-label-tertiary, #adb2b8);\n --m-caption: var(--dsw-alias-label-caption, #81858c);\n --m-accent: #5686fe;\n --m-accent-soft: rgba(86, 134, 254, 0.14);\n --m-primary-bg: var(--dsw-alias-brand-primary, #f9fafb);\n --m-primary-fg: var(--dsw-alias-label-primary-foreground, #0f1115);\n --m-hover: var(--dsw-alias-interactive-bg-hover, #ffffff14);\n --m-danger: #f25a5a;\n --m-ok: #3fbf7f;\n --m-warn: var(--dsw-alias-state-warn-label, #dd8629);\n --m-radius: 8px;\n --m-shadow: 0 18px 60px rgba(0, 0, 0, 0.5);\n\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--m-bg);\n color: var(--m-text);\n font-size: 13px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n\n.mailharbor *,\n.mailharbor *::before,\n.mailharbor *::after {\n box-sizing: border-box;\n}\n\n/* ---------- base controls ---------- */\n\n.mailharbor :where(button) {\n font: inherit;\n color: inherit;\n background: transparent;\n border: 0;\n margin: 0;\n cursor: pointer;\n}\n\n.mailharbor button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 30px;\n padding: 0 12px;\n border-radius: var(--m-radius);\n border: 1px solid transparent;\n color: var(--m-text-2);\n font-size: 12.5px;\n font-weight: 500;\n white-space: nowrap;\n transition:\n background 120ms ease,\n color 120ms ease,\n border-color 120ms ease;\n}\n\n.mailharbor button:hover:not(:disabled) {\n background: var(--m-hover);\n color: var(--m-text);\n}\n\n.mailharbor button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.mailharbor button.primary {\n background: var(--m-primary-bg);\n color: var(--m-primary-fg);\n border-color: transparent;\n}\n\n.mailharbor button.primary:hover:not(:disabled) {\n background: var(--m-primary-bg);\n filter: brightness(0.94);\n color: var(--m-primary-fg);\n}\n\n.mailharbor button.ghost {\n border-color: var(--m-line);\n color: var(--m-text-2);\n}\n\n.mailharbor button.ghost:hover:not(:disabled) {\n border-color: var(--m-line-strong);\n color: var(--m-text);\n}\n\n.mailharbor button.subtle {\n color: var(--m-text-3);\n padding: 0 8px;\n}\n\n.mailharbor button.icon {\n width: 30px;\n padding: 0;\n}\n\n.mailharbor button.danger {\n color: var(--m-danger);\n}\n\n.mailharbor input,\n.mailharbor select,\n.mailharbor textarea {\n font: inherit;\n color: var(--m-text);\n background: var(--m-bg-1);\n border: 1px solid var(--m-line);\n border-radius: var(--m-radius);\n padding: 0 10px;\n height: 32px;\n min-width: 0;\n}\n\n.mailharbor textarea {\n height: auto;\n padding: 8px 10px;\n resize: vertical;\n line-height: 1.6;\n}\n\n.mailharbor select {\n padding-right: 26px;\n appearance: none;\n background-image:\n linear-gradient(45deg, transparent 50%, var(--m-text-3) 50%),\n linear-gradient(135deg, var(--m-text-3) 50%, transparent 50%);\n background-position:\n calc(100% - 15px) 14px,\n calc(100% - 10px) 14px;\n background-size:\n 5px 5px,\n 5px 5px;\n background-repeat: no-repeat;\n}\n\n.mailharbor ::placeholder {\n color: var(--m-caption);\n}\n\n.mailharbor input:focus-visible,\n.mailharbor select:focus-visible,\n.mailharbor textarea:focus-visible,\n.mailharbor button:focus-visible,\n.mailharbor [contenteditable='true']:focus-visible {\n outline: 2px solid rgba(86, 134, 254, 0.55);\n outline-offset: -1px;\n}\n\n.mailharbor .spacer {\n flex: 1;\n}\n\n.mailharbor .muted {\n color: var(--m-text-3);\n}\n\n.mailharbor .small {\n font-size: 12px;\n}\n\n.mailharbor .badge {\n display: inline-flex;\n align-items: center;\n height: 18px;\n padding: 0 6px;\n border-radius: 999px;\n font-size: 10.5px;\n font-weight: 500;\n background: var(--m-bg-3);\n color: var(--m-text-2);\n}\n\n.mailharbor .badge.ok {\n background: rgba(63, 191, 127, 0.16);\n color: var(--m-ok);\n}\n\n.mailharbor .badge.warn {\n background: rgba(221, 134, 41, 0.16);\n color: var(--m-warn);\n}\n\n.mailharbor .error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.1);\n border-bottom: 1px solid rgba(242, 90, 90, 0.2);\n font-size: 12.5px;\n}\n\n/* ---------- shell ---------- */\n\n.mailharbor-topbar {\n display: flex;\n align-items: center;\n gap: 10px;\n height: 52px;\n padding: 0 14px;\n border-bottom: 1px solid var(--m-line-soft);\n background: var(--m-bg);\n flex: none;\n}\n\n.mailharbor-account {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n max-width: 220px;\n padding: 4px 8px 4px 4px;\n border-radius: 999px;\n border: 1px solid transparent;\n cursor: default;\n}\n\n.mailharbor-account:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-account .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.mailharbor-account select {\n height: 26px;\n background: transparent;\n border-color: transparent;\n font-weight: 500;\n}\n\n.mailharbor-body {\n display: flex;\n flex: 1;\n min-height: 0;\n position: relative;\n}\n\n.mailharbor button.active {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-list {\n display: flex;\n flex-direction: column;\n width: clamp(280px, 28vw, 360px);\n flex: none;\n border-right: 1px solid var(--m-line-soft);\n min-height: 0;\n}\n\n.mailharbor-reader {\n flex: 1;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='reader'] .mailharbor-list {\n display: none;\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='list'] .mailharbor-reader {\n display: none;\n}\n\n/* ---------- segmented control ---------- */\n\n.mailharbor-segment {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n border-radius: 9px;\n background: var(--m-bg-2);\n}\n\n.mailharbor-segment button {\n height: 26px;\n padding: 0 12px;\n border-radius: 7px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor-segment button:hover:not(.active) {\n color: var(--m-text-2);\n background: transparent;\n}\n\n.mailharbor-segment button.active {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n/* ---------- list ---------- */\n\n.mailharbor-filters {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-filters select {\n width: 128px;\n flex: none;\n font-size: 12px;\n}\n\n.mailharbor-filters input[type='search'] {\n flex: 1;\n height: 30px;\n font-size: 12.5px;\n}\n\n.mailharbor-rows {\n flex: 1;\n overflow: auto;\n min-height: 0;\n}\n\n.mailharbor-row {\n display: flex;\n flex-direction: column;\n gap: 3px;\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-bottom: 1px solid var(--m-line-soft);\n border-left: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n text-align: left;\n cursor: pointer;\n user-select: none;\n}\n\n.mailharbor-row:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-row.selected {\n background: var(--m-accent-soft);\n border-left-color: var(--m-accent);\n}\n\n.mailharbor-row .line-1,\n.mailharbor-row .line-2 {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n width: 100%;\n}\n\n.mailharbor-row .from {\n font-weight: 600;\n font-size: 12.5px;\n color: var(--m-text-2);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-row .date {\n margin-left: auto;\n color: var(--m-caption);\n font-size: 11px;\n flex: none;\n}\n\n.mailharbor-row .subject {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n.mailharbor-row .snippet {\n color: var(--m-caption);\n font-size: 11.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n width: 100%;\n}\n\n.mailharbor-row.unread .from,\n.mailharbor-row.unread .subject {\n color: var(--m-text);\n}\n\n.mailharbor-row .dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--m-accent);\n flex: none;\n}\n\n.mailharbor-row .paperclip {\n color: var(--m-caption);\n flex: none;\n display: inline-flex;\n}\n\n.mailharbor-list-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-top: 1px solid var(--m-line-soft);\n color: var(--m-text-3);\n font-size: 11.5px;\n flex: none;\n}\n\n.mailharbor-empty {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 48px 24px;\n color: var(--m-text-3);\n text-align: center;\n}\n\n.mailharbor-empty svg {\n opacity: 0.5;\n}\n\n.mailharbor-empty .title {\n color: var(--m-text-2);\n font-size: 13px;\n font-weight: 500;\n}\n\n/* ---------- reader ---------- */\n\n.mailharbor-reader-head {\n padding: 16px 20px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.mailharbor-reader-title {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.mailharbor-reader-title h2 {\n margin: 0;\n font-size: 17px;\n line-height: 1.35;\n font-weight: 600;\n letter-spacing: -0.01em;\n word-break: break-word;\n}\n\n.mailharbor-reader-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px 10px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor-reader-meta .who {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: var(--m-text-2);\n}\n\n.mailharbor-reader-meta .who strong {\n color: var(--m-text);\n font-weight: 600;\n}\n\n.mailharbor-reader-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.mailharbor-reader-body {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding: 14px 18px 18px;\n background: var(--m-bg-2);\n}\n\n.mailharbor-reader-body iframe {\n flex: 1;\n width: 100%;\n border: 0;\n border-radius: 10px;\n background: #fff;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n}\n\n.mailharbor-reader-body pre {\n flex: 1;\n overflow: auto;\n margin: 0;\n padding: 20px 22px;\n white-space: pre-wrap;\n word-break: break-word;\n background: #fff;\n border-radius: 10px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n color: #171a21;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12.5px;\n line-height: 1.7;\n}\n\n.mailharbor-attachments {\n padding: 10px 18px;\n border-top: 1px solid var(--m-line-soft);\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n flex: none;\n background: var(--m-bg);\n}\n\n.mailharbor-attachment {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 30px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: var(--m-radius);\n font-size: 12px;\n text-decoration: none;\n color: var(--m-text-2);\n max-width: 260px;\n background: var(--m-bg-1);\n}\n\n.mailharbor-attachment:hover {\n border-color: var(--m-line-strong);\n color: var(--m-text);\n}\n\n.mailharbor-attachment .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* ---------- AI rail ---------- */\n\n.mailharbor-ai {\n display: flex;\n flex-direction: column;\n width: 340px;\n flex: none;\n min-height: 0;\n border-left: 1px solid var(--m-line-soft);\n background: var(--m-bg);\n}\n\n.mailharbor-ai-head {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 46px;\n padding: 0 8px 0 14px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-head strong {\n font-size: 13px;\n font-weight: 600;\n}\n\n.mailharbor-ai-confirm {\n display: inline-flex;\n gap: 2px;\n}\n\n.mailharbor-ai-context {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 9px 14px 10px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-context strong {\n font-size: 12.5px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-ai-warn {\n padding: 8px 14px;\n color: var(--m-warn);\n background: rgba(221, 134, 41, 0.1);\n font-size: 12px;\n flex: none;\n}\n\n.mailharbor-ai-quick {\n display: flex;\n gap: 6px;\n padding: 10px 14px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-quick button {\n flex: 1;\n padding: 0 6px;\n}\n\n.mailharbor-ai-list {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 12px 14px;\n}\n\n.mailharbor-ai-empty {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 6px;\n padding: 30px 12px;\n text-align: center;\n color: var(--m-text-3);\n}\n\n.mailharbor-ai-empty .title {\n color: var(--m-text-2);\n font-weight: 500;\n font-size: 12.5px;\n}\n\n.mailharbor-ai-card {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n overflow: hidden;\n}\n\n.mailharbor-ai-card.generating {\n opacity: 0.7;\n}\n\n.mailharbor-ai-card-head {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 8px 7px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-ai-card-head > span:first-child {\n color: var(--m-text-2);\n font-weight: 600;\n}\n\n.mailharbor-ai-summary {\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 10px 12px;\n}\n\n.mailharbor-ai-summary section h4 {\n margin: 0 0 3px;\n font-size: 11px;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n\n.mailharbor-ai-summary section p {\n margin: 0;\n white-space: pre-wrap;\n font-size: 12.5px;\n line-height: 1.65;\n color: var(--m-text);\n}\n\n.mailharbor-ai-text {\n padding: 10px 12px;\n\n white-space: pre-wrap;\n font-size: 12.5px;\n line-height: 1.65;\n color: var(--m-text);\n}\n\n.mailharbor-ai-card-actions {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n padding: 6px 8px;\n border-top: 1px solid var(--m-line-soft);\n}\n\n.mailharbor-ai-card-actions button {\n height: 26px;\n padding: 0 8px;\n font-size: 11.5px;\n}\n\n.mailharbor-ai-ask {\n display: flex;\n gap: 6px;\n padding: 10px 12px;\n border-top: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-ai-ask input {\n flex: 1;\n height: 32px;\n}\n\n.mailharbor-ai-error {\n color: var(--m-danger);\n font-size: 12px;\n padding: 0 2px;\n}\n\n@media (max-width: 1540px) {\n .mailharbor-ai {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(420px, 94%);\n z-index: 6;\n border-left: 1px solid var(--m-line);\n box-shadow: -12px 0 40px rgba(0, 0, 0, 0.45);\n }\n}\n\n/* ---------- AI summary ---------- */\n\n.mailharbor-divider {\n width: 1px;\n height: 18px;\n margin: 0 4px;\n background: var(--m-line);\n}\n\n.mailharbor-summary {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.mailharbor-summary section h4 {\n margin: 0 0 6px;\n font-size: 11.5px;\n font-weight: 600;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.mailharbor-summary section p {\n margin: 0;\n white-space: pre-wrap;\n line-height: 1.75;\n color: var(--m-text);\n}\n\n/* ---------- modal / forms ---------- */\n\n.mailharbor-portal {\n position: fixed;\n inset: 0;\n z-index: 80;\n height: auto;\n background: transparent;\n pointer-events: none;\n}\n\n.mailharbor-portal .mailharbor-modal-mask {\n pointer-events: auto;\n}\n\n.mailharbor-modal-mask {\n position: fixed;\n inset: 0;\n z-index: 60;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: rgba(0, 0, 0, 0.55);\n backdrop-filter: blur(2px);\n}\n\n.mailharbor-modal {\n display: flex;\n flex-direction: column;\n width: min(720px, 100%);\n max-height: 86vh;\n overflow: hidden;\n border: 1px solid var(--m-line);\n border-radius: 14px;\n background: var(--m-bg-1);\n color: var(--m-text);\n box-shadow: var(--m-shadow);\n}\n\n.mailharbor-modal > header {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 52px;\n padding: 0 14px 0 18px;\n border-bottom: 1px solid var(--m-line-soft);\n font-size: 14px;\n font-weight: 600;\n}\n\n.mailharbor-modal .content {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 18px;\n overflow: auto;\n}\n\n.mailharbor-modal > footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 18px;\n border-top: 1px solid var(--m-line-soft);\n}\n\n.mailharbor-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n}\n\n.mailharbor-field > input,\n.mailharbor-field > select,\n.mailharbor-field > textarea,\n.mailharbor-card > textarea {\n width: 100%;\n min-width: 0;\n}\n\n.mailharbor-field > label {\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-grid {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: 10px;\n min-width: 0;\n}\n\n.mailharbor-grid.three {\n grid-template-columns: minmax(0, 2fr) minmax(72px, 90px) auto;\n align-items: end;\n min-width: 0;\n}\n\n.mailharbor-toggle {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n color: var(--m-text-2);\n font-size: 12.5px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.mailharbor-toggle input[type='checkbox'] {\n width: 14px;\n height: 14px;\n accent-color: var(--m-accent);\n}\n\n/* ---------- composer ---------- */\n\n.mailharbor-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-wrap: wrap;\n padding: 6px;\n border: 1px solid var(--m-line-soft);\n border-bottom: 0;\n border-radius: 10px 10px 0 0;\n background: var(--m-bg-2);\n}\n\n.mailharbor-toolbar button {\n height: 26px;\n padding: 0 9px;\n border-radius: 6px;\n color: var(--m-text-2);\n font-size: 12px;\n}\n\n.mailharbor-toolbar button:hover {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n.mailharbor-editor {\n min-height: 240px;\n max-height: 44vh;\n overflow: auto;\n padding: 14px 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 0 0 10px 10px;\n background: #fff;\n color: #171a21;\n outline: none;\n font-size: 13.5px;\n line-height: 1.7;\n}\n\n.mailharbor-editor:empty::before {\n content: attr(data-placeholder);\n color: #9aa0ab;\n}\n\n/* ---------- inline confirm ---------- */\n\n.mailharbor-confirm {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-radius: 8px;\n border: 1px solid var(--m-line);\n background: var(--m-bg-2);\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n/* ---------- selection / extraction ---------- */\n\n.mailharbor-selectbar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 5px 6px;\n padding: 8px 10px;\n margin: 0 10px 8px;\n border: 1px solid var(--m-accent);\n border-radius: 9px;\n background: var(--m-bg-1);\n}\n\n.mailharbor-select-count {\n flex: none;\n white-space: nowrap;\n}\n\n.mailharbor-selectbar button {\n padding: 0 8px;\n}\n\n.mailharbor-selectbar .spacer {\n flex: 1 1 0;\n}\n\n.mailharbor-selectbar select {\n flex: 1 1 110px;\n min-width: 0;\n}\n\n.mailharbor-selectbar select {\n height: 28px;\n max-width: 200px;\n}\n\n.mailharbor-row.selectable input[type='checkbox'] {\n width: 15px;\n height: 15px;\n flex: none;\n accent-color: var(--m-accent);\n}\n\n.mailharbor-extract-row {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n padding: 9px 10px;\n border: 1px solid var(--m-line-soft);\n border-radius: 9px;\n background: var(--m-bg-1);\n cursor: pointer;\n}\n\n.mailharbor-extract-row input {\n margin-top: 2px;\n accent-color: var(--m-accent);\n}\n\n.mailharbor-extract-row > span {\n display: flex;\n flex-direction: column;\n gap: 3px;\n min-width: 0;\n}\n\n.mailharbor-kv {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n gap: 6px 12px;\n margin: 0;\n font-size: 12.5px;\n}\n\n.mailharbor-kv dt {\n color: var(--m-text-3);\n}\n\n.mailharbor-kv dd {\n margin: 0;\n overflow-wrap: anywhere;\n}\n\n/* ---------- tasks panel ---------- */\n\n.mailharbor .chip {\n height: 26px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: 999px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor .chip.active {\n background: var(--m-accent-soft);\n border-color: transparent;\n color: var(--m-text);\n}\n\n.tasks-body {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 18px;\n padding: 18px 20px 48px;\n width: 100%;\n max-width: 940px;\n margin: 0 auto;\n}\n\n.tasks-overview {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));\n gap: 12px;\n}\n\n.tasks-progress,\n.tasks-project {\n display: flex;\n flex-direction: column;\n gap: 7px;\n padding: 12px 14px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n min-width: 0;\n}\n\n.tasks-progress-head,\n.tasks-project-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n min-width: 0;\n}\n\n.tasks-project-head .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 12.5px;\n font-weight: 500;\n}\n\n.tasks-bar {\n height: 6px;\n border-radius: 999px;\n background: var(--m-bg-3);\n overflow: hidden;\n}\n\n.tasks-bar span {\n display: block;\n height: 100%;\n border-radius: 999px;\n background: var(--m-accent);\n transition: width 200ms ease;\n}\n\n.tasks-bar.small {\n height: 4px;\n}\n\n.tasks-filters {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.tasks-list {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.tasks-row {\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 9px 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.tasks-row input[type='checkbox'] {\n width: 16px;\n height: 16px;\n flex: none;\n accent-color: var(--m-accent);\n}\n\n.tasks-row .tasks-title {\n flex: 1;\n min-width: 0;\n height: auto;\n padding: 0;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n text-align: left;\n border: 0;\n background: transparent;\n}\n\n.tasks-row .tasks-title:hover {\n background: transparent;\n}\n\n.tasks-row .tasks-title > span:first-child {\n font-size: 13px;\n color: var(--m-text);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 100%;\n}\n\n.tasks-row.done .tasks-title > span:first-child {\n color: var(--m-text-3);\n text-decoration: line-through;\n}\n\n.tasks-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.tasks-meta .due.overdue {\n color: var(--m-danger);\n}\n\n.tasks-list-wrap {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n/* ---------- markdown ---------- */\n\n.mailharbor-markdown {\n display: flex;\n flex-direction: column;\n gap: 8px;\n font-size: 12.5px;\n line-height: 1.68;\n overflow-wrap: anywhere;\n}\n\n.mailharbor-markdown > *:first-child {\n margin-top: 0;\n}\n\n.mailharbor-markdown > *:last-child {\n margin-bottom: 0;\n}\n\n.mailharbor-markdown p {\n margin: 0;\n white-space: pre-wrap;\n}\n\n.mailharbor-markdown h1,\n.mailharbor-markdown h2,\n.mailharbor-markdown h3,\n.mailharbor-markdown h4,\n.mailharbor-markdown h5,\n.mailharbor-markdown h6 {\n margin: 4px 0 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--m-text);\n}\n\n.mailharbor-markdown ul,\n.mailharbor-markdown ol {\n margin: 0;\n padding-left: 20px;\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.mailharbor-markdown li::marker {\n color: var(--m-text-3);\n}\n\n.mailharbor-markdown a {\n color: var(--m-accent);\n text-decoration: none;\n}\n\n.mailharbor-markdown a:hover {\n text-decoration: underline;\n}\n\n.mailharbor-markdown code {\n padding: 1px 4px;\n border-radius: 4px;\n background: var(--m-bg-2);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11.5px;\n}\n\n.mailharbor-markdown pre {\n margin: 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--m-bg);\n border: 1px solid var(--m-line-soft);\n overflow: auto;\n}\n\n.mailharbor-markdown pre code {\n padding: 0;\n background: transparent;\n}\n\n.mailharbor-markdown blockquote {\n margin: 0;\n padding-left: 10px;\n border-left: 2px solid var(--m-line);\n color: var(--m-text-2);\n}\n\n.mailharbor-markdown hr {\n width: 100%;\n margin: 4px 0;\n border: 0;\n border-top: 1px solid var(--m-line-soft);\n}\n\n/* ---------- composer AI ---------- */\n\n.mailharbor-toolbar button.ai {\n color: var(--m-accent);\n}\n\n.mailharbor-compose-foot {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n flex-wrap: wrap;\n}\n\n.mailharbor-versions {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n padding-top: 8px;\n}\n\n.mailharbor-versions .chip {\n height: 22px;\n padding: 0 8px;\n border: 1px solid var(--m-line);\n border-radius: 999px;\n color: var(--m-text-3);\n font-size: 11px;\n}\n\n.mailharbor-versions .chip.active {\n background: var(--m-accent-soft);\n border-color: transparent;\n color: var(--m-text);\n}\n\n/* ---------- settings ---------- */\n\n.mailharbor.mailharbor-settings-page {\n height: auto;\n min-height: 100%;\n overflow: visible;\n}\n\n.mailharbor-settings {\n flex: 0 0 auto;\n width: 100%;\n max-width: 100%;\n min-width: 0;\n padding: 18px 20px 48px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n overflow-x: hidden;\n}\n\n.mailharbor-settings > * {\n min-width: 0;\n}\n\n.mailharbor-settings h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n\n.mailharbor-settings h3 {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.mailharbor-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n min-width: 0;\n overflow: hidden;\n}\n\n.mailharbor-account-row {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.mailharbor-account-row .meta {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.mailharbor-account-row .meta strong {\n font-weight: 600;\n}\n\n.mailharbor-account-row .meta span {\n color: var(--m-text-3);\n font-size: 11.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mailharbor .avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n border-radius: 50%;\n background: var(--m-accent-soft);\n color: var(--m-accent);\n font-weight: 600;\n}\n\n.mailharbor-log {\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--m-bg);\n border: 1px solid var(--m-line-soft);\n color: var(--m-text-2);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 1.6;\n max-height: 220px;\n overflow: auto;\n white-space: pre-wrap;\n}\n\n.mailharbor-kv {\n display: grid;\n grid-template-columns: minmax(120px, 170px) 1fr;\n gap: 6px 14px;\n font-size: 12px;\n margin: 0;\n}\n\n.mailharbor-kv dt {\n color: var(--m-text-3);\n}\n\n.mailharbor-kv dd {\n margin: 0;\n color: var(--m-text-2);\n word-break: break-all;\n}\n\n.mailharbor hr {\n border: 0;\n border-top: 1px solid var(--m-line-soft);\n margin: 2px 0;\n}\n\n/* ---------- conversation rows ---------- */\n\n.mailharbor-thread {\n display: flex;\n flex-direction: column;\n}\n\n.mailharbor-row.compact {\n padding-top: 6px;\n padding-bottom: 6px;\n padding-left: 34px;\n background: var(--m-bg);\n}\n\n.mailharbor-row.compact .line-1 {\n opacity: 0.85;\n}\n\n.mailharbor-row.compact .snippet {\n -webkit-line-clamp: 1;\n}\n\n.mailharbor .to-label {\n font-size: 10.5px;\n color: var(--m-text-3);\n flex: none;\n}\n\n.mailharbor .thread-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-3);\n color: var(--m-text-2);\n font-size: 10.5px;\n flex: none;\n}\n\n.mailharbor .thread-count:hover {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-account {\n height: auto;\n padding: 3px 8px 3px 3px;\n border-radius: 8px;\n gap: 8px;\n}\n\n.mailharbor-account:hover {\n background: var(--m-hover);\n}\n\n/* ---------- mailbox sidebar ---------- */\n\n.mailharbor-side {\n display: flex;\n flex-direction: column;\n gap: 2px;\n width: 214px;\n flex: none;\n padding: 10px 8px;\n overflow: auto;\n border-right: 1px solid var(--m-line-soft);\n background: var(--m-bg);\n}\n\n.mailharbor-side-section {\n padding: 12px 8px 4px;\n font-size: 10.5px;\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--m-text-3);\n}\n\n.mailharbor-side-item {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n height: 32px;\n padding: 0 8px;\n border-radius: 8px;\n color: var(--m-text-2);\n font-size: 12.5px;\n text-align: left;\n flex: none;\n}\n\n.mailharbor-side-item:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-side-item.active {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-side-item .name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-side-item .sub {\n display: block;\n font-size: 10.5px;\n color: var(--m-text-3);\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mailharbor-side-item .count {\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.mailharbor-side-item svg {\n flex: none;\n color: var(--m-text-3);\n}\n\n.mailharbor-side-item.active svg {\n color: var(--m-accent);\n}\n\n/* ---------- task board ---------- */\n\n.tasks-board-wrap {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 16px 18px 40px;\n}\n\n.tasks-summary {\n display: flex;\n align-items: center;\n gap: 20px;\n padding: 14px 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n}\n\n.tasks-summary-main {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 7px;\n}\n\n.tasks-summary-labels {\n display: flex;\n align-items: baseline;\n gap: 10px;\n}\n\n.tasks-stats {\n display: flex;\n gap: 18px;\n}\n\n.tasks-stat {\n display: flex;\n flex-direction: column;\n gap: 1px;\n min-width: 42px;\n}\n\n.tasks-stat strong {\n font-size: 16px;\n font-weight: 600;\n color: var(--m-text);\n}\n\n.tasks-stat span {\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.tasks-stat.danger strong {\n color: var(--m-danger);\n}\n\n.tasks-toolbar {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.tasks-board {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 14px;\n align-items: start;\n}\n\n.task-column {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-height: 140px;\n padding: 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n}\n\n.task-column-head {\n display: flex;\n align-items: center;\n gap: 7px;\n padding: 2px 4px 6px;\n}\n\n.task-column-head strong {\n font-size: 12.5px;\n font-weight: 600;\n}\n\n.task-column-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-3);\n color: var(--m-text-3);\n font-size: 10.5px;\n}\n\n.task-dot {\n width: 7px;\n height: 7px;\n border-radius: 999px;\n background: var(--m-text-3);\n}\n\n.task-dot.TODO {\n background: #8a8f98;\n}\n\n.task-dot.IN-PROCESS {\n background: var(--m-accent);\n}\n\n.task-dot.COMPLETED {\n background: var(--m-ok);\n}\n\n.task-dot.CANCELLED {\n background: var(--m-danger);\n opacity: 0.7;\n}\n\n.task-column-body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-height: 60px;\n}\n\n.task-column-empty {\n padding: 18px 8px;\n text-align: center;\n color: var(--m-text-3);\n font-size: 11.5px;\n border: 1px dashed var(--m-line-soft);\n border-radius: 9px;\n}\n\n.task-card {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 11px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg);\n cursor: grab;\n transition:\n border-color 120ms ease,\n box-shadow 120ms ease;\n}\n\n.task-card:hover {\n border-color: var(--m-line);\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.16);\n}\n\n.task-card.dragging {\n opacity: 0.5;\n}\n\n.task-card-top {\n display: flex;\n align-items: flex-start;\n gap: 7px;\n}\n\n.task-card-title {\n flex: 1;\n min-width: 0;\n font-size: 12.5px;\n line-height: 1.45;\n color: var(--m-text);\n overflow-wrap: anywhere;\n}\n\n.task-priority {\n width: 3px;\n height: 14px;\n margin-top: 2px;\n border-radius: 999px;\n background: transparent;\n flex: none;\n}\n\n.task-priority.p5 {\n background: #d9a441;\n}\n\n.task-priority.p9 {\n background: var(--m-danger);\n}\n\n.task-card-delete {\n width: 18px;\n height: 18px;\n flex: none;\n border-radius: 5px;\n color: var(--m-text-3);\n opacity: 0;\n}\n\n.task-card:hover .task-card-delete {\n opacity: 1;\n}\n\n.task-card-notes {\n margin: 0;\n font-size: 11.5px;\n line-height: 1.55;\n color: var(--m-text-3);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.task-card-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n font-size: 10.5px;\n color: var(--m-text-3);\n}\n\n.task-due,\n.task-owner,\n.task-project,\n.task-priority-label {\n display: inline-flex;\n align-items: center;\n gap: 3px;\n padding: 1px 6px;\n border-radius: 5px;\n background: var(--m-bg-2);\n}\n\n.task-due.overdue {\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.12);\n}\n\n.task-project {\n color: var(--m-accent);\n background: var(--m-accent-soft);\n}\n\n.task-source {\n align-self: flex-start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n height: 22px;\n padding: 0 6px;\n border-radius: 5px;\n color: var(--m-text-3);\n font-size: 10.5px;\n}\n\n.task-source:hover {\n background: var(--m-hover);\n color: var(--m-text-2);\n}\n\n@media (max-width: 1180px) {\n .tasks-board {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n}\n\n@media (max-width: 720px) {\n .tasks-board {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* ---------- AI search ---------- */\n\n.mailharbor-ai-search {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 12px 8px;\n padding: 7px 10px;\n border-radius: 8px;\n background: var(--m-accent-soft);\n color: var(--m-text-2);\n font-size: 12px;\n}\n\n.mailharbor-ai-search.searching {\n background: var(--m-bg-2);\n color: var(--m-text-3);\n}\n\n/* ---------- task editor ---------- */\n\n.mailharbor-tasks .mailharbor-modal {\n max-width: 760px;\n}\n\n.task-editor {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 230px;\n gap: 18px;\n}\n\n.task-editor-main {\n display: flex;\n flex-direction: column;\n gap: 14px;\n min-width: 0;\n}\n\n.task-editor-title input {\n width: 100%;\n height: 38px;\n font-size: 15px;\n font-weight: 500;\n}\n\n.task-editor-section {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.task-editor-section label,\n.task-editor-field label {\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.task-editor-section textarea {\n width: 100%;\n resize: vertical;\n}\n\n.task-editor-side {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n align-self: start;\n}\n\n.task-editor-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n}\n\n.task-editor-field input,\n.task-editor-field select {\n width: 100%;\n}\n\n.task-priority-picker {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 4px;\n padding: 3px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n}\n\n.task-priority-picker button {\n height: 26px;\n border-radius: 6px;\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.task-priority-picker button.active {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.task-editor-foot {\n display: flex;\n align-items: center;\n gap: 10px;\n width: 100%;\n}\n\n/* ---------- project manager ---------- */\n\n.project-manager {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.project-manager-row {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.project-manager-main {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 3px;\n}\n\n.project-manager-main strong {\n font-size: 13px;\n}\n\n.project-manager-main .small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.project-manager-main input {\n width: 100%;\n height: 28px;\n}\n\n.project-manager-actions {\n display: flex;\n gap: 4px;\n flex: none;\n align-items: center;\n}\n\n/* ---------- task editor v2 ---------- */\n\n.task-editor-v2 {\n display: flex;\n flex-direction: column;\n gap: 16px;\n}\n\n.task-editor-head {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.task-editor-head .task-title-input {\n width: 100%;\n height: 42px;\n padding: 0 12px;\n border-radius: 10px;\n border: 1px solid var(--m-line);\n background: var(--m-bg);\n color: var(--m-text);\n font-size: 16px;\n font-weight: 500;\n}\n\n.task-editor-head .task-title-input:focus {\n outline: none;\n border-color: var(--m-accent);\n}\n\n.task-status-picker {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 4px;\n padding: 4px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.task-status-picker button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 30px;\n border-radius: 7px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.task-status-picker button:hover {\n background: var(--m-hover);\n}\n\n.task-status-picker button.active {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n.task-editor-columns {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 250px;\n gap: 18px;\n}\n\n.task-editor-col {\n display: flex;\n flex-direction: column;\n gap: 8px;\n min-width: 0;\n}\n\n.task-editor-col textarea {\n width: 100%;\n resize: vertical;\n min-height: 120px;\n}\n\n.task-editor-col.side {\n padding: 12px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n align-self: start;\n}\n\n.task-label {\n font-size: 11px;\n color: var(--m-text-3);\n margin-top: 2px;\n}\n\n.task-hint {\n margin: 0;\n font-size: 11.5px;\n color: var(--m-text-3);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.task-hint.danger {\n color: var(--m-danger);\n white-space: normal;\n}\n\n.task-source-row {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n.task-due {\n position: relative;\n}\n\n.task-due-trigger {\n display: flex;\n align-items: center;\n gap: 7px;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n.task-due-trigger.empty {\n color: var(--m-text-3);\n}\n\n.task-due-trigger span {\n flex: 1;\n text-align: left;\n}\n\n.task-due-popover {\n position: absolute;\n z-index: 20;\n top: calc(100% + 6px);\n left: 0;\n width: 250px;\n padding: 10px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-2);\n box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35);\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.task-due-quick {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 5px;\n}\n\n.task-due-quick button {\n height: 28px;\n border-radius: 7px;\n background: var(--m-bg-1);\n border: 1px solid var(--m-line-soft);\n font-size: 11.5px;\n color: var(--m-text-2);\n}\n\n.task-due-quick button.active {\n background: var(--m-accent-soft);\n border-color: transparent;\n color: var(--m-text);\n}\n\n.task-due-popover input[type='date'] {\n width: 100%;\n}\n\n.task-due-foot {\n display: flex;\n justify-content: space-between;\n}\n\n.task-priority-picker {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 4px;\n padding: 3px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n}\n\n.task-priority-picker button {\n height: 28px;\n border-radius: 6px;\n font-size: 11.5px;\n color: var(--m-text-3);\n border: 1px solid transparent;\n}\n\n.task-priority-picker button.p3 {\n color: #5aa7f0;\n}\n\n.task-priority-picker button.p5 {\n color: #d9a441;\n}\n\n.task-priority-picker button.p9 {\n color: var(--m-danger);\n}\n\n.task-priority-picker button.active {\n background: var(--m-bg-3);\n border-color: var(--m-line);\n color: var(--m-text);\n}\n\n.task-priority-picker button.p9.active {\n background: rgba(242, 90, 90, 0.16);\n border-color: rgba(242, 90, 90, 0.35);\n color: var(--m-danger);\n}\n\n.task-priority-picker button.p5.active {\n background: rgba(217, 164, 65, 0.16);\n border-color: rgba(217, 164, 65, 0.35);\n color: #d9a441;\n}\n\n.task-priority-picker button.p3.active {\n background: rgba(90, 167, 240, 0.16);\n border-color: rgba(90, 167, 240, 0.35);\n color: #5aa7f0;\n}\n\n.task-priority.p3 {\n background: #5aa7f0;\n}\n\n.task-priority-label.p9 {\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.12);\n}\n\n.task-priority-label.p5 {\n color: #d9a441;\n background: rgba(217, 164, 65, 0.12);\n}\n\n.task-priority-label.p3 {\n color: #5aa7f0;\n background: rgba(90, 167, 240, 0.12);\n}\n\n@media (max-width: 720px) {\n .task-editor-columns {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.mailharbor-spinner {\n display: inline-block;\n width: 13px;\n height: 13px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: mailharbor-spin 0.7s linear infinite;\n opacity: 0.8;\n vertical-align: -2px;\n flex: none;\n}\n\n@keyframes mailharbor-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n.extract-body {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.extract-title {\n width: 100%;\n height: 30px;\n font-size: 13px;\n font-weight: 500;\n}\n\n.extract-meta {\n display: grid;\n grid-template-columns: 150px 110px minmax(0, 1fr);\n gap: 6px;\n}\n\n.extract-meta input,\n.extract-meta select {\n height: 28px;\n font-size: 11.5px;\n width: 100%;\n}\n\n.extract-owner {\n width: 100%;\n}\n\n@media (max-width: 720px) {\n .extract-meta {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* ---------- conversation reading ---------- */\n\n.mailharbor-thread-view {\n flex: 1;\n min-height: 0;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 10px;\n padding: 14px 18px 32px;\n background: var(--m-bg);\n}\n\n.mailharbor-thread-hint {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 4px 2px;\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-thread-msg {\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n overflow: hidden;\n}\n\n.mailharbor-thread-msg.selected {\n border-color: var(--m-accent);\n box-shadow: 0 0 0 1px var(--m-accent-soft);\n}\n\n.mailharbor-thread-head {\n display: flex;\n align-items: center;\n gap: 9px;\n width: 100%;\n height: auto;\n padding: 9px 12px;\n text-align: left;\n border-radius: 0;\n}\n\n.mailharbor-thread-head:hover {\n background: var(--m-hover);\n}\n\n.thread-who {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.thread-who strong {\n font-size: 12.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.thread-to {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-thread-preview {\n padding: 0 14px 10px 47px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-thread-body {\n padding: 0 12px 12px;\n}\n\n.mailharbor-thread-frame {\n height: 380px;\n border: 1px solid var(--m-line-soft);\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n}\n\n.mailharbor-thread-frame iframe {\n display: block;\n width: 100%;\n height: 100%;\n border: 0;\n background: #fff;\n}\n\n.thread-loading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 4px 12px;\n}\n\n@media (max-width: 900px) {\n .thread-to {\n display: none;\n }\n}\n\n/* ---------- compact reader ---------- */\n\n.mailharbor-reader-head {\n padding: 10px 16px 8px;\n gap: 6px;\n}\n\n.mailharbor-reader-title h2 {\n font-size: 15px;\n}\n\n.mailharbor-reader-meta.compact {\n gap: 10px;\n align-items: center;\n}\n\n.mailharbor-reader-meta.compact .who {\n gap: 6px;\n}\n\n.mailharbor-reader-recipients {\n display: flex;\n flex-wrap: wrap;\n gap: 6px 14px;\n font-size: 11.5px;\n color: var(--m-text-3);\n padding: 0 2px;\n}\n\n.mailharbor-reader-actions {\n gap: 4px;\n flex-wrap: wrap;\n}\n\n.mailharbor-reader-actions button {\n height: 28px;\n padding: 0 8px;\n}\n\n.mailharbor-attachments.compact {\n display: flex;\n gap: 6px;\n padding: 6px 16px;\n overflow-x: auto;\n border-top: 1px solid var(--m-line-soft);\n flex-wrap: nowrap;\n}\n\n.mailharbor-attachments.compact .mailharbor-attachment {\n flex: none;\n padding: 4px 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 6px;\n max-width: 260px;\n}\n\n.mailharbor-reader-body {\n flex: 1;\n min-height: 0;\n}\n\n.thread-who {\n flex-direction: row;\n align-items: baseline;\n gap: 6px;\n min-width: 0;\n}\n\n.thread-who strong {\n max-width: 45%;\n}\n\n.thread-who .small {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n.thread-date {\n flex: none;\n}\n\n.mailharbor button.mailharbor-thread-head {\n justify-content: flex-start;\n padding: 7px 10px;\n gap: 8px;\n}\n\n.mailharbor-thread-preview {\n padding: 0 12px 8px 40px;\n}\n\n.mailharbor-thread-frame {\n height: clamp(220px, 42vh, 420px);\n}\n\n.mailharbor-refreshing {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 0 14px 6px;\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.mailharbor-attachment-chips {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 0 2px;\n}\n\n.mailharbor-attachment-chips .mailharbor-attachment {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n max-width: 280px;\n padding: 4px 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 6px;\n background: var(--m-bg-1);\n font-size: 11.5px;\n}\n\n.mailharbor-attachment-chips .mailharbor-attachment .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-thread-recipients {\n display: flex;\n flex-wrap: wrap;\n gap: 4px 14px;\n padding: 0 2px 8px;\n}\n\n.mailharbor-thread-frame {\n height: clamp(260px, 55vh, 640px);\n}\n\n.mailharbor-thread-body {\n padding: 8px 12px 12px;\n}\n\n.mailharbor-ai-summary.clamp,\n.mailharbor-ai-text.clamp {\n max-height: 150px;\n overflow: hidden;\n mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);\n -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%);\n}\n\n.mailharbor-ai-full {\n display: flex;\n flex-direction: column;\n gap: 14px;\n max-height: 66vh;\n overflow: auto;\n padding-right: 4px;\n font-size: 13px;\n line-height: 1.7;\n color: var(--m-text);\n}\n\n.mailharbor-ai-full h4 {\n margin: 0 0 4px;\n font-size: 11px;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--m-text-3);\n}\n\n.mailharbor-ai-full .mailharbor-markdown {\n font-size: 13px;\n line-height: 1.7;\n}\n\n/* ---------- sync popover ---------- */\n\n.mailharbor-sync {\n position: relative;\n}\n\n.mailharbor-sync-pop {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n z-index: 30;\n width: 320px;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-2);\n box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);\n}\n\n.mailharbor-sync-head {\n display: flex;\n align-items: baseline;\n gap: 8px;\n}\n\n.mailharbor-sync-stats {\n display: flex;\n justify-content: space-between;\n gap: 8px;\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-sync-log {\n max-height: 110px;\n overflow: auto;\n padding: 6px 8px;\n border-radius: 6px;\n background: var(--m-bg);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 10.5px;\n white-space: pre-wrap;\n color: var(--m-text-3);\n}\n\n.mailharbor-sync-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mailharbor-thread-msg,\n.mailharbor-ai-card {\n flex: none;\n}\n\n.mailharbor-unread-banner {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 0 10px 8px;\n padding: 6px 10px;\n border-radius: 8px;\n background: var(--m-accent-soft);\n color: var(--m-text-2);\n font-size: 11.5px;\n text-align: left;\n}\n\n.mailharbor-unread-banner:hover {\n background: var(--m-accent-soft);\n color: var(--m-text);\n}\n\n.mailharbor-starred {\n display: inline-flex;\n align-items: center;\n color: #e0b341;\n flex: none;\n}\n\n.mailharbor-reader-actions select {\n height: 28px;\n max-width: 130px;\n font-size: 11.5px;\n}\n\n.mailharbor-sync-error {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 0 12px 6px;\n padding: 6px 10px;\n border-radius: 8px;\n background: rgba(242, 90, 90, 0.12);\n color: var(--m-danger);\n font-size: 11.5px;\n}\n\n.mailharbor-onboarding {\n display: grid;\n gap: 6px;\n margin: 12px 0;\n padding: 10px 12px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-2);\n font-size: 12px;\n}\n\n.mailharbor-onboarding strong {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 18px;\n height: 18px;\n margin-right: 6px;\n border-radius: 50%;\n background: var(--m-accent-soft);\n color: var(--m-text);\n font-size: 11px;\n}\n\n/* ---------- responsive shell ---------- */\n\n.mailharbor-scrim,\n.mailharbor-ai-scrim {\n display: none;\n}\n\n.mailharbor-account {\n flex: 0 1 auto;\n}\n\n.mailharbor-account > div {\n min-width: 0;\n}\n\n.mailharbor-account .small {\n display: block;\n max-width: 150px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-action-label {\n display: inline;\n}\n\n@media (max-width: 1540px) {\n .mailharbor-ai-scrim {\n display: block;\n position: absolute;\n inset: 0;\n z-index: 5;\n border: 0;\n background: rgba(0, 0, 0, 0.32);\n backdrop-filter: blur(1px);\n }\n\n .mailharbor-ai {\n z-index: 6;\n }\n}\n\n@media (max-width: 1220px) {\n .mailharbor-scrim {\n display: block;\n position: absolute;\n inset: 0;\n z-index: 25;\n border: 0;\n background: rgba(0, 0, 0, 0.38);\n }\n\n .mailharbor-side {\n position: absolute;\n inset: 0 auto 0 0;\n z-index: 30;\n display: flex;\n width: min(290px, 86%);\n box-shadow: 20px 0 50px rgba(0, 0, 0, 0.45);\n animation: mailharbor-drawer 160ms ease-out;\n }\n\n .mailharbor-list {\n width: clamp(260px, 36vw, 320px);\n }\n}\n\n@keyframes mailharbor-drawer {\n from {\n transform: translateX(-12px);\n opacity: 0.4;\n }\n to {\n transform: none;\n opacity: 1;\n }\n}\n\n@media (max-width: 900px) {\n .mailharbor-narrow .mailharbor-list {\n width: 100%;\n flex: 1;\n min-width: 0;\n border-right: 0;\n }\n\n .mailharbor-narrow .mailharbor-body[data-mode='reader'] .mailharbor-reader {\n width: 100%;\n flex: 1;\n }\n\n .mailharbor-reader-head {\n padding: 12px 14px 10px;\n gap: 8px;\n }\n\n .mailharbor-reader-title h2 {\n font-size: 16px;\n }\n\n .mailharbor-reader-body {\n padding: 10px 12px 12px;\n }\n\n .mailharbor-ai {\n width: min(420px, 100%);\n }\n}\n\n@media (max-width: 760px) {\n .mailharbor-topbar {\n flex-wrap: wrap;\n height: auto;\n min-height: 52px;\n padding: 8px 10px;\n gap: 6px;\n }\n\n .mailharbor-account {\n max-width: 170px;\n }\n\n .mailharbor-account .small {\n max-width: 105px;\n }\n\n .mailharbor-action-label {\n display: none;\n }\n\n .mailharbor-topbar button.ghost,\n .mailharbor-topbar button.primary {\n padding: 0 9px;\n }\n\n .mailharbor-filters {\n flex-wrap: wrap;\n gap: 6px;\n padding: 8px 10px;\n }\n\n .mailharbor-filters input[type='search'] {\n flex: 1 1 100%;\n order: -1;\n }\n\n .mailharbor-settings-page {\n padding: 16px 12px;\n }\n\n .mailharbor-grid {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .mailharbor-grid.three {\n grid-template-columns: minmax(0, 1fr) minmax(64px, 80px) auto;\n }\n\n .mailharbor-sync-pop {\n position: fixed;\n top: 56px;\n left: 10px;\n right: 10px;\n width: auto;\n }\n}\n\n@media (max-width: 560px) {\n .mailharbor-topbar {\n gap: 4px;\n }\n\n .mailharbor-account {\n max-width: 132px;\n }\n\n .mailharbor-account .small {\n display: none;\n }\n\n .mailharbor-account .badge {\n display: none;\n }\n\n .mailharbor-row {\n padding: 9px 12px;\n }\n\n .mailharbor-row .snippet {\n -webkit-line-clamp: 1;\n }\n\n .mailharbor-reader-actions {\n gap: 4px;\n }\n\n .mailharbor-reader-actions button {\n padding: 0 7px;\n }\n}\n\n/* Reader actions collapse on phones: keep reply/forward, put the rest behind \u66F4\u591A. */\n.mailharbor .mailharbor-more-toggle {\n display: none;\n}\n\n@media (max-width: 760px) {\n .mailharbor-reader-actions .mailharbor-secondary {\n display: none;\n }\n\n .mailharbor-reader-actions.expanded .mailharbor-secondary {\n display: inline-flex;\n }\n\n .mailharbor-reader-actions .mailharbor-more-toggle {\n display: inline-flex;\n }\n\n .mailharbor-reader-actions .mailharbor-divider.mailharbor-secondary {\n display: none;\n }\n}\n\n/* Subtle scrollbars keep long lists readable without stealing width. */\n.mailharbor ::-webkit-scrollbar {\n width: 9px;\n height: 9px;\n}\n\n.mailharbor ::-webkit-scrollbar-thumb {\n background: var(--m-line-strong);\n border: 2px solid transparent;\n border-radius: 999px;\n background-clip: padding-box;\n}\n\n.mailharbor ::-webkit-scrollbar-thumb:hover {\n background: var(--m-text-3);\n background-clip: padding-box;\n}\n\n/* ---------- attachment preview & drop target ---------- */\n\n.mailharbor-preview {\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 320px;\n max-height: 68vh;\n overflow: auto;\n border-radius: 10px;\n background: var(--m-bg);\n}\n\n.mailharbor-preview.text {\n align-items: stretch;\n justify-content: flex-start;\n}\n\n.mailharbor-preview img {\n display: block;\n max-width: 100%;\n max-height: 66vh;\n object-fit: contain;\n}\n\n.mailharbor-preview iframe {\n width: 100%;\n height: 66vh;\n border: 0;\n border-radius: 10px;\n background: #fff;\n}\n\n.mailharbor-preview-text {\n width: 100%;\n max-height: 66vh;\n margin: 0;\n padding: 16px;\n overflow: auto;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12px;\n color: var(--m-text-2);\n}\n\n.mailharbor-editor.dragging {\n outline: 2px dashed var(--m-accent);\n outline-offset: -2px;\n background: var(--m-accent-soft);\n}\n\n/* Rows off screen skip layout/paint work in large mailboxes. */\n.mailharbor-row {\n content-visibility: auto;\n contain-intrinsic-size: auto 68px;\n}\n\n/* ---------- structured filters ---------- */\n\n.mailharbor-filter-wrap {\n position: relative;\n flex: none;\n}\n\n.mailharbor-filter-pop {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 25;\n width: 290px;\n padding: 12px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-1);\n box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);\n}\n\n.mailharbor-filter-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 11px;\n color: var(--m-text-3);\n}\n\n.mailharbor-filter-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: 8px;\n}\n\n.mailharbor-filter-check {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--m-text-2);\n}\n\n.mailharbor-filter-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.mailharbor-filter-actions .primary {\n margin-left: auto;\n}\n\n@media (max-width: 560px) {\n .mailharbor-filter-pop {\n position: fixed;\n top: 120px;\n left: 10px;\n right: 10px;\n width: auto;\n }\n}\n\n/* Thread cards: sender + snippet, recipients only when expanded. */\n.thread-main {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 1px;\n}\n\n.thread-line {\n display: flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n\n.thread-name {\n font-size: 12.5px;\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 60%;\n}\n\n.thread-count {\n flex: none;\n font-size: 10.5px;\n color: var(--m-text-3);\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-2);\n}\n\n.thread-snippet {\n font-size: 11.5px;\n line-height: 1.45;\n color: var(--m-text-3);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.thread-line .dot {\n flex: none;\n width: 6px;\n height: 6px;\n}\n\n.thread-date {\n flex: none;\n margin-left: auto;\n font-size: 10.5px;\n color: var(--m-caption);\n font-variant-numeric: tabular-nums;\n}\n\n.mailharbor-thread-head {\n align-items: center;\n}\n\n.thread-main {\n justify-content: center;\n}\n\n.mailharbor mark {\n background: rgba(224, 179, 65, 0.32);\n color: inherit;\n border-radius: 2px;\n padding: 0 1px;\n}\n\n/* Saved searches */\n.mailharbor-saved {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n}\n\n.mailharbor-saved-list {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.mailharbor-saved-chip {\n display: inline-flex;\n align-items: center;\n border: 1px solid var(--m-line);\n border-radius: 999px;\n overflow: hidden;\n}\n\n.mailharbor-saved-chip button {\n height: 22px;\n padding: 0 6px;\n font-size: 11px;\n}\n\n/* Project task progress */\n.project-progress {\n display: flex;\n align-items: center;\n gap: 6px;\n margin: 2px 0;\n}\n\n.project-progress-bar {\n width: 90px;\n height: 5px;\n border-radius: 999px;\n background: var(--m-bg-2);\n overflow: hidden;\n}\n\n.project-progress-bar span {\n display: block;\n height: 100%;\n background: var(--m-accent);\n}\n\n.tasks-filters .chip-count {\n margin-left: 5px;\n padding: 0 5px;\n border-radius: 999px;\n background: var(--m-bg-2);\n font-size: 10px;\n}\n\n/* Project detail */\n.project-manager-meta {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 3px;\n}\n\n.badge.project-done {\n color: var(--m-ok);\n border-color: var(--m-ok);\n}\n\n.badge.project-archived {\n color: var(--m-text-3);\n}\n\n.project-detail-head {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 10px;\n}\n\n.project-detail-tabs {\n display: flex;\n gap: 6px;\n}\n\n.project-detail-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n}\n\n.project-note-compose {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px;\n border: 1px solid var(--m-line);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.project-note-compose textarea {\n border: 0;\n background: transparent;\n resize: vertical;\n}\n\n.project-note-compose-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.project-note {\n margin-top: 10px;\n padding: 10px;\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n background: var(--m-bg-1);\n}\n\n.project-note-head {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.project-note-body {\n margin-top: 6px;\n white-space: pre-wrap;\n font-size: 12.5px;\n color: var(--m-text-2);\n}\n\n.project-note-edit {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin-top: 6px;\n}\n\n.project-note-selection {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 10px 0;\n padding: 6px 8px;\n border-radius: 8px;\n background: var(--m-accent-soft);\n}\n\n.project-tasks {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.project-task-add {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.project-task-add input {\n flex: 1;\n}\n\n.project-task-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 7px 8px;\n border: 1px solid var(--m-line-soft);\n border-radius: 8px;\n background: var(--m-bg-1);\n}\n\n.project-task-row.child {\n margin-left: 24px;\n background: var(--m-bg);\n}\n\n.project-task-row select {\n width: 90px;\n flex: none;\n}\n\n.project-task-title {\n font-size: 12.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.project-task-waiting {\n display: flex;\n gap: 6px;\n margin: 4px 0 4px 24px;\n}\n\n.project-task-waiting input {\n flex: 1;\n}\n\n.project-convert-list {\n margin: 0;\n padding-left: 20px;\n font-size: 12.5px;\n}\n\n@media (max-width: 620px) {\n .project-task-row {\n flex-wrap: wrap;\n }\n}\n\n.task-dot.WAITING {\n background: var(--m-warn);\n}\n\n.project-milestones,\n.project-activity {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.project-milestone {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border: 1px solid var(--m-line-soft);\n border-radius: 8px;\n background: var(--m-bg-1);\n}\n\n.project-milestone .done {\n text-decoration: line-through;\n color: var(--m-text-3);\n}\n\n.project-activity-row {\n display: flex;\n gap: 10px;\n padding: 6px 2px;\n border-bottom: 1px solid var(--m-line-soft);\n font-size: 12px;\n}\n\n.project-activity-row .small {\n flex: none;\n min-width: 130px;\n}\n\n.tasks-projects {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 0 18px 10px;\n}\n\n.project-notes-toolbar {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n}\n\n.project-proposals {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.project-proposal {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 8px 10px;\n border: 1px solid var(--m-line-soft);\n border-radius: 8px;\n background: var(--m-bg-1);\n}\n\n.project-proposal input {\n margin-top: 2px;\n}\n\n.project-proposal > span {\n display: flex;\n flex-direction: column;\n gap: 2px;\n font-size: 12.5px;\n}\n";
|
|
39
39
|
|
|
40
40
|
// src/client/icon.tsx
|
|
41
41
|
var import_react = require("react");
|
|
@@ -239,6 +239,26 @@ var api = {
|
|
|
239
239
|
method: "PATCH",
|
|
240
240
|
body: JSON.stringify(patch)
|
|
241
241
|
}),
|
|
242
|
+
addMilestone: (projectId, title, due = "") => request(`projects/${encodeURIComponent(projectId)}/milestones`, {
|
|
243
|
+
method: "POST",
|
|
244
|
+
body: JSON.stringify({ title, due })
|
|
245
|
+
}),
|
|
246
|
+
updateMilestone: (projectId, milestoneId, patch) => request(
|
|
247
|
+
`projects/${encodeURIComponent(projectId)}/milestones/${encodeURIComponent(milestoneId)}`,
|
|
248
|
+
{ method: "PATCH", body: JSON.stringify(patch) }
|
|
249
|
+
),
|
|
250
|
+
deleteMilestone: (projectId, milestoneId) => request(
|
|
251
|
+
`projects/${encodeURIComponent(projectId)}/milestones/${encodeURIComponent(milestoneId)}`,
|
|
252
|
+
{ method: "DELETE" }
|
|
253
|
+
),
|
|
254
|
+
proposeProjectTasks: (projectId, noteIds) => request("ai/propose/tasks", {
|
|
255
|
+
method: "POST",
|
|
256
|
+
body: JSON.stringify({ projectId, ...noteIds === void 0 ? {} : { noteIds } })
|
|
257
|
+
}),
|
|
258
|
+
createProjectSession: (projectId, purpose = "") => request(`projects/${encodeURIComponent(projectId)}/session`, {
|
|
259
|
+
method: "POST",
|
|
260
|
+
body: JSON.stringify({ purpose })
|
|
261
|
+
}),
|
|
242
262
|
addProjectNote: (id, body, createdAt) => request(`projects/${encodeURIComponent(id)}/notes`, {
|
|
243
263
|
method: "POST",
|
|
244
264
|
body: JSON.stringify({ body, ...createdAt === void 0 ? {} : { createdAt } })
|
|
@@ -1391,6 +1411,12 @@ function ProjectDetail({
|
|
|
1391
1411
|
const [taskTitle, setTaskTitle] = (0, import_react6.useState)("");
|
|
1392
1412
|
const [parentId, setParentId] = (0, import_react6.useState)(null);
|
|
1393
1413
|
const [waitingEdit, setWaitingEdit] = (0, import_react6.useState)(null);
|
|
1414
|
+
const [milestoneTitle, setMilestoneTitle] = (0, import_react6.useState)("");
|
|
1415
|
+
const [milestoneDue, setMilestoneDue] = (0, import_react6.useState)("");
|
|
1416
|
+
const [proposals, setProposals] = (0, import_react6.useState)(null);
|
|
1417
|
+
const [proposalSelected, setProposalSelected] = (0, import_react6.useState)([]);
|
|
1418
|
+
const [proposing, setProposing] = (0, import_react6.useState)(false);
|
|
1419
|
+
const [sessionNote, setSessionNote] = (0, import_react6.useState)("");
|
|
1394
1420
|
const apply2 = (next) => {
|
|
1395
1421
|
setCurrent(next);
|
|
1396
1422
|
onChanged(next);
|
|
@@ -1503,6 +1529,96 @@ function ProjectDetail({
|
|
|
1503
1529
|
setBusy(false);
|
|
1504
1530
|
}
|
|
1505
1531
|
};
|
|
1532
|
+
const addMilestone = async () => {
|
|
1533
|
+
const title = milestoneTitle.trim();
|
|
1534
|
+
if (title === "") return;
|
|
1535
|
+
setBusy(true);
|
|
1536
|
+
try {
|
|
1537
|
+
const result = await api.addMilestone(current.id, title, milestoneDue);
|
|
1538
|
+
apply2(result.project);
|
|
1539
|
+
setMilestoneTitle("");
|
|
1540
|
+
setMilestoneDue("");
|
|
1541
|
+
} catch (caught) {
|
|
1542
|
+
setError(errorText2(caught));
|
|
1543
|
+
} finally {
|
|
1544
|
+
setBusy(false);
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
const toggleMilestone = async (id, done2) => {
|
|
1548
|
+
try {
|
|
1549
|
+
const result = await api.updateMilestone(current.id, id, { done: done2 });
|
|
1550
|
+
apply2(result.project);
|
|
1551
|
+
} catch (caught) {
|
|
1552
|
+
setError(errorText2(caught));
|
|
1553
|
+
}
|
|
1554
|
+
};
|
|
1555
|
+
const removeMilestone = async (id) => {
|
|
1556
|
+
try {
|
|
1557
|
+
const result = await api.deleteMilestone(current.id, id);
|
|
1558
|
+
apply2(result.project);
|
|
1559
|
+
} catch (caught) {
|
|
1560
|
+
setError(errorText2(caught));
|
|
1561
|
+
}
|
|
1562
|
+
};
|
|
1563
|
+
const proposeTasks = async () => {
|
|
1564
|
+
if (current.notes.length === 0) {
|
|
1565
|
+
setError("\u5148\u6DFB\u52A0\u81F3\u5C11\u4E00\u6761\u9879\u76EE\u8BB0\u5F55\uFF0C\u518D\u8BA9 AI \u63D0\u8BAE\u4EFB\u52A1");
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
setProposing(true);
|
|
1569
|
+
setError("");
|
|
1570
|
+
try {
|
|
1571
|
+
const noteIds = selected.length > 0 ? selected : current.notes.slice(0, 20).map((note) => note.id);
|
|
1572
|
+
const result = await api.proposeProjectTasks(current.id, noteIds);
|
|
1573
|
+
setProposals(result.suggestions);
|
|
1574
|
+
setProposalSelected(result.suggestions.map((_item, index) => index));
|
|
1575
|
+
} catch (caught) {
|
|
1576
|
+
setError(errorText2(caught));
|
|
1577
|
+
} finally {
|
|
1578
|
+
setProposing(false);
|
|
1579
|
+
}
|
|
1580
|
+
};
|
|
1581
|
+
const createProposals = async () => {
|
|
1582
|
+
if (proposals === null) return;
|
|
1583
|
+
const accountId = current.accountIds[0];
|
|
1584
|
+
if (accountId === void 0) return;
|
|
1585
|
+
setBusy(true);
|
|
1586
|
+
try {
|
|
1587
|
+
for (const index of proposalSelected) {
|
|
1588
|
+
const item = proposals[index];
|
|
1589
|
+
if (item === void 0) continue;
|
|
1590
|
+
await api.createTask({
|
|
1591
|
+
accountId,
|
|
1592
|
+
projectId: current.id,
|
|
1593
|
+
title: item.title,
|
|
1594
|
+
notes: item.notes,
|
|
1595
|
+
due: item.due,
|
|
1596
|
+
priority: item.priority,
|
|
1597
|
+
owner: item.owner,
|
|
1598
|
+
status: "TODO"
|
|
1599
|
+
});
|
|
1600
|
+
}
|
|
1601
|
+
setProposals(null);
|
|
1602
|
+
await loadTasks();
|
|
1603
|
+
} catch (caught) {
|
|
1604
|
+
setError(errorText2(caught));
|
|
1605
|
+
} finally {
|
|
1606
|
+
setBusy(false);
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
const createSession = async () => {
|
|
1610
|
+
setBusy(true);
|
|
1611
|
+
setError("");
|
|
1612
|
+
try {
|
|
1613
|
+
const result = await api.createProjectSession(current.id);
|
|
1614
|
+
apply2(result.project);
|
|
1615
|
+
setSessionNote(`\u4F1A\u8BDD\u5DF2\u521B\u5EFA\uFF1A${result.sessionId.slice(0, 8)}\u2026`);
|
|
1616
|
+
} catch (caught) {
|
|
1617
|
+
setError(errorText2(caught));
|
|
1618
|
+
} finally {
|
|
1619
|
+
setBusy(false);
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1506
1622
|
const rootTasks = tasks.filter((task) => task.parentId === null);
|
|
1507
1623
|
const childOf = (id) => tasks.filter((task) => task.parentId === id);
|
|
1508
1624
|
const selectedNotes = current.notes.filter((note) => selected.includes(note.id));
|
|
@@ -1545,6 +1661,16 @@ function ProjectDetail({
|
|
|
1545
1661
|
(status) => (0, import_react6.createElement)("option", { key: status, value: status }, STATUS_LABEL[status])
|
|
1546
1662
|
)
|
|
1547
1663
|
),
|
|
1664
|
+
(0, import_react6.createElement)(
|
|
1665
|
+
"button",
|
|
1666
|
+
{
|
|
1667
|
+
className: "ghost small",
|
|
1668
|
+
disabled: busy,
|
|
1669
|
+
onClick: () => void createSession()
|
|
1670
|
+
},
|
|
1671
|
+
"\u521B\u5EFA\u4F1A\u8BDD"
|
|
1672
|
+
),
|
|
1673
|
+
sessionNote === "" ? null : (0, import_react6.createElement)("span", { className: "small muted" }, sessionNote),
|
|
1548
1674
|
(0, import_react6.createElement)(
|
|
1549
1675
|
"div",
|
|
1550
1676
|
{ className: "project-detail-tabs" },
|
|
@@ -1557,12 +1683,98 @@ function ProjectDetail({
|
|
|
1557
1683
|
"button",
|
|
1558
1684
|
{ className: tab === "tasks" ? "chip active" : "chip", onClick: () => setTab("tasks") },
|
|
1559
1685
|
`\u4EFB\u52A1 ${String(tasks.length)}`
|
|
1686
|
+
),
|
|
1687
|
+
(0, import_react6.createElement)(
|
|
1688
|
+
"button",
|
|
1689
|
+
{
|
|
1690
|
+
className: tab === "milestones" ? "chip active" : "chip",
|
|
1691
|
+
onClick: () => setTab("milestones")
|
|
1692
|
+
},
|
|
1693
|
+
`\u91CC\u7A0B\u7891 ${String(current.milestones.length)}`
|
|
1694
|
+
),
|
|
1695
|
+
(0, import_react6.createElement)(
|
|
1696
|
+
"button",
|
|
1697
|
+
{ className: tab === "activity" ? "chip active" : "chip", onClick: () => setTab("activity") },
|
|
1698
|
+
"\u6D3B\u52A8"
|
|
1560
1699
|
)
|
|
1561
1700
|
)
|
|
1562
1701
|
),
|
|
1563
|
-
tab === "
|
|
1702
|
+
tab === "milestones" ? (0, import_react6.createElement)(
|
|
1703
|
+
"div",
|
|
1704
|
+
{ className: "project-milestones" },
|
|
1705
|
+
(0, import_react6.createElement)(
|
|
1706
|
+
"div",
|
|
1707
|
+
{ className: "project-task-add" },
|
|
1708
|
+
(0, import_react6.createElement)("input", {
|
|
1709
|
+
value: milestoneTitle,
|
|
1710
|
+
placeholder: "\u91CC\u7A0B\u7891\u540D\u79F0\uFF0C\u4F8B\u5982\uFF1A\u65B9\u6848\u786E\u8BA4",
|
|
1711
|
+
onChange: (event) => setMilestoneTitle(event.target.value)
|
|
1712
|
+
}),
|
|
1713
|
+
(0, import_react6.createElement)("input", {
|
|
1714
|
+
type: "date",
|
|
1715
|
+
value: milestoneDue,
|
|
1716
|
+
"aria-label": "\u91CC\u7A0B\u7891\u65E5\u671F",
|
|
1717
|
+
onChange: (event) => setMilestoneDue(event.target.value)
|
|
1718
|
+
}),
|
|
1719
|
+
(0, import_react6.createElement)(
|
|
1720
|
+
"button",
|
|
1721
|
+
{
|
|
1722
|
+
className: "primary small",
|
|
1723
|
+
disabled: busy || milestoneTitle.trim() === "",
|
|
1724
|
+
onClick: () => void addMilestone()
|
|
1725
|
+
},
|
|
1726
|
+
"\u6DFB\u52A0"
|
|
1727
|
+
)
|
|
1728
|
+
),
|
|
1729
|
+
current.milestones.length === 0 ? (0, import_react6.createElement)("p", { className: "small muted" }, "\u8FD8\u6CA1\u6709\u91CC\u7A0B\u7891\u3002\u91CC\u7A0B\u7891\u662F\u53EF\u9009\u7684\u68C0\u67E5\u70B9\u3002") : current.milestones.map(
|
|
1730
|
+
(milestone) => (0, import_react6.createElement)(
|
|
1731
|
+
"div",
|
|
1732
|
+
{ key: milestone.id, className: "project-milestone" },
|
|
1733
|
+
(0, import_react6.createElement)("input", {
|
|
1734
|
+
type: "checkbox",
|
|
1735
|
+
checked: milestone.done,
|
|
1736
|
+
"aria-label": "\u91CC\u7A0B\u7891\u5B8C\u6210",
|
|
1737
|
+
onChange: (event) => void toggleMilestone(milestone.id, event.target.checked)
|
|
1738
|
+
}),
|
|
1739
|
+
(0, import_react6.createElement)("span", { className: milestone.done ? "done" : "" }, milestone.title),
|
|
1740
|
+
milestone.due === "" ? null : (0, import_react6.createElement)("span", { className: "small muted" }, milestone.due),
|
|
1741
|
+
(0, import_react6.createElement)("span", { className: "spacer" }),
|
|
1742
|
+
(0, import_react6.createElement)(
|
|
1743
|
+
"button",
|
|
1744
|
+
{ className: "subtle small danger", onClick: () => void removeMilestone(milestone.id) },
|
|
1745
|
+
"\u5220\u9664"
|
|
1746
|
+
)
|
|
1747
|
+
)
|
|
1748
|
+
)
|
|
1749
|
+
) : tab === "activity" ? (0, import_react6.createElement)(
|
|
1750
|
+
"div",
|
|
1751
|
+
{ className: "project-activity" },
|
|
1752
|
+
current.activity.length === 0 ? (0, import_react6.createElement)("p", { className: "small muted" }, "\u8FD8\u6CA1\u6709\u6D3B\u52A8\u8BB0\u5F55\u3002") : current.activity.map(
|
|
1753
|
+
(event) => (0, import_react6.createElement)(
|
|
1754
|
+
"div",
|
|
1755
|
+
{ key: event.id, className: "project-activity-row" },
|
|
1756
|
+
(0, import_react6.createElement)("span", { className: "small muted" }, new Date(event.at).toLocaleString()),
|
|
1757
|
+
(0, import_react6.createElement)("span", null, event.text)
|
|
1758
|
+
)
|
|
1759
|
+
)
|
|
1760
|
+
) : tab === "notes" ? (0, import_react6.createElement)(
|
|
1564
1761
|
"div",
|
|
1565
1762
|
{ className: "project-notes" },
|
|
1763
|
+
(0, import_react6.createElement)(
|
|
1764
|
+
"div",
|
|
1765
|
+
{ className: "project-notes-toolbar" },
|
|
1766
|
+
(0, import_react6.createElement)("span", { className: "small muted" }, "AI \u4F1A\u6839\u636E\u8BB0\u5F55\u548C\u672A\u5B8C\u6210\u4EFB\u52A1\u63D0\u8BAE\uFF0C\u786E\u8BA4\u540E\u624D\u521B\u5EFA"),
|
|
1767
|
+
(0, import_react6.createElement)("span", { className: "spacer" }),
|
|
1768
|
+
(0, import_react6.createElement)(
|
|
1769
|
+
"button",
|
|
1770
|
+
{
|
|
1771
|
+
className: "ghost small",
|
|
1772
|
+
disabled: proposing || busy,
|
|
1773
|
+
onClick: () => void proposeTasks()
|
|
1774
|
+
},
|
|
1775
|
+
proposing ? "AI \u63D0\u8BAE\u4E2D\u2026" : "AI \u63D0\u8BAE\u4EFB\u52A1"
|
|
1776
|
+
)
|
|
1777
|
+
),
|
|
1566
1778
|
(0, import_react6.createElement)(
|
|
1567
1779
|
"div",
|
|
1568
1780
|
{ className: "project-note-compose" },
|
|
@@ -1654,8 +1866,16 @@ function ProjectDetail({
|
|
|
1654
1866
|
onChange: (event) => setEditing({ ...editing, date: event.target.value })
|
|
1655
1867
|
}),
|
|
1656
1868
|
(0, import_react6.createElement)("span", { className: "spacer" }),
|
|
1657
|
-
(0, import_react6.createElement)(
|
|
1658
|
-
|
|
1869
|
+
(0, import_react6.createElement)(
|
|
1870
|
+
"button",
|
|
1871
|
+
{ className: "ghost small", onClick: () => setEditing(null) },
|
|
1872
|
+
"\u53D6\u6D88"
|
|
1873
|
+
),
|
|
1874
|
+
(0, import_react6.createElement)(
|
|
1875
|
+
"button",
|
|
1876
|
+
{ className: "primary small", onClick: () => void saveNote() },
|
|
1877
|
+
"\u4FDD\u5B58"
|
|
1878
|
+
)
|
|
1659
1879
|
)
|
|
1660
1880
|
) : (0, import_react6.createElement)("div", { className: "project-note-body" }, note.body)
|
|
1661
1881
|
)
|
|
@@ -1767,6 +1987,57 @@ function ProjectDetail({
|
|
|
1767
1987
|
)
|
|
1768
1988
|
)
|
|
1769
1989
|
),
|
|
1990
|
+
proposals === null ? null : (0, import_react6.createElement)(
|
|
1991
|
+
Modal,
|
|
1992
|
+
{
|
|
1993
|
+
title: "AI \u63D0\u8BAE\u7684\u4EFB\u52A1",
|
|
1994
|
+
wide: true,
|
|
1995
|
+
onClose: () => setProposals(null),
|
|
1996
|
+
footer: (0, import_react6.createElement)(
|
|
1997
|
+
"div",
|
|
1998
|
+
{ className: "project-detail-foot" },
|
|
1999
|
+
(0, import_react6.createElement)("span", { className: "small muted" }, `\u5DF2\u9009 ${String(proposalSelected.length)} \u4E2A`),
|
|
2000
|
+
(0, import_react6.createElement)("span", { className: "spacer" }),
|
|
2001
|
+
(0, import_react6.createElement)("button", { className: "ghost", onClick: () => setProposals(null) }, "\u53D6\u6D88"),
|
|
2002
|
+
(0, import_react6.createElement)(
|
|
2003
|
+
"button",
|
|
2004
|
+
{
|
|
2005
|
+
className: "primary",
|
|
2006
|
+
disabled: busy || proposalSelected.length === 0,
|
|
2007
|
+
onClick: () => void createProposals()
|
|
2008
|
+
},
|
|
2009
|
+
"\u521B\u5EFA\u9009\u4E2D\u4EFB\u52A1"
|
|
2010
|
+
)
|
|
2011
|
+
)
|
|
2012
|
+
},
|
|
2013
|
+
proposals.length === 0 ? (0, import_react6.createElement)("p", { className: "small muted" }, "AI \u6CA1\u6709\u627E\u5230\u9700\u8981\u65B0\u589E\u7684\u4EFB\u52A1\u3002") : (0, import_react6.createElement)(
|
|
2014
|
+
"div",
|
|
2015
|
+
{ className: "project-proposals" },
|
|
2016
|
+
proposals.map(
|
|
2017
|
+
(item, index) => (0, import_react6.createElement)(
|
|
2018
|
+
"label",
|
|
2019
|
+
{ key: `${item.title}-${String(index)}`, className: "project-proposal" },
|
|
2020
|
+
(0, import_react6.createElement)("input", {
|
|
2021
|
+
type: "checkbox",
|
|
2022
|
+
checked: proposalSelected.includes(index),
|
|
2023
|
+
onChange: (event) => setProposalSelected(
|
|
2024
|
+
(ids) => event.target.checked ? [...ids, index] : ids.filter((id) => id !== index)
|
|
2025
|
+
)
|
|
2026
|
+
}),
|
|
2027
|
+
(0, import_react6.createElement)(
|
|
2028
|
+
"span",
|
|
2029
|
+
null,
|
|
2030
|
+
(0, import_react6.createElement)("strong", null, item.title),
|
|
2031
|
+
item.due === "" && item.notes === "" ? null : (0, import_react6.createElement)(
|
|
2032
|
+
"span",
|
|
2033
|
+
{ className: "small muted" },
|
|
2034
|
+
[item.due, item.notes].filter((part) => part !== "").join(" \xB7 ")
|
|
2035
|
+
)
|
|
2036
|
+
)
|
|
2037
|
+
)
|
|
2038
|
+
)
|
|
2039
|
+
)
|
|
2040
|
+
),
|
|
1770
2041
|
confirmConvert ? (0, import_react6.createElement)(
|
|
1771
2042
|
Modal,
|
|
1772
2043
|
{
|
|
@@ -6469,6 +6740,35 @@ function TasksPanel() {
|
|
|
6469
6740
|
),
|
|
6470
6741
|
(0, import_react12.createElement)("span", { className: "small muted" }, "\u62D6\u52A8\u5361\u7247\u53EF\u6539\u53D8\u72B6\u6001")
|
|
6471
6742
|
),
|
|
6743
|
+
(0, import_react12.createElement)(
|
|
6744
|
+
"div",
|
|
6745
|
+
{ className: "tasks-projects" },
|
|
6746
|
+
(0, import_react12.createElement)(
|
|
6747
|
+
"button",
|
|
6748
|
+
{
|
|
6749
|
+
className: projectFilter === "" ? "chip active" : "chip",
|
|
6750
|
+
onClick: () => setProjectFilter("")
|
|
6751
|
+
},
|
|
6752
|
+
"\u5168\u90E8\u9879\u76EE"
|
|
6753
|
+
),
|
|
6754
|
+
projects.map((project) => ({
|
|
6755
|
+
project,
|
|
6756
|
+
count: tasks.filter(
|
|
6757
|
+
(task) => task.projectId === project.id && task.status !== "COMPLETED" && task.status !== "CANCELLED"
|
|
6758
|
+
).length
|
|
6759
|
+
})).filter((item) => item.count > 0).map(
|
|
6760
|
+
(item) => (0, import_react12.createElement)(
|
|
6761
|
+
"button",
|
|
6762
|
+
{
|
|
6763
|
+
key: item.project.id,
|
|
6764
|
+
className: projectFilter === item.project.id ? "chip active" : "chip",
|
|
6765
|
+
onClick: () => setProjectFilter(item.project.id)
|
|
6766
|
+
},
|
|
6767
|
+
item.project.name,
|
|
6768
|
+
(0, import_react12.createElement)("span", { className: "chip-count" }, String(item.count))
|
|
6769
|
+
)
|
|
6770
|
+
)
|
|
6771
|
+
),
|
|
6472
6772
|
(0, import_react12.createElement)(
|
|
6473
6773
|
"div",
|
|
6474
6774
|
{ className: "tasks-board" },
|
|
@@ -6874,7 +7174,7 @@ function TaskEditor({
|
|
|
6874
7174
|
}
|
|
6875
7175
|
|
|
6876
7176
|
// src/client/index.tsx
|
|
6877
|
-
var VERSION = "0.
|
|
7177
|
+
var VERSION = "0.25.0";
|
|
6878
7178
|
var inject = ["slots"];
|
|
6879
7179
|
var PANEL_ID = "mailharbor";
|
|
6880
7180
|
var TASKS_PANEL_ID = "mailharbor-tasks";
|